未在calico中创建hostendpoint,导致开启隔离后,在kubernetes的node上无法访问pod

目录

现象描述

kubernetes集群的网络组件是calico,在kubernetes中设置网络隔离后,在node上无法访问pod。

更改一下calico的kube-policy-controller

kubernetes中的networkpolicy没有考虑到node,虽然在1.8.x版本中支持IP,但还是很麻烦。

因此,修改了calico的kube-policy-controller中的代码,在calico管理的每个policy中增加了一条规则。

这里使用的calico: kube-controllers的v0.7.0版本,在handlers/network_policy.py中增加两行:

 50         extra_rule=Rule(action="allow", src_selector="calico/k8s_ns in { \"kube-system\" }")
 51         inbound_rules.append(extra_rule)

这两行代码将会在calico的所有policy增加一条规则:

 - action: allow
   destination: {}
   source:
     selector: calico/k8s_ns in { "kube-system" }

未开启ipip模式的时候

calico中的endpoint,分为workloadendpointhostendpoint

workloadendpoint对应在k8s中对应的就是分配给pod的接口,hostendpoint对应的是node的接口。

如果想在node上直接访问pod,需要为node创建带有合适标签的hostendpoint。

例如在集群中创建的一个policy如下:

$ calicoctl get policy lijiaocn-space.isolation-access-rules -o yaml
- apiVersion: v1
  kind: policy
  metadata:
    name: lijiaocn-space.isolation-access-rules
  spec:
    egress:
    - action: allow
      destination: {}
      source: {}
    ingress:
    - action: allow
      destination: {}
      source:
        selector: calico/k8s_ns in { "kube-system", "lijiaocn-space" }
    order: 1000
    selector: calico/k8s_ns == 'lijiaocn-space'

这个policy允许带有calico/k8s_ns=kube-system或者calico/k8s_ns=lijiaocn-space标签的endpoint访问。

为ip地址为10.39.0.113的node创建的hostendpoint如下:

$ calico get hostendpoint --node=10.39.0.113 -o yaml
- apiVersion: v1
  kind: hostEndpoint
  metadata:
    labels:
      calico/k8s_ns: kube-system
    name: eth0
    node: 10.39.0.113
  spec:
    expectedIPs:
    - 10.39.0.113
    interfaceName: eth0
    profiles:
    - k8s_ns.kube-system

node的ip地址是10.39.0.113,带有标签calico/k8s_ns: kube-system,符合policy的要求。

如果没有使用ipip,这时候在node10.39.0.113上就可以访问了pod。

如果开启了ipip模式

如果开启了ipip模式:

$ calicoctl get ippool -o yaml
- apiVersion: v1
  kind: ipPool
  metadata:
    cidr: 192.168.0.0/16
  spec:
    ipip:
      enabled: true
    nat-outgoing: true

还需要为每个node再次添加一个hostendpoint的。

这是因为开启ipip模式后,node访问pod的报文是封装在ipip隧道中传送的,这时候node使用的源ip是ip tunnl的ip:

$ ip addr |grep tun
84: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN qlen 1
    inet 192.168.139.230/32 scope global tunl0

因此还需要为tunl0创建一个对应的hostendpoint:

$ calicoctl get hostendpoint tunl0 --node=10.39.0.113  -o yaml
- apiVersion: v1
  kind: hostEndpoint
  metadata:
    labels:
      calico/k8s_ns: kube-system
    name: tunl0
    node: 10.39.0.113
  spec:
    expectedIPs:
    - 192.168.139.230
    interfaceName: tunl0
    profiles:
    - k8s_ns.kube-system

这时候又可以访问pod了。

提供几个脚本

提供几个用于方便操作的脚本。

脚本1,为kubernetes的所有的node创建hostendpoint:

#!/bin/bash
for i in `kubectl get node  -o go-template="{{ range .items }} {{ index .status.addresses 1 \"address\" }} {{end}}"`
do
    echo $i
cat >/tmp/hostendpoint.yaml <<EOF
apiVersion: v1
kind: hostEndpoint
metadata:
  name: eth0
  node: $i
  labels:
    calico/k8s_ns: kube-system
spec:
  interfaceName: eth0
  expectedIPs:
  - $i
  profiles:
  - k8s_ns.kube-system
EOF
calicoctl create -f /tmp/hostendpoint.yaml
done

这个脚本在master上执行,可以一次性为所有的node的创建hostendpoint。

脚本2,生成每个node上的tunl0对应的hostendpoint:

#!/bin/bash
IP=`ip addr |grep tunl0 |grep inet|awk '{print $2}'|sed -e 's@/32@@'`
NAME=`ip addr |grep eth0  |grep inet|awk '{print $2}'|sed -e 's@/24@@'`

