作者:MeshCloud脉时云公有云架构师 陈博文
用途:
使用容器时,如 Google Kubernetes Engine,从 Pod IP 发出的流量将被拒绝出站。 为了避免这种情况,我们必须将 Pod IP 隐藏在 VM 自己的 IP 地址后面 – 通常称为“伪装”。 默认情况下,代理配置为将 RFC 1918 指定的三个私有 IP 范围视为非伪装 CIDR。 这些范围是 10.0.0.0/8,172.16.0.0/12 和 192.168.0.0/16。
需求:
- pod访问目标地址(des)为: 10.0.0.0/8 的aws服务器 将pod ip伪装成node ip
IP Masquerade Agent作用:
- 通过iptables做Snat 使用nodeip 作为pod的源ip进行请求
GKE 会在以下情况执行 IP 伪装或 SNAT:
对于标准模式下的集群:
- 安装了 ip-masq-agent DaemonSet。
- ip-masq-agent ConfigMap 包括 nonMasqueradeCIDRs 和 masqLinkLocal 参数。
- 使用 –disable-default-snat flag 创建了集群。
GKE默认非伪装目标:
https://cloud.google.com/kubernetes-engine/docs/concepts/ip-masquerade-agent#default-non-masq-dests
仅在集群满足以下条件时会涉及默认的非伪装目标:
● 您在创建集群时未使用 --disable-default-snat标志,并且
● 满足以下一个或两个条件:
○ 您尚未部署ip-masq-agentDaemonSet。
○ ip-masq-agent ConfigMap 中未指定nonMasqueradeCIDRs列表。这也包括您未指定 ip-masq-agent ConfigMap 文件的情况。
对于满足上述条件的集群,GKE 会执行以下操作:
● 如果数据包的目标位于默认非伪装目标列表中,则集群会保留来源 Pod IP 地址。
● 如果数据包的目标不在默认非伪装目标列表中,则集群会将来源 IP 地址从 Pod IP 地址更改为运行 Pod 的节点的 IP 地址。
如果您配置了既部署了 ip-masq-agent DaemonSet 同时又在 ip-masq-agent ConfigMap 中指定了 nonMasqueradeCIDRs 列表的集群,则默认非伪装目标将不再适用。这是因为非伪装目标会改为在 nonMasqueradeCIDRs 列表中指定。
一、环境:
创建两个vpc 用vpc peering模拟 aws服务
源(gke pod):
- pod name: cbw-pod-1
- pod 所在node ip :10.140.15.217
- podip: 10.16.1.6
目标(使用不同vpc模拟aws,使用vpc peering连接两个vpc,在新的vpc中创建vm):
- vmip: 10.70.0.2
- service: httpd
1、未部署IP Masquerade Agent;请求结果为 pod ip :10.16.1.6
#curl 不同vpc中vm 10.140.15.215
kubectl exec -it cbw-pod-1 -- curl 10.70.0.2
#登录同一vpc中的一台vm 查看httpd日志 显示请求的源地址为10.72.2.6为podip
10.16.1.6 - - [16/Sep/2022:08:27:36 +0000] "GET / HTTP/1.1" 403 4897 "-" "curl/7.74.0"
二、配置 IP Masquerade Agent
1、查看是否存在configmap,存在的话修改ipcdir即可
2、创建configmap,如果上面未找到相关configmap
①编辑配置文件
#随意起一个名字写入下面内容 例如:
vim ipmasq.cfg
nonMasqueradeCIDRs:
- $<CIDR1>
- $<CIDR2>
masqLinkLocal: false
resyncInterval: $<SYNC_INTERVAL>/$<UNIT_OF_TIME>
-----------------------------------------------------------------------------
$<CIDR1>和$<CIDR2>: 采用 CIDR 格式的 IP 地址范围。当数据包发送到这些目标时,您的集群将不会伪装 IP 地址来源,而是会保留来源 Pod IP 地址。如果您需要超过两个 CIDR,请按照相同格式向 nonMasqueradeCIDRs 列表添加更多条目。nonMasqueradeCIDRs 属性至少应包含集群的节点 IP 范围和 Pod IP 地址范围。
#注意:自定义 nonMasqueradeCIDRs 必须至少包含集群的节点 IP 范围和 Pod IP 地址范围。如果您启用了节点内可见性,则这一点尤为重要。如果 nonMasqueradeCIDRs 中不存在 Pod IP 地址范围,并且您已启用节点内可见性,则 Pod 之间将无法正确通信。
$<SYNC_INTERVAL>:每个 ip-masq-agent Pod 检查 ip-masq-agent ConfigMap 内容并将任何更改写入其本地 /etc/config/ip-masq-agent 文件的间隔时间。默认值为 60。
$<UNIT_OF_TIME>:resyncInterval 的时间单位。有效值包括 s(以秒为单位)和 ms(以毫秒为单位)。默认值为 s。
-----------------------------------------------------------------------------
例如:
nonMasqueradeCIDRs:
#nodeip range
- 10.16.0.0/14
#podip range
- 10.140.0.0/20
masqLinkLocal: false
#default 60 s
resyncInterval: 60s
②创建configmap
kubectl create configmap ip-masq-agent \
--namespace=kube-system \
--from-file=config=$</path>
-----------------------------------------------------------------------------
$</path>: 上面步骤①中编写的配置文件路径
-----------------------------------------------------------------------------
例如:
kubectl create configmap ip-masq-agent \
--namespace=kube-system \
--from-file=config=/Users/cbw/testdir/ip-masq-agent-cm.text
③查看configmap
kubectl get configmap -n kube-system | grep ip-masq-agent
2、创建daemonset
[可选]①添加
.spec.template.spec.nodeSelector 指定node来进行节点选择。选择自己想使用ip-masq的节点
你必须同时将适当的节点标签应用于集群中希望代理运行的任何节点,如果不指定会在所有node上部署 ip-masq-agent。
kubectl label nodes my-node beta.kubernetes.io/masq-agent-ds-ready=true
②daemonset.yaml文件。可以根据自己需求修改名字,卷名字等
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ip-masq-agent
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: ip-masq-agent
template:
metadata:
labels:
k8s-app: ip-masq-agent
spec:
hostNetwork: true
containers:
- name: ip-masq-agent
image: k8s.gcr.io/networking/ip-masq-agent:v2.7.0
args:
# The masq-chain must be IP-MASQ
- --masq-chain=IP-MASQ
# To non-masquerade reserved IP ranges by default,
# uncomment the following line.
# - --nomasq-all-reserved-ranges
securityContext:
privileged: true
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: ip-masq-agent
optional: true
items:
- key: config
path: ip-masq-agent
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
- key: "CriticalAddonsOnly"
operator: "Exists"
②创建daemonset.yaml
kubectl apply -f daemonset.yaml
③检查,三个节点全部ready
④登录node查看iptables
$ iptables -t nat -L IP-MASQ
Chain IP-MASQ (2 references)
target prot opt source destination
RETURN all -- anywhere 169.254.0.0/16 /* ip-masq-agent: local traffic is not subject to MASQUERADE */
# configmap 配置的地址段 return
RETURN all -- anywhere 10.16.0.0/14 /* ip-masq-agent: local traffic is not subject to MASQUERADE */
# configmap 配置的地址段 return
RETURN all -- anywhere 10.140.0.0/20 /* ip-masq-agent: local traffic is not subject to MASQUERADE */
# # configmap 配置以外的地址段 会进行伪装
MASQUERADE all -- anywhere anywhere /* ip-masq-agent: outbound traffic is subject to MASQUERADE (must be last in chain) */
三、验证
①访问10.70.0.2的httpd服务
#curl 同一vpc中的一台vm
kubectl exec -it cbw-pod-1 -- curl 10.70.0.2
#登录不同vpc中的vm 查看httpd日志 显示请求的源地址为10.140.15.217为node ip
10.140.15.217 - - [16/Sep/2022:08:59:21 +0000] "GET / HTTP/1.1" 403 4897 "-" "curl/7.74.0"
由pod ip 变为node ip
②访问同一集群的另外一个 pod的nginx服务 ,使用pod ip
四、删除daemonset
如果不想使用了就删除 daemonset和iptables 规则
#删除 daemonset
kubectl -f delete ip-masq.yaml
这里发现删除daemonset和configmap后并没有删除节点上的iptables规则,所以再去节点删除iptables规则
$ iptables -t nat -L IP-MASQ --line
num target prot opt source destination
1 RETURN all -- anywhere 169.254.0.0/16 /* ip-masq-agent: local traffic is not subject to MASQUERADE */
2 RETURN all -- anywhere 10.16.0.0/14 /* ip-masq-agent: local traffic is not subject to MASQUERADE */
3 RETURN all -- anywhere 10.140.0.0/20 /* ip-masq-agent: local traffic is not subject to MASQUERADE */
4 MASQUERADE all -- anywhere anywhere
#默认情况下,本地链路范围 (169.254.0.0/16) 也由 ip-masq agent 处理, 该代理设置适当的 iptables 规则。 要使 ip-masq-agent 忽略本地链路, 可以在 ConfigMap 中将 masqLinkLocal 设置为 true。
#这里删除234条即可
$ iptables -t nat -D IP-MASQ <numline>
验证 访问地址又从node ip变回了 pod ip