跳转至

在 AWS Cilium CNI 下使用 EgressGateway

介绍

本文介绍了在 AWS Kubernetes 的 Cilium CNI 网络环境下,运行 EgressGateway。EgressGateway 支持多个 Node 作为 Pod 的高可用(HA)出口网关,你可以通过 EgressGateway 来节省公网 IP 费用,同时实现对需要访问外部网络的 Pod 进行精细化控制。

EgressGateway 相对于 Cilium 的 Egress 功能,支持 HA 高可用。如果你没有此需要,应当先考虑使用 Cilium 的 Egress 功能。

接下来的章节将逐步引导您安装 EgressGateway,创建一个示例 Pod,并为该 Pod 配置 Egress 策略,使其通过出口网关节点访问互联网。

创建集群及安装 Cilium

参考 Cilium 安装指南 文档创建 AWS 集群,并安装 Cilium。 编写本文时,使用的 Cilium 版本为 1.15.6,如果您在其他版本出现非预期情况,请和我们反馈。

你创建的 Kubernetes 集群时,加入的 EC2 节点要具备公网 IP。你可以 ssh root@host 到您的节点进行测试。

curl ipinfo.io

通过 curl 您可以看到返回结果包含你 Node 的公网 IP。

安装 EgressGateway

添加和更新 Helm 仓库以从指定来源安装 EgressGateway。

helm repo add egressgateway https://spidernet-io.github.io/egressgateway/
helm repo update

我们 feature.enableIPv4=true 启用 IPv4 ,通过 feature.enableIPv6=false 禁用 IPv6。在安装过程中,我们可以通过 feature.clusterCIDR.extraCidr 集群的内部 CIDR,这将修改 EgressPolicy 的行为。如果您创建一个 EgressPolicy CR 并且没有指定 spec.destSubnet,EgressGateway 将把 Pod 的所有访问外部的流量(内部 CIDR 除外)转发到网关节点。相反,如果指定了 spec.destSubnet,EgressGateway 将仅将指定的流量转发到网关节点。

helm install egress --wait \
 --debug egressgateway/egressgateway \
 --set feature.enableIPv4=true \
 --set feature.enableIPv6=false \
 --set feature.clusterCIDR.extraCidr[0]=172.16.0.0/16

创建 EgressGateway CR

查看当前节点。

~ kubectl get nodes -A -owide
NAME                             STATUS   ROLES    AGE   VERSION               INTERNAL-IP      EXTERNAL-IP                         
ip-172-16-103-117.ec2.internal   Ready    <none>   25m   v1.30.0-eks-036c24b   172.16.103.117   34.239.162.85  
ip-172-16-61-234.ec2.internal    Ready    <none>   25m   v1.30.0-eks-036c24b   172.16.61.234    54.147.15.230
ip-172-16-62-200.ec2.internal    Ready    <none>   25m   v1.30.0-eks-036c24b   172.16.62.200    54.147.16.130  

我们选择 ip-172-16-103-117.ec2.internalip-172-16-62-200.ec2.internal 作为网关节点。给节点设置 egress=true 标签。

kubectl label node ip-172-16-103-117.ec2.internal role=gateway
kubectl label node ip-172-16-62-200.ec2.internal role=gateway

创建 EgressGateway CR,我们通过 role: gateway 来选择节点作为出口网关。

apiVersion: egressgateway.spidernet.io/v1beta1
kind: EgressGateway
metadata:
  name: "egressgateway"
spec:
  nodeSelector:
    selector:
      matchLabels:
        role: gateway

创建测试 Pod

查看当前节点。

~ kubectl get nodes -A -owide
NAME                             STATUS   ROLES    AGE   VERSION               INTERNAL-IP      EXTERNAL-IP                         
ip-172-16-103-117.ec2.internal   Ready    <none>   25m   v1.30.0-eks-036c24b   172.16.103.117   34.239.162.85  
ip-172-16-61-234.ec2.internal    Ready    <none>   25m   v1.30.0-eks-036c24b   172.16.61.234    54.147.15.230
ip-172-16-62-200.ec2.internal    Ready    <none>   25m   v1.30.0-eks-036c24b   172.16.62.200    54.147.16.130  

我们选择 ip-172-16-61-234.ec2.internal 节点运行 Pod。

apiVersion: v1
kind: Pod
metadata:
  name: mock-app
  labels:
    app: mock-app
spec:
  nodeName: ip-172-16-61-234.ec2.internal
  containers:
  - name: nginx
    image: nginx

查看确保 Pods 处于 Running 状态。

~ kubectl get pods -o wide
NAME                                        READY   STATUS    RESTARTS   AGE   IP               NODE                             NOMINATED NODE   READINESS GATES
egressgateway-agent-zw426                   1/1     Running   0          15m   172.16.103.117   ip-172-16-103-117.ec2.internal   <none>           <none>
egressgateway-agent-zw728                   1/1     Running   0          15m   172.16.61.234    ip-172-16-61-234.ec2.internal    <none>           <none>
egressgateway-controller-6cc84c6985-9gbgd   1/1     Running   0          15m   172.16.51.178    ip-172-16-61-234.ec2.internal    <none>           <none>
mock-app                                    1/1     Running   0          12m   172.16.51.74     ip-172-16-61-234.ec2.internal    <none>           <none>

创建 EgressPolicy CR

我们创建下面 YAML,EgressGateway CR,我们使用 spec.podSelector 来匹配上面创建的 Pod。spec.egressGatewayName 则制定了了我们上面创建的网关。 使用 spec.egressIP.useNodeIP 来指定使用节点的 IP 作为访问互联网的地址。

apiVersion: egressgateway.spidernet.io/v1beta1
kind: EgressPolicy
metadata:
  name: test-egw-policy
  namespace: default
spec:
  egressIP:
    useNodeIP: true
  appliedTo:
    podSelector:
      matchLabels:
        app: mock-app
  egressGatewayName: egressgateway

测试出口 IP 地址

使用 exec 进入容器,运行 curl ipinfo.io,你可以看到当前节点的 Pod 已经使用网关节点访问互联网,ipinfo.io 会回显主机 IP。 由于 EgressGateway 使用主备实现 HA,当 EIP 节点发生切换时,Pod 会自动切换到匹配的备用节点,同时出口 IP 也会发生变化。

kubectl exec -it -n default mock-app bash
curl ipinfo.io
{
  "ip": "34.239.162.85",
  "hostname": "ec2-34-239-162-85.compute-1.amazonaws.com",
  "city": "Ashburn",
  "region": "Virginia",
  "country": "US",
  "loc": "39.0437,-77.4875",
  "org": "AS14618 Amazon.com, Inc.",
  "postal": "20147",
  "timezone": "America/New_York",
  "readme": "https://ipinfo.io/missingauth"
}