新消息:在TwitterMastodon取得專案更新

在 Azure Kubernetes Service (AKS) 上部署 cert-manager 並使用 Let's Encrypt 為 HTTPS 網站簽署憑證

最後驗證時間:2024 年 1 月 11 日

在本教學中,您將學習如何在 Azure Kubernetes Service (AKS) 上部署和設定 cert-manager,以及如何部署 HTTPS 網頁伺服器並使其在網際網路上可用。您將學習如何設定 cert-manager 以從 Let's Encrypt 取得簽署的憑證,這將允許客戶安全地連線到您的 HTTPS 網站。您將設定 cert-manager 以使用 Let's Encrypt DNS-01 挑戰協定搭配 Azure DNS,並使用工作負載身分同盟向 Azure 驗證。

Microsoft Azure:Microsoft 的一套雲端運算服務。
Kubernetes:在您的伺服器上執行。自動化容器化應用程式的部署、擴展和管理。
cert-manager:在 Kubernetes 中執行。取得 TLS/SSL 憑證,並確保憑證有效且為最新狀態。
Let’s Encrypt:網際網路服務。允許您產生免費的短期 SSL 憑證。

第一部分

在本教學的第一部分,您將學習在 Azure Kubernetes 叢集上部署 HTTPS 網站所需的基本知識,使用 cert-manager 為網頁伺服器建立 SSL 憑證。您將為您的網站建立 DNS 網域、建立 Azure Kubernetes 叢集、安裝 cert-manager、建立 SSL 憑證,然後部署網頁伺服器,該伺服器回應來自網際網路上客戶的 HTTPS 請求。但是,第一部分的 SSL 憑證僅用於測試目的。

在第二部分中,您將學習如何設定 cert-manager 以使用 Let's Encrypt 和 Azure DNS 來建立可信賴的 SSL 憑證,您可以在生產環境中使用該憑證。

設定 Azure CLI ( az )

如果您尚未執行此操作,請下載並安裝 Azure CLI ( az )

設定 az 命令以供互動式使用

az init

登入,如果您尚未執行此操作

az login

設定預設資源群組和位置

export AZURE_DEFAULTS_GROUP=your-resource-group # ❗ Your Azure resource group
export AZURE_DEFAULTS_LOCATION=eastus2 # ❗ Your Azure location.

ℹ️ 您將需要 az 版本 >=2.40.0。執行 az version 來列印目前版本。

ℹ️ 當您執行 az init 時,在出現提示時選擇「針對互動進行最佳化」。

ℹ️ 當您執行 az login 時,網頁瀏覽器將在 https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize 開啟。請在網頁瀏覽器中繼續登入,然後返回您的終端機。

📖 閱讀Azure 命令列介面 (CLI) 文件

📖 閱讀 CLI 設定值和環境變數,以了解設定 az 預設值的更多方法。

建立公用網域名稱

在本教學中,您將部署具有可公開存取網域名稱的 HTTPS 網站,因此您需要註冊網域,除非您已擁有一個。您可以使用任何 網域名稱註冊商來註冊您網站的網域名稱。在這裡,我們將使用名為 Gandi 的註冊商,並為了本教學的目的註冊一個便宜的網域名稱。我們將使用網域名稱:cert-manager-tutorial-22.site,但您應該選擇自己的。

現在您知道了您的網域名稱,請將其儲存在環境變數中

export DOMAIN_NAME=cert-manager-tutorial-22.site # ❗ Replace this with your own DNS domain name

並將其作為區域新增至 Azure DNS

az network dns zone create --name $DOMAIN_NAME

登入您網域註冊商的控制面板,並將您網域的 NS 記錄設定為與 Azure 授權 DNS 伺服器的 DNS 名稱相符。您可以透過尋找您 Azure 託管 DNS 區域的 NS 記錄來找到這些。

az network dns zone show --name $DOMAIN_NAME --output yaml

您可以使用 dig 來「追蹤」NS 記錄的階層結構,而不是使用您本機的 DNS 解析器,來檢查 NS 記錄是否已更新

dig $DOMAIN_NAME ns +trace +nodnssec

⏲ 在父區域中更新 NS 記錄可能需要 1 小時以上的時間,而且如果當您在更新 NS 記錄之前查詢 DNS 名稱,則 DNS 解析器伺服器的快取中更換舊的 NS 記錄可能需要一些時間。

📖 閱讀 Gandi.net 文件中的如何更新我的 DNS 記錄?,或尋找您自己的網域名稱註冊商的對應文件。

