Help Center> Cloud Container Engine> User Guide> Old Console> Networking> Ingress> Using kubectl to Create an Nginx Ingress

Using kubectl to Create an Nginx Ingress

Scenario

This section uses an Nginx workload as an example to describe how to create an Nginx ingress using kubectl.

Prerequisites

Creating an Nginx Ingress

  1. Use kubectl to connect to the cluster. For details, see Connecting to a Cluster Using kubectl.
  2. Create a YAML file named ingress-test.yaml. The file name can be customized.

    vi ingress-test.yaml

    • For clusters of v1.15 or later, the value of apiVersion is networking.k8s.io/v1beta1.
    • For clusters of v1.13 or earlier, the value of apiVersion is extensions/v1beta1.

    The following uses HTTP as an example to describe how to configure the YAML file:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: ingress-test
      namespace: default
      annotations:
        kubernetes.io/ingress.class: nginx
        kubernetes.io/elb.port: '80' 
    spec:
      rules:
        - host: ''
          http:
            paths:
              - path: '/'
                backend:
                  serviceName: <your_service_name>  # Replace it with the name of your target Service.
                  servicePort: 80
    Table 1 Key parameters

    Parameter

    Mandatory

    Type

    Description

    kubernetes.io/ingress.class

    Yes

    String

    nginx: indicates that Nginx ingress is used. This option cannot be used if the nginx-ingress add-on is not installed.

    This parameter is mandatory when an ingress is created by calling the API.

    kubernetes.io/elb.port

    Yes

    Integer

    This parameter indicates the external port registered with the address of the LoadBalancer Service.

  3. Create an ingress.

    kubectl create -f ingress-test.yaml

    If information similar to the following is displayed, the ingress has been created.

    ingress/ingress-test created

    View the created ingress.

    kubectl get ingress

    If information similar to the following is displayed, the ingress has been created successfully and the workload is accessible.

    NAME             HOSTS     ADDRESS          PORTS   AGE
    ingress-test     *         121.**.**.**     80      10s

  4. Enter http://121.**.**.**:80 in the address box of the browser to access the workload (for example, Nginx workload).

    121.**.**.** indicates the IP address of the unified load balancer.

Configuring HTTPS Certificates

The HTTPS certificate can be configured to provide security services. Here is an example of YAML configuration:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress 
metadata: 
  name: ingress-test
  annotations: 
    kubernetes.io/ingress.class: nginx
    kubernetes.io/elb.port: '443'
spec:
  tls: 
  - hosts: 
    - foo.bar.com
    secretName: ingress-test-secret
  rules: 
  - host: ''
    http: 
      paths: 
      - path: '/'
        backend: 
              serviceName: <your_service_name>  # Replace it with the name of your target Service.
          servicePort: 80

Configuring a URL Rewriting Rule

In some scenarios, the URL exposed by a backend service is different from the path specified in the ingress rule. If URL rewriting is not configured, a 404 message will be returned for all access requests. URL rewriting can be implemented using the Rewrite method. The nginx.ingress.kubernetes.io/rewrite-target annotation can be used to implement rewriting rules for different URLs.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: 'rewrite.bar.com'
      http:
        paths:
          - path: '/something(/|$)(.*)'
            backend:
              serviceName: <your_service_name>  # Replace it with the name of your target Service.
              servicePort: 80

As long as rewrite-target is specified for one ingress, all paths under the same host in all ingress definitions are case-sensitive, including the ingresses that do not have rewrite-target specified.

In the preceding example, the placeholder $2 indicates that all characters matched by the second parenthesis (.*) are filled in the nginx.ingress.kubernetes.io/rewrite-target annotation.

For example, the preceding ingress definition will result in the following rewrites:
  • rewrite.bar.com/something rewrites to rewrite.bar.com/.
  • rewrite.bar.com/something/ rewrites to rewrite.bar.com/.
  • rewrite.bar.com/something/new rewrites to rewrite.bar.com/new.

In the nginx-ingress-controller container, you can view all ingress configurations in the nginx.conf file in the /etc/nginx directory. The rewriting rule in the preceding example generates a Rewrite command and writes it to the location field in the nginx.conf file.

