当前位置:   article > 正文

(二十八)Kubernetes集群服务发现之Service资源ClusterIP/NodePort/HeadLiness/ExternallName类型详解_headliness service

headliness service

目录

1.service介绍

1.1.service原理

1.2.kube-proxy支持的三种工作模式

1.3.开启ipvs模式

2.service资源清单文件

3.准备一个deployment资源

4.service资源详细配置

4.1.ClusterIP类型的Service

4.1.1.Endpoints资源

4.1.2.service亲和性负载策略

4.2.HeadLiness类型的Service

4.3.NodePort类型的Service

4.4.ExternalName类型的Service


1.service介绍

1.1.service原理

在k8s中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod经常会由于更新导致销毁,因此ip不是固定的,这就意味着不方便直接采用pod的ip对服务进行访问。

为了解决这个问题,kubernetes提供了service资源,service会对提供同一个服务的多个pod进行聚合,并且 提供一个统一的入口地址,通过访问service的入口地址就能访问到后面的pod服务

service原理:service资源创建后将信息写入etcd,kube-proxy通过监听etcd生成最新的ipvs规则,请求首先转发给service,service在根据定义的标签选择器关联到对应的pod上,最终由这一组pod提供服务

请添加图片描述

service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,在每个Node节点上都运行着一个kube-proxy服务进程,当创建service资源后,会通过api-server向etcd中写入创建的service信息,kube-proxy会基于监听机制发现service的变动,最后将最新的service信息转换成对应的访问规则,用户请求service的时候其实就是请求的kube-proxy转换的访问规则
在这里插入图片描述

kube-proxy支持三种模式,以ipvs为例

  1. [root@k8s-master ~]# ipvsadm -Ln
  2. IP Virtual Server version 1.2.1 (size=4096)
  3. Prot LocalAddress:Port Scheduler Flags
  4. -> RemoteAddress:Port Forward Weight ActiveConn InActConn
  5. TCP 10.96.0.10:53 rr
  6. -> 10.244.0.18:53 Masq 1 0 0
  7. -> 10.244.0.19:53 Masq 1 0 0
  • 10.96.0.10:53为service的ip,rr表示轮询,下面10.244.0.18、10.244.0.19都是pod的ip地址
  • 当访问这个service ip时,kube-proxy会根据ipvs策略通过轮询的方式转发给后端的pod
  • 这套规则会在集群上任意节点都生成,因此访问集群任意节点都可以访问到内部的pod
1.2.kube-proxy支持的三种工作模式

userspace模式

userspace模式下,kube-proxy会为每一个service创建一个监听端口,用户请求首先发送给Cluster IP,然后由iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法选择一个提供服务的pod并和其建立连接

该模式下,kube-proxy充当了一个四层负载均衡器的角色,由于kube-proxy运行在userspace下,在转发的过程中会增加内核和用户空间之间的数据拷贝,虽然稳定但是效率比较低

iptables模式

iptables模式下,kube-proxy为service后端的每个pod创建对应的iptables规则,当用户请求时,首先将请求发给cluster IP,然后根据iptables规则,转发到具体的pod上

该模式下kube-proxy的作用仅仅是监听service的变化,生成最新的iptables规则,此时kube-proxy不再承担四层负载均衡器的角色,该模式的优点较userspace模式效率更高,但是不能提供灵活的LB策略,当其中一个pod异常,iptables还是会转发在异常的pod上,并且不会重试

ipvs模式

ipvs模式和iptables模式类似,kube-proxy监控service、pod的变化并创建对应的ipvs规则,ipvs相对于iptables转发效率更高,除此之外,ipvs支持更多的LB算法