建立 Kubernetes 叢集

首先,讓我們在 Microsoft Azure 中建立 Kubernetes 叢集。您將需要為您的叢集選擇一個名稱。在這裡,我們將使用「test-cluster-1」。將其儲存在環境變數中

export CLUSTER=test-cluster-1

現在,使用以下命令建立叢集

az aks create \
--name ${CLUSTER} \
--node-count 1 \
--node-vm-size "Standard_B2s" \
--load-balancer-sku basic

使用新叢集的認證更新您的 kubectl 設定檔

az aks get-credentials --admin --name "$CLUSTER"

現在檢查您是否可以連線到叢集

kubectl get nodes -o wide

⏲ 建立叢集需要 4-5 分鐘的時間。

💵 為了將您的雲端費用降到最低,此命令會使用低成本的虛擬機器和負載平衡器建立一個單節點叢集。

⚠️ 此叢集僅適用於學習目的,不適用於生產環境。

📖 閱讀 在 Azure 中以便宜的方式執行 Kubernetes,以了解更多節省成本的技巧。

安裝 cert-manager

現在您可以安裝和設定 cert-manager。

使用 helm 如下安裝 cert-manager

helm repo add jetstack https://charts.jetstack.io --force-update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.1 \
--set crds.enabled=true

這將在名為 cert-manager 的新命名空間中建立三個部署和一些服務和 Pod。它還會安裝各種叢集範圍的支援資源,例如 RBAC 角色和自訂資源定義。

您可以查看已安裝的一些資源如下

kubectl -n cert-manager get all

您可以使用 kubectl explain 探索自訂資源定義 (cert-manager 的 API),如下所示

kubectl explain Certificate
kubectl explain CertificateRequest
kubectl explain Issuer

📖 閱讀關於其他安裝 cert-manager 的方式

📖 閱讀更多關於憑證和簽發者的資訊。

建立測試 ClusterIssuer 和憑證

現在一切都已準備就緒,您可以建立您的第一個憑證。這將是一個自我簽署的憑證,但稍後我們將用 Let's Encrypt 簽署的憑證取代它。

# clusterissuer-selfsigned.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned
spec:
selfSigned: {}

🔗 clusterissuer-selfsigned.yaml

kubectl apply -f clusterissuer-selfsigned.yaml

然後使用 envsubst 將您選擇的網域名稱代入以下憑證範本

# certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: www
spec:
secretName: www-tls
privateKey:
rotationPolicy: Always
commonName: www.$DOMAIN_NAME
dnsNames:
- www.$DOMAIN_NAME
usages:
- digital signature
- key encipherment
- server auth
issuerRef:
name: selfsigned
kind: ClusterIssuer

🔗 certificate.yaml

envsubst < certificate.yaml | kubectl apply -f -

🔗 如果您還沒有安裝 envsubst,您可以下載並安裝 Go 實作的 envsubst

使用 cmctl status certificate 來檢查憑證的狀態

cmctl status certificate www

如果成功,私密金鑰和簽署的憑證將儲存在名為 www-tls 的 Secret 中。您可以使用 cmctl inspect secret www-tls 來解碼 Secret 的 base64 編碼 X.509 內容

$ cmctl inspect secret www-tls
...
Valid for:
DNS Names:
- www.cert-manager-tutorial-22.site
URIs: <none>
IP Addresses: <none>
Email Addresses: <none>
Usages:
- digital signature
- key encipherment
- server auth
...

部署範例網頁伺服器

現在部署一個簡單的網頁伺服器,該伺服器使用「hello world!」回應 HTTPS 請求。SSL/TLS 金鑰和憑證會透過使用 www-tls Secret 作為磁碟區,並將其內容掛載到 Pod 中 hello-app 容器的檔案系統中,提供給網頁伺服器

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloweb
labels:
app: hello
spec:
selector:
matchLabels:
app: hello
tier: web
template:
metadata:
labels:
app: hello
tier: web
spec:
containers:
- name: hello-app
image: us-docker.pkg.dev/google-samples/containers/gke/hello-app-tls:1.0
imagePullPolicy: Always
ports:
- containerPort: 8443
volumeMounts:
- name: tls
mountPath: /etc/tls
readOnly: true
env:
- name: TLS_CERT
value: /etc/tls/tls.crt
- name: TLS_KEY
value: /etc/tls/tls.key
volumes:
- name: tls
secret:
secretName: www-tls

🔗 deployment.yaml

kubectl apply -f deployment.yaml

