Google Kubernetes 引擎和 VPN
Google Kubernetes Engine & VPN
我正在使用 Google Kubernetes Engine 部署一些需要连接到本地数据库的应用程序。为此,我配置了一个 VPN 隧道并创建了一个 VPC。
然后,我创建了一个使用该 VPC 的 GKE 集群(1 个节点),我可以通过连接到该节点并尝试 ping 数据库服务器来确认数据库可以访问
~ $ sudo toolbox ping 10.197.100.201
Spawning container root-gcr.io_google-containers_toolbox-20180309-00 on
/var/lib/toolbox/root-gcr.io_google-containers_toolbox-20180309-00.
Press ^] three times within 1s to kill container.
PING 10.197.100.201 (10.197.100.201): 56 data bytes
64 bytes from 10.197.100.201: icmp_seq=0 ttl=62 time=45.967 ms
64 bytes from 10.197.100.201: icmp_seq=1 ttl=62 time=44.186 ms`
但是,如果我尝试从 Pod 执行相同的操作,我将无法连接。
root@one-shot-pod:/# traceroute 10.197.100.201
traceroute to 10.197.100.201 (10.197.100.201), 30 hops max, 60 byte
packets
1 10.0.0.1 (10.0.0.1) 0.046 ms 0.009 ms 0.007 ms
2 * * *
3 * * *```
我错过了什么?
我在 this blog.
中找到了解决方案
问题是默认的 iptables 配置如下所示:
iptables -A POSTROUTING ! -d 10.0.0.0/8 \
-m comment --comment “kubenet: outbound traffic" -m addrtype \
! --dst-type LOCAL -j MASQUERADE -t nat
It means that traffic from the pods will be NATted to the host IP only
if the destination is not in 10.0.0.0/8.
This 10.0.0.0/8 is the problem: it’s too large.
它还包括您的 10.197.100.201
IP。
要解决此问题,您可以将以下 DaemonSet 添加到您的 Kubernetes 集群中:
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: fix-nat
labels:
app: fix-nat
spec:
template:
metadata:
labels:
app: fix-nat
spec:
hostPID: true
containers:
- name: fix-nat
image: gcr.io/google-containers/startup-script:v1
imagePullPolicy: Always
securityContext:
privileged: true
env:
- name: STARTUP_SCRIPT
value: |
#! /bin/bash
while true; do
iptables-save | grep MASQUERADE | grep -q "NAT-VPN"
if [ $? -ne 0 ]; then
echo "Missing NAT rule for VPN, adding it"
iptables -A POSTROUTING -d 10.197.100.0/24 -m comment --comment "NAT-VPN: SNAT for outbound traffic through VPN" -m addrtype ! --dst-type LOCAL -j MASQUERADE -t nat
fi
sleep 60
done
This small script will check every minute, forever, if we have the
right iptables rule and, if not, add it.
Note that the privileged: true is necessary for the pod to be able to
change iptables rules from the host.
我遇到了同样的问题,这解决了问题。
经过一番排查,我找到了问题的根本原因。基本上,通信无法正常工作,因为有一种称为 ip 伪装 (https://cloud.google.com/kubernetes-engine/docs/how-to/ip-masquerade-agent) 的东西用于 NAT 转换。
由于 GKE 有一些默认地址被配置为不可伪装(在我使用的版本上,默认值是:10.0.0.0/8
、172.16.0.0/12
和 192.168.0.0/16
)和目标 ip 是 10.197.100.201(10.0.0.0/8 的一部分)并且该 ip 在集群之外,解决方案是修改 nonMasqueradeCIDRs
并删除 10.0.0.0/8
并使用 10.44.0.0/14
(GKE群集 CIDR)代替。
为此,我使用了以下配置图:
apiVersion: v1
data:
config: |-
nonMasqueradeCIDRs:
- 10.44.0.0/14
- 172.16.0.0/12
- 192.168.0.0/16
resyncInterval: 60s
kind: ConfigMap
metadata:
name: ip-masq-agent
namespace: kube-system
之后,要应用配置,您可以使用以下命令上传配置图:
kubectl create configmap ip-masq-agent --from-file <configmap file> --namespace kube-system
我正在使用 Google Kubernetes Engine 部署一些需要连接到本地数据库的应用程序。为此,我配置了一个 VPN 隧道并创建了一个 VPC。
然后,我创建了一个使用该 VPC 的 GKE 集群(1 个节点),我可以通过连接到该节点并尝试 ping 数据库服务器来确认数据库可以访问
~ $ sudo toolbox ping 10.197.100.201
Spawning container root-gcr.io_google-containers_toolbox-20180309-00 on
/var/lib/toolbox/root-gcr.io_google-containers_toolbox-20180309-00.
Press ^] three times within 1s to kill container.
PING 10.197.100.201 (10.197.100.201): 56 data bytes
64 bytes from 10.197.100.201: icmp_seq=0 ttl=62 time=45.967 ms
64 bytes from 10.197.100.201: icmp_seq=1 ttl=62 time=44.186 ms`
但是,如果我尝试从 Pod 执行相同的操作,我将无法连接。
root@one-shot-pod:/# traceroute 10.197.100.201
traceroute to 10.197.100.201 (10.197.100.201), 30 hops max, 60 byte
packets
1 10.0.0.1 (10.0.0.1) 0.046 ms 0.009 ms 0.007 ms
2 * * *
3 * * *```
我错过了什么?
我在 this blog.
中找到了解决方案问题是默认的 iptables 配置如下所示:
iptables -A POSTROUTING ! -d 10.0.0.0/8 \
-m comment --comment “kubenet: outbound traffic" -m addrtype \
! --dst-type LOCAL -j MASQUERADE -t nat
It means that traffic from the pods will be NATted to the host IP only if the destination is not in 10.0.0.0/8.
This 10.0.0.0/8 is the problem: it’s too large.
它还包括您的 10.197.100.201
IP。
要解决此问题,您可以将以下 DaemonSet 添加到您的 Kubernetes 集群中:
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: fix-nat
labels:
app: fix-nat
spec:
template:
metadata:
labels:
app: fix-nat
spec:
hostPID: true
containers:
- name: fix-nat
image: gcr.io/google-containers/startup-script:v1
imagePullPolicy: Always
securityContext:
privileged: true
env:
- name: STARTUP_SCRIPT
value: |
#! /bin/bash
while true; do
iptables-save | grep MASQUERADE | grep -q "NAT-VPN"
if [ $? -ne 0 ]; then
echo "Missing NAT rule for VPN, adding it"
iptables -A POSTROUTING -d 10.197.100.0/24 -m comment --comment "NAT-VPN: SNAT for outbound traffic through VPN" -m addrtype ! --dst-type LOCAL -j MASQUERADE -t nat
fi
sleep 60
done
This small script will check every minute, forever, if we have the right iptables rule and, if not, add it.
Note that the privileged: true is necessary for the pod to be able to change iptables rules from the host.
我遇到了同样的问题,这解决了问题。
经过一番排查,我找到了问题的根本原因。基本上,通信无法正常工作,因为有一种称为 ip 伪装 (https://cloud.google.com/kubernetes-engine/docs/how-to/ip-masquerade-agent) 的东西用于 NAT 转换。
由于 GKE 有一些默认地址被配置为不可伪装(在我使用的版本上,默认值是:10.0.0.0/8
、172.16.0.0/12
和 192.168.0.0/16
)和目标 ip 是 10.197.100.201(10.0.0.0/8 的一部分)并且该 ip 在集群之外,解决方案是修改 nonMasqueradeCIDRs
并删除 10.0.0.0/8
并使用 10.44.0.0/14
(GKE群集 CIDR)代替。
为此,我使用了以下配置图:
apiVersion: v1
data:
config: |-
nonMasqueradeCIDRs:
- 10.44.0.0/14
- 172.16.0.0/12
- 192.168.0.0/16
resyncInterval: 60s
kind: ConfigMap
metadata:
name: ip-masq-agent
namespace: kube-system
之后,要应用配置,您可以使用以下命令上传配置图:
kubectl create configmap ip-masq-agent --from-file <configmap file> --namespace kube-system