1.3.开启ipvs模式
  1. 1.修改kube-proxy的configmap设置mode为ipvs
  2. [root@k8s-master ~]# kubectl edit cm kube-proxy -n kube-system
  3. 44 mode: "ipvs" #在44行左右
  4. configmap/kube-proxy edited
  5. 2.重建所有关于kube-proxy的pod
  6. #-l表示根据标签找到对应的pod
  7. [root@k8s-master ~]# kubectl delete pod -l k8s-app=kube-proxy -n kube-system
  8. pod "kube-proxy-4lvxw" deleted
  9. pod "kube-proxy-lkm8r" deleted
  10. pod "kube-proxy-whmll" deleted
  11. 3.查看ipvs规则
  12. [root@k8s-master ~]# ipvsadm -Ln
  13. IP Virtual Server version 1.2.1 (size=4096)
  14. Prot LocalAddress:Port Scheduler Flags
  15. -> RemoteAddress:Port Forward Weight ActiveConn InActConn
  16. TCP 192.168.81.210:30376 rr
  17. TCP 192.168.122.1:30376 rr
  18. TCP 10.96.0.1:443 rr
  19. -> 192.168.81.210:6443 Masq 1 0 0
  20. TCP 10.96.0.10:53 rr
  21. -> 10.244.0.18:53 Masq 1 0 0
  22. -> 10.244.0.19:53 Masq 1 0 0
  23. TCP 10.96.0.10:9153 rr
  24. -> 10.244.0.18:9153 Masq 1 0 0
  25. -> 10.244.0.19:9153 Masq 1 0 0
  26. TCP 10.101.187.80:80 rr
  27. TCP 10.102.142.245:80 rr
  28. -> 10.244.1.198:8080 Masq 1 0 0
  29. TCP 10.103.231.226:80 rr persistent 10800
  30. -> 10.244.1.202:8080 Masq 1 0 0
  31. TCP 10.111.44.36:443 rr
  32. -> 192.168.81.230:443 Masq 1 1 0
  33. TCP 10.111.227.155:80 rr persistent 10800
  34. TCP 10.244.0.0:30376 rr
  35. TCP 10.244.0.1:30376 rr
  36. TCP 127.0.0.1:30376 rr
  37. TCP 172.17.0.1:30376 rr
  38. UDP 10.96.0.10:53 rr
  39. -> 10.244.0.18:53 Masq 1 0 0
  40. -> 10.244.0.19:53 Masq 1 0 0

2.service资源清单文件

  1. kind: Service //资源类型
  2. apiVersion: v1 //资源版本
  3. metadata: //元数据
  4. name: service //资源名称
  5. namespace: dev //所在的命名空间
  6. spec: //属性
  7. selector: //标签选择器,用于确定当前service代理哪些pod
  8. app: nginx //pod的标签
  9. type: //Service类型, 指定service的访问方式
  10. clusterIP: //虚拟服务的ip地址,即service地址
  11. sessionAffinity: //session亲和性,支持ClientIP、 None两个选项
  12. ports: //端口信息
  13. protocol: TCP
  14. port: 3017 //service端口
  15. targetPort: 5003 //pod端口
  16. nodePort: 31122 //映射的主机端口

service支持四种访问方式:

  • ClusterIP:默认值,由k8s系统自动分配的虚拟IP,只能在集群内部访问
  • NodePort:service通过映射的方式将service端口映射到Node节点上的随机端口,通过此方法就可以在集群外部访问服务
  • LoadBalancer:使用外接负载均衡器完成服务的负载分发,需要外部环境的支持
  • ExternalName:把集群外部的服务引入集群内部直接使用

sessionAffinity亲和性默认情况下,当同一个客户端地址发过来的请求会以轮询的方式转发给不同的pod,但是有时也需要当同一个客户端发来的请求只转发给一个pod时,就需要配置session亲和性了

3.准备一个deployment资源