您還需要建立一個 Kubernetes LoadBalancer 服務,以便將來自網際網路的連線路由至網頁伺服器 Pod。當您建立下列 Kubernetes 服務時,也會建立一個具有臨時公用 IP 位址的 Azure 負載平衡器。

# service.yaml
apiVersion: v1
kind: Service
metadata:
name: helloweb
annotations:
service.beta.kubernetes.io/azure-dns-label-name: $AZURE_LOADBALANCER_DNS_LABEL_NAME
spec:
ports:
- port: 443
protocol: TCP
targetPort: 8443
selector:
app: hello
tier: web
type: LoadBalancer

🔗 service.yaml

為 LoadBalancer 服務建立一個唯一的 DNS 名稱,然後套用它。

export AZURE_LOADBALANCER_DNS_LABEL_NAME=lb-$(uuidgen) # ❗ The label must start with a lowercase ASCII letter
envsubst < service.yaml | kubectl apply -f -

在 2-3 分鐘內,應該會佈建一個具有公用 IP 的負載平衡器。

kubectl get service helloweb

範例輸出

$ kubectl get service helloweb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloweb LoadBalancer 10.0.141.1 20.114.151.62 443:30394/TCP 7m15s

您的 EXTERNAL-IP 會與這裡的不同,而且每次重新建立 LoadBalancer 服務時都可能不同,但它會具有與之關聯的穩定 DNS 主機名稱,因為您使用 azure-dns-label-name 註解了該服務。這個穩定的 DNS 主機名稱可以透過建立 DNS CNAME 記錄,作為您選擇的 $DOMAIN_NAME 的別名。

az network dns record-set cname set-record \
--zone-name $DOMAIN_NAME \
--cname $AZURE_LOADBALANCER_DNS_LABEL_NAME.$AZURE_DEFAULTS_LOCATION.cloudapp.azure.com \
--record-set-name www

檢查 www.$DOMAIN_NAME 現在是否解析為負載平衡器的臨時公用 IP 位址。

$ dig www.$DOMAIN_NAME A
...
;; QUESTION SECTION:
;www.cert-manager-tutorial-22.site. IN A
...
;; ANSWER SECTION:
www.cert-manager-tutorial-22.site. 3600 IN CNAME lb-ec8776e1-d067-4d4c-8cce-fdf07ce48260.eastus2.cloudapp.azure.com.
lb-ec8776e1-d067-4d4c-8cce-fdf07ce48260.eastus2.cloudapp.azure.com. 10 IN A 20.122.27.189
...

如果 DNS 正確且負載平衡器正常運作,且 hello world 網頁伺服器正在執行,您現在應該可以使用 curl 或您的網頁瀏覽器連線到它。

curl --insecure -v https://www.$DOMAIN_NAME

⚠️ 我們使用了 curl 的 --insecure 選項,因為它預設會拒絕自我簽署的憑證。稍後您將學習如何建立由 Let's Encrypt 簽署的可信任憑證。

您應該會看到憑證具有預期的 DNS 名稱,並且是自我簽署的。

...
* Server certificate:
* subject: CN=www.cert-manager-tutorial-22.site
* start date: Jan 4 15:28:30 2023 GMT
* expire date: Apr 4 15:28:30 2023 GMT
* issuer: CN=www.cert-manager-tutorial-22.site
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
...
Hello, world!
Protocol: HTTP/2.0!
Hostname: helloweb-55cb4cd887-tjlvh

📖 閱讀更多關於使用服務來公開您的應用程式的資訊。

📖 閱讀更多關於將公用 IP 位址和 DNS 標籤與 Azure Kubernetes Service (AKS) 負載平衡器搭配使用的資訊。

第 2 部分

在第 1 部分中,您建立了一個測試憑證。現在您將學習如何設定 cert-manager 以使用 Let's Encrypt 和 Azure DNS 來建立一個可信任的憑證,您可以在生產環境中使用該憑證。您需要向 Let's Encrypt 證明您擁有憑證的網域名稱,而一種方法是在該網域中建立一個特殊的 DNS 記錄。這稱為 DNS-01 挑戰類型

cert-manager 可以透過使用 Azure DNS API 為您建立該 DNS 記錄,但它需要先向 Azure 驗證,而目前最安全的驗證方法是使用工作負載身分識別同盟。這種方法的優點是,cert-manager 將使用臨時的 Kubernetes ServiceAccount 權杖向 Azure 進行驗證,並且該權杖不需要儲存在 Kubernetes Secret 中。

