原文:
Life of a Packet in Kubernetes — Part 3
链接:
https://dramasamy.medium.com/life-of-a-packet-in-kubernetes-part-3-dd881476da0f
本章我们会讨论一下 Kubernetes 的 kube-proxy
是如何使用 iptables
控制流量的。注意,kube-proxy
iptables
的组合并非完成该任务的唯一选择。
我们会从 Kubernetes 的多种通信模型和实现开始,如果读者已经了解了 Service、ClusterIP 以及 NodePort 的概念,可以直接跳到 kube-proxy/iptables
一节。
Pod 到 Pod
CNI 会配置节点和 Pod 的路由,kube-proxy
不会介入 Pod 到 Pod 之间的通信过程。所有的容器都无需 NAT 就能互相通信;节点和容器之间的通信也是无需 NAT 的。
Pod 的 IP 地址是不固定的(也有办法做成静态 IP,但是缺省配置是不提供这种保障的)。在 Pod 重启时 CNI 会给他分配新的 IP 地址,CNI 不负责维护 IP 地址和 Pod 的映射。Pod 名称在 Deployment 之中也是不固定的。
Deployment 中的 Pod 是无状态的,一个应用可能会有多个 Pod 副本,因此需要一个负载均衡之类的东西来负责对外开放服务,Kubernetes 中的 Service 对象负责完成这个任务。
Pod 到外部
Kubernetes 会使用 SNAT 完成从 Pod 向外发出的访问。SNAT 会将 Pod 的内部 IP:Port
替换为主机的 IP:Port
。返回数据包到达节点时,IP:Port
又会换回 Pod。这个过程对于原始 Pod 是透明无感知的。
Pod 到 Service
Cluster IP
Kubernetes 有一个叫做 Service
的对象,是一个通向 Pod 的 4 层负载均衡。Service
对象有很多类型,最基本的类型叫做 ClusterIP
,这种类型的 Service 有一个唯一的 VIP 地址,其路由范围仅在集群内部有效。
Kubernetes 集群中,Pod 可能发生移动、重启、升级或者扩缩容,因此向应用 Pod 发送流量是有困难的,另外应用通常有多个副本,我们需要一些方法来进行负载均衡。
Kubernetes 使用 Service
对象来解决这个问题。Service 是一个 API 对象,它用一个虚拟 IP 映射到一组 Pod。另外 Kubernetes 为每个 Service 的名称及其虚拟 IP 建立了 DNS 记录,因此可以轻松地根据名称进行寻址。
虚拟 IP 到 Pod IP 的转换是通过每个节点上的 kube-proxy
完成的。在 Pod 向外发起通信时,这个进程会通过 iptables 或者 IPVS 自动把 VIP 转为 Pod IP,每个连接都有跟踪,所以数据包返回时候,地址还能够被正确地转回原样。IPVS 和 iptables 在 VIP 和 Pod IP 之间承担着负载均衡的角色,IPVS 能够提供更多的负载均衡算法。虚拟 IP 并不存在于网络接口上,而是在 iptable 中:
FrontEnd Deployment:
代码语言:javascript复制apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
labels:
app: webapp
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
Backend Deployment:
代码语言:javascript复制apiVersion: apps/v1
kind: Deployment
metadata:
name: auth
labels:
app: auth
spec:
replicas: 2
selector:
matchLabels:
app: auth
template:
metadata:
labels:
app: auth
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
Service:
代码语言:javascript复制---
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app: frontend
spec:
ports:
- port: 80
protocol: TCP
type: ClusterIP
selector:
app: webapp
---
apiVersion: v1
kind: Service
metadata:
name: backend
labels:
app: backend
spec:
ports:
- port: 80
protocol: TCP
type: ClusterIP
selector:
app: auth
...
现在 FrontEnd Pod 能够通过 ClusterIP 或者 DNS 名称来访问 Backend 了。CoreDNS 这样的 DNS 服务器具备 Kubernetes 集群感知的能力,他们会对 Kubernetes API 进行监控,一旦新建了 Service,就会新建对应的 DNS 记录。如果集群中启用的 DNS,所有 Pod 都能够自动的根据 DNS 名称来解析到 Service。
NodePort(外部到 Pod)
在集群内部可以用 DNS 访问 Service。然而 Service 的 IP 是私有的和虚拟的,所以集群外是无法访问的。
试试看从外部访问 frontEnd 的 Pod(此时还没有给 frontEnd 创建 Service):
Pod IP 是私有的,无法路由。
接下来创建一个 NodePort 类型的 Service 把 FrontEnd 服务开放给外部世界。如果把 type
字段设置为 NodePort
,Kubernetes 控制面使用 --service-node-port-range
参数为 NodePort 服务分配了一个端口范围。每个节点都会会把这个端口映射给特定的服务。Service 使用 .spec.ports[*].nodePort
字段来指定该端口:
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: NodePort
selector:
app: webapp
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 80
targetPort: 80
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: 31380
...
这样就可以在集群外使用任意节点的 nodePort 来访问服务了。还可以给 nodePort
赋值以指定特定开放端口。这种情况下,为了防止端口冲突,需要自行管理端口,并且指定端口也必须在参数中声明的端口范围之内。
ExternalTrafficPolicy
ExternalTrafficPolicy
字段表明所属 Service 对象会把来自外部的流量路由给本节点还是集群范围内的端点。如果赋值为 Local
,会保留客户端源 IP 同时避免 NodePort
类型服务的多余一跳,但是有流量分配不均匀的隐患;如果设置为 Cluster
,会抹掉客户端的源 IP,并导致到其它节点的一跳,但会获得相对较好的均衡效果。
Cluster
这是 Kubernetes Service 的缺省 ExternalTrafficPolicy
。这个选项会把流量平均分配给该 Service 的所有 Pod 上。
这种策略的一个弱点是会存在不必要的节点间网络跳转。例如在一个节点的 NodePort 上接收到流量时,即使本节点上存在可用 Pod,流量还是可能会随机地把流量路由到另外一个节点上的 Pod,造成不必要的跳转。
在 Cluster
策略下,数据包的流向:
- 客户端把数据包发送给
node2:31380
; node2
替换源 IP 地址(SNAT)为自己的 IP 地址;node2
将目标地址替换为 Pod IP;- 数据包被路由到
node1
或者node3
,然后到达 Pod; - Pod 的响应返回到
node2
; - Pod 的响应返回到客户端。
Local
这种策略中,kube-proxy
只会在存在目标 Pod 的节点上加入 NodePort 的代理规则。API Server 要求只有使用 LoadBalancer
或者 NodePort
类型的 Service 才能够使用这种策略。这是因为 Local
策略只跟外部访问相关。
如果使用了 Local
策略,kube-proxy
只会代理到本地 endpoint
的流量,不会向其它节点转发。如果本地没有相应端点,发送到该节点的流量就会被丢弃,所以数据包中会保留正确的源 IP,可以放心的在数据包处理规则中使用。
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: NodePort
externalTrafficPolicy: Local
selector:
app: webapp
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 80
targetPort: 80
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: 31380
...
Local
策略下的数据包:
- 客户端发送数据包到
node1:31380
,这个端点上存在目标 Pod; node1
把数据包路由到端点,其中带有正确的源 IP;- 因为策略限制,
node1
不会把数据包发给node3
; - 客户端发送数据包给
node2:31380
,该节点上不存在目标 Pod; - 数据包被丢弃。
LoadBalancer Service 类型中的 Local 策略
如果在 Google GKE 上使用 Local
策略,由于健康检查的原因,会把不运行对应 Pod 的节点从负载均衡池中剔除,所以不会发生丢弃流量的问题。这种模型对于需要处理大量外部入栈流量,需要避免跨节点跳转从而降低延迟的应用非常有帮助。另外因为不需要进行 SNAT,从而让源 IP 得以保存。然而官方文档声明,这种策略存在不够均衡的短板。
Kube-Proxy(iptable)
Kubernetes 中负责 Service 对象的组件就是 kube-proxy
。它在每个节点上运行,为 Pod 和 Service 生成复杂的 iptables 规则,完成所有的过滤和 NAT 工作。如果登录到 Kubernetes 节点上,运行 iptables-save
,会看到 Kubernetes 或者其它组件生成的规则。最重要的是 KUBE-SERVICE
、KUBE-SVC-*
以及 KUBE-SEP-*
:
KUBE-SERVICE
是Service
包的入口。 它负责匹配 IP:Port,并把数据包发给对应的KUBE-SVC-*
。KUBE-SVC-*
担任负载均衡的角色,会平均分配数据包到KUBE-SEP-*
。 每个KUBE-SVC-*
都有和Endpoint
同样数量的KUBE-SEP-*
。KUBE-SEP-*
代表的是Service
的EndPoint
,它负责的是 DNAT,会把Service
的 IP:Port 替换为 Pod 的 IP:Port。
Conntrack 会介入 DNAT 过程,使用状态机来跟踪连接状态。为了记住目标地址的变更,并在回包时候进行恢复,这些状态是必须保存的。iptables 还可以根据 conntrack 状态(ctstate)来决定数据包的目标。下面四个 conntrack 状态尤其重要:
NEW
: conntrack 对该数据包一无所知,该状态出现在收到SYN
的时候。ESTABLISHED
: conntrack 知道该数据包属于一个已发布连接,该状态出现于握手完成之后。RELATED
: 这个数据包不属于任何连接,但是他是隶属于其它连接的,在 FTP 之类的协议里常用。INVALID
: 有问题的数据包,conntrack 不知道如何处理。 这种状态是 Kubernetes 问题的常客。
Service 和 Pod 之间的 TCP 连接过程如下:
- 左侧的客户端 Pod 发送数据包到一个 Service:
2.2.2.10:80
; - 数据包经过客户端节点的 iptables 规则,目标改为
1.1.1.20:80
; - 服务端 Pod 处理数据包,发送一个响应包到
1.1.1.10
; - 数据包回到客户端节点,conntrack 认出这个数据包,把源地址改回
2.2.2.10:80
; - 客户端 Pod 收到响应包。
iptables
在 Linux 操作系统中使用 netfilter
处理防火墙工作。这是一个内核模块,决定是否放行数据包。iptables 是 netfilter 的前端。二者经常被混为一谈。
链
每条链负责一种特定任务。
PREROUTING
: 决定数据包刚刚进入网络端口时的对策。 有几种不同的选择,例如修改数据包(NAT),丢弃数据包或者什么都不做使其通过;INPUT
: 其中经常包含一些用于防止恶意行为的严格规则,防止系统遭到入侵。 开放或者屏蔽端口的行为就是在这里进行的;FORWARD
: 顾名思义,负责数据包的转发。 在将服务器作为路由器的时候,就需要在这里完成任务。OUTPUT
: 这里负责所有的网络浏览的行为。 这里可以限制所有数据包的发送。POSTROUTING
: 发生在数据包离开服务器之前,数据包最后的可跟踪位置。
FORWARD
仅在 ip_forward
启用时才有效。所以下面的命令在 Kubernetes 中很重要:
$ sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
$ cat /proc/sys/net/ipv4/ip_forward
1
上面的变更是暂时性的,要持久化这个变更,需要在 /etc/sysctl.conf
中写入 net.ipv4.ip_forward = 1
。
表
接下来会讨论 NAT 表,除此之外还有几个:
Filter
: 缺省表,这里决定是否允许数据包出入本机,因此可以在这里进行屏蔽等操作;Nat
: 是网络地址转换的缩写。 下面会有例子说明;Mangle
: 仅对特定包有用。 它的功能是在包出入之前修改包中的内容;RAW
: 用于处理原始数据包,主要用在跟踪连接状态,下面有一个放行 SSH 连接的例子。Security
: 负责在 Filter 之后保障安全。
Kubernetes 中的 iptables 配置
部署一个 2 副本 Nginx 应用,导出 iptables 规则。
代码语言:javascript复制服务类型 NodePort
$ kubectl get svc webapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webapp NodePort 10.103.46.104 <none> 80:31380/TCP 3d13h
$ kubectl get ep webapp
NAME ENDPOINTS AGE
webapp 10.244.120.102:80,10.244.120.103:80 3d13h
ClusterIP 是一个存在于 iptables 中的虚拟 IP,Kubernetes 会把这个地址存在 CoreDNS 中。
代码语言:javascript复制$ kubectl exec -i -t dnsutils -- nslookup webapp.default
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: webapp.default.svc.cluster.local
Address: 10.103.46.104
为了能够进行包过滤和 NAT,Kubernetes 会创建一个 KUBE-SERVICES
链,把所有 PREROUTING
和 OUTPUT
流量转发给 KUBE-SERVICES
:
sudo iptables -t nat -L PREROUTING | column -t
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
cali-PREROUTING all -- anywhere anywhere /* cali:6gwbT8clXdHdC1b1 */
KUBE-SERVICES all -- anywhere anywhere /* kubernetes service portals */
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
使用 KUBE-SERVICES
介入包过滤和 NAT 之后,Kubernetes 会监控通向 Service 的流量,并进行 SNAT/DNAT 的处理。在 KUBE-SERVICES
链尾部,会写入另一个链 KUBE-SERVICES
,用于处理 NodePort
类型的 Service。
KUBE-SVC-2IRACUALRELARSND
链会处理针对 ClusterIP
的流量,否则的话就会进入 KUBE-NODEPORTS
:
$ sudo iptables -t nat -L KUBE-SERVICES | column -t
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-MARK-MASQ tcp -- !10.244.0.0/16 10.103.46.104 /* default/webapp cluster IP */ tcp dpt:www
KUBE-SVC-2IRACUALRELARSND tcp -- anywhere 10.103.46.104 /* default/webapp cluster IP */ tcp dpt:www
KUBE-NODEPORTS all -- anywhere anywhere /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL
看看 KUBE-NODEPORTS
的内容:
$ sudo iptables -t nat -L KUBE-NODEPORTS | column -t
Chain KUBE-NODEPORTS (1 references)
target prot opt source destination
KUBE-MARK-MASQ tcp -- anywhere anywhere /* default/webapp */ tcp dpt:31380
KUBE-SVC-2IRACUALRELARSND tcp -- anywhere anywhere /* default/webapp */ tcp dpt:31380
看起来 ClusterIP
和 NodePort
处理过程是一样的,那么看看下面的处理流程:
# statistic mode random -> Random load-balancing between endpoints.
$ sudo iptables -t nat -L KUBE-SVC-2IRACUALRELARSND | column -t
Chain KUBE-SVC-2IRACUALRELARSND (2 references)
target prot opt source destination
KUBE-SEP-AO6KYGU752IZFEZ4 all -- anywhere anywhere /* default/webapp */ statistic mode random probability 0.50000000000
KUBE-SEP-PJFBSHHDX4VZAOXM all -- anywhere anywhere /* default/webapp */
$ sudo iptables -t nat -L KUBE-SEP-AO6KYGU752IZFEZ4 | column -t
Chain KUBE-SEP-AO6KYGU752IZFEZ4 (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 10.244.120.102 anywhere /* default/webapp */
DNAT tcp -- anywhere anywhere /* default/webapp */ tcp to:10.244.120.102:80
$ sudo iptables -t nat -L KUBE-SEP-PJFBSHHDX4VZAOXM | column -t
Chain KUBE-SEP-PJFBSHHDX4VZAOXM (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 10.244.120.103 anywhere /* default/webapp */
DNAT tcp -- anywhere anywhere /* default/webapp */ tcp to:10.244.120.103:80
$ sudo iptables -t nat -L KUBE-MARK-MASQ | column -t
Chain KUBE-MARK-MASQ (24 references)
target prot opt source destination
MARK all -- anywhere anywhere MARK or 0x4000
注意:输出内容已经被精简。
- ClusterIP:
KUBE-SERVICES
→KUBE-SVC-XXX
→KUBE-SEP-XXX
- NodePort:
KUBE-SERVICES
→KUBE-NODEPORTS
→KUBE-SVC-XXX
→KUBE-SEP-XXX
NodePort 服务会有一个 ClusterIP 用于处理内外部通信。
上述规则的可视化表达:
ExtrenalTrafficPolicy: Local
如前文所述,使用 ExtrenalTrafficPolicy: Local
会保留源 IP,并在到达节点上没有 Endpoint 的时候丢弃流量。没有本地 Endpoint 的节点上,iptables 的规则会怎样?
使用 ExtrenalTrafficPolicy: Local
部署 Nginx 服务:
$ kubectl get svc webapp -o wide -o jsonpath={.spec.externalTrafficPolicy}
Local
$ kubectl get svc webapp -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
webapp NodePort 10.111.243.62 <none> 80:30080/TCP 29m app=webserver
检查一下没有本地 Endpoint 的节点上的 iptables 规则:
代码语言:javascript复制$ sudo iptables -t nat -L KUBE-NODEPORTS
Chain KUBE-NODEPORTS (1 references)
target prot opt source destination
KUBE-MARK-MASQ tcp — 127.0.0.0/8 anywhere /* default/webapp */ tcp dpt:30080
KUBE-XLB-2IRACUALRELARSND tcp — anywhere anywhere /* default/webapp */ tcp dpt:30080
再看一下 KUBE-XLB-2IRACUALRELARSND
:
$ iptables -t nat -L KUBE-XLB-2IRACUALRELARSND
Chain KUBE-XLB-2IRACUALRELARSND (1 references)
target prot opt source destination
KUBE-SVC-2IRACUALRELARSND all — 10.244.0.0/16 anywhere /* Redirect pods trying to reach external loadbalancer VIP to clusterIP */
KUBE-MARK-MASQ all — anywhere anywhere /* masquerade LOCAL traffic for default/webapp LB IP */ ADDRTYPE match src-type LOCAL
KUBE-SVC-2IRACUALRELARSND all — anywhere anywhere /* route LOCAL traffic for default/webapp LB IP to service chain */ ADDRTYPE match src-type LOCAL
KUBE-MARK-DROP all — anywhere anywhere /* default/webapp has no local endpoints */
这里就会看到,集群级别的流量没什么问题,但是 NodePort 流量会被丢弃。
Headless Service
有的应用并不需要负载均衡和服务 IP。在这种情况下就可以使用 headless
Service,只要设置 .spec.clusterIP
为 None
即可。
可以借助这种服务类型和其他服务发现机制协作,无需和 Kubernetes 绑定。kube-proxy
不对这种没有 IP 的服务提供支持,也就没有什么负载均衡和代理之类的能力了。DNS 的配置要根据 Selector 来确定。
有 Selector
定义了 Selector 的 Headless Service,Endpoint 控制器会创建 Endpoint
记录,并修改 DNS 记录来直接返回 Service 后端的 Pod 地址。
$ kubectl get svc webapp-hs
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webapp-hs ClusterIP None <none> 80/TCP 24s
$ kubectl get ep webapp-hs
NAME ENDPOINTS AGE
webapp-hs 10.244.120.109:80,10.244.120.110:80 31s
无 Selector
没有定义 Selector 的 Headless Service,也就没有 Endpoint 记录。然而 DNS 系统会尝试配置:
ExternalName
类型的服务,会产生CNAME
记录;- 其他类型则是所有 Endpoint 共享服务名称。
如果外部 IP 被路由到集群节点上,Kubernetes Service 可以用 externalIPs
开放出来。通过 externalIP
进入集群的流量,会被路由到 Service Endpoint 上。externalIPs
不是 Kubernetes 管理的,需要集群管理员自行维护。
网络策略
阅读至此,Kubernetes 网络策略的实现方法已经呼之欲出了——是的,就是 iptables。目前是 CNI 而非 kube-proxy
负责实现网络策略。这部分内容本来应该写在第二篇 Calico 的内容里,然而我认为这里写出来可能更合适。
我们创建三个服务:frontend、backend 和 db。
缺省情况下,Pod 没有任何隔离,会接受任何来源的通信。
想要制定规则,禁止 frontend 访问 db:
这里推荐阅读 Guide to Kubernetes Ingress Network Policies 了解网络策略配置方面的更多内容。本节内容关注的是 Kubernetes 中策略的实现方式,而非配置知识。
创建一个策略把 db 和 frontend 隔离开,这样一来 frontend 和 db 之间的流量就会被阻断。
上图中为了简单起见,写的是 Service 而非 Pod,安全策略的控制对象实际上是 Pod。
策略实施之后会产生如下效果,frontend 的 Pod 能访问 backend 但是无法访问 db。backend 的 Pod 可以访问 db。
代码语言:javascript复制$ kubectl exec -it frontend-8b474f47-zdqdv -- /bin/sh
$ curl backend
backend-867fd6dff-mjf92
$ curl db
curl: (7) Failed to connect to db port 80: Connection timed out
$ kubectl exec -it backend-867fd6dff-mjf92 -- /bin/sh
$ curl db
db-8d66ff5f7-bp6kf
看看这里用到的网络策略:只允许 ‘allow-db-access
标签设置为 true
的 Pod 访问 db。
Calico 会把 Kubernetes 网络策略翻译成 Calico 格式:
代码语言:javascript复制$ calicoctl get networkPolicy --output yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
creationTimestamp: "2020-11-05T05:26:27Z"
name: knp.default.allow-db-access
namespace: default
resourceVersion: /53872
uid: 1b3eb093-b1a8-4429-a77d-a9a054a6ae90
spec:
ingress:
- action: Allow
destination: {}
source:
selector: projectcalico.org/orchestrator == 'k8s' && networking/allow-db-access
== 'true'
order: 1000
selector: projectcalico.org/orchestrator == 'k8s' && app == 'db'
types:
- Ingress
kind: NetworkPolicyList
metadata:
resourceVersion: 56821/56821
iptables 的 filter
表在网络策略的实现中起了很重要的作用。Calico 中用到了 ipsec
等高级概念,难于进行反向工程。在这个规则中可以看到,只有来自 backend 的流量才被允许发给 db。
使用 calicoctl
获取 endpoint 详情:
$ calicoctl get workloadEndpoint
WORKLOAD NODE NETWORKS INTERFACE
backend-867fd6dff-mjf92 minikube 10.88.0.27/32 cali2b1490aa46a
db-8d66ff5f7-bp6kf minikube 10.88.0.26/32 cali95aa86cbb2a
frontend-8b474f47-zdqdv minikube 10.88.0.24/32 cali505cfbeac50
cali95aa86cbb2a
就是 db Pod veth 的主机侧。
看看跟这个网络接口有关的 iptables 规则:
代码语言:javascript复制$ sudo iptables-save | grep cali95aa86cbb2a
:cali-fw-cali95aa86cbb2a - [0:0]
:cali-tw-cali95aa86cbb2a - [0:0]
...
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:pm-LK-c1ra31tRwz" -m mark --mark 0x0/0x20000 -j cali-pi-_tTE-E7yY40ogArNVgKt
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:q_zG8dAujKUIBe0Q" -m comment --comment "Return if policy accepted" -m mark --mark 0x10000/0x10000 -j RETURN
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:FUDVBYh1Yr6tVRgq" -m comment --comment "Drop if no policies passed packet" -m mark --mark 0x0/0x20000 -j DROP
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:X19Z-Pa0qidaNsMH" -j cali-pri-kns.default
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:Ljj0xNidsduxDGUb" -m comment --comment "Return if profile accepted" -m mark --mark 0x10000/0x10000 -j RETURN
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:0z9RRvvZI9Gud0Wv" -j cali-pri-ksa.default.default
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:pNCpK-SOYelSULC1" -m comment --comment "Return if profile accepted" -m mark --mark 0x10000/0x10000 -j RETURN
-A cali-tw-cali95aa86cbb2a -m comment --comment "cali:sMkvrxvxj13WlTMK" -m comment --comment "Drop if no profiles matched" -j DROP
$ sudo iptables-save -t filter | grep cali-pi-_tTE-E7yY40ogArNVgKt
:cali-pi-_tTE-E7yY40ogArNVgKt - [0:0]
-A cali-pi-_tTE-E7yY40ogArNVgKt -m comment --comment "cali:M4Und37HGrw6jUk8" -m set --match-set cali40s:LrVD8vMIGQDyv8Y7sPFB1Ge src -j MARK --set-xmark 0x10000/0x10000
-A cali-pi-_tTE-E7yY40ogArNVgKt -m comment --comment "cali:sEnlfZagUFRSPRoe" -m mark --mark 0x10000/0x10000 -j RETURN
检查一下 ipset,会看到只有来自 backend pod 的 10.88.0.27
才能访问 db。
文章转载自伪架构师。点击这里阅读原文了解更多。