创建一个deployment资源用于测试service资源

  1. 1.编写yaml
  2. [root@k8s-master ~/k8s_1.19_yaml/service]# vim deployment-nginx.yaml
  3. apiVersion: apps/v1
  4. kind: Deployment
  5. metadata:
  6. name: deployment-nginx
  7. namespace: dev
  8. spec:
  9. replicas: 3
  10. selector:
  11. matchLabels:
  12. app: nginx-pod
  13. template:
  14. metadata:
  15. labels:
  16. app: nginx-pod
  17. spec:
  18. containers:
  19. - name: nginx
  20. image: nginx:1.17.1
  21. ports:
  22. - containerPort: 80
  23. 2.创建资源
  24. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl create -f deployment-nginx.yaml
  25. deployment.apps/deployment-nginx created
  26. 3.查看资源的状态
  27. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl get deploy,pod -n dev -o wide
  28. NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
  29. deployment.apps/deployment-nginx 3/3 3 3 26s nginx nginx:1.17.1 app=nginx-pod
  30. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  31. pod/deployment-nginx-5ffc5bf56c-788vz 1/1 Running 0 26s 10.244.2.25 k8s-node2 <none> <none>
  32. pod/deployment-nginx-5ffc5bf56c-b2wzp 1/1 Running 0 26s 10.244.2.27 k8s-node2 <none> <none>
  33. pod/deployment-nginx-5ffc5bf56c-zbhpr 1/1 Running 0 26s 10.244.2.26 k8s-node2 <none> <none>
  34. 4.修改nginx访问首页
  35. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl exec -it deployment-nginx-5ffc5bf56c-788vz -n dev /bin/sh
  36. # echo "pod: 10.244.2.25" > /usr/share/nginx/html/index.html
  37. # cat /usr/share/nginx/html/index.html
  38. pod: 10.244.2.25
  39. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl exec -it deployment-nginx-5ffc5bf56c-b2wzp -n dev /bin/sh
  40. # echo "pod: 10.244.2.27" > /usr/share/nginx/html/index.html
  41. # cat /usr/share/nginx/html/index.html
  42. pod: 10.244.2.27
  43. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl exec -it deployment-nginx-5ffc5bf56c-zbhpr -n dev /bin/sh
  44. # echo "pod: 10.244.2.26" > /usr/share/nginx/html/index.html
  45. # cat /usr/share/nginx/html/index.html
  46. pod: 10.244.2.26
  47. 5.测试nginx
  48. [root@k8s-master ~/k8s_1.19_yaml/service]# curl 10.244.2.25
  49. pod: 10.244.2.25
  50. [root@k8s-master ~/k8s_1.19_yaml/service]# curl 10.244.2.26
  51. pod: 10.244.2.26
  52. [root@k8s-master ~/k8s_1.19_yaml/service]# curl 10.244.2.27
  53. pod: 10.244.2.27

4.service资源详细配置

4.1.ClusterIP类型的Service

ClusterIP类型的service资源只能在集群内部使用,集群外部无法访问

  1. 1.编写yaml
  2. [root@k8s-master ~/k8s_1.19_yaml/service]# vim service-clusterip.yaml
  3. apiVersion: v1 #版本
  4. kind: Service #控制器类型
  5. metadata: #元数据
  6. name: service-clusterip #service的名称
  7. namespace: dev #所在的命名空间
  8. spec: #属性
  9. selector: #标签选择器
  10. app: nginx-pod #关联上pod定义的标签而不是deployment的标签
  11. clusterIP: 10.100.100.100 #service ip地址,不填写k8s也会自动生成
  12. type: ClusterIP #service类型为ClusterIP
  13. ports: #端口设置
  14. - port: 80 #service的端口
  15. targetPort: 80 #pod的端口
  16. 2.创建service资源
  17. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl create -f service-clusterip.yaml
  18. service/service-clusterip created
  19. 3.查看service资源
  20. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl get svc -n dev
  21. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  22. service-clusterip ClusterIP 10.100.100.100 <none> 80/TCP 4m53s
  23. 4.查看svc的详细信息
  24. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl describe svc service-clusterip -n dev
  25. Name: service-clusterip
  26. Namespace: dev
  27. Labels: <none>
  28. Annotations: <none>
  29. Selector: app=nginx-pod
  30. Type: ClusterIP
  31. IP: 10.100.100.100
  32. Port: <unset> 80/TCP
  33. TargetPort: 80/TCP
  34. Endpoints: 10.244.1.207:80,10.244.2.28:80,10.244.2.29:80 #endpoints也是一种k8s资源,显示当前svc对应后端的pod信息
  35. Session Affinity: None
  36. Events: <none>
  37. 5.查看ipvs映射规则
  38. [root@k8s-master ~/k8s_1.19_yaml/service]# ipvsadm -Ln
  39. TCP 10.100.100.100:80 rr #svc的地址、负载算法为rr
  40. -> 10.244.1.207:80 Masq 1 0 0
  41. -> 10.244.2.28:80 Masq 1 0 0
  42. -> 10.244.2.29:80 Masq 1 0 0
  43. 6.访问service查看效果
  44. [root@k8s-master ~/k8s_1.19_yaml/service]# curl 10.100.100.100:80
  45. pod: 10.244.2.28
  46. [root@k8s-master ~/k8s_1.19_yaml/service]# curl 10.100.100.100:80
  47. pod: 10.244.1.207
  48. [root@k8s-master ~/k8s_1.19_yaml/service]# curl 10.100.100.100:80
  49. pod: 10.244.2.29
  50. 7.由于默认的service负载是rr算法,我们使用循环测试一下
  51. [root@k8s-master ~/k8s_1.19_yaml/service]# while true; do curl 10.100.100.100:80;sleep 3 ;done
  52. pod: 10.244.1.207
  53. pod: 10.244.2.29
  54. pod: 10.244.2.28
  55. pod: 10.244.1.207
  56. pod: 10.244.2.29
  57. pod: 10.244.2.28
  58. #可以看到非常的负载均衡