cat >./hostendpoint-tunl0.yaml <<EOF
apiVersion: v1
kind: hostEndpoint
metadata:
  name: tunl0
  node: $NAME
  labels:
    calico/k8s_ns: kube-system
spec:
  interfaceName: tunl0
  expectedIPs:
  - $IP
  profiles:
  - k8s_ns.kube-system
EOF

这个脚本在每个node上执行,生成这个node上的tunl0对应的hostendpoint文件。 之后还需要手动的创建:

$ calicoctl create -f hostendpoint-tunl0.yaml

脚本3,也可以将以上过程在一个脚本中完成: create_hostendpoint_for_all_node.sh

参考

  1. calico hostendpoint
  2. calico workloadendpoint
  3. calico: kube-controllers
  4. create_hostendpoint_for_all_node.sh

kubernetes_problem

  1. kubernetes ingress-nginx 启用 upstream 长连接,需要注意,否则容易 502
  2. kubernetes ingress-nginx 的 canary 影响指向同一个 service 的所有 ingress
  3. ingress-nginx 启用 tls 加密,配置了不存在的证书,导致 unable to get local issuer certificate
  4. https 协议访问,误用 http 端口,CONNECT_CR_SRVR_HELLO: wrong version number
  5. Kubernetes ingress-nginx 4 层 tcp 代理,无限重试不存在的地址,高达百万次
  6. Kubernetes 集群中个别 Pod 的 CPU 使用率异常高的问题调查
  7. Kubernetes 集群 Node 间歇性变为 NotReady 状态: IO 负载高,延迟严重
  8. Kubernetes的nginx-ingress-controller刷新nginx的配置滞后十分钟导致504
  9. Kubernetes的Nginx Ingress 0.20之前的版本,upstream的keep-alive不生效
  10. Kubernetes node 的 xfs文件系统损坏,kubelet主动退出且重启失败,恢复后无法创建pod
  11. Kubernetes的Pod无法删除,glusterfs导致docker无响应,集群雪崩
  12. Kubernetes集群node无法访问service: kube-proxy没有正确设置cluster-cidr
  13. Kubernetes集群node上的容器无法ping通外网: iptables snat规则缺失导致
  14. Kubernetes问题调查: failed to get cgroup stats for /systemd/system.slice
  15. Kubelet1.7.16使用kubeconfig时,没有设置--require-kubeconfig,导致node不能注册
  16. Kubelet从1.7.16升级到1.9.11,Sandbox以外的容器都被重建的问题调查
  17. Kubernetes: 内核参数rp_filter设置为Strict RPF,导致Service不通
  18. Kubernetes使用过程中遇到的一些问题与解决方法
  19. Kubernetes集群节点被入侵挖矿,CPU被占满
  20. kubernetes的node上的重启linux网络服务后,pod无法联通
  21. kubernetes的pod因为同名Sandbox的存在,一直无法删除
  22. kubelet升级,导致calico中存在多余的workloadendpoint,node上存在多余的veth设备
  23. 使用petset创建的etcd集群在kubernetes中运行失败
  24. Kubernetes 容器启动失败: unable to create nf_conn slab cache
  25. 未在calico中创建hostendpoint,导致开启隔离后,在kubernetes的node上无法访问pod
  26. calico分配的ip冲突,pod内部arp记录丢失,pod无法访问外部服务
  27. kubernetes的dnsmasq缓存查询结果,导致pod偶尔无法访问域名
  28. k8s: rbd image is locked by other nodes
  29. kuberntes的node无法通过物理机网卡访问Service

calico

  1. Calico的hostendpoint的IP地址为空,导致felix退出
  2. calico-cni使pod的删除反复重试,statefulset创建的pod被调度到以往的node上后,静态arp丢失,无法联通
  3. calico的ipam的数据混乱,重建ipam记录
  4. calico node重启时路由同步信息延迟高达4分钟
  5. 未在calico中创建hostendpoint,导致开启隔离后,在kubernetes的node上无法访问pod
  6. kubernetes 跨网段通信: 通过 calico 的 ipip 模式
  7. calico的felix组件的工作过程
  8. kubernetes 与 calico 的衔接过程
  9. 怎样排查calico的网络故障?
  10. calico路由丢失问题的调查
  11. calico分配的ip冲突,pod内部arp记录丢失,pod无法访问外部服务
  12. calico的架构设计与组件交互过程
  13. Calico网络的原理、组网方式与使用

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  系统软件  程序语言  运营经验  水库文集  网络课程  微信网文  发现知识星球