乐趣区

关于kubernetes:做一个不背锅运维K8S-Service底层策略初探和分析

创立用于测试的 Deployment 和 Service

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test-goweb
  name: test-goweb
spec:
  replicas: 6
  selector:
    matchLabels:
      app: test-goweb
  template:
    metadata:
      labels:
        app: test-goweb
    spec:
      containers:
      - image: 192.168.11.247/web-demo/goweb-demo:20221229v3
        imagePullPolicy: IfNotPresent
        name: goweb-demo
        ports:
        - containerPort: 8090
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: test-goweb
  name: test-goweb
spec:
  ports:
  - name: 80-8090
    nodePort: 30010
    port: 80
    protocol: TCP
    targetPort: 8090
  selector:
    app: test-goweb
  type: NodePort

Service 底层有哪些 iptables 链

当在 Kubernetes 中创立 Service 时,将会创立以下几个 iptables 链。这些链都是用于实现 Service 的外围性能,上面列出所波及到的链:

  1. PREROUTING 链:此链是由 kube-proxy 组件创立的,用于将 Service IP 地址映射到对应的 Pod IP 地址上。当申请进入节点时,该链将被触发,它依据申请的 Service IP 地址来查找对应的 Pod IP 地址,并将申请转发到该 Pod。
  2. KUBE-SERVICES 链:此链蕴含了一系列规定,用于将 Service IP 地址映射到对应的 Pod IP 地址上。当申请进入节点时,该链将被触发,并依据申请的 Service IP 地址来查找对应的 Pod IP 地址。如果找到了对应的 Pod IP 地址,申请将被转发到该 Pod。
  3. KUBE-SVC-XXX 链:此链蕴含了一系列规定,其中 XXX 代表 Service 的名称。每个 Service 都有一个对应的 KUBE-SVC-XXX 链。当申请进入节点时,该链将被触发,并依据 Service IP 地址查找对应的 KUBE-SVC-XXX 链。该链中的规定将申请转发到对应的 Pod。
  4. KUBE-SEP-XXX 链:此链蕴含了一系列规定,其中 XXX 代表 Service 的名称。每个 Service 都有一个对应的 KUBE-SEP-XXX 链。当申请进入节点时,该链将被触发,并依据 Service IP 地址查找对应的 KUBE-SEP-XXX 链。该链中的规定将申请转发到对应的 Pod。
  5. KUBE-FIREWALL 链:此链用于解决来自 Kubernetes 的外部流量。该链蕴含了一些规定,用于管制拜访 Kubernetes 的 API、DNS 和其余一些服务。
  6. KUBE-NODEPORT 链:当 Service 类型为 NodePort 时,此链将被创立。该链蕴含了一些规定,用于将节点的端口映射到 Service 的端口上。
  7. KUBE-MARK-DROP 链:当申请被回绝时,会触发此链。该链蕴含了一些规定,用于标记被回绝的数据包。

这些 iptables 链是 Kubernetes 中实现 Service 的要害组件。它们使得客户端能够应用 Service 名称来拜访运行在 Pod 中的应用程序,而不用理解其具体 IP 地址。

查看和这个 service 无关的 iptables 规定

# iptables-save | grep test-goweb

