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:
-
An ACK managed cluster or an ACK dedicated cluster that uses Terway as the network plugin. For more information, see Create an ACK managed cluster and Create an ACK dedicated cluster (new creation stopped)
-
An Internet NAT gateway created in the cluster's VPC, managed by the natgw controller. For more information, see Internet NAT Gateway
-
A basic understanding of how DNAT rules map a public IP address and port to a private IP address and port. For more information, see Use the DNAT feature of an Internet NAT gateway to allow an ECS instance to provide services over the internet
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:
-
Selects an available EIP from the NAT gateway's EIP pool.
-
Allocates a public port from the configured range (
portRangeStart–portRangeEnd). -
Creates a DNAT forward entry that maps the public IP and port to the pod's private IP and the specified private port.
-
Records the allocation in a
PodDNATCustom 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. |
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.
-
Log on to the Container Service Management Console. In the left navigation pane, click Container Service Management ConsoleClusters.
-
On the Clusters page, click your cluster name. In the left navigation pane, click Cluster Information.
-
On the Basic Information tab, click the link next to Worker RAM Role.
-
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": {} } -
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.
-
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 -
After the pod starts, the natgw controller creates a
PodDNATCR with the same name as the pod. Run the following command to view the allocation.Field Description spec.externalIPThe public IP address of the NAT gateway. Use this to reach the pod from the internet. spec.externalPortThe public port allocated from portRangeStart–portRangeEnd. In this example:512.spec.internalIPThe pod's private IP address. spec.portMapping[].internalPortThe pod's listening port. In this example: 80.status.entries[].forwardEntryIdThe ID of the DNAT forward entry created in the NAT gateway. kubectl get poddnats -oyamlExpected 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: tcpThe key fields in the output are: The pod is now reachable at
114.55..:512from the internet.
What's next
-
To expose multiple ports on the same pod, set
k8s.aliyun.com/pod-dnat-expose-portto a comma-separated list, for example"80,443". -
To use UDP instead of TCP, set
k8s.aliyun.com/pod-dnat-expose-protocoltoudp. -
To retain the same public port across pod restarts, add the
k8s.aliyun.com/pod-dnat-fixedannotation.