1 Service 概述 1.1 为什么要使用Service
Kubernetes Pod是平凡的,由
Deployment等控制器管理的
Pod对象都是有生命周期的,它们会被创建,也会意外挂掉。虽然它们可以由控制器自动重建或者滚动更新,但是重建或更新之后的
Pod对象的IP地址等都会发生新的变化。这样就会导致一个问题,如果一组
Pod(称为
backend)为其它
Pod(称为
frontend)提供服务,那么那些
frontend该如何发现,并连接到这组
Pod中的哪些
backend呢? 这时候就用到了:
Service
示例说明为什么要使用Service
如下图所示,当Nginx Pod
作为客户端访问Tomcat Pod
中的应用时,IP
的变动或应用规模的缩减会导致客户端访问错误。而Pod
规模的扩容又会使得客户端无法有效的使用新增的Pod
对象,从而影响达成规模扩展之目的。为此,Kubernetes
特地设计了Service
资源来解决此类问题。
1.2 Service实现原理 Service
资源基于标签选择器将一组Pod
定义成一个逻辑组合,并通过自己的IP
地址和端口调度代理请求至组内的Pod
对象之上,如下图所示,它向客户端隐藏了真实的、处理用户请求的Pod
资源,使得客户端的请求看上去就像是由Service
直接处理并响应一样。
Service
对象的IP
地址也称为Cluster IP
,它位于Kubernetes
集群配置指定专用IP
地址的范围之内,是一种虚拟IP
地址,它在Service
对象创建后既保持不变,并且能够被同一集群中的Pod
资源所访问。
Service
端口用于接收客户端请求并将其转发至其后端的Pod
中的相应端口之上,因此,这种代理机构也称为“端口代理”(port proxy
)或四层代理,工作于TCP/IP
协议栈的传输层。
Service
资源会通过API Server
持续监视着(watch
)标签选择器匹配到的后端Pod
对象,并实时跟踪各对象的变动,例如,IP
地址变动、对象增加或减少等。Service
并不直接链接至Pod
对象,它们之间还有一个中间层——Endpoints
资源对象,它是一个由IP
地址和端口组成的列表,这些IP
地址和端口则来自由Service
的标签选择器匹配到的Pod
资源。当创建service
对象时,其关联的Endpoints
对象会自动创建。
1.3 虚拟IP和服务代理 一个Service
对象就是工作节点上的一些iptables
或ipvs
规则,用于将到达Service
对象IP
地址的流量调度转发至相应的Endpoints
对象指定的IP
地址和端口之上。kube-proxy
组件通过API Server
持续监控着各Service
及其关联的Pod
对象,并将其创建或变动实时反映到当前工作节点上的iptables
规则或ipvs
规则上。
ipvs
是借助于Netfilter
实现的网络请求报文调度框架,支持rr
、wrr
、lc
、wlc
、sh
、sed
和nq
等十余种调度算法,用户空间的命令行工具是ipvsadm
,用于管理工作与ipvs
之上的调度规则。
Service IP
事实上是用于生成iptables
或ipvs
规则时使用的IP
地址,仅用于实现Kubernetes
集群网络的内部通信,并且能够将规则中定义的转发服务的请求作为目标地址予以相应,这也是将其称为虚拟IP
的原因之一。
kube-proxy
将请求代理至相应端点的方式有三种:userspace(用户空间) 、iptables 和ipvs 。
1.3.1 userspace代理模式 userspace
是Linux
操作系统的用户空间。这种模式下,kube-proxy
负责跟踪API Server
上Service
和Endpoints
对象的变动(创建或移除),并据此调整Service
资源的定义。对于每个Service
对象,它会随机打开一个本地端口(运行于用户控件的kube-proxy
进程负责监听),任何到达此端口的连接请求都将代理至当前Service
资源后端的各Pod
对象上,至于会挑选中哪个Pod
对象则取决于当前Service
资源的调度方式(通过Service
的SessionAffinity
来确定),默认的调度算法是轮循(round-robin
)。
其代理的过程是:请求到达service
后,其被转发至内核空间,经由套接字送往用户空间的kube-proxy
,而后再由它送回内核空间,并调度至后端Pod
。其传输效率太低,在1.1
版本前是默认的转发策略。
1.3.2 iptables代理模式 iptables
代理模式中,kube-proxy
负责跟踪API Server
上Service
和Endpoints
对象的变动(创建或移除),并据此作出Service
资源定义的变动。同时,对于每个Service
对象,它都会创建iptables
规则直接捕获到达Cluster IP
(虚拟IP)和Port
的流量,并将其重定向至当前Service
的后端。对于每个Endpoints
对象,Service
资源会为其创建iptables
规则并关联至挑选的后端Pod
资源,默认的调度算法是随机调度(random
)。实现基于客户端IP
的会话亲和性(来自同一个用户的请求始终调度到后端固定的一个Pod
),可将service.spec.sessionAffinity
的值设置为“ClientIP”
(默认值为“None”
)。
其代理过程是:请求到达service
后,其请求被相关service
上的iptables
规则进行调度和目标地址转换(DNAT
)后再转发至集群内的Pod
对象之上。
相对userspace
模式来说,iptables
模式无须将流量在用户空间和内核空间来回切换,因而更加高效和可靠。其缺点是iptables
代理模型不会在被挑中的Pod
资源无响应时自动进行重定向;而userspace
模式则可以。
1.3.3 ipvs代理模式 kube-proxy
跟踪API Server
上Service
的Endpoints
对象的变动,据此来调用netlink
接口创建ipvs
规则,并确保与API Server
中的变动保持同步,其请求流量的调度功能由ipvs
实现,其余的功能由iptables
实现。ipvs
支持众多调度算法,如rr
、lc
、dh
、sh
、sed
和nq
等。
2 Service资源的基础应用 创建Service
对象的常用方法有两种,一是直接使用命令“kubectl expose”
命令,二是使用资源清单配置文件。定义Service
资源清单文件时,spec
的两个较为常用的内嵌字段分别是selector
和port
,分别用于定义使用的标签选择器和要暴露的端口。
一、命令方式定义
1)首先创建一组pod
资源
1 2 3 4 5 6 7 8 9 [root@k8s-master ~]# kubectl run nginx --image=nginx:1.12 --replicas=3 #创建pod资源指定副本数量为3个 [root@k8s-master ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-67685f79b5-688s7 1/1 Running 0 5s 10.244.2.61 k8s-node2 <none> <none> nginx-67685f79b5-gpc2f 1/1 Running 0 5s 10.244.1.63 k8s-node1 <none> <none> nginx-67685f79b5-grlrz 1/1 Running 0 5s 10.244.2.60 k8s-node2 <none> <none> [root@k8s-master ~]# kubectl get deployment #查看deployment控制器资源 NAME READY UP-TO-DATE AVAILABLE AGE nginx 3/3 3 3 35s
2)为其创建对应的service
资源
1 2 3 4 5 6 7 # 下面这条命令表示为deployment控制器资源nginx创建一个service对象,并取名为nginx、端口为80、pod内暴露端口80、协议为TCP协议。 [root@k8s-master ~]# kubectl expose deployment nginx --name=nginx --port=80 --target-port=80 --protocol=TCP service/nginx exposed [root@k8s-master ~]# kubectl get service #查看创建的service资源 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d nginx ClusterIP 10.104.116.156 <none> 80/TCP 9s
3)查看生成的endpoints
对应关系
1 2 3 4 [root@k8s-master ~]# kubectl get endpoints NAME ENDPOINTS AGE kubernetes 192.168.1.31:6443 27d nginx 10.244.1.63:80,10.244.2.60:80,10.244.2.61:80 29s
二、资源清单定义
1)编写资源清单文件(这里先定义一个Deployment
控制器资源对象,然后定义Service
进行关联)。注:同一个文件编写多个资源对象时,通过—进行分割。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [root@k8s-master ~ ] apiVersion: apps/v1 kind: Deployment metadata: name: service-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: service-deploy-demo template: metadata: name: svc-deploy labels: app: service-deploy-demo spec: containers: - name: svc-pod image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: service-demo spec: selector: app: service-deploy-demo ports: - port: 80 targetPort: 80 protocol: TCP
2)创建并查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@k8s-master ~]# kubectl apply -f manfests/service-demo.yaml #创建资源对象 deployment.apps/service-deploy created service/service-demo created [root@k8s-master ~]# kubectl get svc #查看service资源对象,"kubectl get svc"等于"kubectl get service" NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d nginx ClusterIP 10.104.116.156 <none> 80/TCP 80m service-demo ClusterIP 10.98.31.157 <none> 80/TCP 7s [root@k8s-master ~]# kubectl get pods -o wide -l app=service-deploy-demo #查看pod资源对象 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES service-deploy-66548cc57f-982cd 1/1 Running 0 15s 10.244.2.63 k8s-node2 <none> <none> service-deploy-66548cc57f-blnvg 1/1 Running 0 15s 10.244.1.67 k8s-node1 <none> <none> service-deploy-66548cc57f-vcmxb 1/1 Running 0 15s 10.244.2.62 k8s-node2 <none> <none> [root@k8s-master ~]# kubectl get endpoints service-demo 查看生成的endpoints对应关系 NAME ENDPOINTS AGE service-demo 10.244.1.67:80,10.244.2.62:80,10.244.2.63:80 43s
3)节点访问测试(这里使用创建一个新的pod资源模拟客户端进行访问)
Service
资源的默认类型为ClusterIP
,仅能接收kubernetes
集群节点访问、或集群内部的pod
对象中的客户端程序访问。
1 2 3 4 5 6 7 8 9 10 [root@k8s-master ~]# kubectl run busybox --image=busybox --rm -it -- /bin/sh #使用busybox创建一个临时pod客户端 / # wget -O - -q http://10.98.31.157/ #访问上面创建的service对象的Cluster IP Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> / # for i in 1 2 3 4; do wget -O - -q http://10.98.31.157/hostname.html; done #循环访问测试站点下的hostname.html页面,可以看出是轮循的分配给后端的pod资源。 service-deploy-66548cc57f-982cd service-deploy-66548cc57f-blnvg service-deploy-66548cc57f-982cd service-deploy-66548cc57f-982cd # 说明:myapp容器中的“/hostname.html"页面能够输出当前容器的主机名。
2.1 Service会话粘性 Service
资源支持Session affinity
(粘性会话或会话粘性)机制,能够将来自同一个客户端的请求始终转发至同一个后端的Pod
对象。这意味着会影响调度算法的流量分发功能,进而降低其负载均衡的效果。所以,当客户端访问pod
中的应用程序时,如果有基于客户端身份保存某些私有信息,并基于这些私有信息追踪用户的活动等一类的需求时,就可以启用session affinity
机制。
Session affinity
的效果仅在一段时间期限内生效,默认值为10800
秒,超出此时长之后,客户端的再次访问会被调度算法重新调度。Service
资源的Session affinity
机制仅能基于客户端的IP
地址识别客户端身份,把经由同一个NAT
服务器进行源地址转换的所有客户端识别为同一个客户端,便导致调度效果不佳,所以,这种方法并不常用。
Service
资源通过service.spec.sessionAffinity
和service.spec.sessionAffinityConfig
两个字段配置粘性会话。sessionAffinity
字段用于定义要使用的粘性会话的类型,仅支持使用“None”
和“ClientIp”
两种属性值。
示例
这里将上面创建的service-demo
资源对象进行修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@k8s-master ~ ] ...... spec: selector: app: service-deploy-demo ports: - port: 80 targetPort: 80 protocol: TCP sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 10 [root@k8s-master ~ ] deployment.apps/service-deploy unchanged / service-deploy-66548cc57f-blnvg service-deploy-66548cc57f-blnvg service-deploy-66548cc57f-blnvg service-deploy-66548cc57f-blnvg / service-deploy-66548cc57f-vcmxb service-deploy-66548cc57f-vcmxb service-deploy-66548cc57f-vcmxb service-deploy-66548cc57f-vcmxb
2.2 类型 1 Service`的`IP`地址只能够在集群内部可访问,对一些应用(如`frontend`)的某些部分,可能希望通过外部(`kubernetes`集群外部)`IP`地址暴露`Service`,这时候就需要使用到`NodePort`。`kubernetes
ServiceTypes
支持四种类型:ClusterIP
、NodePort
、LoadBalancer
、ExternalName
,其默认是Cluster IP
类型。
ClusterIP :通过集群内部IP
地址暴露服务,此地址仅在集群内部可进行通行,无法被集群外部的客户端访问。
NodePort :通过每个Node
上的IP
和静态端口(NodePort
)暴露服务,会自动为Service
分配集群IP
地址,并将此作为NodePort
的路有目标。通过请求<NodePort>:<NodePort> --> <ClusterIP>:<ClusterPort> --> <PodIP>:<ContainerPort>
访问到一个NodePort
服务。
LoadBalancer :构建在NodePort
之上,并创建一个外部负载均衡器,路由到ClusterIP
。因此LoadBalancer
一样具有NodePort
和ClusterIP
。
EXternalName :通过返回CNAME
和它的值,可以将服务映射到externalName
字段的内容。换言之,此种类型并非定义由Kubernetes
集群提供的服务,而是把集群外部的某服务以DNS CNAME
记录的方式映射到集群内,从而让集群内的Pod
资源能够访问外部的Service
的一种实现方式。这种类型的Service
没有ClusterIP
和NodePort
,也没有标签选择器用于选择Pod
资源,因此也不会有Endpoints
存在。
2.2.1 ClusterIP类型的Service示例 1)编写配置清单文件(这里使用redis
作为示例);先创建一个deployment
,启动redis pod
;再使用service
绑定这个deployment
下的pod
资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root@k8s-master ~ ] apiVersion: apps/v1 kind: Deployment metadata: name: redis-deploy namespace: default spec: replicas: 2 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis-pod image: redis ports: - name: redis containerPort: 6379 --- apiVersion: v1 kind: Service metadata: name: redis-svc spec: type: ClusterIP selector: app: redis ports: - port: 6379 targetPort: 6379 protocol: TCP [root@k8s-master ~ ] deployment.apps/redis-deploy created service/redis-svc created
2)查看创建的资源对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [root@k8s-master ~]# kubectl get svc #查看service资源 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d nginx ClusterIP 10.104.116.156 <none> 80/TCP 17h redis-svc ClusterIP 10.102.44.127 <none> 6379/TCP 8s service-demo ClusterIP 10.98.31.157 <none> 80/TCP 16h [root@k8s-master ~]# kubectl get pods -l app=redis -o wide #查看标签app=redis的pod资源 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES redis-deploy-6559cc4c4c-5v7kx 1/1 Running 0 33s 10.244.2.65 k8s-node2 <none> <none> redis-deploy-6559cc4c4c-npdtf 1/1 Running 0 33s 10.244.1.69 k8s-node1 <none> <none> [root@k8s-master ~]# kubectl describe svc redis-svc #查看redis-svc资源对象详细信息 Name: redis-svc Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis-svc","namespace":"default"},"spec":{"ports":[{"port":6379,"... Selector: app=redis Type: ClusterIP IP: 10.102.44.127 Port: <unset> 6379/TCP TargetPort: 6379/TCP Endpoints: 10.244.1.69:6379,10.244.2.65:6379 #可以看出这里已经和上面的pod资源绑定 Session Affinity: None Events: <none>
3)集群内部进行测试
1 2 3 4 5 6 7 8 9 10 # (1)集群内部的节点上面测试 [root@k8s-master ~]# redis-cli -h 10.102.44.127 10.102.44.127:6379> ping PONG # (2)在后端pod上面进行测试 [root@k8s-master ~]# kubectl exec redis-deploy-6559cc4c4c-5v7kx -it -- /bin/sh # redis-cli -h 10.102.44.127 10.102.44.127:6379> ping PONG
2.2.2 NodePort类型的Service示例 NodePort
即节点Port
,通常在安装部署Kubernetes
集群系统时会预留一个端口范围用于NodePort
,默认为30000~32767
之间的端口。定义NodePort
类型的Service
资源时,需要使用.spec.type
明确指定类型为NodePort
。
1)编写配置清单文件(这里使用nginx
作为示例);先创建一个deployment
,启动nginx pod
;再使用service
绑定这个deployment
下的pod
资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 [root@k8s-master ~]# vim manfests/nginx-svc.yaml #编写yaml格式的清单文件 apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy namespace: default spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx-pod image: nginx:1.12 ports: - name: nginx containerPort: 6379 --- apiVersion: v1 kind: Service metadata: name: nginx-svc #service对象名 spec: type: NodePort #这里指定使用ClusterIP,默认也是ClusterIP,这里可有可无 selector: app: nginx #匹配上面定义的pod资源 ports: - port: 80 #service端口 targetPort: 80 #后端pod端口 nodePort: 30080 #节点端口 protocol: TCP #协议 [root@k8s-master ~]# kubectl apply -f manfests/nginx-svc.yaml #创建资源对象 deployment.apps/nginx-deploy created service/nginx-svc created
2)查看创建的资源对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@k8s-master ~]# kubectl get svc #查看service资源 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d nginx-svc NodePort 10.105.21.137 <none> 80:30080/TCP 4s redis-svc ClusterIP 10.102.44.127 <none> 6379/TCP 55m service-demo ClusterIP 10.98.31.157 <none> 80/TCP 16h [root@k8s-master ~]# kubectl get pods -l app=nginx -o wide #查看标签app=nginx的pod资源 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deploy-b6f876447-nlv6h 1/1 Running 0 33s 10.244.1.71 k8s-node1 <none> <none> nginx-deploy-b6f876447-xmn2t 1/1 Running 0 33s 10.244.2.66 k8s-node2 <none> <none> [root@k8s-master ~]# kubectl describe svc nginx-svc #查看nginx-svc资源对象详细信息 Name: nginx-svc Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"nginx-svc","namespace":"default"},"spec":{"ports":[{"nodePort":30... Selector: app=nginx Type: NodePort IP: 10.105.21.137 Port: <unset> 80/TCP TargetPort: 80/TCP NodePort: <unset> 30080/TCP #这里可以看到多了NodePort且端口为30080 Endpoints: 10.244.1.71:80,10.244.2.66:80 Session Affinity: None External Traffic Policy: Cluster Events: <none>
3)集群外部进行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@courtoap ~]# curl 192.168.1.31:30080 #访问集群master节点的30080端口 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> [root@courtoap ~]# curl 192.168.1.32:30080 #访问集群node节点的30080端口 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style>
通过上面的测试可以看到通过NodePort
的方式实现了从集群外部端口进行访问,实践中并不建议自定义使用的节点端口,因为容易产生冲突。建议让其自动生成即可。
2.3 Headless类型的Service资源 Service
对象隐藏了各Pod
资源,并负责将客户端请求流量调度至该组Pod
对象之上,但也可能存在客户端直接访问Service
资源后端的所有Pod
资源,这时就应该向客户端暴露每个Pod
资源的IP
地址,而不是中间层Service
对象的ClusterIP
,这种类型的Service
资源便称为Headless Service
(无头服务)。
Headless Service
对象没有ClusterIP
,因此便没有相关负载均衡或代理问题,其如何为此类Service
配置IP
地址,其取决于标签选择器的定义。
具有标签选择器:端点控制器(Endpoints Controller
)会在API
中为其创建Endpoints
记录,并将ClusterDNS
服务中的A
记录直接解析到此Service
后端的各Pod
对象的IP
地址上。
没有标签选择器:端点控制器(Endpoints Controller
)不会再API
中为其创建Endpoints
记录,ClusterDNS
的配置分为两种情形,对ExternalName
类型的服务创建CNAME
记录,对其他三种类型来说,为那些与当前Service
共享名称的所有Endpoints
对象创建一条记录。
2.3.1 Headless类型的Service示例 配置Service
资源配置清单时,只需要将ClusterIP
字段的值设置为“None”
即为其定义为Headless
类型。
1)编写配置清单文件(这里使用apache
作为示例);先创建一个deployment
,启动apache pod
;再使用service
绑定这个deployment
下的pod
资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root@k8s-master ~ ] apiVersion: apps/v1 kind: Deployment metadata: name: httpd-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: httpd template: metadata: labels: app: httpd spec: containers: - name: httpd-pod image: httpd ports: - name: httpd containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: httpd-svc spec: clusterIP: None selector: app: httpd ports: - port: 80 targetPort: 80 protocol: TCP [root@k8s-master ~ ] deployment.apps/httpd-deploy created service/httpd-svc created
2)查看创建的资源对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@k8s-master ~]# kubectl get svc #查看service资源 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd-svc ClusterIP None <none> 80/TCP 4s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d nginx-svc NodePort 10.105.21.137 <none> 80:30080/TCP 112m redis-svc ClusterIP 10.102.44.127 <none> 6379/TCP 168m service-demo ClusterIP 10.98.31.157 <none> 80/TCP 18h [root@k8s-master ~]# kubectl get pods -l app=httpd -o wide #查看标签app=httpd的pod资源 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-deploy-5494485b74-4vx64 1/1 Running 0 27s 10.244.2.72 k8s-node2 <none> <none> httpd-deploy-5494485b74-j6hwm 1/1 Running 0 27s 10.244.2.71 k8s-node2 <none> <none> httpd-deploy-5494485b74-jn48q 1/1 Running 0 27s 10.244.1.74 k8s-node1 <none> <none> [root@k8s-master ~]# kubectl describe svc/httpd-svc #查看httpd-svc资源对象详细信息 Name: httpd-svc Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"httpd-svc","namespace":"default"},"spec":{"clusterIP":"None","por... Selector: app=httpd Type: ClusterIP IP: None Port: <unset> 80/TCP TargetPort: 80/TCP Endpoints: 10.244.1.74:80,10.244.2.71:80,10.244.2.72:80 Session Affinity: None Events: <none>
3)测试资源发现
由Headless Service
工作特性可知,它记录于ClusterDNS
的A
记录的相关解析结果是后端Pod
资源的IP
地址。意味着客户端通过Service
资源的名称发现的是各Pod
资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # (1)通过创建一个专用的测试Pod资源对象,而后通过其交互式接口进行测试 [root@k8s-master ~]# kubectl run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh / # nslookup httpd-svc Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: httpd-svc Address 1: 10.244.2.71 10-244-2-71.httpd-svc.default.svc.cluster.local Address 2: 10.244.1.74 10-244-1-74.httpd-svc.default.svc.cluster.local Address 3: 10.244.2.72 10-244-2-72.httpd-svc.default.svc.cluster.local # (2)直接在kubernetes集群上解析 [root@k8s-master ~]# dig -t A httpd-svc.default.svc.cluster.local. @10.96.0.10 ...... ;; ANSWER SECTION: httpd-svc.default.svc.cluster.local. 26 IN A 10.244.2.72 httpd-svc.default.svc.cluster.local. 26 IN A 10.244.2.71 httpd-svc.default.svc.cluster.local. 26 IN A 10.244.1.74 ......