Service
一.pod存在的意义
kubernetes中一个应用服务会有一个或多个示例(Pod,PodK可以通过rs进行多副本建立),每个实例的ip地址由网络插件动态随机分配(pod重启ip地址会改变)。
为屏蔽这些后端实例的动态变化和对多实例的负载均衡,引入了Service这个资源对象
- 防止pod失联,准备找到提供同一个服务的pod,即服务发现
- 定义一组pod的访问策略(负载均衡)
二.Pod与Service的关系
- Service通过标签关联一组pod
- Service使用iptables或者ipvs为一组pod提供负载均衡的能力
三.Service的定义与创建
创建service: kubectl apply -f service.yaml 查看service: kubectl get service
apiVersion: v1 kind: Service metadata: name: web-nginx # service的name namespace: web # 所属哪个命名空间,一般和pod放在一个同一个命名空间下 spec: ports: - port: 8080 # service端口 protocol: TCP # 协议 targetPort: 80 # 容器端口 selector: # 标签选择器 app: nginx # 指定关联Pod的标签 type: ClusterIP # 服务类型
# selector:指定关联的pod标签
标签获取方式:
通过yaml文件获取
kubectl get svc --show-labels
四.Service三种常用类型
1.ClusterIP
默认类型,分配一个稳定的ip地址,即VIP。只能在集群内部访问
spec: ports: - port: 8080 # service端口 protocol: TCP # 协议 targetPort: 80 # 容器端口 selector: # 标签选择器 app: nginx # 指定关联Pod的标签 type: ClusterIP # 服务类型
#########################################################
[root@k8s-master yaml]# kubectl get svc -o wide -n web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
web-nginx ClusterIP 10.107.185.146 <none> 8080/TCP 13m app=nginx
# 此service只能通过10.107.185.146:8080来访问
2.NodePort
在每个节点启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定的集群ip地址 外部访问:任意nodeip:NodePort 端口范围:30000-32767
apiVersion: v1 kind: Service metadata: name: web-nginx # service的name namespace: web # 所属哪个命名空间,一般和pod放在一个同一个命名空间下 spec: ports: - port: 8080 # service端口 protocol: TCP # 协议 targetPort: 80 # 容器端口 nodePort: 30008 # NodePort的端口 selector: # 标签选择器 app: nginx # 指定关联Pod的标签 type: NodePort # 服务类型
###########################################################################################
[root@k8s-master yaml]# kubectl get svc -n web -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
web-nginx NodePort 10.107.185.146 <none> 8080:30008/TCP 25m app=nginx
集群外部可以通过nodeip:30008来访问
[root@k8s-master yaml]# curl -I http://192.168.11.134:30008
HTTP/1.1 200 OK
3.LoadBalancer
LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴
露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾
讯云、AWS等)上的负载均衡器,将每个Node
([NodeIP]:[NodePort])作为后端添加进去。
五.Service代理模式之iptables实现
集群外部访问service的30008端口,iptables是怎么实现的
以集群中的一个node分析 1.入口规则匹配 -A KUBE-NODEPORTS -p tcp -m comment --comment "web/web-nginx" -m tcp --dport 30008 -j KUBE-SVC-DGUGPUBGLFKE4V6A # 进入30008的数据包被重定向到KUBE-SVC-DGUGPUBGLFKE4V6A这个链
2. 实现负载均衡器(一组规则,有几个pod就创建几条)
A KUBE-SVC-DGUGPUBGLFKE4V6A -m comment --comment "web/web-nginx" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-4Q7O3SKSDAWOI3U5
-A KUBE-SVC-DGUGPUBGLFKE4V6A -m comment --comment "web/web-nginx" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-L4IK2ED63YY2WA7E
-A KUBE-SVC-DGUGPUBGLFKE4V6A -m comment --comment "web/web-nginx" -j KUBE-SEP-Q42CSEQQKNK3LVBU
### --probability 顺序匹配,有33%的概率进入到KUBE-SEP-4Q7O3SKSDAWOI3U5链,有50%的概率进入到KUBE-SEP-L4IK2ED63YY2WA7E链,100%的概率进入到KUBE-SEP-Q42CSEQQKNK3LVBU链,实现了类似轮训的机制 每个链对应一个pod
3.使用DNAT转发到具体的pod上
-A KUBE-SEP-4Q7O3SKSDAWOI3U5 -p tcp -m comment --comment "web/web-nginx" -m tcp -j DNAT --to-destination 10.244.169.186:80
-A KUBE-SEP-L4IK2ED63YY2WA7E -p tcp -m comment --comment "web/web-nginx" -m tcp -j DNAT --to-destination 10.244.36.95:80
-A KUBE-SEP-Q42CSEQQKNK3LVBU -p tcp -m comment --comment "web/web-nginx" -m tcp -j DNAT --to-destination 10.244.36.99:80
4.由具体的pod将数据原路返回客户端
集群内部通过ClusterIP的方式8080请求pod资源,iptables怎么实现的
1.入口匹配 -A KUBE-SERVICES -d 10.100.184.209/32 -p tcp -m comment --comment "web/web-nginx cluster IP" -m tcp --dport 8080 -j KUBE-SVC-DGUGPUBGLFKE4V6A #转发到KUBE-SVC-DGUGPUBGLFKE4V6A链 2.负载均衡实现和nodeport一样 -A KUBE-SVC-DGUGPUBGLFKE4V6A -m comment --comment "web/web-nginx" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-4Q7O3SKSDAWOI3U5 -A KUBE-SVC-DGUGPUBGLFKE4V6A -m comment --comment "web/web-nginx" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-L4IK2ED63YY2WA7E -A KUBE-SVC-DGUGPUBGLFKE4V6A -m comment --comment "web/web-nginx" -j KUBE-SEP-Q42CSEQQKNK3LVBU 3. DNAT转发到对应pod上 -A KUBE-SEP-4Q7O3SKSDAWOI3U5 -p tcp -m comment --comment "web/web-nginx" -m tcp -j DNAT --to-destination 10.244.169.186:80 -A KUBE-SEP-L4IK2ED63YY2WA7E -p tcp -m comment --comment "web/web-nginx" -m tcp -j DNAT --to-destination 10.244.36.95:80 -A KUBE-SEP-Q42CSEQQKNK3LVBU -p tcp -m comment --comment "web/web-nginx" -m tcp -j DNAT --to-destination 10.244.36.99:80 4.由pod将资源原路返回给客户端
六.Service代理模式之ipvs实现
kubeadm方式修改ipvs模式: [root@k8s-master yaml]# kubectl get configmap -n kube-system NAME DATA AGE calico-config 4 12d coredns 1 12d extension-apiserver-authentication 6 12d kube-proxy 2 12d kubeadm-config 2 12d kubelet-config-1.19 1 12d kubectl edit configmap kube-proxy -n kube-system ... mode: “ipvs“ ... #### 1.kube-proxy配置文件是以configmap方式存储 2.如果让所有节点生效,需要重建所有节点的kube-proxy pod
3.ipvs默认调度算法是rr
二进制方式修改ipvs模式: # vi kube-proxy-config.yml mode: ipvs ipvs: scheduler: "rr“ # systemctl restart kube-proxy 注:参考不同资料,文件名可能不同。
ipvs修改已生效
[root@k8s-master yaml]# kubectl logs kube-proxy-ww79n Error from server (NotFound): pods "kube-proxy-ww79n" not found [root@k8s-master yaml]# kubectl logs kube-proxy-ww79n -n kube-system I1130 09:46:32.359435 1 node.go:136] Successfully retrieved node IP: 192.168.11.134 I1130 09:46:32.359667 1 server_others.go:111] kube-proxy node IP is an IPv4 address (192.168.11.134), assume IPv4 operation I1130 09:46:32.435474 1 server_others.go:259] Using ipvs Proxier.
节点上查看ipvs规则,需要安装:yum install ipvsadm -y
[root@k8s-node1 ~]# ipvsadm -L IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP k8s-node1:30008 rr -> 10.244.36.95:http Masq 1 0 0 -> 10.244.36.99:http Masq 1 0 0 -> 10.244.169.186:http Masq 1 0 0 TCP k8s-node1:pago-services1 rr -> 10.244.36.109:pcsync-https Masq 1 0 0 TCP k8s-node1:30008 rr -> 10.244.36.95:http Masq 1 1 0 -> 10.244.36.99:http Masq 1 1 0 -> 10.244.169.186:http Masq 1 1 0 .............
service代理流程图解
七.总结:ipvs和iptables模式的独领风骚
iptables:
灵活,功能强大
规则遍历匹配更新,呈线性时延
缺点:集群中service pod量大时,规则成千上万条时,性能瓶颈就会凸显
ipvs:
工作在内核态,有更好的性能
丰富的调度算法:rr wrr lc wlc [ip hash]等等
八.Service DNS名称
用busybox起一个pod,进行验证 [root@k8s-master yaml]# kubectl run -it dns-test --image=busybox:1.28.4 -- sh 同一命名空间解析: [root@k8s-master ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12d / # nslookup kubernetes Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local 不同命名空间需要加对应的namespace-name [root@k8s-master ~]# kubectl get svc -n web NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis-app NodePort 10.106.73.85 <none> 63790:30010/TCP 14h web-nginx NodePort 10.101.144.136 <none> 8080:30008/TCP 16h / # nslookup web-nginx.web Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: web-nginx.web Address 1: 10.101.144.136 web-nginx.web.svc.cluster.local / # nslookup redis-app.web Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local