Kubernetes 网络排错指南

2019 年 4 月 4 日 DevOps时代


原文链接:https://zhuanlan.zhihu.com/p/34558421


本文介绍各种常见的网络问题以及排错方法,包括 Pod 访问异常、Service 访问异常以及网络安全策略异常等。

说到 Kubernetes 的网络,其实无非就是以下三种情况之一

  • Pod 访问容器外部网络

  • 从容器外部访问 Pod 网络

  • Pod 之间相互访问

当然,以上每种情况还都分别包括本地访问和跨主机访问两种场景,并且一般情况下都是通过 Service 间接访问 Pod。

排查网络问题基本上也是从这几种情况出发,定位出具体的网络异常点,再进而寻找解决方法。网络异常可能的原因比较多,常见的有

CNI 网络插件配置错误,导致多主机网络不通,比如

  • IP 网段与现有网络冲突

  • 插件使用了底层网络不支持的协议

  • 忘记开启 IP 转发等 .sysctl net.ipv4.ip_forward .sysctl net.bridge.bridge-nf-call-iptables

Pod 网络路由丢失,比如

  • kubenet 要求网络中有 podCIDR 到主机 IP 地址的路由,这些路由如果没有正确配置会导致 Pod 网络通信等问题

  • 在公有云平台上,kube-controller-manager 会自动为所有 Node 配置路由,但如果配置不当(如认证授权失败、超出配额等),也有可能导致无法配置路由

Flannel Pods 一直处于 Init:CrashLoopBackOff 状态

Flannel 网络插件非常容易部署,只要一条命令即可

  
  
    
  1. kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

然而,部署完成后,Flannel Pod 有可能会碰到初始化失败的错误

  
  
    
  1. $ kubectl -n kube-system get pod

  2. NAME                            READY     STATUS                  RESTARTS   AGE

  3. kube-flannel-ds-ckfdc           0/1       Init:CrashLoopBackOff   4          2m

  4. kube-flannel-ds-jpp96           0/1       Init:CrashLoopBackOff   4          2m

查看日志会发现

  
  
    
  1. $ kubectl -n kube-system logs kube-flannel-ds-jpp96 -c install-cni

  2. cp: can't create '/etc/cni/net.d/10-flannel.conflist': Permission denied

这一般是由于 SELinux 开启导致的,关闭 SELinux 既可解决。有两种方法:

  • 修改 /etc/selinux/config 文件方法:SELINUX=disabled

  • 通过命令临时修改(重启会丢失):setenforce 0

Pod 无法解析 DNS

如果 Node 上安装的 Docker 版本大于 1.12,那么 Docker 会把默认的 iptables FORWARD 策略改为 DROP。这会引发 Pod 网络访问的问题。解决方法则在每个 Node 上面运行 iptables -P FORWARD ACCEPT,比如

  
  
    
  1. echo "ExecStartPost=/sbin/iptables -P FORWARD ACCEPT" >> /etc/systemd/system/docker.service.d/exec_start.conf

  2. systemctl daemon-reload

  3. systemctl restart docker

如果使用了 flannel/weave 网络插件,更新为最新版本也可以解决这个问题。

DNS 无法解析也有可能是 kube-dns 服务异常导致的,可以通过下面的命令来检查 kube-dns 是否处于正常运行状态

  
  
    
  1. $ kubectl get pods --namespace=kube-system -l k8s-app=kube-dns

  2. NAME                    READY     STATUS    RESTARTS   AGE

  3. ...

  4. kube-dns-v19-ezo1y      3/3       Running   0           1h

  5. ...

如果 kube-dns 处于 CrashLoopBackOff 状态,那么可以参考 Kube-dns/Dashboard CrashLoopBackOff 排错 来查看具体排错方法。

如果 kube-dns Pod 处于正常 Running 状态,则需要进一步检查是否正确配置了 kube-dns 服务:

  
  
    
  1. $ kubectl get svc kube-dns --namespace=kube-system

  2. NAME          CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE

  3. kube-dns      10.0.0.10      <none>        53/UDP,53/TCP        1h


  4. $ kubectl get ep kube-dns --namespace=kube-system

  5. NAME       ENDPOINTS                       AGE

  6. kube-dns   10.180.3.17:53,10.180.3.17:53    1h

