Calico 是一套开源的网络和网络安全解决方案,也是作为 Kubernetes 容器网络解决方案 (CNI: Container Network Interface) 的一种实现。
当前痛点
在多个集群互相访问,企业管理员希望规范化跨集群网络请求。如下图集群 B 中的 Pod 为一组应用,管理员希望右侧同一业务组的 Pod 出集群的流量都使用特定 IP。
EgressGateway 解决方式
👋 针对上述的需求,我们使用 https://github.com/spidernet-io/egressgateway 来解决这个问题。EgressGateway 是一个开源的云原生出口网关,兼容如下 Calico,Flannel,Weave 和 Spiderpool 的 CNI 网络方案。EgressGateway 有如下特性:
- 支持通过
EgressPolicy
配置不通租户的的 Egress 策略 - 支持通过
EgressClusterPolicy
集群级 Egress 策略; - 支持 IPv4/IPv6 双栈;
- 拥有低内核兼容性;
- 自动检测集群内部流量;
- 支持设置租户/集群默认 EgressGateway。
如果你想了解更多详情,请访问 EgressGateway https://spidernet-io.github.io/egressgateway/dev/ 文档站。
实现原理
在数据面,我们通过实施了如下 datapath 来实现 EgressGateway 的功能。左侧节点被 EgressPolicy 策略命中的 Pod 流量,会通过 iptabels, route, ipset 规则并通过 vxlan 转发到网关节点,然后从网关节点将源 IP 转为 Egress IP 离开集群。
安装实施
- 将 Calico 的的
FELIX_CHAININSERTMODE
设置为Append
。
kubectl set env daemonset -n kube-system calico-node FELIX_CHAININSERTMODE=Append
- 安装 EgressGateway。
helm repo add egressgateway https://spidernet-io.github.io/egressgateway/
helm repo update
helm install egressgateway egressgateway/egressgateway \
-n kube-system \
--set feature.tunnelIpv4Subnet="192.200.0.1/16" \ # 选择一个没有被使用的虚拟子网
--wait --debug
- 验证 EgressGateway 都已经启动并就绪。
$ kubectl get pod -n kube-system | grep egressgateway
egressgateway-agent-29lt5 1/1 Running 0 9h
egressgateway-agent-94n8k 1/1 Running 0 9h
egressgateway-agent-klkhf 1/1 Running 0 9h
egressgateway-controller-5754f6658-7pn4z 1/1 Running 0 9h
- 选择一个或者多个节点作为出口网关。我们通过给 node 打上特点的 label 来标识这些节点。
kubectl get node -o wide
kubectl label node $NODE_NAME egressgateway="true"
- 创建 EgressGateway 实例。在创建 EgressGateway 时,我们在
spec.nodeSelector
中将指定网关节点为上面打 label 的节点,并为这些网关分配了可用的spec.ippools
的地址。
cat <<EOF | kubectl apply -f -
apiVersion: egressgateway.spidernet.io/v1beta1
kind: EgressGateway
metadata:
name: default
spec:
ippools:
ipv4:
- "172.22.0.100-172.22.0.110"
nodeSelector:
selector:
matchLabels:
egressgateway: "true"
EOF
- 执行下面命令检查刚才创建的网关,我们可以在
status
中看到已经选择的 2 个节点已经就绪。稍后我们可以通过创建EgressPolicy
CR 来选择可使用的 EgressGateway,并通过 label 匹配业务 Pod,使业务流量通过网关节点离开集群。
$ kubectl get EgressGateway default -o yaml
apiVersion: egressgateway.spidernet.io/v1beta1
kind: EgressGateway
metadata:
name: default
uid: 7ce835e2-2075-4d26-ba63-eacd841aadfe
spec:
ippools:
ipv4:
- 172.22.0.100-172.22.0.110
ipv4DefaultEIP: 172.22.0.110
nodeSelector:
selector:
matchLabels:
egressgateway: "true"
status:
nodeList:
- name: egressgateway-worker1
status: Ready
- name: egressgateway-worker2
status: Ready
- 在开始之前我们先在集群外的任意机器,启动一个容器模拟被访问的外部服务。
docker run -d --net=host ghcr.io/spidernet-io/egressgateway-nettools:latest /usr/bin/nettools-server -protocol web -webPort 8080
- 我们在集群内部创建一个 Deployment,用于模拟需要访问外部使用统一 Egress IP 的业务应用。
kubectl create deployment visitor --image nginx
- 此时我们创建一个 EgressPolicy,来为其实施 Egress 策略。我们通过
spec.egressGatewayName
制定了上面创建的 EgressGateway 名称。
cat <<EOF | kubectl apply -f -
apiVersion: egressgateway.spidernet.io/v1beta1
kind: EgressPolicy
metadata:
name: test
namespace: default
spec:
egressGatewayName: default
appliedTo:
podSelector:
matchLabels:
app: "visitor"
EOF
-
通过 kubectl exec 进我们创建的业务应用,执行测试。
kubectl exec -it visitor-6764bb48cc-29vq9 bash $ curl 10.6.1.92:8080 Remote IP: 172.22.0.110
🎉 通过结果看到,我们的 Egress IP 已经变为了 EgressGateway 池中配置的 IP。当然也可以在创建 EgressPolicy 指定使用的 Egress IP。
总结
在本文中我们分析了 Calico 网络下的 Egress IP 网络需求,并通过 EgressGateway 来解决这个问题,同时对 EgressGateway 的网络原理做了阐述,最后我们介绍了 EgressGateway 的更多功能。
Top comments (0)