跳转至

自建集群安装 EgressGateway

介绍

本文将演示在一个自建集群上快速安装 EgressGateway

要求

  1. 已经具备一个自建好的 Kubernetes 集群,至少有 2 个节点。当前,EgressGateway 支持的 CNI 只包含 Calico

  2. 集群准备好 helm 工具

安装准备

  • 对于 CNI 是 calico 的集群,请执行如下命令,该命令确保 EgressGateway 的 iptables 规则不会被 Calico 规则覆盖,否则 EgressGateway 将不能工作。
# set chainInsertMode
$ kubectl patch FelixConfiguration default --patch '{"spec": {"chainInsertMode": "Append"}}'

# check status
$ kubectl get FelixConfiguration default -o yaml
    apiVersion: crd.projectcalico.org/v1
    kind: FelixConfiguration
    metadata:
      generation: 2
      name: default
      resourceVersion: "873"
      uid: 0548a2a5-f771-455b-86f7-27e07fb8223d
    spec:
      chainInsertMode: Append
      ......

spec.chainInsertMode 的意义可参考 calico 文档

安装 EgressGateway

添加 EgressGateway 仓库

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

安装 EgressGateway

  1. 可使用如下命令快速安装 EgressGateway

    helm install egressgateway egressgateway/egressgateway -n kube-system \
        --set feature.tunnelIpv4Subnet="192.200.0.1/16"
    

    在安装命令中,有如下注意点:

    • 安装命令中,需要提供用于 EgressGateway 隧道节点的 IPv4 和 IPv6 网段,要求该网段和集群内的其他地址不冲突

    • 可使用选项 --set feature.tunnelDetectMethod="interface=eth0" 来定制 EgressGateway 隧道的承载网卡,否则,默认使用默认路由的网卡

    • 如果希望使用 IPv6 ,可使用选项 --set feature.enableIPv6=true 开启,并设置 feature.tunnelIpv6Subnet

    • EgressGateway Controller 支持高可用,可通过 --set controller.replicas=2 设置

  2. 确认所有的 EgressGateway Pod 运行正常。

    $ 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
    

  3. 任何功能配置,可通过调整 EgressGateway 实例租户下的 ConfigMap EgressGateway 来实现。

