使用 Cert Manager 為 Kubernetes 應用自動簽發 HTTPS 證書

varro發表於2020-03-28

Cert-Manager 是一個雲原生證照管理開源專案,用於在 Kubernetes 叢集中提供 HTTPS 證照並自動續期,支援 Let’s Encrypt / HashiCorp / Vault 這些免費證照的簽發。在 Kubernetes 中,可以通過 Kubernetes Ingress 和 Let’s Encrypt 實現外部服務的自動化 HTTPS

此文章按照 Cert Manager 官網 的推薦步驟, 使用 helm3 安裝並配置 Cert-Manager

安裝 Helm3

若你還未安裝 Helm3, 可參考我的 這篇文章 安裝 Helm

安裝 Cert-Manager

建立 CustomResourceDefinition 使用者自定義資源

# 針對 Kubernetes 1.15+ 以上版本使用以下命令
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.14.0/cert-manager.crds.yaml

customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created

建立名稱空間

我使用的名稱空間為 cluster-service,替換為你自己的名稱空間:

$ kubectl create namespace cluster-service

namespace/cluster-service created

新增 Jetstack Helm 倉庫

$ helm repo add jetstack https://charts.jetstack.io

更新 Helm 倉庫

$ helm repo update

安裝 Cert Manager

# Helm v3+
$ helm install \
  cert-manager jetstack/cert-manager \
  --namespace cluster-service \
  --version v0.14.0


NAME: cert-manager
LAST DEPLOYED: Fri Mar 27 06:26:00 2020
NAMESPACE: cluster-service
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://docs.cert-manager.io/en/latest/reference/issuers.html

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://docs.cert-manager.io/en/latest/reference/ingress-shim.html

安裝成功, 檢視安裝結果

我使用的 Kubernetes 管理介面是 Kuboard

1585290595100

配置 Issuer 或 Clusterissuer

官方介紹這中 Issuer 與 ClusterIssuer 的概念:

Issuers, and ClusterIssuers, are Kubernetes resources that represent certificate authorities (CAs) that are able to generate signed certificates by honoring certificate signing requests. All cert-manager certificates require a referenced issuer that is in a ready condition to attempt to honor the request.

Issuer 與 ClusterIssuer 的區別是 ClusterIssuer 可跨名稱空間使用,而 Issuer 需在每個名稱空間下配置後才可使用。我在此使用ClusterIssuer,其型別選擇 Let‘s Encrypt

配置 staging 環境使用的 Let‘s Encrypt ClusterIssuer,並建立:

# cluster-issuer-letsencrypt-staging.yaml

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # 務必將此處替換為你自己的郵箱, 否則會配置失敗。當證照快過期時 Let's Encrypt 會與你聯絡
    email: user@example.com
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # 將用來儲存 Private Key 的 Secret 資源
      name: letsencrypt-staging
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx
$ kubectl create -f cluster-issuer-letsencrypt-staging.yaml

clusterissuer.cert-manager.io/letsencrypt-staging created

配置 production 環境使用的 Let‘s Encrypt ClusterIssuer,並建立:

# cluster-issuer-letsencrypt-prod.yaml

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: varroreve@gmail.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx
$ kubectl create -f cluster-issuer-letsencrypt-prod.yaml

clusterissuer.cert-manager.io/letsencrypt-prod created

檢視:

$ kubectl get clusterissuer

NAME                  READY   AGE
letsencrypt-prod      True    37s
letsencrypt-staging   True    119m

這裡分別配置了測試環境與生產環境兩個 ClusterIssuer, 原因是 Let’s Encrypt 的生產環境有著非常嚴格的介面呼叫限制,最好是在測試環境測試通過後,再切換為生產環境。

Let’s Encrypt 測試環境與生產環境的區別

測試

這裡我假設你已安裝好 Nginx Ingress Controller 並已存在一個 Ingress 物件,現在為它開啟 TLS 選項

# quickstart-example.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kuard
  annotations:
    # 務必新增以下兩個註解, 指定 ingress 型別及使用哪個 cluster-issuer
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer:"letsencrypt-staging"

    # 如果你使用 issuer, 使用以下註解 
    # cert-manager.io/issuer: "letsencrypt-staging"

spec:
  tls:
  - hosts:
    - example.example.com                # TLS 域名
    secretName: quickstart-example-tls   # 用於儲存證照的 Secret 物件名字 
  rules:
  - host: example.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kuard
          servicePort: 80

應用此更新

$ kubectl create -f quickstart-example.yaml

之後 Cert-manager 會讀取註解並建立證照,使用以下命令檢視:

$ kubectl get certificate -A

NAME                     READY   SECRET                   AGE
quickstart-example-tls   True    quickstart-example-tls   16m

當 Ready 為 True 時代表證照安裝成功若出現問題可使用 descirbe 命令檢視具體出錯原因:

$ kubectl describe certificate -A 

切換到生產環境

當一切就緒後,將 Ingress 物件中的 cluster-issuer 註解改為 Let’s Encrypt 生產環境

# quickstart-example.yaml

cert-manager.io/cluster-issuer: "letsencrypt-prod"

更新 Ingress 後訪問你的網站,應該可以看到 HTTPS 證照配置

1585373007182

1585373024926

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章