全部產品
Search
文件中心

:Nginx Ingress進階用法

更新時間:Jun 19, 2024

在Kubernetes叢集中,Nginx Ingress對叢集服務(Service)中外部可訪問的API對象進行管理,提供七層負載平衡能力。您可以給Nginx Ingress配置提供外部可訪問的URL、Rewrite配置、HTTPS服務,以及灰階發布功能等。本文介紹如何配置安全的路由服務、HTTPS雙向認證、網域名稱支援正則化及泛化,申請免費的HTTPS認證等功能。

前提條件

配置說明

針對Nginx Ingress Controller,阿里雲Container Service團隊採用與社區完全相容的配置方式。關於所有的配置說明,請參見NGINX Configuration

目前其主要支援三種配置方式:

  • 基於Annotation的方式:在每個Nginx Ingress YAML的Annotation裡配置,只對本Nginx Ingress生效。更多資訊,請參見Annotations

  • 基於ConfigMap的方式:通過kube-system/nginx-configuration configmap的配置,是一個全域的配置,對所有的Nginx Ingress生效。更多資訊,請參見ConfigMaps

  • 自訂NGINX Template模板的方式:對Nginx Ingress Controller內部的NGINX Template有特殊配置要求,且當前通過Annotation和ConfigMap方式都無法滿足訴求的情況下採用該方式。更多資訊,請參見Custom NGINX template

配置URL重新導向的路由服務

當您在使用Nginx Ingress Controller的時候,Nginx會將路徑完整轉寄到後端(如,從Ingress訪問的/service1/api路徑會直接轉寄到後端Pod的/service1/api/路徑)。如果您後端的服務路徑為/api,則會出現路徑錯誤,導致404的情況。該情況下,您可以通過配置nginx.ingress.kubernetes.io/rewrite-target的方式,來將路徑重寫至需要的目錄。

根據不同叢集版本,建立Nginx Ingress。

1.19及之後版本叢集

cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: foo.bar.com
  namespace: default
  annotations:
    # URL重新導向。
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
    # 在Ingress Controller的版本≥0.22.0之後,path中需要使用Regex定義路徑,並在rewrite-target中結合擷取的群組一起使用。
      - path: /svc(/|$)(.*)
        backend:
          service: 
            name: web1-service
            port: 
              number: 80
        pathType: ImplementationSpecific
EOF

1.19及之前版本叢集

cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: foo.bar.com
  namespace: default
  annotations:
    # URL重新導向。
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
    # 在Ingress Controller的版本≥0.22.0之後,path中需要使用Regex定義路徑,並在rewrite-target中結合擷取的群組一起使用。
      - path: /svc(/|$)(.*)
        backend:
          serviceName: web1-service
          servicePort: 80
EOF
  1. 訪問Nginx服務。

    1. 執行以下命令,擷取ADDRESS

      kubectl  get  ingress

      預期輸出:

      NAME           CLASS   HOSTS                ADDRESS          PORTS   AGE
      foo.bar.com    nginx   foo.bar.com        172.16.XX.XX       80      46m
    2. 執行以下命令,替換ADDRESS為Ingress對應的IP。

      curl -k -H "Host: foo.bar.com"  http://<ADDRESS>/svc/foo

      預期輸出:

      web1: /foo

Rewrite配置

除了使用nginx.ingress.kubernetes.io/rewrite-target註解支援基本的Rewrite配置。具體操作,可參考配置URL重新導向的路由服務

如果對於一些複雜進階的Rewrite需求,可以通過如下註解來實現:

  • nginx.ingress.kubernetes.io/server-snippet:擴充配置到Server章節。

  • nginx.ingress.kubernetes.io/configuration-snippet:擴充配置到Location章節。

這兩個註解分別為Ingress組件的Nginx server模組添加自訂的程式碼片段,這提供了擴充和自訂Nginx配置的靈活性,可以應對不同的使用情境。

配置樣本:

annotations:
     nginx.ingress.kubernetes.io/server-snippet: |
         rewrite ^/v4/(.*)/card/query http://foo.bar.com/v5/#!/card/query permanent;
     nginx.ingress.kubernetes.io/configuration-snippet: |
         rewrite ^/v6/(.*)/card/query http://foo.bar.com/v7/#!/card/query permanent;

執行以下命令,查看Nginx Ingress Controller組件中Nginx設定檔。

kubectl exec nginx-ingress-controller-xxxxx --namespace kube-system -- cat /etc/nginx/nginx.conf   /#根據實際環境修改pod名稱

樣本配置產生的nginx.conf如下所示。

