route53で管理するドメインの証明書をcert-managerで管理しGKEで使用する
GCPでKubernetesを使用する場合、AWSと違いTLS証明書を発行してくれるサービスが存在しません。
有料の証明書を購入すれば良い話ではありますが、機能は同じなので無料でいきたいところです。
そこで、今回はLet's Encryptを利用したいと思います。
しかし、Let's Encryptは90日で証明書の期限が切れてしまい管理が大変なので、Kubernetesのアドオンであるcert-managerを使用したいと思います。
環境
- GKE 1.9.7-gke.1
- cert-manager v0.3.1
- route53
Let's Encryptの認証方法
cert-managerではLet's EncryptのACMEプロトコルであるHTTP-01とDNS-01に対応しています。
ACMEプロトコルについての解説は他に譲りますが、HTTP-01だとhttpアクセスを受け入れるため、ingressとの関わりが生まれてしまいます。
できるだけシンプルに管理したいので、今回はDNS-01を使用します。
また、DNS-01だとDNSのTXT レコードを操作するため、DNSへのアクセス権を付与する必要があります。
DNSへアクセスできない場合はHTTP-01で行うしかありません。
HTTP-01のやり方はこの記事(英語)がわかりやすいです。
cert-managerのインストール
cert-managerはhelmでインストールします。
$ helm install --name cert-manager --namespace kube-system stable/cert-manager
その他のパラメーターなどの詳細はこちらで確認できます。
route53へアクセスするための設定
IAMの作成
DNS-01で認証するのでroute53に書き込みができるIAMを作成します。
公式ドキュメントにIAMのポリシーが書かれていますが、古くなっているのか執筆時(2018/06/28)では動きませんでした。
ですが、すでにこの事がissueで議論されており、動作するポリシーが書かれているのでそれを利用します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "route53:GetChange", "Resource": "arn:aws:route53:::change/*" }, { "Effect": "Allow", "Action": "route53:ChangeResourceRecordSets", "Resource": "arn:aws:route53:::hostedzone/*" }, { "Effect": "Allow", "Action": "route53:ListHostedZonesByName", "Resource": "*" } ] }
このポリシーを適用したIAMユーザーの認証情報をダウンロードしておきます。
cert-managerが読み込むsecretの作成
cert-managerはAWSのAccess Keyはyamlに生で書き込み、Secret KeyはKubernetesのsecretを経由して読み込みます。
そのため、まずはSecret Keyをsecretとして定義します。
$ echo -n 'youreSecretKey' | base64
apiVersion: v1 kind: Secret metadata: name: prod-route53-credentials-secret type: Opaque data: secret-access-key: hogePiyoFaaaa==
base64でエンコードしたsecretKeyをsecret-access-keyに入れます。
Issuerの作成
Issuerという名前の通り、Let's Encryptに発行を依頼するのに必要な情報を記述します。
ドメインの情報は、次に作成するCertificateで定義するのでそれ以外の情報をここで定義します。
apiVersion: certmanager.k8s.io/v1alpha1 kind: Issuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: hoge@hoge.com privateKeySecretRef: name: letsencrypt-prod dns01: providers: - name: prod-dns route53: accessKeyID: YOUREROUTE53ACCESSKEYID secretAccessKeySecretRef: name: prod-route53-credentials-secret key: secret-access-key
emailとaccessKeyIDを正しいものに書き換えます。
Certificateの作成
作成する証明書のドメイン情報を定義します。
apiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata: name: sample-com spec: secretName: hoge-tls issuerRef: name: letsencrypt-prod commonName: 'hoge.com' dnsNames: - hoge.com acme: config: - dns01: provider: prod-dns domains: - '*.hoge.com' - hoge.com
ドメインを正しいものに書き換えてください。
Certificateが存在するnamespaceにsecretNameで指定した名前でTLS証明書がsecretに加工された状態で作成されます。
証明書の作成
ここまでに作成したIssuerとCertificateをKubernetesに適用します。
そうするとcert-managerでの管理が始まり、証明書が作成されます。
作成状況はdescribeコマンドで確認できます。
$ kubectl describe certificate ... Type Reason Message ---- ------ ------- ... Normal CeritifcateIssued Certificated issued successfully
このような出力になれば証明書の作成に成功しています。
この証明書はcert-managerによって管理され、失効まで30日を切ると更新されます。