Mercari Engineering Blog

We're the software engineers behind Mercari. Check out our blog to see the tech that powers our marketplace.

Custom Controller で Kubernetes の上の TLS 証明書を監視する

こんにちは!Summer Internship 2018 にて Microservices Platform Team でインターンをしていた @everysick です*1。この記事ではインターン期間中に実装を行い、OSS として公開した Certificate Expiry Monitor Controller の紹介をします。

github.com

背景

有効期限監視の限界

TLS 証明書の運用では有効期限が来る前に TLS 証明書を更新をする必要があります。 これまでのメルカリでは mackerel.io の URL 外形監視機能に登録したエンドポイントの TLS 証明書を監視することで、有効期限が切れる前に通知をする運用を行っていました。

しかしながら、Microservices Platform 環境では日々新しいサービスが立ち上がっているため、従来の運用を適用するのであれば下図のように全ての TLS 証明書の発行を認知して監視対象に追加する必要があります。

f:id:everysick:20180831152138p:plain

Microservices Platform 環境での TLS 証明書

メルカリで全社的に取り組まれている Microservices 化に伴い、各 Microservice がそれぞれで異なるドメインを持つようになったため、TLS 証明書も同様に用意する必要がでてきました。その課題に対応するため、Microservices Platform Team では Kubernetes のクラスタに対して jetstack/kube-legojetstack/cert-manager を導入することにより、Let's Encrypt を用いて TLS 証明書の発行と更新のオペレーションを自動化する仕組みを提供しています。

そのため、現在の Microservices Platform 環境では、Let's Encrypt から発行した TLS 証明書と外部の CA から発行した TLS 証明書の二種類が存在しており、それらの運用・管理を下図のように行っています。

f:id:everysick:20180831152141p:plain

TLS 証明書の発行・更新におけるオペレーションは、各 Microservice 管理者が Ingress resoruce に ACME を有効にするアノテーションを付与することよって半自動化することができました。

しかし、この状態でも監視対象への追加のオペレーションが必要であったり、アノテーションの付け忘れによって TLS 証明書が自動更新されないなどの課題が解決されていません。この課題に対処するため、インターン期間中に Certificate Expiry Monitor Controller というソフトウェアの実装を行いました。

Certificate Expiry Monitor Controller

Certificate Expiry Monitor Controller は Kubernetes の Custom Controller として実装されました。Kubernetes クラスタ上の Ingress に登録されている TLS が有効なエンドポイントへ一定の間隔でリクエストを送ります。

その際、もしTLS 証明書の有効期限が切れている、もしくは閾値に達していた場合、予め設定した通知先へ警告メッセージを送信します。

f:id:everysick:20180831152145p:plain

これにより、従来の運用方法で課題となっていたエンドポイント登録の問題、及びアノテーションの付け忘れといったヒューマンエラーを回避することが可能になりました。

クラスタへのデプロイ

Certificate Expiry Monitor Controller は Docker Hub 上で Docker イメージを配布しています。ローカルの ~/.kube/configを読み込んで動作させることも可能ですが、下のような Deployment の定義を追加して適用するのが最も簡単です。

# deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: certificate-expiry-monitor-controller
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: certificate-expiry-monitor-controller
  template:
    metadata:
      labels:
        app: certificate-expiry-monitor-controller
    spec:
      containers:
        - name: certificate-expiry-monitor-controller
          image: mercari/certificate-expiry-monitor-controller:<VERSION>

この定義を kubectl コマンドを用いて適用するだけ(必要であれば権限等を付与する)でデプロイが可能です。

$ kubectl apply -n <YOUR_NAME_SPACE> -f deployment.yml

初期状態では有効期限の監視結果が stderr に出力されるため、同じく kubectl コマンドでログを取得して動作を確認することができます。

$ kubectl logs -n <YOUR_NAME_SPACE> <POD_NAME>
{"level":"info","ts":1535617901.5555878,"caller":"controller/controller.go:58","msg":"Starting controller..."}
...

まとめ

インターン期間中に実装・公開した Certificate Expiry Monitor Controller について、その実装背景と動作概要を説明しました。

より詳しい設定や仕様に関してはREADME を参照してください。 記事公開現在のバージョンは 0.0.1 です。今後も様々なケースに対応するため、OSS として積極的に機能追加をしていく予定です。

*1:8/31をもってインターン終了