在 Azure Kubernetes Service (AKS) 上搭配輸入控制器使用 TLS

傳輸層安全性 (TLS) 通訊協定會使用憑證來提供通訊、加密、驗證和完整性的安全性。 在 AKS 上搭配輸入控制器使用 TLS,可讓您保護應用程式之間的通訊,並體驗輸入控制器的優點。

您可以攜帶自己的憑證,並將其與「秘密存放區」CSI 驅動程式整合。 或者,您可以使用 cert-manager \(英文\),其會自動產生並設定 Let's Encrypt \(英文\) 憑證。 有兩個應用程式會在 AKS 叢集中執行,每個均可透過單一 IP 位址來存取。

重要

建議將應用程式路由附加元件用於 AKS 中的輸入。 如需詳細資訊,請參閱具有應用程式路由附加元件的受控 nginx 輸入

重要

Microsoft「不」會管理或支援憑證管理員,以及其使用所產生的任何問題。 如需 cert-manager 的問題,請參閱 cert-manager 疑難解答文件。

以 Nginx 為基礎的 Kubernetes 具有兩個開放原始碼輸入控制器:一個由 Kubernetes 社群維護 (kubernetes/ingress-nginx),一個則由 NGINX, Inc. 維護 (nginxinc/kubernetes-ingress)。 本文使用「Kubernetes 社群輸入控制器」

開始之前

  • 此文章假設您已設定輸入控制器與應用程式。 如果您需要輸入控制器或範例應用程式,請參閱建立輸入控制器

  • 本文使用 Helm 3,在Kubernetes 的已支援版本上安裝 NGINX 輸入控制器。 確定您使用的是最新版的 Helm,而且可以存取 ingress-nginxjetstack Helm 存放庫。 本文所述的步驟可能與舊版 Helm 圖表、NGINX 輸入控制器或 Kubernetes 不相容。

  • 此文章假設您有具有整合式 Azure Container Registry (ACR) 的現有 AKS 叢集。 如需使用整合式 ACR 來建立 AKS 叢集的詳細資訊,請參閱從 AKS 使用 ACR 進行驗證

  • 如果您使用 Azure CLI,此文章會要求您執行 Azure CLI 2.0.64 版或更新版本。 執行 az --version 以尋找版本。 如果您需要安裝或升級,請參閱安裝 Azure CLI

  • 如果您使用 Azure PowerShell,此文章會要求您執行 Azure PowerShell 5.9.0 版或更新版本。 執行 Get-InstalledModule -Name Az 以尋找版本。 如果您需要安裝或升級,請參閱安裝 Azure PowerShell

透過「秘密存放區」CSI 驅動程式搭配您自己的憑證使用 TLS

若要透過祕密存放區 CSI 驅動程式搭配您自己的憑證使用 TLS,您需要已設定祕密存放區 CSI 驅動程式的 AKS 叢集,以及 Azure Key Vault 執行個體。

如需詳細資訊,請參閱「秘密存放區」CSI 驅動程式以啟用具有 TLS 的 NGINX 輸入控制器

將 TLS 與 Let's Encrypt 一起使用

若要搭配 Let's Encrypt \(英文\) 憑證使用 TLS,您必須部署 cert-manager \(英文\),其會自動產生並設定 Let's Encrypt 憑證。

將 Helm 圖表所使用的影像匯入至您的 ACR

  • 使用 az acr import,將下列映像匯入您的 ACR。

    REGISTRY_NAME=<REGISTRY_NAME>
    CERT_MANAGER_REGISTRY=quay.io
    CERT_MANAGER_TAG=v1.8.0
    CERT_MANAGER_IMAGE_CONTROLLER=jetstack/cert-manager-controller
    CERT_MANAGER_IMAGE_WEBHOOK=jetstack/cert-manager-webhook
    CERT_MANAGER_IMAGE_CAINJECTOR=jetstack/cert-manager-cainjector
    
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG
    

注意

您也可以將 Helm 圖表匯入至 ACR。 如需詳細資訊,請參閱將 Helm 圖表推送並提取至 ACR

輸入控制器設定選項

您可以使用靜態公用 IP 位址或動態公用 IP 位址來設定 NGINX 輸入控制器。 如果您使用自訂網域,則必須將 A 記錄新增至您的 DNS 區域。 如果您未使用自訂網域,則可以設定輸入控制器 IP 位址的完整網域名稱 (FQDN)。