如果 kube-dns service 不存在,或者 endpoints 列表为空,则说明 kube-dns service 配置错误,可以重新创建 kube-dns service,比如

  
  
    
  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4.  name: kube-dns

  5.  namespace: kube-system

  6.  labels:

  7.    k8s-app: kube-dns

  8.    kubernetes.io/cluster-service: "true"

  9.    kubernetes.io/name: "KubeDNS"

  10. spec:

  11.  selector:

  12.    k8s-app: kube-dns

  13.  clusterIP: 10.0.0.10

  14.  ports:

  15.  - name: dns

  16.    port: 53

  17.    protocol: UDP

  18.  - name: dns-tcp

  19.    port: 53

  20.    protocol: TCP

Service 无法访问

访问 Service ClusterIP 失败时,可以首先确认是否有对应的 Endpoints

  
  
    
  1. kubectl get endpoints <service-name>

如果该列表为空,则有可能是该 Service 的 LabelSelector 配置错误,可以用下面的方法确认一下

  
  
    
  1. # 查询 Service 的 LabelSelector

  2. kubectl get svc <service-name> -o jsonpath='{.spec.selector}'


  3. # 查询匹配 LabelSelector 的 Pod

  4. kubectl get pods -l key1=value1,key2=value2

如果 Endpoints 正常,可以进一步检查

  • Pod 的 containerPort 与 Service 的 containerPort 是否对应

  • 直接访问 podIP:containerPort 是否正常 再进一步,即使上述配置都正确无误,还有其他的原因会导致 Service 无法访问,比如

  • Pod 内的容器有可能未正常运行或者没有监听在指定的 containerPort 上

  • CNI 网络或主机路由异常也会导致类似的问题

  • kube-proxy 服务有可能未启动或者未正确配置相应的 iptables 规则,比如正常情况下名为 hostnames的服务会配置以下 iptables 规则

  
  
    
  1. $ iptables-save | grep hostnames

  2. -A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000

  3. -A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376

  4. -A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000

  5. -A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376

  6. -A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000

  7. -A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376

  8. -A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3

  9. -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ

  10. -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3

  11. -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR

Pod 无法通过 Service 访问自己

这通常是 hairpin 配置错误导致的,可以通过 Kubelet 的 --hairpin-mode 选项配置,可选参数包括 "promiscuous-bridge"、"hairpin-veth" 和 "none"(默认为"promiscuous-bridge")。