## start server rewrite.bar.com
        server {
                server_name rewrite.bar.com ;
                ...
                location ~* "^/something(/|$)(.*)" {
                        set $namespace      "default";
                        set $ingress_name   "ingress-test";
                        set $service_name   "<your_service_name>";
                        set $service_port   "80";
                        ...
                        rewrite "(?i)/something(/|$)(.*)" /$2 break;
                        ...
                }
        }
        ## end server rewrite.bar.com
The basic syntaxof the Rewrite command is as follows:
rewrite regex replacement [flag];
  • regex: regular expression used to match a URI. In the preceding example, (?i)/something(/|$)(.*) is the regular expression for matching URIs, where (?i) indicates case-insensitive.
  • replacement: content to rewrite. In the preceding example, /$2 indicates that the path is rewritten to all the characters matched by the second parenthesis (.*).
  • flag: rewrite format.
    • last: continues to match the next rule after the current rule is matched.
    • break: stops matching after the current rule is matched.
    • redirect: returns a temporary redirect with the 302 code.
    • permanent: returns a permanent redirect with the 301 code.

Some complex, advanced rewrite requirements can be implemented by modifying the Nginx configuration file nginx.conf. The essence is to modify the Nginx configuration file nginx.conf. However, the nginx.ingress.kubernetes.io/rewrite-target annotation function can be customized to meet more complex Rewrite requirements.

  • nginx.ingress.kubernetes.io/server-snippet: Add custom configuration to the server configuration block in the nginx.conf file.
  • nginx.ingress.kubernetes.io/configuration-snippet: Add custom configuration to the location configuration block in the nginx.conf file.

You can use the preceding two annotations to insert a Rewrite command into the server or location field in the nginx.conf file to rewrite the URL. The following is an example:

annotations:
     kubernetes.io/ingress.class: "nginx"
     nginx.ingress.kubernetes.io/configuration-snippet: |
        rewrite ^/stylesheets/(.*)$ /something/stylesheets/$1 redirect;  # Add the /something prefix.
        rewrite ^/images/(.*)$ /something/images/$1 redirect;  # Add the /something prefix.
In the preceding two rules, the /something path is added to the access URL.
  • When a user accesses rewrite.bar.com/stylesheets/new.css, it rewrites to rewrite.bar.com/something/stylesheets/new.css.
  • When a user accesses rewrite.bar.com/images/new.jpg, it rewrites to rewrite.bar.com/something/images/new.jpg.

Creating a Load Balancing Rule

The native Nginx supports multiple load balancing rules, including weighted round robin and IP hash. An Nginx ingress supports load balancing by using consistent hashing based on the native Nginx capabilities.

By default, the IP hash method supported by Nginx uses the linear hash space. The backend server is selected based on the hash value of the IP address. However, when this method is used to add or delete a node, all IP addresses need to be hashed again and then routed again. As a result, a large number of sessions are lost or the cache becomes invalid. Therefore, consistent hashing is introduced to the Nginx ingress to solve this problem.

Consistent hashing is a special hash algorithm, which constructs a ring hash space to replace the common linear hash space. When a node is added or deleted, only the target route is migrated clockwise, and other routes do not need to be changed. In this way, rerouting can be reduced as much as possible, resolving the load balancing issue caused by dynamic node addition and deletion.

If a consistent hashing rule is configured, the newly added server will share the load of all other servers. Similarly, when a server is removed, all other servers can share the load of the removed server. This effectively balances the load among nodes in the cluster and prevents the avalanche effect caused by the breakdown of a node.

An Nginx ingress can use the nginx.ingress.kubernetes.io/upstream-hash-by annotation to configure consistent hashing rules. The following is an example configuration:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"  # Perform hashing based on the request URI.
spec:
  rules:
    - host: ''
      http:
        paths:
          - path: '/'
            backend:
              serviceName: <your_service_name>  # Replace it with the name of your target Service.
              servicePort: 80
The value of nginx.ingress.kubernetes.io/upstream-hash-by can be an nginx variable, a text value, or any combination:
  • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri" indicates to hash requests based on the request URI.
  • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri$host" indicates to hash requests based on the request URI and domain name.
  • nginx.ingress.kubernetes.io/upstream-hash-by: "${request_uri}-text-value" indicates to hash requests based on the request URI and text value.