-A KUBE-EXT-XRKWZPWLY5ZGEEBK -m comment --comment "masquerade traffic for default/test-goweb:80-8090 external destinations" -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp --dport 30010 -j KUBE-EXT-XRKWZPWLY5ZGEEBK
-A KUBE-SEP-2KC5TQ77EILRJT77 -s 10.244.240.51/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ
-A KUBE-SEP-2KC5TQ77EILRJT77 -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.51:8090
-A KUBE-SEP-5AVQRPMC6RQQAAKG -s 10.244.240.9/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ
-A KUBE-SEP-5AVQRPMC6RQQAAKG -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.9:8090
-A KUBE-SEP-7QBH2WDQDSESRX53 -s 10.244.240.19/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ
-A KUBE-SEP-7QBH2WDQDSESRX53 -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.19:8090
-A KUBE-SEP-KGPYN3PAVPO2A2G3 -s 10.244.240.20/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ
-A KUBE-SEP-KGPYN3PAVPO2A2G3 -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.20:8090
-A KUBE-SEP-VXCKMNYZWUWZOOOJ -s 10.244.240.38/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ
-A KUBE-SEP-VXCKMNYZWUWZOOOJ -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.38:8090
-A KUBE-SEP-XH5PMCJ3CYSK4B7L -s 10.244.240.56/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ
-A KUBE-SEP-XH5PMCJ3CYSK4B7L -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.56:8090
-A KUBE-SERVICES -d 10.104.238.165/32 -p tcp -m comment --comment "default/test-goweb:80-8090 cluster IP" -m tcp --dport 80 -j KUBE-SVC-XRKWZPWLY5ZGEEBK
-A KUBE-SVC-XRKWZPWLY5ZGEEBK ! -s 10.244.0.0/16 -d 10.104.238.165/32 -p tcp -m comment --comment "default/test-goweb:80-8090 cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SVC-XRKWZPWLY5ZGEEBK -m comment --comment "default/test-goweb:80-8090 -> 10.244.240.19:8090" -m statistic --mode random --probability 0.16666666651 -j KUBE-SEP-7QBH2WDQDSESRX53
-A KUBE-SVC-XRKWZPWLY5ZGEEBK -m comment --comment "default/test-goweb:80-8090 -> 10.244.240.20:8090" -m statistic --mode random --probability 0.20000000019 -j KUBE-SEP-KGPYN3PAVPO2A2G3
-A KUBE-SVC-XRKWZPWLY5ZGEEBK -m comment --comment "default/test-goweb:80-8090 -> 10.244.240.38:8090" -m statistic --mode random --probability 0.25000000000 -j KUBE-SEP-VXCKMNYZWUWZOOOJ
-A KUBE-SVC-XRKWZPWLY5ZGEEBK -m comment --comment "default/test-goweb:80-8090 -> 10.244.240.51:8090" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-2KC5TQ77EILRJT77
-A KUBE-SVC-XRKWZPWLY5ZGEEBK -m comment --comment "default/test-goweb:80-8090 -> 10.244.240.56:8090" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XH5PMCJ3CYSK4B7L
-A KUBE-SVC-XRKWZPWLY5ZGEEBK -m comment --comment "default/test-goweb:80-8090 -> 10.244.240.9:8090" -j KUBE-SEP-5AVQRPMC6RQQAAKG

下面看到的这一堆规定,就是由 kube-proxy 组件主动创立和保护 iptables 规定,持续往下看,抽几条规定做个简略的剖析。

简略剖析

  1. 先看整体看看这 1 条规定
-A KUBE-EXT-XRKWZPWLY5ZGEEBK -m comment --comment "masquerade traffic for default/test-goweb:80-8090 external destinations" -j KUBE-MARK-MASQ

这是下面第一条 iptables 规定,它用于 Kubernetes 集群中的网络转发和流量假装。具体来说,这个规定将来自 Kubernetes 服务“default/test-goweb”的流量假装为内部指标,以便它们能够通过集群内部拜访。

规定中的参数解释如下:

  • -A:将规定增加到链的开端
  • KUBE-EXT-XRKWZPWLY5ZGEEBK:链的名称
  • -m comment –comment “masquerade traffic for default/test-goweb:80-8090 external destinations”:增加一条正文,阐明此规定是用于假装“default/test-goweb”的流量,并指定了流量端口范畴和指标类型
  • -j KUBE-MARK-MASQ:将流量标记为须要进行假装的流量,以便其可能来到集群并在指标处正确路由

请留神,KUBE-EXT-XRKWZPWLY5ZGEEBK、KUBE-MARK-MASQ 是自定义的链名称,它在 Kubernetes 集群中的不同局部可能会有所不同。在理论应用时,链的名称可能会因不同的部署而有所变动,但规定的作用通常是类似的。

  1. 大略看看第 2 条
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp --dport 30010 -j KUBE-EXT-XRKWZPWLY5ZGEEBK

