All Products
Search
Document Center

Container Service for Kubernetes:Access pods directly using NAT gateway DNAT rules

Last Updated:Mar 26, 2026

In games and peer-to-peer (P2P) applications, clients often need to reach specific pods directly. Rather than assigning an elastic IP address (EIP) to each pod—which is constrained by EIP quotas and complicates security management—configure Destination Network Address Translation (DNAT) rules on an Internet NAT gateway to map a public endpoint to a pod's private IP address and port. This reduces the number of EIPs required and centralizes public access through the NAT gateway.

Prerequisites

Before you begin, ensure that you have:

Limitations

  • Supported on regular ECS nodes only. ECI instances are not supported.

  • The number of DNAT entries is limited by the NAT gateway quota. For details, see DNAT feature FAQ.

How it works

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

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

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

  3. Creates a DNAT forward entry that maps the public IP and port to the pod's private IP and the specified private 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 public port is auto-allocated by the natgw controller from the range you configure. Size the range according to the maximum number of pods you expect to expose simultaneously.

Pod annotations

Apply the following 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 leave blank ("") to enable. To disable DNAT, 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, traffic routed through the DNAT entry is dropped at the security group.

Enable DNAT in ack-extend-network-controller

Step 1: Configure RAM permissions

The natgw controller calls Alibaba Cloud APIs to manage NAT forward entries. Grant the required 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 Container Service Management ConsoleClusters.

  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. For details, 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. For details, 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. For details, see Create a RAM user and Create a custom policy.

Step 2: Install and configure the natgw controller

Install the ack-extend-network-controller component from the marketplace and enable the natgw controller. For installation steps, see Marketplace.

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 using DNAT

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

  1. Apply a Deployment with DNAT annotations. The following 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 with the same name as the pod. Run the following command to view the allocation.

    Field Description
    spec.externalIP The public IP address of the NAT gateway. Use this 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 ID of the DNAT forward entry created in the NAT gateway.
    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 key fields in the output are: The pod is now reachable at 114.55..:512 from the internet.

What's next

  • To expose multiple ports on the same pod, 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.