Help Center/ Cloud Container Engine/ User Guide/ Network/ Ingresses/ Nginx Ingresses/ Advanced Setting Examples of Nginx Ingresses/ Configuring Consistent Hashing for Load Balancing of an Nginx Ingress
Updated on 2024-09-30 GMT+08:00

Configuring Consistent Hashing for Load Balancing of an Nginx Ingress

The native Nginx supports multiple load balancing rules, including weighted round robin and IP hash. 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 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 balances the load among nodes in the cluster and prevents the avalanche effect caused by the breakdown of a node.

Configuring a Consistent Hashing Rule

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

  1. Use kubectl to access 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.23 or later:
    apiVersion: networking.k8s.io/v1
    kind: Ingress 
    metadata: 
      name: ingress-test
      namespace: default
      annotations:
        nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"  # Perform hashing based on the request URI.
    spec:
      rules:
        - host: ''
          http:
            paths:
              - path: '/'
                backend:
                  service:
                    name: <your_service_name>  # Replace it with the name of your target Service.
                    port:
                      number: <your_service_port>  # Replace it with the port number of your target Service.
                property:
                  ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH
                pathType: ImplementationSpecific
      ingressClassName: nginx
    For clusters of v1.21 or earlier:
    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: <your_service_port>  # Replace it with the port number of your target Service.
    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 that requests are hashed based on the request URI.
    • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri$host" indicates that requests are hashed based on the request URI and domain name.
    • nginx.ingress.kubernetes.io/upstream-hash-by: "${request_uri}-text-value" indicates that requests are hashed based on the request URI and text value.

  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

  4. Check the created ingress.

    kubectl get ingress

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

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