# start server foo.bar.com
    server {
        server_name foo.bar.com ;
        listen 80;
        listen [::]:80;
        set $proxy_upstream_name "-";
    # server-snippet配置。
        rewrite ^/v4/(.*)/card/query http://foo.bar.com/v5/#!/card/query permanent;
        ...
    # configuration-snippet配置。
      rewrite ^/v6/(.*)/card/query http://foo.bar.com/v7/#!/card/query permanent;
      ...
    }
    # end server foo.bar.com

同時,snippet也支援一些全域配置。詳細資料,請參見server-snippet

關於rewrite指令的具體用法,請參見Nginx官方文檔對該指令的描述

為路由規則配置HTTPS認證

您可以通過Ingress提供的原生語義來為網站配置 HTTPS 認證。

  1. 準備您的服務憑證。

    說明

    網域名稱需要與您所配置的Host一致,否則將無法被Nginx Ingress Controller正確載入。

    1. 執行以下命令,產生一個認證檔案tls.crt和一個私密金鑰檔案tls.key

      openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=foo.bar.com/O=foo.bar.com"
    2. 執行以下命令,建立密鑰。

      通過該認證和私密金鑰建立一個名為tls-test-ingress的Kubernetes Secret。建立Ingress時需要引用這個Secret。

      kubectl create secret tls tls-test-ingress --key tls.key --cert tls.crt
  2. 執行和部署以下命令與模板,建立Ingress資源,通過tls欄位引用上個步驟中建立的Secret。

    1.19及之後版本叢集

    cat <<EOF | kubectl create -f - 
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: test-test-ingress
    spec:
      # 引用tls認證。
      tls:
      - hosts:
        - foo.bar.com # 認證所對應的網域名稱。 
        secretName: tls-test-ingress
      rules:
      - host: tls-test-ingress.com
        http:
          paths:
          - path: /foo
            backend:
              service:
                name: web1-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
    EOF

    1.19版本之前叢集

    cat <<EOF | kubectl create -f - 
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: test-test-ingress
    spec:
      # 引用tls認證。
      tls:
      - hosts:
        - foo.bar.com # 認證所對應的網域名稱。
        secretName: tls-test-ingress
      rules:
      - host: tls-test-ingress.com
        http:
          paths:
          - path: /foo
            backend:
              serviceName: web1-svc
              servicePort: 80
    EOF
  3. 配置hosts檔案或者設定真實網域名稱來訪問該TLS服務。

    您可以通過https://tls-test-ingress.com/foo訪問到web1-svc服務。

配置HTTPS雙向認證

在某些情況下,您可能需要設定管理員與用戶端之間的雙向HTTPS認證來保證串連的安全性,Nginx Ingress Controller支援通過annotation的方式配置該功能。

  1. 執行以下命令,建立自簽的CA認證。

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

    預期輸出:

    Generating a 4096 bit RSA private key
    .............................................................................................................++
    .....................................................................................++
    writing new private key to 'ca.key'
  2. 執行以下命令,建立Server端認證。

    1. 執行以下命令,產生Server端認證的請求檔案。

      openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=foo.bar.com'

      預期輸出:

      Generating a 4096 bit 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
  3. 執行以下命令,建立Client端認證。

    1. 產生Client端認證的請求檔案。

      openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Fern'

      預期輸出:

      Generating a 4096 bit RSA private key
      .......................................................................................................................................................................................++
      ..............................................++
      writing new private key to 'client.key'
      -----
    2. 執行以下命令,使用根憑證簽發Client端請求檔案,產生Client端認證。

      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=Fern
      Getting CA Private Key
  4. 執行以下命令,檢查建立的認證。

    ls

    預期輸出:

    ca.crt  ca.key  client.crt  client.csr  client.key  server.crt  server.csr  server.key
  5. 執行以下命令,建立CA認證的Secret。

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

    預期輸出:

    secret/ca-secret created
  6. 執行以下命令,建立Server認證的Secret。

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

    預期輸出:

    secret/tls-secret created
  7. 執行和部署以下命令與模板,建立測試用的Nginx Ingress用例。

    1.19及之後版本叢集

    cat <<-EOF | kubectl apply -f -
    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"
        nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
        nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
      name: nginx-test
      namespace: default
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - backend:
              service:
                name: http-svc
                port: 
                  number: 80
            path: /
            pathType: ImplementationSpecific
      tls:
      - hosts:
        - foo.bar.com
        secretName: tls-secret
    EOF

    1.19版本之前叢集

    cat <<-EOF | kubectl apply -f -
    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"
        nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
        nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
      name: nginx-test
      namespace: default
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - backend:
              serviceName: http-svc
              servicePort: 80
            path: /
      tls:
      - hosts:
        - foo.bar.com
        secretName: tls-secret
    EOF

    預期輸出:

    ingress.networking.k8s.io/nginx-test configured
  8. 執行以下命令,查看Ingress的IP地址。

    kubectl get ing

    預期輸出如下,ADDRESS欄位對應的IP地址即為Ingress的IP地址。

    NAME         HOSTS                    ADDRESS         PORTS     AGE
    nginx-test   foo.bar.com              39.102.XX.XX    80, 443   4h42m
  9. 執行以下命令,更新Hosts檔案,替換下面的IP地址為真實擷取的Ingress的IP地址。

    echo "39.102.XX.XX  foo.bar.com" | sudo tee -a /etc/hosts

    結果驗證:

    • 用戶端不傳認證訪問

      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/1.19.0</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>

