新着:プロジェクトの最新情報についてはTwitterMastodonでご確認ください。

Kube-LEGO からの移行

kube-lego は、Let's Encrypt(または他のACMEサーバー)からTLS証明書を取得するための、Jetstackの古いプロジェクトです。

cert-managerのリリース以降、kube-legoは段階的に廃止され、このプロジェクトが推奨されています。両者にはいくつかの重要な違いがあります。

機能kube-legocert-manager
設定IngressリソースへのアノテーションCRD
CAsACMEACME、署名キーペア
Kubernetesv1.2 - v1.8v1.7以上
デバッグログを確認するKubernetes Events API
マルチテナントサポートされていませんサポートされています
証明書ごとに異なる発行元サポートされていませんサポートされています
Ingressコントローラーのサポート (ACME)GCE、NGINXすべて

このガイドでは、サービスを中断することなく、kube-legoのインストールをcert-managerに安全に移行する方法を説明します。

ガイドの最後に、次の状態になっているはずです。

  1. kube-legoのスケールダウンと削除

  2. cert-managerのインストール

  3. ACME秘密鍵のcert-managerへの移行

  4. この秘密鍵を使用して、クラスタ全体で証明書を発行するためのACME ClusterIssuerの作成

  5. kubernetes.io/tls-acme: "true" アノテーションが付いたすべてのIngressリソースに対して、作成したClusterIssuerを使用して、cert-managerのingress-shim を構成してCertificateリソースを自動的にプロビジョニングする

  6. cert-managerのインストールが機能していることを確認する

1. kube-legoのスケールダウン

cert-managerのデプロイを開始する前に、kube-legoデプロイメントをレプリカ数0にスケールダウンすることをお勧めします。これにより、2つのコントローラーが互いに競合するのを防ぎます。公式のデプロイYAMLを使用してkube-legoをデプロイした場合は、次のようなコマンドで実行できます。

$ kubectl scale deployment kube-lego \
--namespace kube-lego \
--replicas=0

その後、kube-lego podが実行されていないことを次のようにして確認できます。

$ kubectl get pods --namespace kube-lego

2. cert-managerのデプロイ

cert-managerは、公式のインストールガイドに従ってHelmを使用してデプロイする必要があります。特別な手順は必要ありません。このガイドの最後に、このデプロイに戻り、cert-managerをデプロイする際に使用するいくつかのCLIフラグをアップグレードします。

Helmとcert-managerをデプロイする際には、RBACが正しく構成されていることを十分に確認してください。デプロイに関するドキュメントにいくつかのニュアンスが記載されています!

3. ACMEアカウント秘密鍵の取得

ユーザーの代わりに証明書の発行と更新を続けるためには、kube-legoが作成したユーザーアカウント秘密鍵をcert-managerに移行する必要があります。

ACMEユーザーアカウントのIDは、秘密リソースに保存されている秘密鍵です。デフォルトでは、kube-legoはkube-lego Deploymentと同じ名前空間にあるkube-lego-accountという名前の秘密にこのキーを保存します。LEGO_SECRET_NAME環境変数の値を使用する場合は、kube-legoをデプロイする際にこの値を上書きしている可能性があります。

この秘密リソースのコピーをダウンロードして、ローカルディレクトリに保存する必要があります。

$ kubectl get secret kube-lego-account -o yaml \
--namespace kube-lego \
--export > kube-lego-account.yaml

保存したら、このファイルを開き、metadata.nameフィールドをcert-managerに関連する名前に変更します。このガイドの残りの部分では、letsencrypt-private-keyを選択したと仮定します。

完了したら、この新しいリソースをcert-manager名前空間に作成する必要があります。デフォルトでは、cert-managerはClusterIssuersのサポートリソースを実行している名前空間に保存し、上記のcert-managerのデプロイ時にはcert-managerを使用しました。cert-managerを別の名前空間にデプロイした場合は、これを変更する必要があります。

$ kubectl create -f kube-lego-account.yaml \
--namespace cert-manager

4. 古いACMEアカウントを使用してACME ClusterIssuerを作成する

以前kube-legoで登録したACMEアカウントに関する情報を保持するClusterIssuerを作成する必要があります。そのためには、古いkube-legoデプロイメントからさらに2つの情報が必要です。ACMEサーバーのサーバーURLと、アカウント登録に使用したメールアドレスです。

これらの情報はどちらも、kube-lego ConfigMapに保存されています。

それらを取得するには、kubectlを使用してConfigMapgetできます。

$ kubectl get configmap kube-lego -o yaml \
--namespace kube-lego \
--export

メールアドレスは.data.lego.emailフィールドに、ACMEサーバーのURLは.data.lego.urlフィールドに表示されます。

このガイドでは、メールアドレスがuser@example.comで、URLがhttps://acme-staging-v02.api.letsencrypt.org/directoryであると仮定します。

秘密鍵を新しいSecretリソースに移行し、ACMEメールアドレスとURLを取得したので、ClusterIssuerリソースを作成できます!

cluster-issuer.yamlという名前のファイルを作成します。

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
# Adjust the name here accordingly
name: letsencrypt-staging
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key from step 3
privateKeySecretRef:
name: letsencrypt-private-key
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
ingressClassName: nginx

次に、このファイルをKubernetesクラスタに送信します。

$ kubectl create -f cluster-issuer.yaml

ACMEアカウントが正常に検証されたことを確認できます。

$ kubectl describe clusterissuer letsencrypt-staging
...
Status:
Acme:
Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/7571319
Conditions:
Last Transition Time: 2019-01-30T14:52:03Z
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready

5. 新しいClusterIssuerをデフォルトで使用するようにingress-shimを構成する

ClusterIssuerが証明書を発行できるようになったので、最後に1つの作業が残っています。ingress-shim(cert-managerの一部としてデプロイされる)を再構成して、適切なアノテーションが付いたすべてのIngressリソースに対してCertificateリソースを自動的に作成する必要があります。

ingress-shimの役割に関する詳細はドキュメントを参照できますが、ここではいくつかの追加フラグを追加するためにhelm upgradeを実行するだけです。ClusterIssuerletsencrypt-stagingという名前を付けた(上記のように)と仮定して、実行します。

$ helm upgrade cert-manager \
jetstack/cert-manager \
--namespace cert-manager \
--set ingressShim.defaultIssuerName=letsencrypt-staging \
--set ingressShim.defaultIssuerKind=ClusterIssuer

cert-manager podが再作成され、起動すると、以前kube-legoが有効になっていたすべてのingressに対してCertificateリソースが自動的に作成されます。

6. 各Ingressに対応するCertificateが存在することを確認する

終了する前に、以前kube-legoを有効にした各IngressリソースにCertificateリソースが作成されていることを確認する必要があります。

次を実行して確認できます。

$ kubectl get certificates --all-namespaces

クラスタ内のkube-legoアノテーションが付いた各Ingressのエントリが表示されます。

cert-managerのログを表示することで、cert-managerが古いTLS証明書を「採用」したことも確認できます。

$ kubectl logs -n cert-manager -l app=cert-manager -c cert-manager
...
I1025 21:54:02.869269 1 sync.go:206] Certificate my-example-certificate scheduled for renewal in 292 hours

ここでは、cert-managerが既存のTLS証明書を検証し、292時間後に更新するようにスケジュールされたことがわかります。