追記
手順が変わっていたので、ワイルドカード証明書の取得方法と合わせて、別記事に書き直しました。
追記ここまで(以下元記事)
Kubernetes(GKE)でLet's Encryptを自動更新するのに「cert-manager」+DNS認証を使うと、サービス側での処理なしで自動更新できて便利だったので、その導入手順メモです。
手順(cert-managerインストールまで)
Helmインストール
「cert-manager」はKubernetesのパッケージマネージャ「Helm」を使ってインストールするため、まず Helmのインストールと、Helmのアカウントを作成します。 (詳しくは https://github.com/ahmetb/gke-letsencrypt に記載されています)
Helmクライアントをインストール
- https://github.com/kubernetes/helm/releases からダウンロードして解凍
- パスを通して実行可能にする
mv linux-amd64/helm /usr/local/bin/helm sudo chown root:root /usr/local/bin/helm sudo chmod 755 /usr/local/bin/helm
Helmアカウント(tiller)をKubernetesに作成、権限付与、およびHelmアップデート
kubectl create serviceaccount -n kube-system tiller kubectl create clusterrolebinding tiller-binding \ --clusterrole=cluster-admin \ --serviceaccount kube-system:tiller helm init --service-account tiller helm repo update
cert-managerインストール
helm install --name cert-manager --version v0.5.2 \ --namespace kube-system stable/cert-manager
エラーが出るようでしたら情報古いかも知れませんので、cert-managerのcert-managerインストールマニュアルで最新情報を取得してください。
全体の流れ
以上でcert-managerのインストールまで完了します。次の手順に進む前に、ざっくりと全体の流れを説明します。
cert-managerの仕組み
cert-managerは大きく「Issuer」と「Certificate」で構成されています。 「Certificate」は主にドメイン・証明書に関する設定が記載されており、「Issure」は証明書取得の手段やアカウントに関する設定が記載されています。 「Certificate」の証明書の取得を「Issuer」で実行し、「Certificate」で定義されているシークレットに保存することにより、証明書を利用できるようにします。
証明書利用の仕組み
上記で取得した証明書はシークレットとしてKubernetesに保存されます。 そして、そのシークレットをIngressから参照することにより証明書を利用します。 (Ingressを用いた証明書の利用方法については別記事「Kubernetes(GKE)でHTTPS通信する方法(Ingress編)」にまとめました)
Let's Encrypt DNS認証の仕組み
Let's Encrypt DNS認証では、Let's Encryptは、DNSレコードに指定した値が書き込まれたかをチェックして、請求者がそのドメインの所有者かをチェックします。 そこで、cert-managerは、GCPのDNSレコードを編集できるサービスアカウントをIssuerと紐付けることによって、IssuerがDNSレコードを編集できるようにし、Let's Encryptからのチェックをパスできるようにします。
手順(残り)
GCPサービスアカウント作成
DNSレコードを編集できるサービスアカウントを作成します
- [GCP]-[IAMと管理]-[サービスアカウント]-[サービスアカウントを作成]で任意のアカウントを作成
- [GCP]-[IAMと管理]-[IAM]-[追加]で作成したアカウントを追加(役割を[DNS]-[DNS管理者]にする)
- [GCP]-[APIとサービス]-[認証情報]-[認証情報を作成]-[サービスアカウントキー]でキーJSONファイルを作成(サービスアカウントを選択してキータイプをJSONにしてキーファイルを保存)
cert-managerからキーファイルの内容を参照できるよう、Kubernetesのシークレットにキーファイルを登録します。
kubectl create secret generic <シークレット名> \ --from-file=key.json=<キーファイルパス>
Issuer作成
issuer.yaml
apiVersion: certmanager.k8s.io/v1alpha1 kind: Issuer metadata: name: letsencrypt-issuer namespace: default spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: <Let's Encryptに登録するemail> privateKeySecretRef: name: letsencrypt-issuer dns01: providers: - name: clouddns clouddns: serviceAccountSecretRef: name: <DNSサービスアカウントのキーファイルのシークレット名> key: key.json project: <GCPプロジェクト名>
kubectl apply -f issuer.yaml
Certificate作成
certificate.yaml
apiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata: name: example-com-certificate namespace: default spec: secretName: example-com-certificate # Ingressから参照するシークレット名 issuerRef: name: letsencrypt-issuer # Issuer名 kind: Issuer commonName: example.com # ドメイン名 dnsNames: - example.com # ドメイン名 acme: config: - dns01: provider: clouddns # Issuerのprovider名 domains: - example.com # ドメイン名
kubectl apply -f certificate.yaml
確認
kubectl describe certificate,issuer,clusterissuer --all-namespaces
で状態をチェックできます。エラーが出ていないようなら証明書の取得が成功しています。 エラーが出ているようなら、下記の方法でcert-managerのログをチェックして原因究明します。
- [GCP]-[Kubernetes Engine]-[ワークロード]-<フィルターOFF>-<cert-manager>-[管理対象ボット]-<ボット名>-[ログ]-[Container Logs]
証明書の利用
Ingressのサンプルを記載します。 tlsのシークレットを、Certificateで設定したシークレット名にすることにより、IngressとCertificateの証明書を紐付けます。 (Ingressを用いた証明書の利用方法については別記事「Kubernetes(GKE)でHTTPS通信する方法(Ingress編)」にまとめました)
ingress.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress annotations: kubernetes.io/ingress.allow-http: "false" kubernetes.io/ingress.global-static-ip-name: "<static ip名>" spec: tls: - secretName: example-com-certificate backend: serviceName: nginx servicePort: 80
補足説明
トライアルアンドエラーを繰り返していると、Let's Encryptの制限に引っかかることがあるので、はじめは本番ではなくステージングでテストした方がよいかと思います。
ステージングは「issuer.yaml」の「server」を「https://acme-staging-v02.api.letsencrypt.org/directory
」にするとなります。
ステージングで取得した証明書は怪しいサイトとなりますが、アクセスは可能です。
また、「cert-manager」のアンインストール、再インストールは下記で行えます。
helm list # インストールされているパッケージ一覧 helm delete <cert-manager名> # <cert-manager>削除 helm install \ --replace \ # 同じ名前で再インストールするには「--replace」をつけます --name <cert-manager名> \ --namespace kube-system \ stable/cert-manager
参考情報
- https://qiita.com/apstndb/items/3a39a1e6acacbbc30765
- https://github.com/ahmetb/gke-letsencrypt
- https://cert-manager.readthedocs.io/en/latest/
- https://medium.com/google-cloud/kubernetes-w-lets-encrypt-cloud-dns-c888b2ff8c0e
- https://github.com/jetstack/cert-manager/issues/339