By default, all pods on a node share the node's security groups and IP address pool. This makes fine-grained network isolation impossible at the pod level — any pod on the node can reach the same resources. The Terway Trunk elastic network interface (ENI) feature solves this by giving each pod its own dedicated ENI, vSwitch, and security group, without reducing the deployment density of other pods on the same node.
The following steps cover how to enable the Terway Trunk ENI feature and configure per-pod network isolation using PodNetworking custom resource definitions (CRDs).
How it works
After you enable the Trunk ENI feature, the terway-controlplane component is deployed in the cluster. When a pod is created, Terway matches its labels against PodNetworking CRDs. If a match is found, Terway allocates a dedicated ENI to the pod from the vSwitch and security groups defined in the matching PodNetworking. Pods without a matching PodNetworking continue to use IP addresses from shared ENIs.
Node configuration modes
Two node modes support per-pod network isolation. Choose based on your cluster type and density requirements.
| Nodes that support Trunk ENIs | Nodes that support ENIs | |
|---|---|---|
| Supported cluster types | ACK managed clusters | ACK managed clusters and ACK dedicated clusters |
| Deployment density | Regular pods use shared ENIs; specified pods use exclusive ENIs — higher overall density | All pods use exclusive ENIs — lower density |
| Supported node types | ECS nodes | ECS nodes |
| Instance types | Instances with EniTrunkSupported=true (see DescribeInstanceTypes) |
Instances that support ENIs |
Limitations
-
ACK dedicated clusters: Apply for the
Container network supports Terway ENI Trunking modequota at the Quota Centerconsole before proceeding. -
Pod count per node: The number of pods per node is limited. For details, see Work with Terway.
-
Same-node traffic: Pod security group rules do not apply to traffic between pods on the same node, or between pods and their host node. To enforce isolation in these scenarios, configure a network policy.
-
ACK managed clusters created before June 2020: This feature may not be supported. Follow Step 1: Check whether the cluster supports the Terway Trunk ENI feature to verify.
-
Irreversible: Static IP addresses, vSwitches, and security groups cannot be disabled after they are enabled.
Prerequisites
Before you begin, ensure that you have:
-
An ACK managed cluster or ACK dedicated cluster with the
terway-eniipnetwork plug-in installed -
(ACK dedicated clusters only) A submitted ticket to apply for Trunk ENI ECS instance permissions
-
Nodes with instance types that support Trunk ENIs (
EniTrunkSupported=true), if you plan to use the Trunk ENI node mode -
Sufficient available IP addresses in the vSwitches you plan to assign to pods
Step 1: Enable the Terway Trunk ENI feature
Enable Trunk ENI in a new cluster
When creating an ACK cluster, set Network Plug-in to Terway and set Terway Mode to Support for ENI Trunking. The network plug-in type in this mode is terway-eniip. For instructions, see Create an ACK dedicated cluster (discontinued) and Create an ACK managed cluster.
The Trunk ENI feature is enabled by default for newly created ACK managed clusters running Kubernetes 1.31 or later.
The Trunk ENI feature cannot be disabled after it is enabled.
Enable Trunk ENI in an existing cluster
Step 1: Check whether the cluster supports the Terway Trunk ENI feature
-
Skip this step if you use an ACK dedicated cluster. Instead, submit a ticket to apply for Trunk ENI ECS instance permissions and proceed to Step 2.
-
For existing ACK managed clusters or ACK managed clusters that are upgraded from ACK dedicated clusters, you need to check whether the cluster supports the Terway Trunk ENI feature and modify the configuration. You do not need to apply for permissions to use ECS instances that support Trunk ENIs.
Run the following command to check the token configuration:
kubectl get secret -nkube-system addon.network.token
Expected output:
NAME TYPE DATA AGE
addon.network.token Opaque 1 69m
If the token exists, proceed to Step 2. If it does not exist, the cluster does not support the Trunk ENI feature. Create a new cluster with Trunk ENI enabled instead.
Step 2: Update and configure terway-eniip
-
Log on to the ACK console. In the left-side navigation pane, click Clusters.
-
Click the cluster name. In the left-side navigation pane, choose Operations > Add-ons.
-
On the Add-ons page, click the Networking tab and find terway-eniip.
-
In the terway-eniip card, click Upgrade to update to the latest version. If the Upgrade button is not displayed, the latest version is already installed.
-
Edit the
eni-configConfigMap to enable Trunk ENI:Parameter Value Description enable_eni_trunkingtrueEnables the Trunk ENI feature. Cannot be disabled after enabled. credential_path/var/addon/token-configRequired for ACK managed clusters only. Add this parameter manually if it is not present. kubectl edit cm -nkube-system eni-configSet the following parameters in the ConfigMap. Do not modify other parameters. The ConfigMap content must be in JSON format. Example ConfigMap:
apiVersion: v1 data: eni_conf: | { "min_pool_size": 0, "enable_eni_trunking": true, "credential_path": "/var/addon/token-config", ... } kind: ConfigMap -
Restart Terway pods for the changes to take effect:
kubectl delete pod -n kube-system -l app=terway-eniip -
On the Add-ons page, click the Networking tab and install terway-controlplane. After installation, Installed is displayed in the terway-controlplane card.
Step 2: Create a PodNetworking
A PodNetworking is a Terway CRD that defines network configurations for a set of pods. Create one PodNetworking per network plane you want to configure.
-
Log on to the ACK console and click Clusters.
-
Click the cluster name. In the left-side navigation pane, choose Workloads > Custom Resources.
-
On the Custom Resources page, click the CRDs tab, and then click Create from YAML.
-
Paste the following template and modify the parameters for your environment:
Parameter Description allocationType.typeElastic: IP is released when the pod is deleted.Fixed: pod retains its IP address across restarts. Fixed mode applies only to pods with fixed names (StatefulSets and pods withoutownerReferencesby default). If you need to configure custom workloads, configure terway-controlplane in component management. When using Fixed mode, pods are always recreated in the same zone.releaseStrategyApplies only when typeisFixed.TTL: release the IP after the delay specified inreleaseAfter(minimum 5 minutes).Never: the IP is never released automatically; delete PodENIs manually to free the address.releaseAfterApplies only when releaseStrategyisTTL. Uses Go duration format. Examples:2h45m,5m0s.podSelectorMatches pod labels. If both podSelectorandnamespaceSelectorare set, a pod must match both to use this PodNetworking. Each pod must match at most one PodNetworking — if a pod matches multiple, the network configuration used is undefined.namespaceSelectorMatches namespace labels. Same matching rules as podSelector.vSwitchOptionsA list of vSwitches. Terway selects one vSwitch per pod. Pods can only be scheduled to nodes in the same zone as the listed vSwitches. Make sure the vSwitches have enough available IP addresses — pod creation fails if no IPs are available. If node auto scaling is enabled, this zone constraint may prevent the node pool from scaling out. vSwitchSelectOptions.vSwitchSelectionPolicySupported in Terway v1.11.0 and later. ordered(default): use vSwitches in the order listed.most: use the vSwitch with the most available IPs.random: select randomly.securityGroupIDsOne to five security group IDs. All specified security groups take effect simultaneously. eniOptions.eniTypeSupported in Terway v1.11.0 and later. Default(default): Trunk ENI mode in shared ENI clusters; exclusive ENI mode in exclusive ENI clusters.ENI: exclusive ENI mode.Trunk: Trunk ENI mode.apiVersion: network.alibabacloud.com/v1beta1 kind: PodNetworking metadata: name: example spec: allocationType: type: Fixed # IP allocation policy: Elastic or Fixed releaseStrategy: TTL # Only for Fixed policy: TTL or Never releaseAfter: "1h" # Only for TTL strategy: delay before releasing the IP selector: podSelector: matchLabels: foo: bar # Pods with this label use this PodNetworking namespaceSelector: matchLabels: foo: bar # Namespace must also match if namespaceSelector is set securityGroupIDs: - sg-bpxxxx # Up to 5 security group IDs; all take effect simultaneously vSwitchOptions: - vsw-bpxxxx # One or more vSwitches; Terway selects one per pod status: status: ReadyThe following table describes the parameters.
-
Click Create.
Verify the PodNetworking is ready:
kubectl describe PodNetworking example # Replace example with your PodNetworking name
Wait until the status field shows Ready. The PodNetworking does not take effect on pods until it reaches Ready status.
(Optional) Step 3: Add labels to the namespace
If your PodNetworking uses a namespaceSelector, add matching labels to the target namespace.
-
Create a test namespace:
kubectl create ns example -
Add the label that matches your
namespaceSelector:kubectl label namespaces example foo=bar # Replace example with your namespace name -
Verify the label was applied:
kubectl get namespace example --show-labels # Replace example with your namespace nameExpected output:
NAME STATUS AGE LABELS example Active 24s foo=bar,kubernetes.io/metadata.name=example
(Optional) Step 4: Deploy a pod and verify network configuration
-
Create a
my-nginx.yamlfile with the following content:apiVersion: apps/v1 kind: StatefulSet metadata: name: my-nginx # Application name namespace: example # Target namespace labels: app: nginx spec: serviceName: "nginx-service" replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx foo: bar # Must match the podSelector in your PodNetworking spec: containers: - name: nginx image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 ports: - containerPort: 80 # If the StatefulSet requires persistent storage, add volumeClaimTemplates: # volumeClaimTemplates: # - metadata: # name: nginx-storage # spec: # accessModes: ["ReadWriteOnce"] # storageClassName: "my-storage-class" # resources: # requests: # storage: 1Gi -
Deploy the application:
kubectl apply -f my-nginx.yaml -
Verify that the pod is using the PodNetworking configuration. If the pod matched a PodNetworking, the annotation
k8s.aliyun.com/pod-networkingis added to the pod:apiVersion: v1 kind: Pod metadata: annotations: k8s.aliyun.com/pod-eni: "true" k8s.aliyun.com/pod-networking: podnetworking labels: app: example pod-ip: elastic -
Inspect the PodENI that Terway automatically created for the pod:
kubectl get podenis.network.alibabacloud.com <my-nginx-0> -n <example> -o yaml # Replace <my-nginx-0> with the pod name and <example> with the namespaceThe output confirms the ENI, vSwitch, security groups, and IP address assigned to the pod:
apiVersion: network.alibabacloud.com/v1beta1 kind: PodENI metadata: finalizers: - pod-eni generation: 1 name: <my-nginx-0> namespace: default spec: allocations: - allocationType: type: Elastic eni: id: eni-bp1xxxx mac: 00:16:xx:xx:xx:xx securityGroupIDs: - sg-bp1xxxx vSwitchID: vsw-bp1xxxx zone: cn-hangzhou-h ipv4: 192.168.x.x ipv4CIDR: 192.168.x.x/19 ipv6: 2408:x:x:x:x:x:x:x ipv6CIDR: 2408:x:x:x::/64 zone: cn-hangzhou-h status: eniInfos: eni-bp1xxxx: id: eni-bp1xxxx status: Bind vid: 1001 instanceID: i-bp1xxxx phase: Bind podLastSeen: "2021-xx-xxT00:00:00Z" trunkENIID: eni-bp1xxxx
Stop terway-controlplane before cluster migration
If you have enabled pod custom configurations on an ACK dedicated cluster, you cannot directly migrate workloads to an ACK managed Pro cluster. Stop terway-controlplane before migrating and re-enable it afterward.
Before migration:
-
Stop
terway-controlplane:kubectl scale deploy -nkube-system terway-controlplane --replicas 0 -
Back up the webhook configurations, then delete them:
# Back up kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io terway-controlplane -oyaml > terway-controlplane.mutatingwebhookconfigurations.yaml kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io terway-controlplane -oyaml > terway-controlplane.validatingwebhookconfigurations.yaml # Delete kubectl delete -f terway-controlplane.mutatingwebhookconfigurations.yaml kubectl delete -f terway-controlplane.validatingwebhookconfigurations.yaml
After migration:
For migration instructions, see Hot migration from ACK dedicated clusters to ACK managed Pro clusters.
-
If migration fails: Restore the webhook and
terway-controlplane:kubectl apply -f terway-controlplane.mutatingwebhookconfigurations.yaml kubectl apply -f terway-controlplane.validatingwebhookconfigurations.yaml kubectl scale deploy -nkube-system terway-controlplane --replicas 1 -
If migration succeeds: Delete
terway-controlplaneand reinstall it from the Add-ons page:kubectl delete deploy -nkube-system terway-controlplaneFor reinstallation instructions, see Manage system components.
FAQ
Why is a pod not using the expected PodNetworking?
Check the following in order:
-
The PodNetworking
statusmust beReady. Runkubectl describe PodNetworking <name>to check. -
The pod's labels must match exactly one PodNetworking. If they match multiple PodNetworkings, the network configuration used is undefined.
-
If the PodNetworking uses the Fixed allocation policy, it only applies to StatefulSets and pods without
ownerReferences. Pods managed by Deployments or other controllers are not matched.
What's next
-
Configure multiple security groups per ENI for more granular pod-level firewall policies: Configure multiple security groups for an ENI.
-
Troubleshoot container network issues: FAQs about container networks.