建立靜態或動態公用 IP 位址

使用靜態公用 IP 位址

您可以使用靜態公用 IP 位址來設定輸入控制器。 如果您刪除輸入控制器,則仍會保留靜態公用 IP 位址。 如果您刪除 AKS 叢集,則「不」會保留 IP 位址。

當您升級輸入控制器時,必須將參數傳遞至 Helm 版本,確保輸入控制器服務知道將對其進行配置的負載平衡器。 為了讓 HTTPS 憑證正常運作,您使用 DNS 標籤來設定輸入控制器 IP 位址的 FQDN。

  1. 使用 az aks show 命令來取得 AKS 叢集的資源群組名稱。

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
  2. 使用 az network public-ip create 命令,建立具有「靜態」配置方法的公用 IP 位址。 下列範例會在上於一個步驟取得的 AKS 叢集資源群組中,建立名為 myAKSPublicIP 的公用 IP 位址。

    az network public-ip create --resource-group MC_myResourceGroup_myAKSCluster_eastus --name myAKSPublicIP --sku Standard --allocation-method static --query publicIp.ipAddress -o tsv
    

注意

或者,您可以在不同的資源群組中建立可與 AKS 叢集分開管理的 IP 位址。 如果您在不同的資源群組中建立 IP 位址,請確定下列為真:

  • AKS 叢集所使用的叢集身分識別具有資源群組的委派權限,例如:網路參與者
  • 新增 --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="<RESOURCE_GROUP>" 參數。 將 <RESOURCE_GROUP> 取代為 IP 位址所在的資源群組名稱。
  1. 新增 --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>" 參數。 可以在輸入控制器第一次部署時設定 DNS 標籤,也可以稍後進行設定。

  2. 新增 --set controller.service.loadBalancerIP="<STATIC_IP>" 參數。 指定您在上一個步驟中所建立的自有公用 IP 位址。

    DNS_LABEL="<DNS_LABEL>"
    NAMESPACE="ingress-basic"
    STATIC_IP=<STATIC_IP>
    
    helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
      --namespace $NAMESPACE \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNS_LABEL \
      --set controller.service.loadBalancerIP=$STATIC_IP \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz
    

如需詳細資訊,請參閱搭配 AKS 負載平衡器使用靜態公用 IP 位址和 DNS 標籤

使用動態公用 IP 位址

建立時,會建立輸入控制器的 Azure 公用 IP 位址。 在輸入控制器的生命週期內,公用 IP 位址為靜態。 如果您刪除輸入控制器,則「不」會保留公用 IP 位址。 如果您建立新的輸入控制器,則其將會獲指派新的公用 IP 位址。 輸出看起來應該類似下列範例輸出。

  • 使用 kubectl get service 命令,以取得輸入控制器的公用 IP 位址。

    # Get the public IP address for your ingress controller
    
    kubectl --namespace ingress-basic get services -o wide -w nginx-ingress-ingress-nginx-controller
    
    # Sample output
    
    NAME                                     TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE   SELECTOR
    nginx-ingress-ingress-nginx-controller   LoadBalancer   10.0.74.133   EXTERNAL_IP     80:32486/TCP,443:30953/TCP   44s   app.kubernetes.io/component=controller,app.kubernetes.io/instance=nginx-ingress,app.kubernetes.io/name=ingress-nginx
    

將 A 記錄新增至您的 DNS 區域

如果您要使用自訂網域,則需要將「A」 記錄新增至您的 DNS 區域。 如果您未使用自訂網域,則可以設定具有 FQDN 的公用 IP 位址。

  • 使用 az network dns record-set a add-record,以將「A」記錄新增至具有 NGINX 服務外部 IP 位址的 DNS 區域。

    az network dns record-set a add-record \
        --resource-group myResourceGroup \
        --zone-name MY_CUSTOM_DOMAIN \
        --record-set-name "*" \
        --ipv4-address MY_EXTERNAL_IP
    

設定輸入控制器的 FQDN

您可以選擇性地設定 DNS 標籤來設定輸入控制器 IP 位址的 FQDN,而不是自訂網域。 FQDN 應該遵循此格式:<CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com

重要

DNS 標籤在其 Azure 位置內必須是唯一的。

