更新时间:2024-05-07 GMT+08:00
分享

使用Annotation配置Nginx Ingress

CCE的Nginx Ingress插件使用社区模板与镜像,Nginx Ingress默认的其他参数无法满足业务需求时,也可通过添加注解Annotation(注解)的方式自定义参数,例如默认后端、超时时间、请求body体大小等。

本文介绍在创建Nginx类型的Ingress时常用的Annotation。

  • 注解的键值只能是字符串,其他类型(如布尔值或数值)必须使用引号,例如"true"、"false"、"100"。
  • Nginx Ingress支持社区的原生注解,详情请参考Annotations

Ingress类型

表1 Ingress类型注解

参数

类型

描述

支持的集群版本

kubernetes.io/ingress.class

String

  • nginx:表示使用Nginx Ingress。
  • cce:表示使用自研ELB Ingress。

通过API接口创建Ingress时必须增加该参数。

v1.23及以上集群使用ingressClassName参数代替,详情请参见通过Kubectl命令行创建Nginx Ingress

仅v1.21及以下集群

上述注解的使用方法详情请参见通过Kubectl命令行创建Nginx Ingress

配置重定向规则

表2 重定向规则注解

参数

类型

描述

nginx.ingress.kubernetes.io/permanent-redirect

String

将访问请求永久重定向至某个目标网址(状态码为301)。

nginx.ingress.kubernetes.io/permanent-redirect-code

String

修改永久重定向的返回状态码为指定值。

nginx.ingress.kubernetes.io/temporal-redirect

String

将访问请求临时重定向至某个目标网址(状态码为302)。

nginx.ingress.kubernetes.io/ssl-redirect

String

是否只能通过SSL访问(当Ingress包含证书时默认为true),将HTTP请求重定向至HTTPS。

nginx.ingress.kubernetes.io/force-ssl-redirect

String

是否强制重定向到HTTPS,即使Ingress未启用TLS,通过HTTP访问时,请求将会被强制重定向(状态码为308)到HTTPS。

具体使用场景和说明请参见Nginx Ingress配置重定向规则

配置URL重写规则

表3 URL重写规则注解

参数

类型

描述

nginx.ingress.kubernetes.io/rewrite-target

String

重定向流量的目标URI。

具体使用场景和说明请参见Nginx Ingress配置URL重写规则

对接HTTPS协议的后端服务

表4 对接HTTPS协议的后端服务注解

参数

类型

描述

nginx.ingress.kubernetes.io/backend-protocol

String

参数值为'HTTPS',表示使用HTTPS协议转发请求到后端业务容器。

具体使用场景和说明请参见Nginx Ingress对接HTTPS协议的后端服务

创建一致性哈希负载均衡规则

表5 一致性哈希负载均衡注解

参数

类型

描述

nginx.ingress.kubernetes.io/upstream-hash-by

String

为后端启用一致性哈希进行负载均衡,参数值支持nginx参数、文本值或任意组合,例如:
  • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"代表按照请求uri进行hash。
  • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri$host"代表按照请求uri和域名进行hash。
  • nginx.ingress.kubernetes.io/upstream-hash-by: "${request_uri}-text-value"代表按照请求uri和文本值进行hash。

具体使用场景和说明请参见Nginx Ingress使用一致性哈希负载均衡

自定义超时时长

表6 自定义超时时长注解

参数

类型

描述

nginx.ingress.kubernetes.io/proxy-connect-timeout

String

自定义连接超时时长,设置超时值时无需填写单位,默认单位为秒。

例如:

nginx.ingress.kubernetes.io/proxy-connect-timeout: '120'

自定义Body体大小

表7 自定义Body体大小注解

参数

类型

描述

nginx.ingress.kubernetes.io/proxy-body-size

String

当请求中的Body体大小超过允许的最大值时,将向客户端返回413错误,您可通过该参数调整Body体的限制大小。

例如:

nginx.ingress.kubernetes.io/proxy-body-size: 8m

HTTPS双向认证

