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
posted @ 2020-11-30 18:03  碎梦重拾  阅读(457)  评论(0编辑  收藏  举报