使用网关DNAT规则直接访问Pod

在游戏、P2P等场景中,您通常需要客户端直接访问Pod。传统模式下,您可以为Pod分配EIP来访问Pod。但这种方式存在一些问题,例如EIP数量限制、安全管理问题等。您可以在NAT网关上配置EIP,使用公网NAT网关的DNAT方式暴露Pod的访问入口,从而节省EIP数量。

前提条件

  • 已创建ACK托管集群ACK专有集群,且集群网络插件为Terway。详细信息,请参见创建ACK托管集群创建ACK专有集群(已停止新建)

  • 已在VPC中创建NAT网关并使用natgw控制器,如何创建NAT网关请参见创建和管理公网NAT网关实例

  • 已在DNAT规则中建立公网IP、公网端口、私网端口、私网IP的映射关系。关于DNAT原理请参见通过公网NAT网关DNAT功能实现ECS对外提供服务

    • 公网IP: 为公网NAT网关上配置的EIP。

    • 公网端口:为natgw控制器配置文件中配置的portRangeStartportRangeEnd范围,由natgw控制器自动分配,分配后信息在Pod同名CR poddnats.alibabacloud.com中记录。

    • 私网端口:为Pod Annotations中配置的Pod监听的端口。

    • 私网IP: 为Pod IP。

使用限制

  • 本功能仅支持普通ECS节点,不支持ECI实例。

  • 配置条目数受限于NAT网关能力,使用约束请参见DNAT功能FAQ

Pod注解说明

您可以使用以下Pod Annotations配置:

Pod Annotations

Value

k8s.aliyun.com/pod-dnat

Pod开启DNAT能力,取值为true或空("")时都可开启。如需关闭DNAT能力,请移除全部DNAT相关Annotations。

k8s.aliyun.com/pod-dnat-expose-port

Pod监听端口,多个端口使用逗号分隔,例如:"80,443"

k8s.aliyun.com/pod-dnat-expose-protocol

协议类型,支持tcpudp。默认为tcp

k8s.aliyun.com/pod-dnat-fixed

为有状态容器启用配置保持。

重要

安全组配置:Pod所属的安全组中需要开放入方向的允许规则,规则中的端口为暴露Pod的端口。

ack-extend-network-controller中启用DNAT功能

ack-extend-network-controller需要访问阿里云OpenAPI来创建资源,您需要在RAM中配置相应的权限,然后在应用市场中安装ack-extend-network-controller,并通过注解为指定Pod创建和关联DNAT 。

步骤一:配置DNAT所需的RAM权限

ACK集群

  1. 登录容器服务管理控制台,在左侧导航栏单击集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择集群信息

  3. 集群信息页面的基本信息页签下,单击Worker RAM角色右侧链接。

  4. 创建自定义权限策略,策略内容如下。具体操作,请参见步骤一:创建自定义权限策略

    {
          "Effect": "Allow",
          "Action": [
            "ecs:DescribeNetworkInterfaces",
            "vpc:DescribeNatGateways",
            "vpc:DescribeForwardTableEntries",
            "vpc:CreateForwardEntry",
            "vpc:DescribeEipAddresses",
            "vpc:DeleteForwardEntry",
            "vpc:DescribeRouteTableList",
            "vpc:DescribeRouteEntryList"
          ],
          "Resource": [
            "*"
          ],
          "Condition": {}
        }
  5. 为集群的Worker RAM角色授权。具体操作,请参见步骤二:为集群的Worker RAM角色授权

ACK Serverless集群

请为RAM用户生成访问密钥(AccessKey)。具体操作,请参见创建RAM用户创建自定义权限策略

步骤二:为ack-extend-network-controller组件开启natgw控制器

您需要安装ack-extend-network-controller组件,并且开启natgw控制器。关于ack-extend-network-controller组件的安装入口,请参见应用市场

natgw控制器配置参数如下。

clusterID: "c11ba338192xxxxxxx"          # 请按实际情况填写。
regionID: "cn-hangzhou"                  # 请按实际情况填写。
vpcID: "vpc-bp1rkq0zxxxxxx"              # 请按实际情况填写。
enableControllers:
  - natgw                                  # 启用DNAT。

networkController:
  natGwPool:
    - natgwId: "< nat gateway id. >"                   # nat 公网网关ID。
      zoneId: "< nat gateway zone id. cn-hangzhou-j >" # nat 公网网关可用区ID。
      portRangeStart: 512                              # 起始端口。
      portRangeEnd: 1024                               # 结束端口。
      eips:
        - "<auto config all nat gateway eips if not config. 0.0.0.0 >"  # 使用公网网关EIP,如不设置,则使用网关上配置的全部EIP。

credential:                               # 使用AK/SK,ACK集群推荐使用RamRole模式配置。 若使用步骤一为集群的Worker RAM角色授权,此处无需配置。
  accessKey: ""
  accessSecret: ""

使用自定义资源跟踪配置

  1. 创建Pod后,控制器会创建与Pod同名的自定义资源。以下示例将为Pod配置DNAT规则,将Pod80端口暴露到公网。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example
      labels:
        app: example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: example
      template:
        metadata:
          labels:
            app: example
          annotations:
            k8s.aliyun.com/pod-dnat: ""
            k8s.aliyun.com/pod-dnat-expose-port: "80"
        spec:
          containers:
          - name: example
            image: nginx
  2. 执行如下命令,读取poddnats.alibabacloud.com中的分配信息来获取Pod的外部地址和端口。

    kubectl get poddnats -oyaml 

    预期输出:

    apiVersion: alibabacloud.com/v1
    kind: PodDNAT
    metadata:
      creationTimestamp: "20**-09-20T03:26:44Z"
      finalizers:
      - natgw-controller
      generation: 2
      name: example-6cd498d7b-9****
      namespace: default
      ownerReferences:
      - apiVersion: v1
        blockOwnerDeletion: true
        kind: Pod
        name: example-6cd498d7b-9****
        uid: 7af54e1c-eeb7-4fd0-b070-ff99ddbd****
      resourceVersion: "357150"
      uid: 2fad9bb7-cc84-46b4-b6eb-5d15f06c****
    spec:
      eni: eni-xxx
      externalIP: 114.55.**.**
      internalIP: 172.16.**.**
      portMapping:
      - externalPort: "512"
        internalPort: "80"
      protocol: tcp
      tableId: ngw-xxx
      vswitch: vsw-xxx
      zoneID: cn-hangzhou-k
    status:
      entries:
      - externalIP: 114.55.**.**
        externalPort: "512"
        forwardEntryId: fwd-xxx
        internalIP: 172.16.**.**
        internalPort: "80"
        ipProtocol: tcp

    其中Pod的外部地址和端口如下:

    • externalIP:NAT网关的公网IP,即外部访问的地址。在本示例中为114.55.**.**

    • externalPort:公网端口,由控制器在端口范围中分配。在本示例中为"512"