4.1.1.Endpoints资源

在上面测试了ClusterIP效果后,在查看svc详细信息时看到有个Endpoints,里面显示了pod的所有ip信息

其实Endpoints也是k8s一种资源类型,存储在etcd中,用来记录一个service对应的所有pod访问地址,它是根据service配置文件中selector标签选择器产生的

一个service由一组pod组成,这些pod通过Endpoints暴露出来,Endpoints是实现实际服务的端点集合,service和pod之间的联系是通过endpoints实现的
在这里插入图片描述

  1. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl get endpoints -n dev
  2. NAME ENDPOINTS AGE
  3. service-clusterip 10.244.1.207:80,10.244.2.28:80,10.244.2.29:80 18m
4.1.2.service亲和性负载策略

当用户访问service时,请求都会被平均的分配到后端的pod上,目前k8s提供了两种负载分发策略

  • 如果不定义,默认为none,默认使用kube-proxy策略,比如随机、轮询
  • 基于客户端地址的会话保持模式,来自同一个客户端发起的所有请求都会被转发到一个固定的pod上,类似于nginx的ip_hash

基于客户端地址的亲和性策略可以配置在spec中的sessionAffinity参数中

  1. 1.配置亲和性策略为ClientIP
  2. [root@k8s-master ~/k8s_1.19_yaml/service]# vim service-clusterip.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6. name: service-clusterip
  7. namespace: dev
  8. spec:
  9. selector:
  10. app: nginx-pod
  11. sessionAffinity: ClientIP #session亲和性为ClientIP
  12. clusterIP: 10.100.100.100
  13. type: ClusterIP
  14. ports:
  15. - port: 80
  16. targetPort: 80
  17. 2.更新资源
  18. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl apply -f service-clusterip.yaml
  19. service/service-clusterip configured
  20. 3.查看资源配置是否生效
  21. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl describe svc -n dev
  22. Name: service-clusterip
  23. Namespace: dev
  24. Labels: <none>
  25. Annotations: <none>
  26. Selector: app=nginx-pod
  27. Type: ClusterIP
  28. IP: 10.100.100.100
  29. Port: <unset> 80/TCP
  30. TargetPort: 80/TCP
  31. Endpoints: 10.244.1.207:80,10.244.2.28:80,10.244.2.29:80
  32. Session Affinity: ClientIP #已经生效
  33. Events: <none>
  34. 4.循环测试一下
  35. [root@k8s-master ~/k8s_1.19_yaml/service]# while true; do curl 10.100.100.100:80;sleep 3 ;done
  36. pod: 10.244.1.207
  37. pod: 10.244.1.207
  38. pod: 10.244.1.207
  39. pod: 10.244.1.207
  40. pod: 10.244.1.207
  41. #来自同一个客户端的ip是否请求在一个pod上

在这里插入图片描述

4.2.HeadLiness类型的Service

在某些场景中,开发人员可能不想使用service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness service,这类service不会分配ClusterIP,如果想要访问service,只能通过service的域名进行查询

service有默认的域名:service名称.命令空间.svc.cluster.local,svc.cluster.local是创建集群是配置的,不配置默认就是svc.cluster.local

  1. 1.编写yaml
  2. [root@k8s-master ~/k8s_1.19_yaml/service]# vim service-headliness.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6. name: service-headliness
  7. namespace: dev
  8. spec:
  9. selector:
  10. app: nginx-pod
  11. sessionAffinity: ClientIP
  12. clusterIP: None #和ClusterIP配置基本一致,只需要把clusterIP填写成None即可
  13. type: ClusterIP
  14. ports:
  15. - port: 80
  16. targetPort: 80
  17. 2.创建资源
  18. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl create -f service-headliness.yaml
  19. service/service-headliness created
  20. 3.查看svc的状态
  21. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl get svc service-headliness -n dev
  22. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  23. service-headliness ClusterIP None <none> 80/TCP 41s
  24. #可以看到svc没有clusterIP,因此只能通过域名来访问
  25. 4.获取pod所使用的域名解析地址
  26. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl exec -it deployment-nginx-5d4468bc6d-cxhgd /bin/bash -n dev
  27. root@deployment-nginx-5d4468bc6d-cxhgd:/# cat /etc/resolv.conf
  28. nameserver 10.96.0.10 #dns地址
  29. search dev.svc.cluster.local svc.cluster.local cluster.local #域名
  30. options ndots:5
  31. 5.解析域名
  32. [root@k8s-master ~/k8s_1.19_yaml/service]# dig @10.96.0.10 service-headliness.dev.svc.cluster.local
  33. ;; ANSWER SECTION:
  34. service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.207
  35. service-headliness.dev.svc.cluster.local. 30 IN A 10.244.2.28
  36. service-headliness.dev.svc.cluster.local. 30 IN A 10.244.2.29