ℹ️ cert-manager >= v1.11.0 支援使用 Azure DNS 進行 ACME (Let's Encrypt) DNS-01 的工作負載身分識別同盟。較舊版本的 cert-manager 支援其他驗證機制,本教學課程未涵蓋這些機制。

📖 閱讀關於其他使用 Azure DNS 設定 ACME 發行者的資訊

安裝 Azure 工作負載身分識別功能

Azure AKS 中的工作負載身分識別功能相對較新(在撰寫本文時),它們需要啟用一些非預設的功能。

安裝 Azure CLI AKS Preview 延伸模組,您需要它來在您的 AKS 叢集上設定一些進階的工作負載身分識別同盟功能。

az extension add --name aks-preview

註冊 EnableWorkloadIdentityPreview 功能標誌,這是此示範中的 AKS 叢集所需的。

az feature register --namespace "Microsoft.ContainerService" --name "EnableWorkloadIdentityPreview"
# It takes a few minutes for the status to show Registered. Verify the registration status by using the az feature list command:
az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/EnableWorkloadIdentityPreview')].{Name:name,State:properties.state}"
# When ready, refresh the registration of the Microsoft.ContainerService resource provider by using the az provider register command:
az provider register --namespace Microsoft.ContainerService

📖 閱讀更多關於註冊 EnableWorkloadIdentityPreview 功能標誌的資訊。

重新設定叢集

接下來,在您先前建立的叢集上啟用工作負載身分識別同盟功能。

az aks update \
--name ${CLUSTER} \
--enable-oidc-issuer \
--enable-workload-identity # ℹ️ This option is currently only available when using the aks-preview extension.

📖 閱讀在 Azure Kubernetes Service (AKS) 叢集上部署和設定工作負載身分識別,以取得關於 --enable-workload-identity 功能的更多資訊。

重新設定 cert-manager

我們將標記 cert-manager 控制器 Pod 和 ServiceAccount,以引起 Azure 工作負載身分識別 webhook 的注意,這將導致 cert-manager 控制器 Pod 具有額外的磁碟區,其中包含它將用於向 Azure 進行驗證的 Kubernetes ServiceAccount 權杖。

可以使用下面的 Helm values 檔案來設定標籤。

# values.yaml
podLabels:
azure.workload.identity/use: "true"
serviceAccount:
labels:
azure.workload.identity/use: "true"

🔗 values.yaml

existing_cert_manager_version=$(helm get metadata -n cert-manager cert-manager | grep '^VERSION' | awk '{ print $2 }')
helm upgrade cert-manager jetstack/cert-manager \
--reuse-values \
--namespace cert-manager \
--version $existing_cert_manager_version \
--values values.yaml

新推出的 cert-manager Pod 將設定一些新的環境變數,並將 Azure 工作負載身分識別 ServiceAccount 權杖作為投影磁碟區。

kubectl describe pod -n cert-manager -l app.kubernetes.io/component=controller
Containers:
...
cert-manager-controller:
...
Environment:
...
AZURE_CLIENT_ID:
AZURE_TENANT_ID: f99bd6a4-665c-41cf-aff1-87a89d5c62d4
AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/
Mounts:
/var/run/secrets/azure/tokens from azure-identity-token (ro)
Volumes:
...
azure-identity-token:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3600

📖 閱讀關於Azure AD Kubernetes 工作負載身分識別中 Mutating Admission Webhook 的角色的資訊。

📖 閱讀關於cert-manager Helm chart 中可以自訂的其他值的資訊。

建立 Azure 受管理身分

當 cert-manager 使用 Let's Encrypt 建立憑證時,它可以使用 DNS 記錄來證明它控制著憑證中的 DNS 網域名稱。為了讓 cert-manager 使用 Azure API 並操作 Azure DNS 區域中的記錄,它需要一個 Azure 帳戶,而最佳的帳戶類型稱為「受管理身分」。此帳戶不附帶密碼或 API 金鑰,並且設計用於機器而不是人類。

選擇一個受管理身分名稱。

export USER_ASSIGNED_IDENTITY_NAME=cert-manager-tutorials-1 # ❗ Replace with your preferred managed identity name

建立受管理身分。

az identity create --name "${USER_ASSIGNED_IDENTITY_NAME}"

授予它修改 DNS 區域記錄的權限。

export USER_ASSIGNED_IDENTITY_CLIENT_ID=$(az identity show --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -o tsv)
az role assignment create \
--role "DNS Zone Contributor" \
--assignee $USER_ASSIGNED_IDENTITY_CLIENT_ID \
--scope $(az network dns zone show --name $DOMAIN_NAME -o tsv --query id)

📖 閱讀 什麼是 Azure 資源的受管理身分? 以取得受管理身分及其用途的概觀。

📖 閱讀 Azure 內建角色,以了解「DNS 區域參與者」角色。

新增同盟身分

現在我們將設定 Azure 以信任某些 Kubernetes ServiceAccount 權杖,特別是來自我們特定 Kubernetes 叢集的服務帳戶權杖,而且只有與 cert-manager ServiceAccount 相關聯的權杖。cert-manager 將使用短暫的 Kubernetes ServiceAccount 權杖向 Azure 進行驗證,並且它將能夠模擬您在上一步中建立的受管理身分。

首先匯出包含 cert-manager 控制器使用的 Kubernetes ServiceAccount 名稱和命名空間的下列環境變數。

export SERVICE_ACCOUNT_NAME=cert-manager # ℹ️ This is the default Kubernetes ServiceAccount used by the cert-manager controller.
export SERVICE_ACCOUNT_NAMESPACE=cert-manager # ℹ️ This is the default namespace for cert-manager.

然後,透過提供其「主體」(Kubernetes ServiceAccount 的識別名稱)及其「發行者」(可以下載 JWT 簽署憑證和其他中繼資料的 URL),設定受管理身分以信任 cert-manager Kubernetes ServiceAccount。

export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group $AZURE_DEFAULTS_GROUP --name $CLUSTER --query "oidcIssuerProfile.issuerUrl" -o tsv)
az identity federated-credential create \
--name "cert-manager" \
--identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
--issuer "${SERVICE_ACCOUNT_ISSUER}" \
--subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"

