

Calico 3.6 转发外部流量到集群 Pod
source link: https://mritd.com/2019/06/18/calico-3.6-forward-network-traffic/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

由于开发有部份服务使用 GRPC 进行通讯,同时采用 Consul 进行服务发现;在微服务架构下可能会导致一些访问问题,目前解决方案就是打通开发环境网络与测试环境 Kubernetes 内部 Pod 网络;翻了好多资料发现都是 2.x 的,而目前测试集群 Calico 版本为 3.6.3,很多文档都不适用只能自己折腾,目前折腾完了这里记录一下
本文默认为读者已经存在一个运行正常的 Kubernetes 集群,并且采用 Calico 作为 CNI 组件,且 Calico 工作正常;同时应当在某个节点完成了 calicoctl 命令行工具的配置
一、问题描述
在微服务架构下,由于服务组件很多,开发在本地机器想测试应用需要启动整套服务,这对开发机器的性能确实是个考验;但如果直接连接测试环境的服务,由于服务发现问题最终得到的具体服务 IP 是 Kubernetes Pod IP,此 IP 由集群内部 Calico 维护与分配,外部不可访问;最终目标为打通开发环境与集群内部网络,实现开发网络下直连 Pod IP,这或许在以后对生产服务暴露负载均衡有一定帮助意义;目前网络环境如下:
开发网段: 10.10.0.0/24
测试网段: 172.16.0.0/24
Kubernetes Pod 网段: 10.20.0.0/16
二、打通网络
首先面临的第一个问题是 Calico 处理,因为如果想要让数据包能从开发网络到达 Pod 网络,那么必然需要测试环境宿主机上的 Calico Node 帮忙转发;因为 Pod 网络由 Calico 维护,只要 Calico Node 帮忙转发那么数据一定可以到达 Pod IP 上;
一开始我很天真的认为这就是个 ip route add 10.20.0.0/16 via 172.16.0.13
的问题… 后来发现
经过翻文档、issue、blog 等最终发现需要进行以下步骤
2.1、关闭全互联模式
注意: 关闭全互联时可能导致网络暂时中断,请在夜深人静时操作
首先执行以下命令查看是否存在默认的 BGP 配置
calicoctl get bgpconfig default
如果存在则将其保存为配置文件
calicoctl get bgpconfig default -o yaml > bgp.yaml
修改其中的 spec.nodeToNodeMeshEnabled
为 false
,然后进行替换
calicoctl apply -f bgp.yaml
如果不存在则手动创建一个配置,然后应用
cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 63400
EOF
本部分参考:
2.2、开启集群内 RR 模式
在 Calico 3.3 后支持了集群内节点的 RR 模式,即将某个集群内的 Calico Node 转变为 RR 节点;将某个节点设置为 RR 节点只需要增加 routeReflectorClusterID
既可,为了后面方便配置同时增加了一个 lable 字段 route-reflector: "true"
calicoctl get node CALICO_NODE_NAME -o yaml > node.yaml
然后增加 routeReflectorClusterID
字段,样例如下
apiVersion: projectcalico.org/v3
kind: Node
metadata:
annotations:
projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/hostname":"d13.node","node-role.kubernetes.io/k8s-master":"true"}'
creationTimestamp: 2019-06-17T13:55:44Z
labels:
beta.kubernetes.io/arch: amd64
beta.kubernetes.io/os: linux
kubernetes.io/hostname: d13.node
node-role.kubernetes.io/k8s-master: "true"
route-reflector: "true" # 增加 lable
name: d13.node
resourceVersion: "61822269"
uid: 9a1897e0-9107-11e9-bc1c-90b11c53d1e3
spec:
bgp:
ipv4Address: 172.16.0.13/19
ipv4IPIPTunnelAddr: 10.20.73.82
routeReflectorClusterID: 172.16.20.1 # 添加集群 ID
orchRefs:
- nodeName: d13.node
orchestrator: k8s
事实上我们应当导出多个 Calico Node 的配置,并将其配置为 RR 节点以进行冗余;对于 routeReflectorClusterID
目前测试只是作为一个 ID(至少在本文是这样的),所以理论上可以是任何 IP,个人猜测最好在同一集群网络下采用相同的 IP,由于这是真正的测试环境我没有对 ID 做过多的测试(怕玩挂)
修改完成后只需要应用一下就行
calicoctl apply -f node.yaml
接下来需要创建对等规则,规则文件如下
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
name: peer-to-rrs
spec:
nodeSelector: "!has(route-reflector)"
peerSelector: has(route-reflector)
---
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
name: rr-mesh
spec:
nodeSelector: has(route-reflector)
peerSelector: has(route-reflector)
假定规则文件名称为 rr.yaml
,则创建命令为 calicoctl create -f rr.yaml
;此时在 RR 节点上使用 calicoctl node status
应该能看到类似如下输出
Calico process is running.
IPv4 BGP status
+--------------+---------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+--------------+---------------+-------+----------+-------------+
| 172.16.0.19 | node specific | up | 05:43:51 | Established |
| 172.16.0.16 | node specific | up | 05:43:51 | Established |
| 172.16.0.17 | node specific | up | 05:43:51 | Established |
| 172.16.0.13 | node specific | up | 13:01:17 | Established |
+--------------+---------------+-------+----------+-------------+
IPv6 BGP status
No IPv6 peers found.
PEER ADDRESS
应当包含所有非 RR 节点 IP(由于真实测试环境,以上输出已人为修改)
同时在非 RR 节点上使用 calicoctl node status
应该能看到以下输出
Calico process is running.
IPv4 BGP status
+--------------+---------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+--------------+---------------+-------+----------+-------------+
| 172.16.0.10 | node specific | up | 05:43:51 | Established |
| 172.16.0.13 | node specific | up | 13:01:20 | Established |
+--------------+---------------+-------+----------+-------------+
IPv6 BGP status
No IPv6 peers found.
PEER ADDRESS
应当包含所有 RR 节点 IP,此时原本的 Pod 网络连接应当已经恢复
本部分参考:
2.3、调整 IPIP 规则
先说一下 Calico IPIP 模式的三个可选项:
Always
: 永远进行 IPIP 封装(默认)CrossSubnet
: 只在跨网段时才进行 IPIP 封装,适合有 Kubernetes 节点在其他网段的情况,属于中肯友好方案Never
: 从不进行 IPIP 封装,适合确认所有 Kubernetes 节点都在同一个网段下的情况
在默认情况下,默认的 ipPool 启用了 IPIP 封装(至少通过官方安装文档安装的 Calico 是这样),并且封装模式为 Always
;这也就意味着任何时候都会在原报文上封装新 IP 地址,在这种情况下将外部流量路由到 RR 节点,RR 节点再转发进行 IPIP 封装时,可能出现网络无法联通的情况(没仔细追查,网络渣,猜测是 Pod 那边得到的源 IP 不对导致的);此时我们应当调整 IPIP 封装策略为 CrossSubnet
导出 ipPool 配置
calicoctl get ippool default-ipv4-ippool -o yaml > ippool.yaml
修改 ipipMode
值为 CrossSubnet
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
creationTimestamp: 2019-06-17T13:55:44Z
name: default-ipv4-ippool
resourceVersion: "61858741"
uid: 99a82055-9107-11e9-815b-b82a72dffa9f
spec:
blockSize: 26
cidr: 10.20.0.0/16
ipipMode: CrossSubnet
natOutgoing: true
nodeSelector: all()
重新使用 calicoctl apply -f ippool.yaml
应用既可
本部分参考:
2.4、增加路由联通网络
万事俱备只欠东风,最后只需要在开发机器添加路由既可
将 Pod IP 10.20.0.0/16
和 Service IP 10.254.0.0/16
路由到 RR 节点 172.16.0.13
# Pod IP
ip route add 10.20.0.0/16 via 172.16.0.13
# Service IP
ip route add 10.254.0.0/16 via 172.16.0.13
当然最方便的肯定是将这一步在开发网络的路由上做,设置完成后开发网络就可以直连集群内的 Pod IP 和 Service IP 了;至于想直接访问 Service Name 只需要调整上游 DNS 解析既可
Recommend
-
14
为了部署有状态服务,需要给k8s提供一套可持久化存储的方案,我们使用ceph来做底层存储。一般k8s对接ceph有两种:- 通过rook部署和对接ceph,使用k8s提供ceph服务。rook官方文档非常详细,里面也有常见问题的fix版本,本人一路用下来非常顺利,这里不再赘述。文档...
-
8
漏洞概述 漏洞CVE-2020-8554是一个能够影响多用户Kubernetes群集的漏洞,如果潜在的攻击者可以创建或编辑服务和Pod,那么他们就可以拦...
-
13
Prometheus 监控外部 Kubernetes 集群 发表于 June 29, 2020 ...
-
14
kube-prometheus监控集群外部主机 发表于 2021-05-27...
-
6
k8s集群service外部流量策略如何优雅的处理Pod终止过程中的流量丢失问题? 面试官:"k8s集群service外部流量策略如何优雅的处理Pod终止过程中的流量丢失问题?" ...
-
11
Weave/Flannel/Calico 的转发流程 09 Apr 2022 这篇文章主要讨论 weave 和 flannel 各自怎么使用 vxlan 实现跨主机网络的情况。从网络设备、主机路由、IP管理、CNI实现、容器路由、vxlan发现几个角度来比较...
-
6
记录一次KubeSphere集群Calico组件报错 精选 原创 云烟旧梦 2022-08-31 09:13:08
-
6
如何暴露Pod中的服务到Kubernetes集群外? 作者:徐福工程师 2022-09-22 12:11:38 在Pod的yaml定义文件中配置该选项后,Pod就使用宿主机的网络栈,这样和直接访问运行在宿主机上的服务没有什么区别。
-
3
V2EX › Kubernetes 如何从 redis 等外部系统里看到 k8s pod ip
-
10
wsl 中 docker-compose 搭建 kafka 集群出现的外部访问错误 在 wsl 中用 docker-compose 搭建了一台 zookeeper + 三台 broker 的 kafk...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK