All Products
Search
Document Center

Container Service for Kubernetes:Use network policies

Last Updated:Apr 15, 2024

You can use Kubernetes network policies to implement policy-based access control. If you want to control network traffic to specific applications based on IP addresses or ports, you can configure network policies. This topic describes the use scenarios of network policies in an ACK Serverless cluster.

Prerequisites

Usage notes

  • You can use network policies only in ACK Serverless Pro clusters and ACK Pro clusters.

  • Network policies do not support IPv6 addresses.

  • Network policies do not support the endPort field.

  • You can use label selectors in network policies to select namespaces and pods. If you create a large number of network policies in a cluster, the process of matching requests against rules in network policies will be time-consuming. In addition, cluster management and troubleshooting become complicated if the cluster has a large number of network policies. We recommend that you create less than 40 network policies in a cluster.

Step 1: Enable network policies

To enable network policies for an ACK Serverless Pro cluster, perform the following operations.

  1. Install the Poseidon component.

    1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

    2. On the Clusters page, click the name of the cluster that you want to manage and choose Operations > Add-ons in the left-side navigation pane.

    3. On the Add-ons page, click the Networking tab. In the Poseidon card, click Install.

    4. In the Install Poseidon dialog box, select Enable the NetworkPolicy feature for elastic container instances and click OK.

      After the component is installed, Installed is displayed in the upper-right corner of the card.

Step 2: Create an NGINX application that allows access from other pods

Use the ACK console

  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. On the Clusters page, click the name of the cluster that you want to manage and choose Workloads > Deployments in the left-side navigation pane.

  3. On the Deployments tab, click Create from Image. On the Create page, create an application named nginx and expose the application by using a Service. After you complete the application configuration, click Create.

    You can configure the following parameters based on the description in the following table and use default settings for other parameters. For more information, see Create a Deployment from an image.

    Wizard page

    Parameter

    Description

    Example

    Basic Information

    Name

    Specify a custom application name.

    nginx

    Replicas

    Specify the value based on your business requirements.

    1

    Container

    Image Name

    Click Select Image. In the dialog box that appears, select an image and click OK.

    In this example, an NGINX image is selected. On the Search tab, select Docker Images from the drop-down list, enter NGINX in the search box, and then click Search.

    Advanced

    Services

    Click Create to the right of Services. In the Create Service dialog box, set the parameters.

    Name: nginx

    Type:

    • Server Load Balancer

    • Public Access

    • Create SLB Instance

    Port Mapping:

    • Name: nginx

    • Service Port: 80

    • Container Port: 80

    • Protocol: TCP

  4. Return to the Deployments page, click Create from Image. On the Create page, create a client application named busybox to test the accessibility of the nginx Service created in the preceding step.

    You can configure the following parameters for the busybox client application based on the description in the following table and use default settings for other parameters. For more information, see Create a Deployment from an image.

    Wizard page

    Parameter

    Description

    Example

    Basic Information

    Name

    Specify a custom application name.

    busybox

    Replicas

    Specify a value based on your business requirements.

    1

    Container Start Parameter

    Image Name

    Click Select Image. In the dialog box that appears, select an image and click OK.

    In this example, a busybox image is selected. On the Search tab, select Docker Images from the drop-down list, enter busybox in the search box, and then click Search.

    Container Start Parameter

    None

    Select stdin and tty.

  5. Check whether the busybox client application can access the nginx Service.

    1. On the Deployments page, find the busybox application and click its name.

    2. On the Pods page, select a pod named busybox-{hash value} and click Terminal in the Actions column.

      image.png

    3. In the terminal, run the wget nginx command to access the nginx Service.

      connection

      The preceding output indicates that busybox can access the nginx Service.