对于 hairpin-veth 模式,可以通过以下命令来确认是否生效

  
  
    
  1. $ for intf in /sys/devices/virtual/net/cbr0/brif/*; do cat $intf/hairpin_mode; done

  2. 1

  3. 1

  4. 1

  5. 1

而对于 promiscuous-bridge 模式,可以通过以下命令来确认是否生效

  
  
    
  1. $ ifconfig cbr0 |grep PROMISC

  2. UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1460  Metric:1

无法访问 Kubernetes API

很多扩展服务需要访问 Kubernetes API 查询需要的数据(比如 kube-dns、Operator 等)。通常在 Kubernetes API 无法访问时,可以首先通过下面的命令验证 Kubernetes API 是正常的:

  
  
    
  1. $ kubectl run curl  --image=appropriate/curl -i -t  --restart=Never --command -- sh

  2. If you don't see a command prompt, try pressing enter.

  3. / #

  4. / # KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

  5. / # curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/default/pods

  6. {

  7.  "kind": "PodList",

  8.  "apiVersion": "v1",

  9.  "metadata": {

  10.    "selfLink": "/api/v1/namespaces/default/pods",

  11.    "resourceVersion": "2285"

  12.  },

  13.  "items": [

  14.   ...

  15.  ]

  16. }

如果出现超时错误,则需要进一步确认名为 kubernetes 的服务以及 endpoints 列表是正常的:

  
  
    
  1. $ kubectl get service kubernetes

  2. NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE

  3. kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   25m

  4. $ kubectl get endpoints kubernetes

  5. NAME         ENDPOINTS          AGE

  6. kubernetes   172.17.0.62:6443   25m

然后可以直接访问 endpoints 查看 kube-apiserver 是否可以正常访问。无法访问时通常说明 kube-apiserver 未正常启动,或者有防火墙规则阻止了访问。

但如果出现了 403 - Forbidden 错误,则说明 Kubernetes 集群开启了访问授权控制(如 RBAC),此时就需要给 Pod 所用的 ServiceAccount 创建角色和角色绑定授权访问所需要的资源。比如 CoreDNS 就需要创建以下 ServiceAccount 以及角色绑定:

  
  
    
  1. # 1. service account

  2. apiVersion: v1

  3. kind: ServiceAccount

  4. metadata:

  5.  name: coredns

  6.  namespace: kube-system

  7.  labels:

  8.      kubernetes.io/cluster-service: "true"

  9.      addonmanager.kubernetes.io/mode: Reconcile

  10. ---

  11. # 2. cluster role

  12. apiVersion: rbac.authorization.k8s.io/v1

  13. kind: ClusterRole

  14. metadata:

  15.  labels:

  16.    kubernetes.io/bootstrapping: rbac-defaults

  17.    addonmanager.kubernetes.io/mode: Reconcile

  18.  name: system:coredns

  19. rules:

  20. - apiGroups:

  21.  - ""

  22.  resources:

  23.  - endpoints

  24.  - services

  25.  - pods

  26.  - namespaces

  27.  verbs:

  28.  - list

  29.  - watch

  30. ---

  31. # 3. cluster role binding

  32. apiVersion: rbac.authorization.k8s.io/v1

  33. kind: ClusterRoleBinding

  34. metadata:

  35.  annotations:

  36.    rbac.authorization.kubernetes.io/autoupdate: "true"

  37.  labels:

  38.    kubernetes.io/bootstrapping: rbac-defaults

  39.    addonmanager.kubernetes.io/mode: EnsureExists

  40.  name: system:coredns

  41. roleRef:

  42.  apiGroup: rbac.authorization.k8s.io

  43.  kind: ClusterRole

  44.  name: system:coredns

  45. subjects:

  46. - kind: ServiceAccount

  47.  name: coredns

  48.  namespace: kube-system

  49. ---

  50. # 4. use created service account

  51. apiVersion: extensions/v1beta1

  52. kind: Deployment

  53. metadata:

  54.  name: coredns

  55.  namespace: kube-system

  56.  labels:

  57.    k8s-app: coredns

  58.    kubernetes.io/cluster-service: "true"

  59.    addonmanager.kubernetes.io/mode: Reconcile

  60.    kubernetes.io/name: "CoreDNS"

  61. spec:

  62.  replicas: 2

  63.  selector:

  64.    matchLabels:

  65.      k8s-app: coredns

  66.  template:

  67.    metadata:

  68.      labels:

  69.        k8s-app: coredns

  70.    spec:

  71.      serviceAccountName: coredns

  72.      ...

登录查看更多
2

相关内容

域名系统(英文: Domain  Name  System, DNS)是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
[ICML-Google]先宽后窄:对深度薄网络的有效训练
专知会员服务
33+阅读 · 2020年7月5日
专知会员服务
59+阅读 · 2020年3月19日
【2020新书】Kafka实战:Kafka in Action,209页pdf
专知会员服务
65+阅读 · 2020年3月9日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
68+阅读 · 2020年1月17日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
94+阅读 · 2019年12月4日
机器学习相关资源(框架、库、软件)大列表
专知会员服务
38+阅读 · 2019年10月9日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
TensorFlow 2.0如何在Colab中使用TensorBoard
专知
17+阅读 · 2019年3月15日
百度开源项目OpenRASP快速上手指南
黑客技术与网络安全
5+阅读 · 2019年2月12日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
手把手 | 关于商业部署机器学习,这有一篇详尽指南
10个深度学习软件的安装指南(附代码)
数据派THU
17+阅读 · 2017年11月18日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Monocular Plan View Networks for Autonomous Driving
Arxiv
6+阅读 · 2019年5月16日
Deep Reinforcement Learning: An Overview
Arxiv
17+阅读 · 2018年11月26日
Arxiv
11+阅读 · 2018年4月25日
VIP会员
相关资讯
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
TensorFlow 2.0如何在Colab中使用TensorBoard
专知
17+阅读 · 2019年3月15日
百度开源项目OpenRASP快速上手指南
黑客技术与网络安全
5+阅读 · 2019年2月12日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
手把手 | 关于商业部署机器学习,这有一篇详尽指南
10个深度学习软件的安装指南(附代码)
数据派THU
17+阅读 · 2017年11月18日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Top
微信扫码咨询专知VIP会员