Edited at

Kubernetes(GKE)でLet's Encryptを自動更新する方法


追記

手順が変わっていたので、ワイルドカード証明書の取得方法と合わせて、別記事に書き直しました。

追記ここまで(以下元記事)


本記事について

本記事では、Kubernetes(GKE)でLet's Encryptを自動更新する方法について記載します。

Kubernetesのパッケージ「cert-manager」を用いて「DNS認証」によるチェックを行います。


手順(cert-managerインストールまで)


Helmインストール

「cert-manager」はKubernetesのパッケージマネージャ「Helm」を使ってインストールするため、まず Helmのインストールと、Helmのアカウントを作成します。

(詳しくは https://github.com/ahmetb/gke-letsencrypt に記載されています)


Helmクライアントをインストール



  1. https://github.com/kubernetes/helm/releases からダウンロードして解凍

  2. パスを通して実行可能にする


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 \
--namespace kube-system \
stable/cert-manager


全体の流れ

以上でcert-managerのインストールまで完了します。次の手順に進む前に、ざっくりと全体の流れを説明します。


cert-managerの仕組み

cert-managerは大きく「Issuer」と「Certificate」で構成されています。

「Certificate」は主にドメイン・証明書に関する設定が記載されており、「Issure」は証明書取得の手段やアカウントに関する設定が記載されています。

「Certificate」の証明書の取得を「Issuer」で実行し、「Certificate」で定義されているシークレットに保存することにより、証明書を利用できるようにします。


証明書利用の仕組み

上記で取得した証明書はシークレットとしてKubernetesに保存されます。

そして、そのシークレットをIngressから参照することにより証明書を利用します。

(Ingressを用いた証明書の利用方法については別記事「Kubernetes(GKE)でHTTPS通信する方法」にまとめました)


Let's Encrypt DNS認証の仕組み

Let's Encrypt DNS認証では、Let's Encryptは、DNSレコードに指定した値が書き込まれたかをチェックして、請求者がそのドメインの所有者かをチェックします。

そこで、cert-managerは、GCPのDNSレコードを編集できるサービスアカウントをIssuerと紐付けることによって、IssuerがDNSレコードを編集できるようにし、Let's Encryptからのチェックをパスできるようにします。


手順(残り)


GCPサービスアカウント作成

DNSレコードを編集できるサービスアカウントを作成します


  1. [GCP]-[IAMと管理]-[サービスアカウント]-[サービスアカウントを作成]で任意のアカウントを作成

  2. [GCP]-[IAMと管理]-[IAM]-[追加]で作成したアカウントを追加(役割を[DNS]-[DNS管理者]にする)

  3. [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.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


参考情報


元記事