Use the CLI

  1. Run the following command to create an application named nginx. Then, create a Service named nginx to expose the application.

    Create an application named nginx:

    kubectl run nginx --image=nginx

    Expected output:

    pod/nginx created

    Query whether the pod of the application is started:

    kubectl get pod

    Expected output:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx                    1/1     Running   0          45s

    Create a Service named nginx:

    kubectl expose pod nginx --port=80

    Expected output:

    service/nginx exposed

    View the Service:

    kubectl get service

    Expected output:

    NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   172.XX.XX.1     <none>        443/TCP   30m
    nginx        ClusterIP   172.XX.XX.48    <none>        80/TCP    12s
  2. Run the following command to create a pod named busybox and use the pod to access the nginx Service:

    kubectl run busybox --rm -ti --image=busybox /bin/sh

    Expected output:

    If you don't see a command prompt, try pressing enter.
    / #
    / #

    Obtain the nginx Service:

    If you don't see a command prompt, try pressing enter.
    / #
    / # wget nginx  # Enter wget nginx.

    Expected output:

    Connecting to nginx (172.XX.XX.48:80)
    saving to 'index.html'
    index.html           100% |****************************************************************************************************************************************************|   612  0:00:00 ETA
    'index.html' saved

Step 3: Configure a network policy

Configure a network policy based on the following scenarios.

Scenario 1: Allow only applications with specific labels to access a Service

  1. Run the vim policy.yaml command to create a file named policy.yaml with the following YAML template.

    vim policy.yaml

    The following code block shows the content of the YAML template:

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: access-nginx
    spec:
      podSelector:
        matchLabels:
          run: nginx
      ingress:
      - from:
        - podSelector:
            matchLabels:
              access: "true"
  2. Run the following command to create a network policy by using the preceding policy.yaml file:

    kubectl apply -f policy.yaml 

    Expected output:

    networkpolicy.networking.k8s.io/access-nginx created
  3. Run the following command to access the nginx Service. A connection timeout error is returned because the pod does not have the specified label:

    kubectl run busybox --rm -ti --image=busybox /bin/sh

    Test the accessibility of the nginx Service:

    wget nginx

    Expected output:

    Connecting to nginx (172.19.XX.XX:80)
    wget: can't connect to remote host (172.19.XX.XX): Connection timed out
  4. Run the following command to add the specified label to the pod:

    kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh

    Test the accessibility of the nginx Service:

    wget nginx

    Expected output:

    Connecting to nginx (172.21.XX.XX:80)
    saving to 'index.html'
    index.html           100% |****************************************************************************************************************************************************|   612  0:00:00 ETA
    'index.html' saved

    The output shows that the progress of the connection is 100%. This indicates that the pod can access the nginx Service as expected.

