Service是什么?

  • 背景:每个Pod具有IP地址,当使用Deployment控制器时,Pod的IP地址往往动态变化。
  • 解决方法:通过Service可以获得稳定的IP地址,且在Service的生命周期有效,与Pod的IP地址变化与否无关。
  • 实质:Service本质就是一个LB负载均衡器
Service存在的意义

Pod与Service的关系

Service定义和创建

创建Nginx

[root@k8s-master ~]# vim deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deployment labels:  app: nginxspec: replicas: 3 selector:  matchLabels:   app: nginx template:  metadata:   labels:    app: nginx  spec:   containers:   - name: nginx    image: nginx:1.14.2    ports:    - containerPort: 80

查看刚刚部署的Nginx服务标签

[root@k8s-master ~]# kubectl get pods --show-labelsNAME            READY  STATUS  RESTARTS   AGE  LABELSnginx-6799fc88d8-s5rnz      1/1  Running  0     24d  app=nginx,pod-template-hash=6799fc88d8nginx-deployment-66b6c48dd5-hxv7h  1/1   Running  0     70s  app=nginx,pod-template-hash=66b6c48dd5nginx-deployment-66b6c48dd5-jjkk4  1/1   Running  0     70s  app=nginx,pod-template-hash=66b6c48dd5nginx-deployment-66b6c48dd5-tsgvb  1/1   Running  0     70s  app=nginx,pod-template-hash=66b6c48dd5
查看当前namespace(default)下有哪些svc

[root@k8s-master ~]# kubectl get svcNAME     TYPE   CLUSTER-IP  EXTERNAL-IP  PORT(S)    AGEkubernetes  ClusterIP   10.96.0.1   <none>    443/TCP    24dnginx    NodePort  10.108.41.4  <none>    80:31434/TCP  24d
定义并创建Service

[root@k8s-node2 ~]# vim service.yamlapiVersion: v1kind: Servicemetadata: name: web namespace: defaultspec: ports: - port: 80    # Service端口  protocol: TCP  # 协议  targetPort: 80  # 容器端口(程序启动端口,比如django默认是8000端口) selector:   app: nginx   # 指定关联Pod的标签(上面已经查到了,app=nginx) type: ClusterIP   # 服务类型
创建svc

[root@k8s-master ~]# kubectl apply -f service.yaml
通过Service访问Nginx集群

[root@k8s-master ~]# kubectl get svcNAME     TYPE    CLUSTER-IP   EXTERNAL-IP  PORT(S)    AGEkubernetes  ClusterIP  10.96.0.1    <none>   443/TCP    24dnginx    NodePort  10.108.41.4   <none>   80:31434/TCP  24dweb     ClusterIP  10.105.53.183   <none>    80/TCP    2m40s[root@k8s-master ~]# curl 10.105.53.183    # 可以通过web的地址访问后面三个nginx集群[root@k8s-master ~]# kubectl delete svc web2   # 可以删除其中一个
Service三种常用类型

  • ClusterIP:集群内部使用

  • NodePort:对外暴露应用(集群外)

  • LoadBalancer:对外暴露应用,适用公有云

ClusterIP(VIP)

NodePort

部署并测试

[root@k8s-master ~]# vim deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deployment labels:  app: nginxspec: replicas: 3 selector:  matchLabels:   app: nginx template:  metadata:   labels:    app: nginx  spec:   containers:   - name: nginx    image: nginx:1.14.2    ports:    - containerPort: 80
查看nginx服务的标签

[root@k8s-master ~]# kubectl get pods --show-labelsNAME            READY  STATUS  RESTARTS   AGE  LABELSnginx-6799fc88d8-s5rnz      1/1  Running  0     24d  app=nginx,pod-template-hash=6799fc88d8nginx-deployment-66b6c48dd5-hxv7h  1/1   Running  0     70s  app=nginx,pod-template-hash=66b6c48dd5nginx-deployment-66b6c48dd5-jjkk4  1/1   Running  0     70s  app=nginx,pod-template-hash=66b6c48dd5nginx-deployment-66b6c48dd5-tsgvb  1/1   Running  0     70s  app=nginx,pod-template-hash=66b6c48dd5
使用NodePort创建svc

[root@k8s-node2 ~]# vim service-nodeport.yamlapiVersion: v1kind: Servicemetadata: name: web-nodeport namespace: defaultspec: ports: - port: 80    # Service端口  protocol: TCP  # 协议  targetPort: 80  # 容器端口(程序启动端口,比如django默认是8000端口)  nodePort: 30706  # 指定NodePort监听的外网端口 selector:   app: nginx   # 指定关联Pod的标签(上面已经查到了,app=nginx) type: NodePort   # 服务类型(只需要把服务类型修改成NodePort即可)
创建svc