配置HTTPS服務轉寄到後端容器為HTTPS協議

Nginx Ingress Controller預設使用HTTP協議轉寄請求到後端業務容器。當您的業務容器為HTTPS協議時,可以通過使用註解nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"來使得Nginx Ingress Controller使用HTTPS協議轉寄請求到後端業務容器。

Nginx Ingress配置樣本如下:

1.19及之後版本叢集

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: backend-https
  annotations:
    # 注意這裡:必須指定後端服務為HTTPS服務。
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  tls:
  - hosts:
    - <your-host-name>
    secretName: <your-secret-cert-name>
  rules:
  - host: <your-host-name>
    http:
      paths:
      - path: /
        backend:
          service:
            name: <your-service-name>
            port: 
              number: <your-service-port>
        pathType: ImplementationSpecific

1.19版本之前叢集

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: backend-https
  annotations:
    # 注意這裡:必須指定後端服務為HTTPS服務。
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  tls:
  - hosts:
    - <your-host-name>
    secretName: <your-secret-cert-name>
  rules:
  - host: <your-host-name>
    http:
      paths:
      - path: /
        backend:
          serviceName: <your-service-name>
          servicePort: <your-service-port>

佈建網域名支援正則化

在Kubernetes叢集中,Ingress資源不支援對網域名稱配置Regex,但是可以通過nginx.ingress.kubernetes.io/server-alias註解來實現。

  1. 執行和部署以下命令與模板,以Regex~^www\.\d+\.example\.com為例。

    1.19及之後版本叢集

    cat <<-EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-regex
      namespace: default
      annotations:
        nginx.ingress.kubernetes.io/server-alias: '~^www\.\d+\.example\.com$, abc.example.com'
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - path: /foo
            backend:
              service:
                name: http-svc1
                port:
                  number: 80
            pathType: ImplementationSpecific
    EOF

    1.19版本之前叢集

    cat <<-EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: ingress-regex
      namespace: default
      annotations:
        nginx.ingress.kubernetes.io/server-alias: '~^www\.\d+\.example\.com$, abc.example.com'
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - path: /foo
            backend:
              serviceName: http-svc1
              servicePort: 80
     EOF
  2. 查看對應Nginx Ingress Controller的配置。

    1. 執行以下命令,查看部署Nginx Ingress Controller服務的Pod。

      kubectl get pods -n kube-system | grep nginx-ingress-controller

      預期輸出:

      nginx-ingress-controller-77cd987c4c-c****         1/1     Running   0          1h
      nginx-ingress-controller-77cd987c4c-x****         1/1     Running   0          1h
    2. 執行以下命令,查看對應Nginx Ingress Controller的配置,可以發現生效的配置(Server_Name欄位)。

      kubectl exec -n kube-system nginx-ingress-controller-77cd987c4c-c**** cat /etc/nginx/nginx.conf | grep -C3 "foo.bar.com"

      預期輸出:

        # start server foo.bar.com
        server {
      --
        server {
          server_name foo.bar.com abc.example.com ~^www\.\d+\.example\.com$ ;
          listen 80  ;
          listen 443  ssl http2 ;
      --
      --
          }
        }
        # end server foo.bar.com
  3. 執行以下命令,擷取Ingress對應的IP。

    kubectl get ing

    預期輸出:

    NAME            HOSTS         ADDRESS          PORTS     AGE
    ingress-regex   foo.bar.com   101.37.XX.XX     80        11s
  4. 執行以下命令,進行不同規則下的服務訪問測試。

    配置以下IP_ADDRESS為上一步擷取的IP地址。

    • 執行以下命令,通過Host: foo.bar.com訪問服務。

      curl -H "Host: foo.bar.com" <IP_ADDRESS>/foo

      預期輸出:

      /foo
    • 執行以下命令,通過Host: www.123.example.com訪問服務。

      curl -H "Host: www.123.example.com" <IP_ADDRESS>/foo

      預期輸出:

      /foo
    • 執行以下命令,通過Host: www.321.example.com訪問服務。

      curl -H "Host: www.321.example.com" <IP_ADDRESS>/foo

      預期輸出:

      /foo