创建 EgressGateway 实例

  1. EgressGateway 定义了一组节点作为集群的出口网关,集群内的 egress 流量将会通过这组节点转发而出集群。 因此,我们需要预先定义一组 EgressGateway,例子如下

    cat <<EOF | kubectl apply -f -
    apiVersion: egressgateway.spidernet.io/v1beta1
    kind: EgressGateway
    metadata:
      name: default
    spec:
      ippools:
        ipv4:
        - "10.6.1.60-10.6.1.66"
      nodeSelector:
        selector:
          matchLabels:
            egressgateway: "true"
    EOF
    

    创建命令中:

    • 如上 yaml 例子中,spec.ippools.ipv4 定义了一组 egress 的 出口 VIP 地址,需要根据具体环境的实际情况调整, 其中,spec.ippools.ipv4 的 CIDR 应该是与网关节点上的出口网卡(一般情况下是默认路由的网卡)的子网相同,否则,极有可能导致 egress 访问不通。
    • 通过 EgressGateway 的 spec.nodeSelector 来 select 一组节点作为出口网关,它支持 select 多个节点来实现高可用。
  2. 给出口网关节点打上 label,可以给多个 node 打上 label,作为生成环境,建议 2 个节点,作为 POC 环境, 建议 1 个节点即可

    kubectl label node $NodeName egressgateway="true"
    
  3. 查看状态如下

    $ kubectl get EgressGateway default -o yaml
        apiVersion: egressgateway.spidernet.io/v1beta1
        kind: EgressGateway
        metadata:
          name: default
          uid: 7ce835e2-2075-4d26-ba63-eacd841aadfe
        spec:
          clusterDefault: true
          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
    

    在如上输出中: * status.nodeList 字段已经识别到了符合 spec.nodeSelector 的节点及该节点对应的 EgressTunnel 对象的状态 * spec.ippools.ipv4DefaultEIP 字段会从 `spec.ippools.ipv4`` 中随机选择一个 IP 地址作为该组 EgressGateway 的默认 VIP,它的作用是:当为应用创建 EgressPolicy 对象时,如果未指定 VIP 地址,则默认分配使用该默认 VIP

创建应用和出口策略

  1. 创建一个应用,它将用于测试 POD 访问集群外部用途,并给它打上 label。
kubectl create deployment visitor --image nginx
  1. 为应用创建 EgressPolicy CR 对象。 EgressPolicy 实例用于定义哪些 POD 的出口流量要经过 egressGateway node 转发,以及其它的配置细节。 可创建如下例子,当匹配的 pod 访问任意集群外部的地址(任意不是 Node IP、CNI Pod CIDR、ClusterIP 的地址)时,都会被 EgressGateway Node 转发。注意的是, EgressPolicy 对象是租户级别的,因此,它务必创建在 selected 应用的租户下

    cat <<EOF | kubectl apply -f -
    apiVersion: egressgateway.spidernet.io/v1beta1
    kind: EgressPolicy
    metadata:
      name: test
      namespace: default
    spec:
      appliedTo:
        podSelector:
          matchLabels:
            app: "visitor"
    EOF
    

    如上创建命令中:

    • spec.egressGatewayName 指定了使用哪一组 EgressGateway 的名字。
    • spec.appliedTo.podSelector 指定了本策略生效在集群内的哪些 Pod。
    • 集群的 egress 流量的源 IP 地址有两种选择:
      • 可使用网关节点的 IP。它可适用于公有云和传统网络等环境,缺点是,随着网关节点的故障,出口源 IP 可能会发生变化。可设置 spec.egressIP.useNodeIP=true 来生效。
      • 可使用独立的 VIP,因为 EgressGateway 是基于 ARP 原理生效 VIP,所以它适用于传统网络,而不适用于公有云等环境,它的优点是,出口源 IP 永久是固定的。在 EgressPolicy 中不做任何设置,则默认使用 egressGatewayName 的缺省 VIP,或者可单独手动指定 spec.egressIP.ipv4 ,其 IP 值务必是符合 EgressGateway 中的 IP 池。
  2. 查看 EgressPolicy 的状态

    $ kubectl get EgressPolicy -A
    NAMESPACE   NAME   GATEWAY   IPV4           IPV6   EGRESSTUNNEL
    default     test   default   172.22.0.110          egressgateway-worker2
    
    $ kubectl get EgressPolicy test -o yaml
    apiVersion: egressgateway.spidernet.io/v1beta1
    kind: EgressPolicy
    metadata:
      name: test
      namespace: default
    spec:
      appliedTo:
        podSelector:
          matchLabels:
            app: visitor
      egressIP:
        allocatorPolicy: default
        useNodeIP: false
    status:
      eip:
        ipv4: 172.22.0.110
      node: egressgateway-worker2
    

    如上输出中:

    • status.eip 展示了该组应用出集群时使用的出口 IP 地址

    • status.node 展示了哪一个 EgressGateway 的节点在实时的负责出口流量的转发。注:EgressGateway 节点支持高可用,当存在多个 EgressGateway 节点时,所有的 EgressPolicy 会均摊到不同的 EgressGateway 节点上实施。

  3. 查看 EgressEndpointSlices 的状态

    每个 EgressPolicy 对象,都有一个对应的 EgressEndpointSlices 对象,其中存储了 EgressPolicy select 的 Pod 的 IP 地址集合。当应用无法出口访问时,可排查该对象中的 IP 地址是否正常。

    $ kubectl get egressendpointslices -A
      NAMESPACE   NAME         AGE
      default     test-kvlp6   18s
    
    $ kubectl get egressendpointslices test-kvlp6 -o yaml
    apiVersion: egressgateway.spidernet.io/v1beta1
    endpoints:
    - ipv4:
      - 172.40.14.195
      node: egressgateway-worker
      ns: default
      pod: visitor-6764bb48cc-29vq9
    kind: EgressEndpointSlice
    metadata:
      name: test-kvlp6
      namespace: default
    

测试效果

  1. 可在集群外部部署应用 nettools,用于模拟一个集群外部的服务,nettools 会在 http 回复中返回请求者的源 IP 地址。

    docker run -d --net=host ghcr.io/spidernet-io/egressgateway-nettools:latest /usr/bin/nettools-server -protocol web -webPort 8080
    

  2. 在集群内部的 visitor Pod 中,验证出口流量的效果,我们可以看到 visitor 访问外部服务,nettools 返回的源 IP 符合了 EgressPolicy .status.eip 的效果。

    $ kubectl get pod
      NAME                       READY   STATUS    RESTARTS   AGE
      visitor-6764bb48cc-29vq9   1/1     Running   0          15m
    
    $ kubectl exec -it visitor-6764bb48cc-29vq9 bash
      $ curl 10.6.1.92:8080
      Remote IP: 10.6.1.60