您可以使用下列其中一個方法來設定 FQDN:

  • 使用 Azure CLI 或 Azure PowerShell 來設定 DNS 標籤。
  • 使用 Helm 圖表設定來設定 DNS 標籤。

如需詳細資訊,請參閱公用 IP 位址 DNS 名稱標籤

使用 Azure CLI 或 Azure PowerShell 來設定 DNS 標籤

請務必將 <DNS_LABEL> 取代為您的唯一 DNS 標籤。

# Public IP address of your ingress controller
IP="MY_EXTERNAL_IP"

# Name to associate with public IP address
DNSLABEL="<DNS_LABEL>"

# Get the resource-id of the public IP
PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv)

# Update public IP address with DNS name
az network public-ip update --ids $PUBLICIPID --dns-name $DNSLABEL

# Display the FQDN
az network public-ip show --ids $PUBLICIPID --query "[dnsSettings.fqdn]" --output tsv

使用 Helm 圖表設定來設定 DNS 標籤

您可以使用 --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" 參數,以將註釋設定傳遞至 Helm 圖表設定。 可以在輸入控制器第一次部署時設定此參數,也可以稍後進行設定。

下列範例說明如何在部署控制器之後更新此設定。 請務必將 <DNS_LABEL> 取代為您的唯一 DNS 標籤。

DNSLABEL="<DNS_LABEL>"
NAMESPACE="ingress-basic"

helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNSLABEL \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz

安裝 cert-manager

NGINX 輸入控制器支援 TLS 終止。 有數種方式可以擷取和設定 HTTPS 的憑證。 此文章使用 cert-manager \(英文\),其會提供自動化的 Lets Encrypt \(英文\) 憑證產生與管理功能。

若要安裝 cert-manager 控制器,請使用下列命令。

# Set variable for ACR location to use for pulling images
ACR_URL=<REGISTRY_URL>

# Label the ingress-basic namespace to disable resource validation
kubectl label namespace ingress-basic cert-manager.io/disable-validation=true

# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io

# Update your local Helm chart repository cache
helm repo update

# Install the cert-manager Helm chart
helm install cert-manager jetstack/cert-manager \
  --namespace ingress-basic \
  --version=$CERT_MANAGER_TAG \
  --set installCRDs=true \
  --set nodeSelector."kubernetes\.io/os"=linux \
  --set image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CONTROLLER \
  --set image.tag=$CERT_MANAGER_TAG \
  --set webhook.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_WEBHOOK \
  --set webhook.image.tag=$CERT_MANAGER_TAG \
  --set cainjector.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CAINJECTOR \
  --set cainjector.image.tag=$CERT_MANAGER_TAG

如需 cert-manager 設定的詳細資訊,請參閱 cert-manager 專案

建立 CA 叢集簽發者

發行憑證之前,cert-manager 需要下列其中一個簽發者:

  • 簽發者 \(英文\),其可在單一命名空間中運作。
  • ClusterIssuer \(英文\) 資源,其可跨所有命名空間運作。

如需詳細資訊,請參閱 cert-manager 簽發者文件。

  1. 使用下列範例資訊清單來建立叢集簽發者,例如 cluster-issuer.yaml。 使用您組織的有效位址來取代 MY_EMAIL_ADDRESS

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: MY_EMAIL_ADDRESS
        privateKeySecretRef:
          name: letsencrypt
        solvers:
        - http01:
            ingress:
              class: nginx
              podTemplate:
                spec:
                  nodeSelector:
                    "kubernetes.io/os": linux
    
  2. 使用 kubectl apply 命令來套用簽發者。

    kubectl apply -f cluster-issuer.yaml --namespace ingress-basic
    

更新輸入路由

您必須更新輸入路由來處理流向您 FQDN 或自訂網域的流量。

在下列範例中,流量會以如下方式路由傳送:

  • 流向 hello-world-ingress.MY_CUSTOM_DOMAIN 的流量會路由傳送至 aks-helloworld-one 服務。
  • 流向 hello-world-ingress.MY_CUSTOM_DOMAIN/hello-world-two 的流量會路由傳送至 aks-helloworld-two 服務。
  • hello-world-ingress.MY_CUSTOM_DOMAIN/static 的流量會路由傳送至 aks-helloworld-one,以取得靜態資產。

注意

如果您已針對輸入控制器 IP 位址設定 FQDN,而不是自訂網域,請使用 FQDN 而不是 hello-world-ingress.MY_CUSTOM_DOMAIN