[root@k8s-master ~]# kubectl apply -f service-nodeport.yaml
访问

  • 访问地址:<任意NodeIP>:NodePort

  • 端口范围:30000-32767

NodePort弊端

LoadBalancer

LB说明

  • 负责均衡器有哪些:nginx、LVS、haproxy

  • 私有云:SLB、ELB

配置LB

  • 直接找一个nginx配置反向代理即可
stream {  log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';  access_log /var/log/nginx/django-access.log main;  upstream django-apiserver {        server 192.168.56.62:30706;        server 192.168.56.63:30706;      }    server {    listen 88;    proxy_pass django-apiserver;  }}
注意:生产最好使用云厂商的ELB或者SLB

Service二种特殊类型

  • ExternalName:引用集群外的服务

  • Headless允许Pod通过其主机名被访问

ExternalName Service

ExternalName Service说明:

ExternalName Service 是一种特殊类型的 Service,它不分配 ClusterIP,也不选择 Pods。相反,它允许你通过 Kubernetes Service 来引用外部的服务,比如一个托管在集群外的数据库或任何其他服务。

使用场景:

  • 引用集群外的服务。
  • 简化对外部服务的引用,不需要修改应用程序配置。

操作步骤:

  1. 创建一个ExternalName类型的 Service YAML 文件,指定type: ExternalNameexternalName字段。
  2. 应用该 YAML 文件来创建 Service。
apiVersion: v1kind: Servicemetadata: name: external-db-servicespec: type: ExternalName externalName: my.database.com ports: - port: 5432

实现效果:

  • 当你创建了上述 Service 后,Kubernetes 会创建一个 DNS 记录,使得external-db-service.default.svc.cluster.local解析到my.database.com
  • 集群内的 Pod 可以通过这个 DNS 名称和端口号5432来访问外部的数据库服务。

ExternalName Service 优缺点:

优点

  1. 简化外部服务引用:不需要修改应用程序的配置即可引用外部服务。
  2. 集成外部服务:可以无缝地将外部服务集成到Kubernetes集群的服务发现机制中。
  3. 灵活性:可以引用任何可通过DNS解析的服务,不限于特定的服务类型或协议。

缺点

  1. 依赖外部服务:如果外部服务不可用,那么通过ExternalNameService 访问它也会失败。
  2. 没有负载均衡:不提供内置的负载均衡功能,所有流量直接转发到外部服务。
  3. 安全性:如果外部服务需要特定的安全措施,可能需要额外的配置。
Headless Service

Headless Service说明:

Headless Service 是一种不分配 ClusterIP 的 Service,它允许每个 Pod 通过其主机名直接被访问。

使用场景:

  • 当你不需要 Kubernetes 来管理负载均衡和路由时。
  • 当你想要直接控制 Pod 的访问方式时。

操作步骤:

  1. 创建一个 Service YAML 文件,不要指定clusterIP: None(默认就是 None)。
  2. 应用该 YAML 文件来创建 Service。
apiVersion: v1kind: Servicemetadata: name: headless-servicespec: # 注意这里不指定 clusterIP selector:  app: my-app ports: - name: http  port: 80  targetPort: 8080

实现效果

  • 创建 Service 后,Kubernetes 会为每个匹配的 Pod 创建一个 DNS 记录
  • Pod 可以通过<pod-name>.headless-service.default.svc.cluster.local来访问同一 Service 下的其他 Pod。
  • 这种方式不提供负载均衡,直接通过 DNS 解析到具体的 Pod。

Headless Service 优缺点:

优点

  1. 直接访问:允许直接通过Pod的主机名访问,无需通过负载均衡器。
  2. 简单性:不需要Kubernetes进行流量管理和负载均衡,简化了网络架构。
  3. 适用于无状态服务:对于不需要负载均衡的无状态服务,Headless Service是一个轻量级的选择。

缺点

  1. 没有负载均衡:不提供负载均衡,可能导致某些Pod过载而其他Pod空闲。
  2. 管理复杂性:需要手动管理Pod的访问和负载分配,增加了运维的复杂性。
  3. 扩展性问题:当服务需要水平扩展时,手动管理Pod的访问可能会变得不切实际。

本篇文章来源于微信公众号: 运维人生活指南



微信扫描下方的二维码阅读本文

此作者没有提供个人介绍
最后更新于 2024-08-02