Scenario 2: Allow only specific source IP addresses to access a Service through an Internet-facing SLB instance

  1. Run the following command to create an SLB instance for the preceding nginx application. Set the Service type to LoadBalancer to make the application accessible over the Internet.

    vim nginx-service.yaml

    In this example, a file named nginx-service.yaml is used.

    # Copy the following YAML content to the nginx-service.yaml file: 
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        run: nginx
      name: nginx-slb
    spec:
      externalTrafficPolicy: Local
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: nginx
      type: LoadBalancer

    Run the following command to create a network policy by using the nginx-service.yaml file:

    kubectl apply -f nginx-service.yaml 

    Expected output:

    service/nginx-slb created

    Check whether the application is exposed by using the nginx Service:

    kubectl get service nginx-slb

    Expected output:

    NAME        TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
    nginx-slb   LoadBalancer   172.19.xx.xxx   47.110.xxx.xxx   80:32240/TCP   8m
  2. Run the following command to connect to the IP address of the created SLB instance: 47.110.xxx.xxx. The output shows that the connection failed.

    wget 47.110.xxx.xxx

    Expected output:

    --2018-11-21 11:46:05--  http://47.110.xx.xxx/
    Connecting to 47.110.XX.XX:80... failed: Connection refused.
    Note

    The connection failed due to the following reasons:

    • The nginx Service can be accessed only by applications that have the access=true label.

    • When you connect to the IP address of the SLB instance from your on-premises machine, you are accessing the nginx Service from outside the Kubernetes cluster. This is not the same as when you use a network policy to allow only applications with specified labels to access the nginx Service.

    Solution: Modify the network policy to allow the source IP address to access the nginx Service.

  3. Run the following command to query the IP address of your on-premises machine:

    curl myip.ipip.net

    Expected output:

    IP address: 10.0.x.x. From: China Beijing Beijing        # This is an example. Use the actual IP address.

  4. Run the following command to modify the policy.yaml file:

    vim policy.yaml

    Example of the policy.yaml file:

    # The following content is an example of the YAML file. 
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: access-nginx
    spec:
      podSelector:
        matchLabels:
          run: nginx
      ingress:
      - from:
        - podSelector:
            matchLabels:
              access: "true"
        - ipBlock:
            cidr: 100.64.0.0/10
        - ipBlock:
            cidr: 10.0.0.1/24      # This is an example. Use the actual IP address.

    Run the following command to create a network policy by using the preceding policy.yaml file:

    kubectl apply -f policy.yaml 

    Expected output:

    networkpolicy.networking.k8s.io/access-nginx unchanged
    Note
    • The request may come from different IP addresses. Therefore, specify a CIDR block with a mask length of 24.

    • The IP addresses used by SLB for health checks are within the 100.64.0.0/10 CIDR block. Therefore, make sure that you add 100.64.0.0/10 to the rule.

  5. Run the following command to create the resources that are provisioned for the nginx Service:

    kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh

    Access the nginx Service:

    wget 47.110.XX.XX

    Expected output:

    Connecting to 47.110.XX.XX (47.110.XX.XX:80)
    index.html           100% |***********************************************************|   612  0:00:00 ETA

    If the output shows 100%, this indicates that the nginx Service can be accessed.

Scenario 3: Allow a pod to access a specific address

  1. Run the following command to query the IP addresses to which www.aliyun.com is resolved:

    dig +short www.aliyun.com

    Expected output:

    www-jp-de-intl-adns.aliyun.com.
    www-jp-de-intl-adns.aliyun.com.gds.alibabadns.com.
    v6wagbridge.aliyun.com.
    v6wagbridge.aliyun.com.gds.alibabadns.com.
    106.XX.XX.21
    140.XX.XX.4
    140.XX.XX.13
    140.XX.XX.3
  2. Run the following command to create a file named busybox-policy:

    vim busybox-policy.yaml

    Example of the busybox-policy file:

    # The following content is a sample YAML file. 
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: busybox-policy
    spec:
      podSelector:
        matchLabels:
          run: busybox
      egress:
      - to:
        - ipBlock:
            cidr: 106.XX.XX.21/32
        - ipBlock:
            cidr: 140.XX.XX.4/32
        - ipBlock:
            cidr: 140.XX.XX.13/32
        - ipBlock:
            cidr: 140.XX.XX.3/32
      - to:
        - ipBlock:
            cidr: 0.0.0.0/0
        - namespaceSelector: {}
        ports:
        - protocol: UDP
          port: 53
    Note

    Egress rules are configured in the busybox-policy file to restrict outbound access from the application. You must allow the application to access UDP port 53. Otherwise, the domain name cannot be resolved.

  3. Run the following command to create a network policy based on the busybox-policy file:

    kubectl apply -f busybox-policy.yaml 

    Expected output:

    networkpolicy.networking.k8s.io/busybox-policy created
  4. Run the following command to create the busybox application:

    kubectl run busybox --rm -ti --image=busybox /bin/sh

    Access a website other than www.aliyun.com, such as www.taobao.com:

    wget www.taobao.com

    Expected output:

    Connecting to www.taobao.com (64.13.XX.XX:80)
    wget: can't connect to remote host (64.13.XX.XX): Connection timed out

    The output shows the can't connect to remote host message. This indicates that the application failed to access the domain name.

  5. Run the following command to access www.aliyun.com:

    wget www.aliyun.com

    Expected output:

    Connecting to www.aliyun.com (140.205.XX.XX:80)
    Connecting to www.aliyun.com (140.205.XX.XX:443)
    wget: note: TLS certificate validation not implemented
    index.html           100% |***********************************************************|  462k  0:00:00 ETA

    The output shows that the progress of the connection is 100%. This indicates that the application can access the domain name as expected.