例如,如果您的 FQDN 是 demo-aks-ingress.eastus.cloudapp.azure.com,將 hello-world-ingress.MY_CUSTOM_DOMAIN 取代為 hello-world-ingress.yaml 中的 demo-aks-ingress.eastus.cloudapp.azure.com

  1. 使用下列範例 YAML 檔案來建立或更新 hello-world-ingress.yaml 檔案。 將 spec.tls.hostsspec.rules.host 更新為您在上一個步驟中所建立的 DNS 名稱。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
        nginx.ingress.kubernetes.io/use-regex: "true"
        cert-manager.io/cluster-issuer: letsencrypt
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - hello-world-ingress.MY_CUSTOM_DOMAIN
        secretName: tls-secret
      rules:
      - host: hello-world-ingress.MY_CUSTOM_DOMAIN
        http:
          paths:
          - path: /hello-world-one(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
          - path: /hello-world-two(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-two
                port:
                  number: 80
          - path: /(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress-static
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.ingress.kubernetes.io/rewrite-target: /static/$2
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - hello-world-ingress.MY_CUSTOM_DOMAIN
        secretName: tls-secret
      rules:
      - host: hello-world-ingress.MY_CUSTOM_DOMAIN
        http:
          paths:
          - path: /static(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    
  2. 使用 kubectl apply 命令更新輸入資源。

    kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic
    

驗證是否已建立憑證物件

接下來,必須建立憑證資源。 憑證資源會定義所需的 X.509 憑證。 如需詳細資訊,請參閱 cert-manager 憑證

Cert-manager 會使用 ingress-shim 自動為您建立憑證物件,自 0.2.2 版起,ingress-shim 即會隨著 cert-manager 會自動部署。 如需詳細資訊,請參閱 ingress-shim 文件

若要驗證是否已成功建立憑證,請使用 kubectl get certificate --namespace ingress-basic 命令,並確認 READY 是否為 True。 可能需要幾分鐘的時間才能取得輸出。

kubectl get certificate --namespace ingress-basic

下列輸出顯示憑證的狀態。

NAME         READY   SECRET       AGE
tls-secret   True    tls-secret   11m

測試輸入組態

將網頁瀏覽器開啟至 Kubernetes 輸入控制器的 hello-world-ingress.MY_CUSTOM_DOMAIN。 確保下列條件成立:

  • 系統已將您重新導向至使用 HTTPS。
  • 憑證是「受信任的」
  • 示範應用程式已顯示於網頁瀏覽器中。
  • /hello-world-two 新增至網域結尾,並確定已顯示具有自訂標題的第二個示範應用程式。

清除資源

本文使用 Helm 來安裝輸入元件、憑證及範例應用程式。 部署 Helm 圖表時會建立許多 Kubernetes 資源。 這些資源包含 Pod、部署和服務。 若要清除這些資源,您可以刪除整個範例命名空間或個別資源。

刪除範例命名空間和所有資源

刪除範例命名空間也會刪除命名空間中的所有資源。

  • 使用 kubectl delete 命令,並指定命名空間名稱,以刪除整個範例命名空間。

    kubectl delete namespace ingress-basic
    

個別刪除資源

或者,您可以個別刪除資源。

  1. 移除叢集簽發者資源。

    kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
    
  2. 使用helm list命令,列出 Helm 版本。 尋找名為 nginxcert-manager 的圖表,如下列範例輸出所示。

    $ helm list --namespace ingress-basic
    
    NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
    cert-manager            ingress-basic   1               2020-01-15 10:23:36.515514 -0600 CST    deployed        cert-manager-v0.13.0    v0.13.0
    nginx                   ingress-basic   1               2020-01-15 10:09:45.982693 -0600 CST    deployed        nginx-ingress-1.29.1    0.27.0
    
  3. 使用 helm uninstall 命令,以解除安裝這些版本。 下列範例會解除安裝 NGINX 輸入和 cert-manager 部署。

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. 移除這兩個範例應用程式。

    kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
    
  5. 移除將流量導向範例應用程式的輸入路由。

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. 刪除自身的命名空間。 使用 kubectl delete 命令,並指定命名空間名稱。

    kubectl delete namespace ingress-basic
    

下一步

本文包含 AKS 的一些外部元件。 若要深入了解這些元件,請參閱下列專案頁面:

您也可以: