GKEでLet’s Encryptを使ってSSL証明書の自動更新をしています。それとは別に、GKEのIngressとして作成していないロードバランサやGAEにもSSL証明書を使用しています。
GAEは証明書の自動更新をしてくれますが、ワイルドカード証明書には対応していません。
私が作っている環境はワイルドカード証明書を利用しているので、GKEで自動更新設定しているSSL証明書をGCP/GAEにも適用してみます。
GKEでSSL証明書の自動更新の設定をする
こっちは本題ではないので、かなり簡潔に書きます。HTTPではなくDNS01で行います。また、cert-managerは0.3以上じゃないとワイルドカード証明書に対応していません。
HELM INSTALLcurl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get> get_helm.sh chmod 700 get_helm.sh ./get_helm.sh
|
HELM UPDATE(既にインストール済みの場合はUpdateする)helm init --upgrade
$HELM_HOME has been configured at /Users/tamtam180/.helm.
Tiller (the Helm server-side component) has been upgraded to the current version. Happy Helming!
|
RBAC設定kubectl create serviceaccount tiller --namespace kube-system kubectl create clusterrolebinding tiller --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
|
Install Tillerhelm init --upgrade --service-account tiller
|
cert-managergit clone https://github.com/kubernetes/charts cd charts helm install --set image.tag=v0.3.2 --name cert-manager --namespace kube-system stable/cert-manager
|
cert-managerがCloudDNSを操作できるようにするGCLOUD_PROJECT=my-sample-project gcloud iam service-accounts create cert-manager --display-name "cert-manager" gcloud projects add-iam-policy-binding ${GCLOUD_PROJECT} --member serviceAccount:cert-manager@${GCLOUD_PROJECT}.iam.gserviceaccount.com --role roles/dns.admin
|
service accountのkeyを作るgcloud iam service-accounts keys create cert-manager-key.json --iam-account cert-manager@${GCLOUD_PROJECT}.iam.gserviceaccount.com
|
service accountをsecretに登録するkubectl create secret generic clouddns-service-account --from-file=cert-manager-key.json=cert-manager-key.json --namespace=kube-system
|
ClusterIssuerを作る
clusterissuer.yamlapiVersion: certmanager.k8s.io/v1alpha1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod dns01: providers: - name: prod-dns clouddns: serviceAccountSecretRef: name: clouddns-service-account key: cert-manager-key.json project: my-sample-project
|
kubectl apply -f clusterissuer.yaml
|
Certificateを作る
ドメイン名はCloudDNSに登録している自分のドメインを指定します。
namespaceにdev
を指定していますが、そこも自分の環境に合わせて調整してください。(私の場合はワイルドカード証明書を使っている関係で、dev環境やstaging環境に別のドメインを使っているため、環境ごとにnamesapceを分けています)
certificate.yamlapiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata: name: example-com-tls namespace: dev spec: secretName: example-com-tls commonName: example.com dnsNames: - "example.com" - "*.example.com" acme: config: - dns01: provider: prod-dns domains: - "example.com" - "*.example.com" issuerRef: name: letsencrypt-prod kind: ClusterIssuer
|
kubectl apply -f certificate.yaml
|
GKEのSSL証明書をGAEに設定する
GAEは既存の証明書をupdate
コマンドで一発で更新できます。
gcloud app ssl-certificates list 2>/dev/null
で証明書の一覧が取得できます。
GAEの証明書のExpire時間を計算するCERT_ID=xxxxx T=$(LANG=C date --date $(gcloud app ssl-certificates describe ${CERT_ID} | grep expireTime | sed -e "s/'//g" | cut -d " " -f 2) +'%s') expr \( $T - $(date +'%s') \) / 86400
|
こんな感じで今の証明書があと何日で期限切れになるのか計算できます。cert-managerでは30日前に自動更新するようになっているので、30日とか25日あたりを閾値にすると良いと思います。
GAEの証明書を更新する
kubectl get secret example-com-tls -o json --namespace=dev | jq -r '.data["tls.key"]' | base64 --decode > /tmp/tls.key
kubectl get secret example-com-tls -o json --namespace=dev | jq -r '.data["tls.crt"]' | base64 --decode > /tmp/tls.crt
|
証明書の有効期限が延長済みであることを確認するには、次のコマンドで証明書の有効期限を見れば良いです。
cat /tmp/tls.crt | openssl x509 -noout -enddate notAfter=Oct 29 08:40:28 2018 GMT
date --date "$(cat /tmp/tls.crt | openssl x509 -noout -enddate | cut -d'=' -f2)" +"%s"
|
CERT_ID=xxxx gcloud app ssl-certificates update "${CERT_ID}" \ --display-name "*.example.com lets" \ --certificate "/tmp/tls.crt" \ --private-key "/tmp/tls.key"
|
ロードバランサの証明書を更新する
※GKE(k8s)のIngressとして作成したロードバランサは、cert-managerで勝手に更新されます。そうではない野良のロードバランサが対象です。
GCP管理の証明書を一覧する gcloud compute ssl-certificates list
|
残念ながらGAEのようなupdateコマンドがありません。
手順はSSL証明書を作成し、target-https-proxiesにその作成した証明書を設定します。
SSL証明書の更新CERT_NAME="star-dev-example-com-$(date +'%Y-%m-%d')" gcloud compute ssl-certificates create "${CERT_NAME}" \ --certificate "/tmp/tls.crt" \ --private-key "/tmp/tls.key"
TARGET_PROXY="star-example-com-target-proxy-2" gcloud compute target-https-proxies update "${TARGET_PROXY}" \ --ssl-certificates "${CERT_NAME}"
|
これでGKEの環境で証明書を自動更新しつつ、ほかの環境にも展開できるようになりました。実運用はk8sのcronjobを定義して↑の内容をよしなに処理するスクリプトを作れば良いと思います。