Nginx Ingress支持配置服务器与客户端之间的双向HTTPS认证来保证连接的安全性。

  1. 请参见通过kubectl连接集群,使用kubectl连接集群。
  2. 执行以下命令,创建自签名的CA证书。

    openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=Ingress Cert Authority'

    预期输出:

    Generating a RSA private key
    .............++++
    ................................................++++
    writing new private key to 'ca.key'
    -----

  3. 执行以下命令,创建Server端证书。

    1. 执行以下命令,生成Server端证书的请求文件。
      openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=foo.bar.com'

      预期输出:

      Generating a RSA private key
      .....................................................++++
      ..........++++
      writing new private key to 'server.key'
      -----
    2. 执行以下命令,使用根证书签发Server端请求文件,生成Server端证书。
      openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

      预期输出:

      Signature ok
      subject=CN = foo.bar.com
      Getting CA Private Key

  4. 执行以下命令,生成Client端证书。

    1. 执行以下命令,生成Client端证书的请求文件。
      openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Ingress'

      预期输出:

      Generating a RSA private key
      .................................++++
      ................................................++++
      writing new private key to 'client.key'
      -----
    2. 执行以下命令,使用根证书签发Server端请求文件,生成Server端证书。
      openssl x509 -req -sha256 -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt

      预期输出:

      Signature ok
      subject=CN = Ingress
      Getting CA Private Key

  5. 执行ls命令,查看创建的证书。

    预期输出:

    ca.crt  ca.key  client.crt  client.csr  client.key  server.crt  server.csr  server.key

  6. 执行以下命令,生成CA证书的Secret。

    kubectl create secret generic ca-secret --from-file=ca.crt=ca.crt

    预期输出:

    secret/ca-secret created

  7. 执行以下命令,生成Server端证书的Secret。

    kubectl create secret generic tls-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key

    预期输出:

    secret/tls-secret created

  8. 创建名为“ingress-test.yaml”的YAML文件,此处文件名可自定义。

    vi ingress-test.yaml

    • 1.23及以上版本集群
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
          nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"   #替换您的CA证书秘钥
          nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
          nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
        name: ingress-test
        namespace: default
      spec:
        rules:
        - host: foo.bar.com
          http:
            paths:
            - backend:
                service:
                  name: nginx-test  #替换为您的目标服务名称
                  port: 
                    number: 80  #替换为您的目标服务端口
              path: /
              pathType: ImplementationSpecific
        tls:
        - hosts:
          - foo.bar.com
          secretName: tls-secret   #替换您的TLS证书秘钥
        ingressClassName: nginx
    • 1.21及以下版本集群
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress 
      metadata: 
        annotations: 
          nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
          nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"   #替换您的CA证书秘钥
          nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
          nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
        name: ingress-test
        namespace: default
      spec:
        rules: 
        - host: foo.bar.com
          http: 
            paths: 
            - path: '/'
              backend: 
                serviceName: nginx-test  #替换为您的目标服务名称
                servicePort: 80  #替换为您的目标服务端口
        tls: 
        - hosts: 
          - foo.bar.com
          secretName: tls-secret   #替换为您的TLS密钥证书
        ingressClassName: nginx

  9. 执行以下命令,创建Ingress。

    kubectl create -f ingress-test.yaml

    预期输出:

    ingress.networking.k8s.io/ingress-test created

  10. 执行以下命令,查看Ingress的IP地址。

    kubectl get ingress

    预期输出:

    NAME         CLASS   HOSTS         ADDRESS      PORTS     AGE
    nginx-test   nginx   foo.bar.com   10.3.xx.xx   80, 443   27m

  11. 执行以下命令,将Ingress的IP地址更新到Hosts文件中,替换下面的IP地址为真实获取的Ingress的IP地址

    echo "10.3.xx.xx  foo.bar.com" | sudo tee -a /etc/hosts

    预期输出:

    10.3.xx.xx  foo.bar.com

  12. 结果验证。

    • 客户端不传证书访问
      curl --cacert ./ca.crt  https://foo.bar.com

      预期输出:

      <html>
      <head><title>400 No required SSL certificate was sent</title></head>
      <body>
      <center><h1>400 Bad Request</h1></center>
      <center>No required SSL certificate was sent</center>
      <hr><center>nginx</center>
      </body>
      </html>
    • 客户端传证书访问
      curl --cacert ./ca.crt --cert ./client.crt --key ./client.key https://foo.bar.com

      预期输出:

      <!DOCTYPE html>
      <html>
      <head>
      <title>Welcome to nginx!</title>
      <style>
      body {
          width: 35em;
          margin: 0 auto;
          font-family: Tahoma, Verdana, Arial, sans-serif;
      }
      </style>
      </head>
      <body>
      <h1>Welcome to nginx!</h1>
      <p>If you see this page, the nginx web server is successfully installed and
      working. Further configuration is required.</p>
       
      <p>For online documentation and support please refer to
      <a href="http://nginx.org/">nginx.org</a>.<br/>
      Commercial support is available at
      <a href="http://nginx.com/">nginx.com</a>.</p>
       
      <p><em>Thank you for using nginx.</em></p>
      </body>
      </html>

域名正则化

Nginx Ingress支持配置“nginx.ingress.kubernetes.io/server-alias”注解实现域名配置正则表达式。

  1. 请参见通过kubectl连接集群,使用kubectl连接集群。
  2. 创建名为“ingress-test.yaml”的YAML文件,此处文件名可自定义。

    vi ingress-test.yaml

    以正则表达式~^www\.\d+\.example\.com$,abc.example.com为例,表示使用www.{一个或多个数字}.example.com和abc.example.com域名也可正常访问Ingress。

    • 1.23及以上版本集群
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          nginx.ingress.kubernetes.io/server-alias: '~^www\.\d+\.example\.com$,abc.example.com'
        name: ingress-test
        namespace: default
      spec:
        rules:
        - host: foo.bar.com
          http:
            paths:
            - backend:
                service:
                  name: nginx-93244  #替换为您的目标服务名称
                  port: 
                    number: 80  #替换为您的目标服务端口
              path: /
              pathType: ImplementationSpecific
        ingressClassName: nginx
    • 1.21及以下版本集群
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress 
      metadata: 
        annotations: 
          nginx.ingress.kubernetes.io/ server-alias: '~^www\.\d+\.example\.com$,abc.example.com'
        name: ingress-test
        namespace: default
      spec:
        rules: 
        - host: foo.bar.com
          http: 
            paths: 
            - path: '/'
              backend: 
                serviceName: nginx-test  #替换为您的目标服务名称
                servicePort: 80  #替换为您的目标服务端口
        ingressClassName: nginx

  3. 执行以下命令,创建Ingress。

    kubectl create -f ingress-test.yaml

    预期输出:

    ingress.networking.k8s.io/ingress-test created

  4. 查看Nginx Ingress Controller的配置。

    1. 执行以下命令,查看Nginx Ingress Controller服务的Pod
      kubectl get pods -n kube-system | grep nginx-ingress-controller

      预期输出:

      cceaddon-nginx-ingress-controller-68d7bcc67-dxxxx        1/1     Running   0          18h
      cceaddon-nginx-ingress-controller-68d7bcc67-cxxxx        1/1     Running   0          18h
    2. 执行以下命令,查看Nginx Ingress Controller的配置
      kubectl exec -n kube-system cceaddon-nginx-ingress-controller-68d7bcc67-dxxxx cat /etc/nginx/nginx.conf | grep -C3 "foo.bar.com"

      预期输出:

               ## start server foo.bar.com
               server {
                        server_name foo.bar.com abc.example.com ~^www\.\d+\.example\.com$ ;
                        
                        listen 80  ;
                        listen [::]:80  ;
      --
                        }
                        
               }
               ## end server foo.bar.com

  5. 执行以下命令,获取Ingress对应的IP。

    kubectl get ingress

    预期输出:

    NAME         CLASS   HOSTS         ADDRESS      PORTS   AGE
    nginx-test   nginx   foo.bar.com   10.3.xx.xx   80      14m

  6. 执行以下命令,测试不同规则下的服务访问。

    • 执行以下命令,通过Host: foo.bar.com访问服务。
      curl -H "Host: foo.bar.com" 10.3.xx.xx/

      预期可正常访问网页。

    • 执行以下命令,通过Host: www.123.example.com访问服务
      curl -H "Host: www.123.example.com" 10.3.xx.xx/

      预期可正常访问网页。

    • 执行以下命令,通过Host: www.321.example.com访问服务
      curl -H "Host: www.321.example.com" 10.3.xx.xx/

      预期可正常访问网页。

灰度发布

灰度发布功能可以通过设置注解来实现,为了启用灰度发布功能,需要设置注解nginx.ingress.kubernetes.io/canary: "true",通过不同注解可以实现不同的灰度发布功能:

表8 灰度发布注解

参数

类型

描述

nginx.ingress.kubernetes.io/canary-weight

String

设置请求到指定服务的百分比(值为0~100的整数)。

nginx.ingress.kubernetes.io/canary-by-header

String

基于Request Header的流量切分,如果请求头中包含指定的header名称,并且值为“always”,就将该请求转发给Canary Ingress定义的对应后端服务。如果值为“never”则不转发,可用于回滚到旧版本。如果为其他值则忽略该annotation,并通过优先级将请求流量分配到其他规则。

nginx.ingress.kubernetes.io/canary-by-header-value

String

必须与canary-by-header一起使用,可自定义请求头的取值,包含但不限于“always”或“never”。当请求头的值命中指定的自定义值时,请求将会转发给Canary Ingress定义的对应后端服务,如果是其他值则忽略该annotation,并通过优先级将请求流量分配到其他规则。

nginx.ingress.kubernetes.io/canary-by-header-pattern

String

与canary-by-header-value类似,唯一区别是该annotation用正则表达式匹配请求头的值,而不是某一个固定值。如果该annotation与canary-by-header-value同时存在,该annotation将被忽略。

nginx.ingress.kubernetes.io/canary-by-cookie

String

基于Cookie的流量切分,当配置的cookie值为always时,请求流量将被分配到灰度服务入口;当配置的cookie值为never时,请求流量将不会分配到灰度服务入口。

  • 以上注解规则会按优先级进行评估,优先级为:canary-by-header -> canary-by-cookie -> canary-weight。
  • 当Ingress被标记为Canary Ingress时,除了nginx.ingress.kubernetes.io/load-balance和nginx.ingress.kubernetes.io/upstream-hash-by外,所有其他非Canary的注解都将被忽略。

更多信息,请参见通过Nginx Ingress实现灰度发布和蓝绿发布

以下为部分注解配置示例:

  • 基于权重灰度:配置灰度服务的权重为20%。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-weight: "20"
    ...
  • 基于Header灰度:请求Header为cce:always时将访问灰度服务;请求Header为cce:never时将不访问灰度服务;其他Header将根据灰度权重将流量分配给灰度服务。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-weight: "50"
        nginx.ingress.kubernetes.io/canary-by-header: "cce"
    ...
  • 基于Header灰度(自定义header值):当请求Header为cce:test时将访问灰度服务;其他Header将根据灰度权重将流量分配给灰度服务。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-weight: "20"
        nginx.ingress.kubernetes.io/canary-by-header: "cce"
        nginx.ingress.kubernetes.io/canary-by-header-value: "test"
    ...
  • 基于Cookie灰度:当Header不匹配时,请求的Cookie为region=always时将访问灰度服务。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-weight: "20"
        nginx.ingress.kubernetes.io/canary-by-header: "cce"
        nginx.ingress.kubernetes.io/canary-by-header-value: "test"
        nginx.ingress.kubernetes.io/canary-by-cookie: "region"
    ...

相关文档

更多关于Nginx Ingress支持的注解参数,请参见Annotations

分享:

    相关文档

    相关产品