Scenario 4: Control pod access to the Internet in specific namespaces

Note

The operations in this section may affect services that communicate with the Internet. We recommend that you create an empty namespace to perform the following operations.

  1. Run the following command to create a namespace for testing.

    Create a namespace named test-np.

    kubectl create ns test-np

    Expected output:

    namespace/test-np created
  2. Run the following command to create a default network policy that allows pods in the test-np namespace to access only internal services:

    vim default-deny.yaml

    Example of the default-deny.yaml file:

    # The following content is a sample YAML file. 
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      namespace: test-np
      name: deny-public-net
    spec:
      podSelector: {}
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      egress:
      - to:
        - ipBlock:
            cidr: 192.168.0.0/16
        - ipBlock:
            cidr: 172.16.0.0/12
        - ipBlock:
            cidr: 10.0.0.0/8

    Check whether a network policy is created by using the default-deny.yaml file.

    kubectl apply -f default-deny.yaml

    Expected output:

    networkpolicy.networking.k8s.io/deny-public-net created

    View the network policy:

    kubectl get networkpolicy -n test-np

    Expected output:

    NAME                              POD-SELECTOR          AGE
    deny-public-net                   <none>                1m
  3. Run the following command to allow pods with specific labels to access the Internet.

    vim allow-specify-label.yaml

    In this example, the public-network=true label is used.

    # The following content is a sample YAML file. 
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-public-network-for-labels
      namespace: test-np
    spec:
      podSelector:
        matchLabels:
          public-network: "true"
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      egress:
      - to:
        - ipBlock:
            cidr: 0.0.0.0/0
        - namespaceSelector:
            matchLabels:
              ns: kube-system

    Run the following command to create the network policy:

    kubectl apply -f allow-specify-label.yaml

    Expected output:

    networkpolicy.networking.k8s.io/allow-public-network-for-labels created

    View the network policy:

    kubectl get networkpolicy -n test-np

    Expected output:

    NAME                              POD-SELECTOR          AGE
    allow-public-network-for-labels   public-network=true    1m
    deny-public-net                   <none>                 3m
  4. Run the following command to verify that a pod without the specified label cannot access the Internet:

    kubectl run -it --namespace test-np --rm --image busybox  busybox-intranet
    ping aliyun.com

    Expected output:

    PING aliyun.com (106.11.2xx.xxx): 56 data bytes
    ^C
    --- aliyun.com ping statistics ---
    9 packets transmitted, 0 packets received, 100% packet loss

    The output shows 0 packets received. This indicates that the pod failed to access the Internet.

    Note

    The pod failed to access the Internet because the deny-public-net network policy does not allow pods in the test-np namespace to access the Internet. Therefore, pods with default labels cannot access the Internet.

  5. Run the following command to verify that a pod with the public-network=true label can access the Internet:

    kubectl run -it --namespace test-np --labels public-network=true --rm --image busybox  busybox-internet
    ping aliyun.com

    Expected output:

    PING aliyun.com (106.11.1xx.xx): 56 data bytes
    64 bytes from 106.11.1xx.xx: seq=0 ttl=47 time=4.235 ms
    64 bytes from 106.11.1xx.xx: seq=1 ttl=47 time=4.200 ms
    64 bytes from 106.11.1xx.xx: seq=2 ttl=47 time=4.182 ms
    ^C
    --- aliyun.com ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max = 4.182/4.205/4.235 ms

    The output shows 0% packet loss. This indicates that the pod can access the Internet.

    Note

    The pod can access the Internet because the allow-public-network-for-labels network policy allows pods with the public-network=true label to access the Internet. The busybox-internet pod has this label and therefore can access the Internet.