它的作用是将从 NodePort 类型的 Service 拜访到的流量(指标端口为 30010/tcp)转发到名为 KUBE-EXT-XRKWZPWLY5ZGEEBK 的链上进行进一步解决。

  1. 大略看看第 3 条
-A KUBE-SEP-2KC5TQ77EILRJT77 -s 10.244.240.51/32 -m comment --comment "default/test-goweb:80-8090" -j KUBE-MARK-MASQ

它的作用是将来自 IP 地址为 10.244.240.51 的源地址流量进行 SNAT 转换,以便将源 IP 地址更改为 Node 的 IP 地址,从而使流量可能返回到客户端。该规定应用名为 KUBE-MARK-MASQ 的链进行转换。

  1. 再看看第 4 条
-A KUBE-SEP-2KC5TQ77EILRJT77 -p tcp -m comment --comment "default/test-goweb:80-8090" -m tcp -j DNAT --to-destination 10.244.240.51:8090

它的作用是将从集群内某个节点上的 Pod 拜访 Service 的流量进行 DNAT 转换,以便将流量重定向到特定 Pod 的 IP 地址和端口上。

k8s 的 iptables 规定是由 k8s 本身主动保护的,它应用 kube-proxy 组件来主动创立和保护 iptables 规定,当创立一个 Service 时,kube-proxy 会主动为该 Service 创立一组 iptables 规定,当 Pod 被增加或删除时,kube-proxy 会相应地更新这些规定。所以,不须要人为手动治理这些规定,几乎是香到不行。

将 Service 底层的代理模式改为 IPVS 后

tantianran@test-b-k8s-master:~$ kubectl get svc test-goweb
NAME         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
test-goweb   NodePort   10.104.238.165   <none>        80:30010/TCP   25h

在其中一台节点上看虚构服务器信息

tantianran@test-b-k8s-node01:~$ sudo ipvsadm-save
-A -t test-b-k8s-node01:30001 -s rr
-a -t test-b-k8s-node01:30001 -r 10.244.240.11:8443 -m -w 1
-A -t test-b-k8s-node01:30010 -s rr
-a -t test-b-k8s-node01:30010 -r 10.244.240.24:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.48:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.52:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.54:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.62:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.63:8090 -m -w 1
-A -t test-b-k8s-node01:30001 -s rr
-a -t test-b-k8s-node01:30001 -r 10.244.240.11:8443 -m -w 1
-A -t test-b-k8s-node01:30010 -s rr
-a -t test-b-k8s-node01:30010 -r 10.244.240.24:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.48:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.52:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.54:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.62:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.63:8090 -m -w 1
-A -t test-b-k8s-node01:https -s rr
-a -t test-b-k8s-node01:https -r test-b-k8s-master:6443 -m -w 1
-A -t test-b-k8s-node01:domain -s rr
-a -t test-b-k8s-node01:domain -r 10.244.82.19:domain -m -w 1
-a -t test-b-k8s-node01:domain -r 10.244.240.60:domain -m -w 1
-A -t test-b-k8s-node01:9153 -s rr
-a -t test-b-k8s-node01:9153 -r 10.244.82.19:9153 -m -w 1
-a -t test-b-k8s-node01:9153 -r 10.244.240.60:9153 -m -w 1
-A -t test-b-k8s-node01:https -s rr
-a -t test-b-k8s-node01:https -r 10.244.240.11:8443 -m -w 1
-A -t test-b-k8s-node01:8000 -s rr
-a -t test-b-k8s-node01:8000 -r 10.244.240.16:8000 -m -w 1
-A -t test-b-k8s-node01:http -s rr
-a -t test-b-k8s-node01:http -r 10.244.240.24:8090 -m -w 1
-a -t test-b-k8s-node01:http -r 10.244.240.48:8090 -m -w 1
-a -t test-b-k8s-node01:http -r 10.244.240.52:8090 -m -w 1
-a -t test-b-k8s-node01:http -r 10.244.240.54:8090 -m -w 1
-a -t test-b-k8s-node01:http -r 10.244.240.62:8090 -m -w 1
-a -t test-b-k8s-node01:http -r 10.244.240.63:8090 -m -w 1
-A -t test-b-k8s-node01:https -s rr
-a -t test-b-k8s-node01:https -r 10.244.240.15:4443 -m -w 1
-A -t test-b-k8s-node01:30001 -s rr
-a -t test-b-k8s-node01:30001 -r 10.244.240.11:8443 -m -w 1
-A -t test-b-k8s-node01:30010 -s rr
-a -t test-b-k8s-node01:30010 -r 10.244.240.24:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.48:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.52:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.54:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.62:8090 -m -w 1
-a -t test-b-k8s-node01:30010 -r 10.244.240.63:8090 -m -w 1
-A -u test-b-k8s-node01:domain -s rr
-a -u test-b-k8s-node01:domain -r 10.244.82.19:domain -m -w 1
-a -u test-b-k8s-node01:domain -r 10.244.240.60:domain -m -w 1

