无法从 EC2 上的主节点访问 Kubernetes 服务
Kubernetes service unreachable from master node on EC2
我使用 kubeadm 在 AWS 上创建了一个 k8s 集群,其中有 1 个主节点和 1 个工作节点遵循可用指南 here。
然后,我启动了 1 个 ElasticSearch 容器:
kubectl run elastic --image=elasticsearch:2 --replicas=1
并且它已成功部署到 worker 上。然后,我尝试将其作为集群上的服务公开:
kubectl expose deploy/elastic --port 9200
并且曝光成功:
NAMESPACE NAME READY STATUS RESTARTS AGE
default elastic-664569cb68-flrrz 1/1 Running 0 16m
kube-system etcd-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
kube-system kube-apiserver-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
kube-system kube-controller-manager-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
kube-system kube-dns-86f4d74b45-mc24s 3/3 Running 0 17m
kube-system kube-flannel-ds-fjkkc 1/1 Running 0 16m
kube-system kube-flannel-ds-zw4pq 1/1 Running 0 17m
kube-system kube-proxy-4c8lh 1/1 Running 0 17m
kube-system kube-proxy-zkfwn 1/1 Running 0 16m
kube-system kube-scheduler-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default elastic ClusterIP 10.96.141.188 <none> 9200/TCP 16m
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 17m
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system kube-flannel-ds 2 2 2 2 2 beta.kubernetes.io/arch=amd64 17m
kube-system kube-proxy 2 2 2 2 2 <none> 17m
NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
default elastic 1 1 1 1 16m
kube-system kube-dns 1 1 1 1 17m
NAMESPACE NAME DESIRED CURRENT READY AGE
default elastic-664569cb68 1 1 1 16m
kube-system kube-dns-86f4d74b45 1 1 1 17m
但是,当我尝试执行到 http://10.96.141.188:9200 的 curl(从主节点)时,我遇到了超时,并且一切都表明无法从主节点访问生成的集群 IP。它仅在工作节点上工作。
我尝试了我能找到的一切:
给 iptables 添加一堆规则
iptables -P FORWARD ACCEPT
iptables -I FORWARD 1 -i cni0 -j ACCEPT -m comment --comment "flannel subnet"
iptables -I FORWARD 1 -o cni0 -j ACCEPT -m comment --comment "flannel subnet"
iptables -t nat -A POSTROUTING -s 10.244.0.0/16 ! -d 10.244.0.0/16 -j MASQUERADE
- 禁用防火墙
- 启用 ec2 安全策略上的所有端口(从任何地方)
- 使用不同的 docker 版本(1.13.1、17.03、17.06、17.12)
- 不同的k8s版本(1.9.0 ~1.9.6)
- 不同的 CNI(法兰绒和编织)
- 向 kubeadm init 命令添加一些参数(--node-name 与 FQDN 和--apiserver-advertise-address 与 public master IP)
但是 none 这行得通。这似乎是 AWS 上的一个特定问题,因为教程指南在 Linux Academy Cloud Server 上运行良好。
还有什么我可以尝试的吗?
观察:
目前,我在 Centos7 上使用 docker 1.13 和 k8s 1.9.6(带有 flannel 0.9.1)。
kubectl run elastic --image=elasticsearch:2 --replicas=1
据我所知,您没有通知 kubernetes elasticsearch:2
图像侦听任何端口,它不会自行推断。如果您只是 运行 docker
下的图像而没有类似地指定 --publish
或 --publish-all
选项,您会遇到同样的问题。
因此,当 ClusterIP
尝试将流量从端口 9200 转发到与其选择器匹配的 Pod
s 时,这些数据包会落入 /dev/null
,因为容器没有监听它们.
Add a bunch of rules to iptables
绝对不要那样做;如果你观察过,已经有大量的 iptables 规则由 kube-proxy
管理:事实上,它的主要工作是在它所在的节点上拥有 iptables 规则 运行ning。你的规则只会让 kube-proxy 以及任何跟随你的人感到困惑,他们试图找出这些随机规则的来源。如果您还没有将它们永久化,那么要么撤消它们,要么重新启动机器以刷新这些表。保留 ad-hoc 规则不会 100% 使您的故障排除过程变得更容易。
终于找到问题了。根据this page,Flannel需要在Master和Worker节点上开放UDP 8285和8472端口。有趣的是,官方 kubeadm 文档中并未提及这一点。
我使用 kubeadm 在 AWS 上创建了一个 k8s 集群,其中有 1 个主节点和 1 个工作节点遵循可用指南 here。
然后,我启动了 1 个 ElasticSearch 容器:
kubectl run elastic --image=elasticsearch:2 --replicas=1
并且它已成功部署到 worker 上。然后,我尝试将其作为集群上的服务公开:
kubectl expose deploy/elastic --port 9200
并且曝光成功:
NAMESPACE NAME READY STATUS RESTARTS AGE
default elastic-664569cb68-flrrz 1/1 Running 0 16m
kube-system etcd-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
kube-system kube-apiserver-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
kube-system kube-controller-manager-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
kube-system kube-dns-86f4d74b45-mc24s 3/3 Running 0 17m
kube-system kube-flannel-ds-fjkkc 1/1 Running 0 16m
kube-system kube-flannel-ds-zw4pq 1/1 Running 0 17m
kube-system kube-proxy-4c8lh 1/1 Running 0 17m
kube-system kube-proxy-zkfwn 1/1 Running 0 16m
kube-system kube-scheduler-ip-172-31-140-179.ec2.internal 1/1 Running 0 16m
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default elastic ClusterIP 10.96.141.188 <none> 9200/TCP 16m
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 17m
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system kube-flannel-ds 2 2 2 2 2 beta.kubernetes.io/arch=amd64 17m
kube-system kube-proxy 2 2 2 2 2 <none> 17m
NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
default elastic 1 1 1 1 16m
kube-system kube-dns 1 1 1 1 17m
NAMESPACE NAME DESIRED CURRENT READY AGE
default elastic-664569cb68 1 1 1 16m
kube-system kube-dns-86f4d74b45 1 1 1 17m
但是,当我尝试执行到 http://10.96.141.188:9200 的 curl(从主节点)时,我遇到了超时,并且一切都表明无法从主节点访问生成的集群 IP。它仅在工作节点上工作。
我尝试了我能找到的一切:
给 iptables 添加一堆规则
iptables -P FORWARD ACCEPT
iptables -I FORWARD 1 -i cni0 -j ACCEPT -m comment --comment "flannel subnet"
iptables -I FORWARD 1 -o cni0 -j ACCEPT -m comment --comment "flannel subnet"
iptables -t nat -A POSTROUTING -s 10.244.0.0/16 ! -d 10.244.0.0/16 -j MASQUERADE
- 禁用防火墙
- 启用 ec2 安全策略上的所有端口(从任何地方)
- 使用不同的 docker 版本(1.13.1、17.03、17.06、17.12)
- 不同的k8s版本(1.9.0 ~1.9.6)
- 不同的 CNI(法兰绒和编织)
- 向 kubeadm init 命令添加一些参数(--node-name 与 FQDN 和--apiserver-advertise-address 与 public master IP)
但是 none 这行得通。这似乎是 AWS 上的一个特定问题,因为教程指南在 Linux Academy Cloud Server 上运行良好。
还有什么我可以尝试的吗?
观察: 目前,我在 Centos7 上使用 docker 1.13 和 k8s 1.9.6(带有 flannel 0.9.1)。
kubectl run elastic --image=elasticsearch:2 --replicas=1
据我所知,您没有通知 kubernetes elasticsearch:2
图像侦听任何端口,它不会自行推断。如果您只是 运行 docker
下的图像而没有类似地指定 --publish
或 --publish-all
选项,您会遇到同样的问题。
因此,当 ClusterIP
尝试将流量从端口 9200 转发到与其选择器匹配的 Pod
s 时,这些数据包会落入 /dev/null
,因为容器没有监听它们.
Add a bunch of rules to iptables
绝对不要那样做;如果你观察过,已经有大量的 iptables 规则由 kube-proxy
管理:事实上,它的主要工作是在它所在的节点上拥有 iptables 规则 运行ning。你的规则只会让 kube-proxy 以及任何跟随你的人感到困惑,他们试图找出这些随机规则的来源。如果您还没有将它们永久化,那么要么撤消它们,要么重新启动机器以刷新这些表。保留 ad-hoc 规则不会 100% 使您的故障排除过程变得更容易。
终于找到问题了。根据this page,Flannel需要在Master和Worker节点上开放UDP 8285和8472端口。有趣的是,官方 kubeadm 文档中并未提及这一点。