如何用 k8s ingress 以手動取得的 tls cert 來架 https 站

作者:   發佈於: ,更新於:   #certbot #kubernetes

這篇算是給自己看的筆記。

主要目的是把某個已經跑在 k8s cluster 內的兩個 TLD 相同的網站(foo.example.com, bar.example.com)加上 https。現有 Ingress 為 nginx​、憑證的來源為 letsencript​。大致上需要做的事是:

  1. 透過 certbot 工具來將憑證檔下載回來​
  2. 將憑證檔內容放入 k8s secret​
  3. 修改現有 Ingress 宣言,指定使用方才建立的 k8s secret 做為 TLS 憑證

日後憑證的定期更新就是第 1 與第 2 步的反覆。這三個步驟都是在個人設備(筆電)上做。也就是說每三個月要手動執行 certbot​。只是個權宜之計,其自動化以後再說。

各步驟指令如下。

透過 certbot 工具來將憑證檔下載回來​

#!/bin/bash

certbot --server https://acme-v02.api.letsencrypt.org/directory \
    -d "*.example.com" --manual \
    --preferred-challenges dns-01 certonly \
    --work-dir ~/var/certbot/example.com/work \
    --config-dir ~/var/certbot/config \
    --logs-dir ~/var/certbot/example.com/logs

這邊是指定用 DNS Challange ,所以會有要依照畫面指示修改 DNS 內容的步驟。細節參考 certbot 文件

做完之後,輸出會在 ~/var/certbot/。這個目錄不能丟,在未來更新憑證時還會用到。

將憑證檔內容放入 k8s secret​

#!/bin/bash
cd ~/var/certbot/config/live/example.com
kubectl create secret tls wildcard-example-com --key=privkey.pem --cert=fullchain.pem

這裡有個要注意的部分:​提供給 cert 參數的是 fullchain.pem 而不是 cert.pem​​。fullchain.pem 內除了包含了 cert.pem 證書全文之外,還包含了中遊與上游的證書。如果只提供 cert.pem​,會被某些瀏覽器視為安全性不足、網頁內容也不會被顯示出來。

修改現有 Ingress 宣言,指定使用方才建立的 k8s secret 做為 TLS 憑證

以下是整個 Ingress 宣言檔範例,主要是要加上 spec.tls​,secretName 要跟第二步的內給的名字相同(wildcard-example-com)。參考: Ingress 文件​。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-com
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - foo.example.com
    - bar.example.com
    secretName: wildcard-example-com
  rules:
  - host: foo.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: foo-service
            port:
              number: 80
  - host: bar.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: bar-service
            port:
              number: 80