📖 閱讀 Microsoft 身分識別平台文件中關於工作負載身分識別同盟的資訊。

為 Let's Encrypt Staging 建立 ClusterIssuer

ClusterIssuer 是一種自訂資源,它會告知 cert-manager 如何簽署憑證。在這種情況下,將設定 ClusterIssuer 以連線到 Let's Encrypt Staging 伺服器,這可讓我們在不耗盡網域名稱的 Let's Encrypt 憑證配額的情況下測試所有內容。

將下列內容儲存到名為 clusterissuer-lets-encrypt-staging.yaml 的檔案,將 email 欄位變更為使用您的電子郵件地址,然後套用它。

# clusterissuer-lets-encrypt-staging.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: $EMAIL_ADDRESS
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- dns01:
azureDNS:
resourceGroupName: $AZURE_DEFAULTS_GROUP
subscriptionID: $AZURE_SUBSCRIPTION_ID
hostedZoneName: $DOMAIN_NAME
environment: AzurePublicCloud
managedIdentity:
clientID: $USER_ASSIGNED_IDENTITY_CLIENT_ID

🔗 clusterissuer-lets-encrypt-staging.yaml

如您所見,clusterissuer-lets-encrypt-staging.yaml 中有一些變數需要您在套用之前填寫;大部分已在本教學稍早定義,但您需要設定以下內容

export EMAIL_ADDRESS=<email-address> # ❗ Replace this with your email address
export AZURE_SUBSCRIPTION=<your-subscription-or-billing-account> # ❗ Replace this with your Azure account name

現在使用 envsubst 來填寫變數,並將其導向至 kubectl apply,如下所示

export AZURE_SUBSCRIPTION_ID=$(az account show --name $AZURE_SUBSCRIPTION --query 'id' -o tsv)
envsubst < clusterissuer-lets-encrypt-staging.yaml | kubectl apply -f -

您可以檢查 ClusterIssuer 的狀態

kubectl describe clusterissuer letsencrypt-staging

範例輸出

Status:
Acme:
Last Registered Email: firstname.lastname@example.com
Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/77882854
Conditions:
Last Transition Time: 2022-11-29T13:05:33Z
Message: The ACME account was registered with the ACME server
Observed Generation: 1
Reason: ACMEAccountRegistered
Status: True
Type: Ready

ℹ️ Let's Encrypt 使用自動憑證管理環境 (ACME) 協定,這就是為什麼上面的設定在一個名為 acme 的金鑰下。

ℹ️ 電子郵件地址僅供 Let's Encrypt 用於提醒您在到期前 30 天續訂憑證。只有在 cert-manager 續訂憑證時發生錯誤,您才會收到這封電子郵件。