佈建網域名支援泛化

在Kubernetes叢集中,Nginx Ingress資源支援對網域名稱配置泛網域名稱,例如,可配置*. ingress-regex.com泛網域名稱。

  1. 執行和部署以下命令與模板,建立Nginx Ingress。

    1.19及之後版本叢集

    cat <<-EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-regex
      namespace: default
    spec:
      rules:
    - host: *.ingress-regex.com
        http:
          paths:
          - path: /foo
            backend:
              service:
                name: http-svc1
                port:
                  number: 80
            pathType: ImplementationSpecific
    EOF

    1.19版本之前叢集

    $ cat <<-EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: ingress-regex
      namespace: default
    spec:
      rules:
     - host: *.ingress-regex.com
        http:
          paths:
          - path: /foo
            backend:
              serviceName: http-svc1
              servicePort: 80
     EOF
  2. 執行以下命令,查看對應Nginx Ingress Controller的配置,可以發現生效的配置(Server_Name欄位)。

    kubectl exec -n kube-system <nginx-ingress-pod-name> cat /etc/nginx/nginx.conf | grep -C3 "*.ingress-regex.com"
    說明

    替換nginx-ingress-pod-name為實際環境的nginx-ingress pod。

    預期輸出:

    # start server *.ingress-regex.com
      server {
        server_name *.ingress-regex.com ;
        listen 80;
        listen [::]:80;
    ...
      }
      # end server *.ingress-regex.com

    在較新版本的Nginx Ingress Controller中的預期輸出:

    ## start server *.ingress-regex.com
      server {
        server_name ~^(?<subdomain>[\w-]+)\.ingress-regex\.com$ ;
        listen 80;
        listen [::]:80;
    ...
      }
      ## end server *.ingress-regex.com
  3. 執行以下命令,擷取Ingress對應的IP。

    kubectl get ing

    預期輸出:

    NAME            HOSTS                 ADDRESS           PORTS     AGE
    ingress-regex   *.ingress-regex.com   101.37.XX.XX      80        11s
  4. 執行以下命令,進行不同規則下的服務訪問測試。

    配置以下IP_ADDRESS為上一步擷取的IP地址。

    • 執行以下命令,通過Host: abc.ingress-regex.com訪問服務。

      curl -H "Host: abc.ingress-regex.com" <IP_ADDRESS>/foo

      預期輸出:

      /foo
    • 執行以下命令,通過Host: 123.ingress-regex.com訪問服務。

      curl -H "Host: 123.ingress-regex.com" <IP_ADDRESS>/foo

      預期輸出:

      /foo
    • 執行以下命令,通過Host: a1b1.ingress-regex.com訪問服務。

      curl -H "Host: a1b1.ingress-regex.com" <IP_ADDRESS>/foo

      預期輸出:

      /foo

通過註解實現灰階發布

灰階發布功能可以通過設定註解來實現,為了啟用灰階發布功能,需要設定註解nginx.ingress.kubernetes.io/canary: "true",通過不同註解可以實現不同的灰階發布功能:

  • nginx.ingress.kubernetes.io/canary-weight:佈建要求到指定服務的百分比(值為0~100的整數)。

  • nginx.ingress.kubernetes.io/canary-by-header:基於Request Header的流量切分,當配置的header值為always時,請求流量會被分配到灰階服務入口;當header值為never時,請求流量不會分配到灰階服務;將忽略其他header值,並通過灰階優先順序將請求流量分配到其他規則設定的灰階服務。

  • nginx.ingress.kubernetes.io/canary-by-header-valuenginx.ingress.kubernetes.io/canary-by-header:當請求中的headerheader-value與設定的值匹配時,請求流量會被分配到灰階服務入口;將忽略其他header值,並通過灰階優先順序將請求流量分配到其他規則設定的灰階服務。

  • nginx.ingress.kubernetes.io/canary-by-cookie:基於Cookie的流量切分,當配置的cookie值為always時,請求流量將被分配到灰階服務入口;當配置的cookie值為never時,請求流量將不會分配到灰階服務入口。

以下為部分註解配置樣本,更多資訊,請參見通過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為ack:always時將訪問灰階服務;請求Header為ack: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: "ack"
  • 基於Header灰階(自訂header值):當請求Header為ack:alibaba時將訪問灰階服務;其他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: "ack"
        nginx.ingress.kubernetes.io/canary-by-header-value: "alibaba"
  • 基於Cookie灰階:當Header不匹配時,請求的Cookie為hangzhou_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: "ack"
        nginx.ingress.kubernetes.io/canary-by-header-value: "alibaba"
        nginx.ingress.kubernetes.io/canary-by-cookie: "hangzhou_region"
說明
  • 基於Cookie的灰階不支援設定自訂,只有alwaysnever

  • 灰階優先順序順序:基於Header > 基於Cookie > 基於權重(從高到低)。

使用cert-manager申請免費的HTTPS認證

cert-manager是一個雲原生認證管理開源工具,用於在Kubernetes叢集中提供HTTPS認證並自動續期。以下樣本介紹了如何使用cert-manager申請免費認證並自動續期。

  1. 執行以下命令,部署cert-manager。

    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
    說明

    上述命令中的YAML樣本僅適用於在ACK叢集中部署cert-manager。關於如何在ACK Serverless叢集中部署cert-manager,請參見使用cert-manager申請免費的HTTPS認證

  2. 執行以下命令,查看Pod狀態。

    kubectl get pods -n cert-manager

    預期輸出:

    NAME                     READY   STATUS    RESTARTS   AGE
    cert-manager-1           1/1     Running   0          2m11s
    cert-manager-cainjector  1/1     Running   0          2m11s
    cert-manager-webhook     1/1     Running   0          2m10s
  3. 執行以下命令,建立ClusterIssuer。

    cat <<EOF | kubectl apply -f -
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod-http01
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: <your_email_name@gmail.com>  # 替換為您的郵箱名。
        privateKeySecretRef:
          name: letsencrypt-http01
        solvers:
        - http01: 
            ingress:
              class: nginx
    EOF
  4. 執行以下命令,查看ClusterIssuer。

    kubectl get clusterissuer

    預期輸出:

    NAME                         READY   AGE
    letsencrypt-prod-http01      True    17s
  5. 執行以下命令,建立Nginx Ingress資來源物件。

    1.19及之後版本叢集

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-tls
      annotations:
        kubernetes.io/ingress.class: "nginx"
        cert-manager.io/cluster-issuer: "letsencrypt-prod-http01"
    spec:
      tls:
      - hosts:
        - <your_domain_name>        # 替換為您的網域名稱。
        secretName: ingress-tls   
      rules:
      - host: <your_domain_name>    # 替換為您的網域名稱。
        http:
          paths:
          - path: /
            backend:
              service:
                name: <your_service_name>  # 替換為您的後端服務名。
                port: 
                  number: <your_service_port>  # 替換為您的服務連接埠。
            pathType: ImplementationSpecific
    EOF

    1.19版本之前叢集

    cat <<EOF | kubectl apply -f -
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: ingress-tls
      annotations:
        kubernetes.io/ingress.class: "nginx"
        cert-manager.io/cluster-issuer: "letsencrypt-prod-http01"
    spec:
      tls:
      - hosts:
        - <your_domain_name>        # 替換為您的網域名稱。
        secretName: ingress-tls   
      rules:
      - host: <your_domain_name>    # 替換為您的網域名稱。
        http:
          paths:
          - path: /
            backend:
              serviceName: <your_service_name>  # 替換為您的後端服務名。
              servicePort: <your_service_port>  # 替換為您的服務連接埠。
    EOF
    說明

    替換的網域名稱your_domain_name必須符合以下條件:

    • 網域名稱不能超過64個字元。

    • 不支援泛網域名稱。

    • 在公網以HTTP協議可正常訪問。

  6. 執行以下命令,查看認證。

    kubectl get cert

    預期輸出:

    NAME          READY   SECRET        AGE
    ingress-tls   True    ingress-tls   52m
    說明

    如果READY狀態不為True,可通過kubectl describe cert ingress-tls查看認證處理過程。

  7. 執行以下命令,查看Secret。

    kubectl get secret  ingress-tls

    預期輸出:

    NAME          TYPE                DATA   AGE
    ingress-tls   kubernetes.io/tls   2      2m
  8. 通過Web瀏覽器輸入https://[網站網域名稱]訪問設定的網域名稱。

配置HTTP重新導向至HTTPS

Nginx Ingress的nginx.ingress.kubernetes.io/ssl-redirect註解可以強制將HTTP重新導向到HTTPS。樣本如下所示:

1.19及之後版本叢集

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true" # 強制將HTTP流量重新導向到HTTPS。

1.19版本之前叢集

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true" # 強制將HTTP流量重新導向到HTTPS。