学习目标:
- 了解service的概念
- 掌握service的类型和数据转发流程
- 掌握定位的思路和方式
学习内容:
Service的概念
kubernetes为service定义了这样一个抽象:一个Pod的逻辑分组,一种可以访问它们的策略—通常称为微服务,这一组Pod能够被service访问到,通常是通过Label Selector
优缺点
Service能够提供负载均衡的能力,但是在使用上有一下限制:
只提供四层负载均衡能力,而没有七层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上四层负载均衡是不支持的
Service的类型
Service在K8S中有以下四种类型:
- ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟ip
- NodeIp:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过:NodePort来访问该服务
- LoadBalancer:在NodePort的基础上,借助cloud provider创建一个外部负载均衡,并将请求转发到:NodePort
- ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用,没有任何类型代理被创建,这只有k8s 1.7或更高版本的kube-dns才支持
步骤:
1、首先apiserver通过kube-proxy去监控服务和端点
2、kube-proxy负责去监控到匹配到信息的Pod,把这些信息写入到iptables规则中去
3、当客户端想要去访问SVC时,其实就是访问iptables规则
4、然后根据iptables规则被导向到后端的Pod,实现访问
VIP和Service代理
在K8S集群中,每个Node运行一个kube-proxy进程,kube-proxy负责为Service实现一种VIP(虚拟ip)的形式,在K8S v1.0版本,代理完全在userspace。K8S v1.1版本,新增了iptables代理,但不是默认的运行模式,从K8S v1.2起,默认就是iptables代理,在K8S v1.8.0-beta中,添加了IPVS代理
在K8S v1.14版本开始默认使用IPVS代理
在K8S v1.0版本,Service是四层概念,在K8S v1.1版本,新增了ingress API ,用来表示七层服务
ClusterIP
ClusterIP主要在每个Node节点使用iptables,将发向clusterIP对应端口的数据转发到kube-proxy中,然后kube-proxy自己内部实现有负载均衡的方法,并可以查询这个service下对应pod的地址和端口,进而把数据转发给对应的pod的地址和端口
为了实现图上的功能,主要需要以下几个组件的协同工作:
apiserver用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中
k8s的每个节点中都有一个kube-proxy的进程,这个进程负责感知servce、pod的变化,并将变化的信息写入到本地的iptables规则中
iptables使用NAT等技术将virtualIP的流量转发至endpoint中
- 样例:
Headless Service
有时不需要或不想要负载均衡;以及单独的Service IP,遇到这种情况,可以通过指定ClusterIP(spec.clusterIP)的值为"None"来创建Headless Service,这类Service并不会ClusterIP,kube-proxy不会处理他们,而且平台也不会为他们进行负载均衡和路由
- 样例:
NodePort
nodeport的原理在node上开了一个端口,将向该端口的流量导入到kube-proxy,然后由kube-proxy进一步给到对应的pod
查询流程
-
iptables -t nat -nvL
##各参数的含义为: -L表示查看当前表的所有规则,默认查看的是filter表,如果要查看nat表,可以加上-t nat参数 -n 表示不对ip地址进行反查,加上这个参数显示速度将会加快 -v 表示输出详细信息,包含通过该规则的数据包数量,总字节数以及相应的网络接口
-
域名解析nslookup和dig
[root@paas-core01 paas]# nslookup redisservice-server-headless.fst-manage.svc.cluster.local
Server: 10.247.0.20
Address: 10.247.0.20#53
Name: redisservice-server-headless.fst-manage.svc.cluster.local
Address: 172.16.0.21
Name: redisservice-server-headless.fst-manage.svc.cluster.local
Address: 172.16.0.9
Name: redisservice-server-headless.fst-manage.svc.cluster.local
Address: 172.16.0.39
[root@paas-core01 paas]# dig @172.16.0.3 -p 5353 redisservice-server-headless.fst-manage.svc.cluster.local
; <<>> DiG 9.11.21-9.11.21-4.h15.eulerosv2r10 <<>> @172.16.0.3 -p 5353 redisservice-server-headless.fst-manage.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21782
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: dcfd7eb3bd3e1898 (echoed)
;; QUESTION SECTION:
;redisservice-server-headless.fst-manage.svc.cluster.local. IN A
;; ANSWER SECTION:
redisservice-server-headless.fst-manage.svc.cluster.local. 30 IN A 172.16.0.21
redisservice-server-headless.fst-manage.svc.cluster.local. 30 IN A 172.16.0.9
redisservice-server-headless.fst-manage.svc.cluster.local. 30 IN A 172.16.0.39
;; Query time: 18 msec
;; SERVER: 172.16.0.3#5353(172.16.0.3)
;; WHEN: Wed Sep 07 14:45:15 CST 2022
;; MSG SIZE rcvd: 317
- iptables-save查看
[root@paas-core01 paas]# kubectl get svc -n fst-manage -owide|grep dns
kube-dns ClusterIP 10.247.0.20 <none> 53/UDP,53/TCP 34d k8s-app=kube-dns
[root@paas-core01 paas]# iptables-save |grep 10.247.0.20
-A KUBE-SERVICES -d 10.247.0.20/32 -p udp -m comment --comment "fst-manage/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.247.0.20/32 -p udp -m comment --comment "fst-manage/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-SVC-ZK7UTMNBIKPQC3OG
-A KUBE-SERVICES -d 10.247.0.20/32 -p tcp -m comment --comment "fst-manage/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.247.0.20/32 -p tcp -m comment --comment "fst-manage/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-L3W4MN7I4JBGNVWH
[root@paas-core01 paas]# iptables-save |grep KUBE-SVC-L3W4MN7I4JBGNVWH
:KUBE-SVC-L3W4MN7I4JBGNVWH - [0:0]
-A KUBE-SERVICES -d 10.247.0.20/32 -p tcp -m comment --comment "fst-manage/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-L3W4MN7I4JBGNVWH
-A KUBE-SVC-L3W4MN7I4JBGNVWH -m comment --comment "fst-manage/kube-dns:dns-tcp" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-UTBQF3HUMKK2MNPP
-A KUBE-SVC-L3W4MN7I4JBGNVWH -m comment --comment "fst-manage/kube-dns:dns-tcp" -j KUBE-SEP-2BMJE5TDC5EL54O4
[root@paas-core01 paas]# iptables-save |grep KUBE-SEP-UTBQF3HUMKK2MNPP
:KUBE-SEP-UTBQF3HUMKK2MNPP - [0:0]
-A KUBE-SEP-UTBQF3HUMKK2MNPP -s 172.16.0.32/32 -m comment --comment "fst-manage/kube-dns:dns-tcp" -j KUBE-MARK-MASQ
-A KUBE-SEP-UTBQF3HUMKK2MNPP -p tcp -m comment --comment "fst-manage/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 172.16.0.32:5353
-A KUBE-SVC-L3W4MN7I4JBGNVWH -m comment --comment "fst-manage/kube-dns:dns-tcp" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-UTBQF3HUMKK2MNPP
[root@paas-core01 paas]# iptables-save |grep KUBE-SEP-2BMJE5TDC5EL54O4
:KUBE-SEP-2BMJE5TDC5EL54O4 - [0:0]
-A KUBE-SEP-2BMJE5TDC5EL54O4 -s 172.16.0.3/32 -m comment --comment "fst-manage/kube-dns:dns-tcp" -j KUBE-MARK-MASQ
-A KUBE-SEP-2BMJE5TDC5EL54O4 -p tcp -m comment --comment "fst-manage/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 172.16.0.3:5353
-A KUBE-SVC-L3W4MN7I4JBGNVWH -m comment --comment "fst-manage/kube-dns:dns-tcp" -j KUBE-SEP-2BMJE5TDC5EL54O4
Loadbalancer
loadbalancer和nodeport其实是同一种方式,区别在于loadbalancer比nodeport多了一步,就是可以调用cloud provider去创建LB访问节点导流
ExternalName
这种类型的service通过返回CNAME和它的值,可以将服务映射到externalname字段的内容。ExternalName Service是Service的特例,它没有selector,也没有定义任何的端口和endpoint,相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
当查询主机my-service.defalut.svc.cluster.local(SVC_NAME.NAMESPACE.svc.cluster.local)时,集群的DNS服务将返回一个值my.database.example.com的CNAME记录,访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在DNS层,而且不会进行代理和转发