要留神了,在下面的虚构服务器信息中能够看到,有的是 -a,有的是 -A,这两个选项都能够用于向 IPVS 中增加一个新的服务(virtual server)。它们的区别不仅仅在于是大小写的区别,更大的区别在于增加服务的形式和语义上略有不同:

  • - a 选项将增加一个新的服务,并将其附加到一个现有的调度器上。如果调度器不存在,则会创立一个新的调度器。
  • - A 选项将增加一个新的服务,并将其附加到一个现有的调度器上。如果调度器不存在,则不会创立新的调度器。如果调度器曾经存在,则服务将被增加到现有的调度器中。

拿这条策略来看看

-a -t test-b-k8s-node01:http -r 10.244.240.24:8090 -m -w 1

以下是每个选项的含意:

  • -a: 增加虚构服务
  • -t test-b-k8s-node01:http: 虚构服务的名称和协定。
  • -r 10.244.240.24:8090: 后端实在服务器的 IP 地址和端口号,也就是 POD 的。
  • -m: 应用 IPVS 的 NAT 模式。
  • -w 1: 将权重设置为 1,行将 1 个申请发送给该服务器。

总而言之它的作用是:它将增加一个名为 test-b-k8s-node01 的 HTTP 虚构服务,并将客户端的申请源 IP 地址改为工作节点的 IP 地址,并将申请发送到后端服务器 10.244.240.24:8090,其中只有一个后端服务器,它的服务能力是 1。

最初的总结

k8s 中的 Service 底层不论是 iptables 还是 ipvs,它们的策略规定都是 k8s 本身主动保护的。具体来说,当创立一个 Service 时,Kubernetes 会在底层为该 Service 创立一个虚构 IP(VIP),并主动配置 iptables 或者 ipvs 规定,使得这个 VIP 能够将流量转发到 Service 中的多个 Pod 实例。

当应用 iptables 时,Kubernetes 会在每个节点上创立 iptables 规定,通过 iptables NAT 性能实现负载平衡和服务发现。而当应用 ipvs 时,Kubernetes 会在每个节点上创立 ipvs 规定,并应用 ipvs 的负载平衡算法实现服务发现和流量转发。

无论是应用 iptables 还是 ipvs,Kubernetes 都会主动保护这些规定,保障 Service 的负载平衡和高可用性。当 Service 中的 Pod 实例发生变化时,Kubernetes 会自动更新 iptables 或 ipvs 规定,以确保流量可能正确地转发到新的 Pod 实例上。Kubernetes 通过自动化的形式,简化了 Service 的配置和保护。

本文转载于 WX 公众号:不背锅运维(喜爱的盆友关注咱们):https://mp.weixin.qq.com/s/3LGRf9NMs9qkMlGvTqVAcA

退出移动版