All Products
Search
Document Center

Container Service for Kubernetes:Expose pods with NAT gateway DNAT rules

Last Updated:Jul 06, 2026

In games and peer-to-peer (P2P) applications, clients often need direct pod access. Instead of assigning an elastic IP address (EIP) to each pod—which is limited by EIP quotas and complicates security management—map public endpoints to pods through NAT gateway DNAT rules.

Prerequisites

Before you begin, ensure that you have:

  • An ACK managed cluster or ACK dedicated cluster with Terway as the network plugin.

  • An Internet NAT gateway created in the cluster's VPC, managed by the natgw controller.

  • Familiarity with how DNAT rules map four values: public IP (an EIP on the NAT gateway), public port (auto-allocated from portRangeStart–portRangeEnd and recorded in the PodDNAT CR), private port (the pod listening port from annotations), and private IP (the pod IP). DNAT rules map a public IP address and port to a private IP address and port.

Limitations

  • Supported on regular ECS nodes only, not ECI instances.

  • DNAT entries are limited by the NAT gateway quota. See DNAT feature FAQ.

How it works

The ack-extend-network-controller runs a sub-controller called the natgw controller. When you annotate a pod to enable DNAT, the natgw controller:

  1. Selects an EIP from the NAT gateway's EIP pool.

  2. Allocates a public port from the configured range (portRangeStartportRangeEnd).

  3. Creates a DNAT forward entry mapping the public IP and port to the pod's private IP and port.

  4. Records the allocation in a PodDNAT Custom Resource (CR) named after the pod.

Each DNAT rule maps four values: public IP address, public port, private IP address, and private port.

The natgw controller auto-allocates public ports from your configured range. Size the range for the maximum number of pods to expose simultaneously.

Pod annotations

Apply these annotations to the pod template to control DNAT behavior.

Annotation

Description

k8s.aliyun.com/pod-dnat

Enables DNAT for the pod. Set to true or "" to enable. To disable, remove all DNAT-related annotations.

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

The pod's listening port. Separate multiple ports with commas. Example: "80,443".

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

The protocol. Valid values: tcp, udp. Default: tcp.

k8s.aliyun.com/pod-dnat-fixed

Enables configuration persistence for a stateful container.

Important

Add an inbound rule to the pod's security group to allow traffic on the exposed port. Without this rule, DNAT traffic is dropped at the security group.

Enable DNAT in ack-extend-network-controller

The ack-extend-network-controller calls Alibaba Cloud OpenAPIs to create resources. Grant the required RAM permissions, install ack-extend-network-controller from the Marketplace, and use pod annotations to create and associate DNAT entries.

Step 1: Configure RAM permissions

The natgw controller calls Alibaba Cloud APIs to manage NAT forward entries. Grant permissions based on your cluster type.

ACK managed or dedicated cluster

The natgw controller uses the cluster's Worker RAM Role. Add a custom policy with the following permissions to the Worker RAM Role.

  1. Log on to the Container Service Management Console. In the left navigation pane, click Clusters.

  2. On the Clusters page, click your cluster name. In the left navigation pane, click Cluster Information.

  3. On the Basic Information tab, click the link next to Worker RAM Role.

  4. Create a custom policy with the following content. See Step 1: Create a custom policy.

    {
      "Effect": "Allow",
      "Action": [
        "ecs:DescribeNetworkInterfaces",
        "vpc:DescribeNatGateways",
        "vpc:DescribeForwardTableEntries",
        "vpc:CreateForwardEntry",
        "vpc:DescribeEipAddresses",
        "vpc:DeleteForwardEntry",
        "vpc:DescribeRouteTableList",
        "vpc:DescribeRouteEntryList"
      ],
      "Resource": ["*"],
      "Condition": {}
    }
  5. Attach the policy to the Worker RAM Role. See Step 2: Grant permissions to the Worker RAM Role.

ACK serverless cluster

Create an AccessKey pair for a RAM user with the equivalent permissions. See Create a RAM user and Create a custom policy.

Step 2: Install and configure the natgw controller

Install ack-extend-network-controller from the Marketplace and enable the natgw controller.

Configure the natgw controller with the following parameters:

clusterID: "c11ba338192xxxxxxx"          # Your cluster ID
regionID: "cn-hangzhou"                  # Your region ID
vpcID: "vpc-bp1rkq0zxxxxxx"              # Your VPC ID
enableControllers:
  - natgw                                # Enable the natgw controller

networkController:
  natGwPool:
    - natgwId: "<nat-gateway-id>"                      # Internet NAT gateway ID
      zoneId: "<zone-id>"                              # Zone of the NAT gateway, e.g., cn-hangzhou-j
      portRangeStart: 512                              # Start of the public port range
      portRangeEnd: 1024                               # End of the public port range
      eips:
        - "<eip-address>"                              # EIP on the NAT gateway. If omitted, all EIPs on the gateway are used.

credential:                              # For ACK clusters using the Worker RAM Role, omit this section.
  accessKey: ""
  accessSecret: ""

Expose a pod with DNAT

After the natgw controller is running, annotate a pod to create a DNAT entry automatically.

  1. Apply a Deployment with DNAT annotations. This example exposes port 80 of an nginx pod.

    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. After the pod starts, the natgw controller creates a PodDNAT CR named after the pod. View the allocation:

    Field

    Description

    spec.externalIP

    The NAT gateway's public IP address. Use this address to reach the pod from the internet.

    spec.externalPort

    The public port allocated from portRangeStartportRangeEnd. In this example: 512.

    spec.internalIP

    The pod's private IP address.

    spec.portMapping[].internalPort

    The pod's listening port. In this example: 80.

    status.entries[].forwardEntryId

    The DNAT forward entry ID.

    kubectl get poddnats -oyaml

    Expected output:

    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

    The pod is reachable at 114.55.**.**:512 from the internet.

Next steps

  • To expose multiple ports, set k8s.aliyun.com/pod-dnat-expose-port to a comma-separated list, for example "80,443".

  • To use UDP instead of TCP, set k8s.aliyun.com/pod-dnat-expose-protocol to udp.

  • To retain the same public port across pod restarts, add the k8s.aliyun.com/pod-dnat-fixed annotation.