ℹ️ Let's Encrypt 生產發行者有非常嚴格的速率限制。當您在實驗和學習時,很容易達到這些限制。由於這個風險,我們將從 Let's Encrypt staging 發行者開始,一旦我們確定它運作正常,我們將切換到生產發行者。

📖 閱讀更多關於設定 ACME 發行者的資訊。

使用 Let's Encrypt 重新發行憑證

修補憑證以使用 staging ClusterIssuer

kubectl patch certificate www --type merge -p '{"spec":{"issuerRef":{"name":"letsencrypt-staging"}}}'

這應該會觸發 cert-manager 來更新憑證:使用 cmctl 檢查

cmctl status certificate www
cmctl inspect secret www-tls

最後,當新的憑證發行後,您必須重新啟動網頁伺服器才能使用它

kubectl rollout restart deployment helloweb

您應該可以再次連線到網站,但這次您會看到 Let's Encrypt staging 憑證

$ curl -v --insecure https://www.$DOMAIN_NAME
...
* Server certificate:
* subject: CN=www.cert-manager-tutorial-22.site
* start date: Jan 5 12:41:14 2023 GMT
* expire date: Apr 5 12:41:13 2023 GMT
* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
...
Hello, world!
Protocol: HTTP/2.0!
Hostname: helloweb-9b8bcdd56-6rxm8

⚠️ 我們再次在這裡使用 curl 的 --insecure 選項,因為 Let's Encrypt staging 發行者會建立不受信任的憑證。接下來您將學習如何建立由 Let's Encrypt 生產發行者簽署的受信任憑證。

建立可供生產環境使用的憑證

現在所有東西都與 Let's Encrypt staging 伺服器運作良好,我們可以切換到生產伺服器並取得受信任的憑證。

透過複製 staging ClusterIssuer YAML 並修改伺服器 URL 和名稱,然後套用,來建立 Let's Encrypt 生產發行者

# clusterissuer-lets-encrypt-production.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: $EMAIL_ADDRESS
privateKeySecretRef:
name: letsencrypt-production
solvers:
- dns01:
azureDNS:
resourceGroupName: $AZURE_DEFAULTS_GROUP
subscriptionID: $AZURE_SUBSCRIPTION_ID
hostedZoneName: $DOMAIN_NAME
environment: AzurePublicCloud
managedIdentity:
clientID: $USER_ASSIGNED_IDENTITY_CLIENT_ID

🔗 clusterissuer-lets-encrypt-production.yaml

envsubst < clusterissuer-lets-encrypt-production.yaml | kubectl apply -f -

檢查 ClusterIssuer 的狀態

kubectl describe clusterissuer letsencrypt-production

修補憑證以使用生產 ClusterIssuer

kubectl patch certificate www --type merge -p '{"spec":{"issuerRef":{"name":"letsencrypt-production"}}}'

這應該會觸發 cert-manager 來更新憑證:使用 cmctl 檢查

cmctl status certificate www
cmctl inspect secret www-tls

最後,當新的憑證發行後,您必須重新啟動網頁伺服器才能使用它

kubectl rollout restart deployment helloweb

現在您應該可以安全地連線到網頁伺服器,而無需 --insecure 旗標,如果您在網頁瀏覽器中造訪該網站,則 URL 旁邊應會顯示一個鎖頭 (🔒) 符號。

curl -v https://www.$DOMAIN_NAME
...
* Server certificate:
* subject: CN=cert-manager-tutorial-22.site
* start date: Nov 30 15:41:40 2022 GMT
* expire date: Feb 28 15:41:39 2023 GMT
* subjectAltName: host "www.cert-manager-tutorial-22.site" matched cert's "www.cert-manager-tutorial-22.site"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
...

本教學到此結束。您已學習如何在 Azure AKS 上部署 cert-manager,以及如何設定它以使用 Azure DNS 透過 DNS-01 協定發行 Let's Encrypt 簽署的憑證。您已了解 Azure 中的工作負載身分識別同盟,並學習如何設定 cert-manager 以使用 Kubernetes ServiceAccount 權杖向 Azure 進行驗證。

清除

完成本教學後,您可以依照以下方式刪除叢集、網域名稱和受管理身分識別來進行清除

az aks delete --name $CLUSTER
az network dns zone delete --name $DOMAIN_NAME
az identity delete --name $USER_ASSIGNED_IDENTITY_NAME

後續步驟

📖 閱讀其他cert-manager 教學入門指南

📖 閱讀更多關於使用 Azure DNS 設定 cert-manager ACME 發行者的資訊。