cert-manager-with-kubernetes-ingress


說起免費的HTTPS cert 很多人都會用let’s encrypt的服務 原因是簡單,易用 在VM上裝一個script然後簡單配置一下nginx就可以生成一張數個月的ssl certificate

但當來到kubernetes就有點麻煩 原因是你配置的服務很多可能都不在同一部機上 當你生成了一張ssl cert之後可能要手動去更新相應的配置 而且要建立自動更新難度更大

所以這時侯就可以用到cert-manager了 https://github.com/jetstack/cert-manager 他是一個k8s的addon 可以生成一系列的resources去幫以上的配置自動化 而且除了let’s encrypt之外也支持其他的ssl cert發行者

如果是用let’s encrypt的話 原理大致如下

首先你會生成一個ingress 並加一些特殊的annotation去表明你想cert-manager去幫你配置ssl cert 在這邊你需要先指定一個secret,讓cert-manager把配置好的ssl存放在裡面

之後cert-manager接收到相應的事件觸發後就會開始工作流程 他會先建立一張self-signed的ssl cert並放在該secret裡面 這個時侯你去訪問ingress就會發現https已經能夠使用 但ssl cert是不被瀏覽器信任的

然後cert-manager會建立一個暫時的ingress 去接收來自let’s encrypt的acme challenge 去證明你擁有該域名 如果驗證成功的話就會生成一張正確的ssl cert並更新secret 之後你再訪問https就會看到鎖頭了

實際操作這邊就懶得說了 直接看這裡 https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/index.html

有一點範例沒有說清楚 但卻至關重要,因為你如你是用nginx-ingress的話好有可能會出現這個問題

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example
  annotations:
    certmanager.k8s.io/cluster-issuer: "letsencrypt-prod"
    certmanager.k8s.io/acme-challenge-type: http01
    certmanager.k8s.io/acme-http01-edit-in-place: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - a1.example.com
    secretName: al-example-com-tls
  rules:
  - host: a1.example.com
    http:
      paths:
      - path: /api
        backend:
          serviceName: backend
          servicePort: 80

當中certmanager.k8s.io/acme-http01-edit-in-place: "true" 這句是很重要的

因為nginx-ingress是不能如時接受兩個ingress resources 就是如果你有兩個ingress,而兩個都有同一個host的話 只有其中一個能運行,另一個則無效 大概猜到原因是nginx的配置有關 因為nginx-ingress-controller會接收ingress的配置並且在/etc/nginx/conf.d中生成配置文件

而cert-manager預設是acme-challenger會生成另一個ingress資源出來 所以你要把這個配置設定成true,目的就是希望cert-manager去更改原本的ingress 且不是新開另一個出來