在这里插入图片描述

4.3.NodePort类型的Service

如果希望将service暴露到集群外部使用,那么就需要使用另一种类型的service,称为NodePort类型,Nodeport的工作原理其实就是将service的端口映射到了Node的一个端口上,然后通过NodeIP:NodePort来访问service

NodePort原理:将service的端口映射到node节点的一个端口上,这个端口会在集群每个节点上都存在,当访问nodeip+nodeport时就会被转发到对应映射端口的service上
在这里插入图片描述

  1. 1.编写yaml
  2. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl create -f service-nodeport.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6. name: service-nodeport
  7. namespace: dev
  8. spec:
  9. selector:
  10. app: nginx-pod
  11. type: NodePort #service类型为NodePort
  12. ports:
  13. - port: 80
  14. targetPort: 80
  15. nodePort: 31001 #指定映射在node节点上的端口号,不知道则会产生一个随机的端口号
  16. 2.创建资源
  17. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl create -f service-nodeport.yaml
  18. service/service-nodeport created
  19. 3.查看资源的状态
  20. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl get svc service-nodeport -n dev
  21. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  22. service-nodeport NodePort 10.96.230.10 <none> 80:31001/TCP 36s
  23. 4.查看ipvs策略
  24. [root@k8s-master ~/k8s_1.19_yaml/service]# ipvsadm -Ln
  25. TCP 10.244.0.0:31001 rr
  26. -> 10.244.1.207:80 Masq 1 0 0
  27. -> 10.244.2.28:80 Masq 1 0 0
  28. -> 10.244.2.29:80 Masq 1 0 0
  29. 5.访问nodeip:nodeport验证是否可用
  30. [root@k8s-master ~/k8s_1.19_yaml/service]# curl http://192.168.81.210:31001/
  31. pod: 10.244.1.207
  32. [root@k8s-master ~/k8s_1.19_yaml/service]# curl http://192.168.81.210:31001/
  33. pod: 10.244.2.29
  34. [root@k8s-master ~/k8s_1.19_yaml/service]# curl http://192.168.81.210:31001/
  35. pod: 10.244.2.28

4.4.ExternalName类型的Service

ExternalName类型的service用于引入集群外部的服务,通过externalName属性指定一个外部的服务地址,引入集群后,就可以在集群内部使用service的域名访问到外部的服务

简而言之ExternalName就是将外部服务引入集群,然后通过service来访问外部的服务

  1. 1.编写yaml
  2. [root@k8s-master ~/k8s_1.19_yaml/service]# vim service-externalname.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6. name: service-externalname
  7. namespace: dev
  8. spec:
  9. type: ExternalName
  10. externalName: www.baidu.com
  11. 2.创建yaml
  12. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl create -f service-externalname.yaml
  13. service/service-externalname created
  14. 3.查看资源状态
  15. [root@k8s-master ~/k8s_1.19_yaml/service]# kubectl get svc service-externalname -n dev
  16. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  17. service-externalname ExternalName <none> www.baidu.com <none> 105s
  18. #这种类型的service也是没有clusterip的
  19. 4.解析域名验证是否能访问到外部服务
  20. [root@k8s-master ~/k8s_1.19_yaml/service]# dig @10.96.0.10 service-externalname.dev.svc.cluster.local
  21. service-externalname.dev.svc.cluster.local. 5 IN CNAME www.baidu.com.
  22. www.baidu.com. 5 IN CNAME www.a.shifen.com.
  23. www.a.shifen.com. 5 IN A 220.181.38.150
  24. www.a.shifen.com. 5 IN A 220.181.38.149
  25. 5.测试域名是否能拿到外部项目
  26. [root@k8s-master ~/k8s_1.19_yaml/service]# curl www.a.shifen.com

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/764474
推荐阅读
相关标签
  

闽ICP备14008679号