CTOのshirailyです。cert-managerの更新でいくつかハマりポイントがあったので紹介します。
はじめに
cert-managerはKubernetesのアドオンで、証明書の取得・更新・利用をシンプルにしてくれます。
Tsunagu.AIではフロントエンド開発を自動化する FRONT-END.AI アプリケーションのSSL証明書ソースとして一部Let's Encryptを利用しており、 その取得・更新・利用のプロセスをGKE上のcert-managerで自動化しています。
弊社ではv1.0.0以前 (0.12.0) というかなり古いバージョンを削除したうえで最新版を新規作成しました。 本記事では、最終的にうまく行った手順や検証時のハマりポイントを紹介します。
前提
- アップデート前: 0.12.0
- アップデート後: 1.7.1 (アップデート作業時点での最新版)
- cert-managerはhelmでインストール
用語
簡易的に↓と記載します。
- カスタムリソースまたは単にAPI: DeploymentやPodsのように、独自に定義したリソース。
- cert-managerはヘビーユーザーとのこと。
- CRDオブジェクト: カスタムリソースのエンティティ(つまり実体)。
たとえばカスタムリソースIssuer
は
# Source: cert-manager/templates/templates.out apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition spec: group: cert-manager.io names: kind: Issuer listKind: IssuerList ...
と宣言し(v1.7.1のファイルはこちら)、kubectl apply
してクラスタで利用できます。
一方CRDオブジェクトは実体で
apiVersion: cert-manager.io/v1 kind: Issuer spec: ...
などとなりますが、内容はユーザー自身が定義します。Deploymentなどと同様です。
手順
最終的な手順はこのようになります*1。ですので正確には「更新」ではなく「削除」+「新規作成」です。
まず、事前に関連するCRDオブジェクト( Certificate
とIssuer
)の宣言を削除、Ingressのマニフェストを更新します。
# 事前準備を適用 helm upgrade # cert-manager自体のアンインストール helm delete --purge cert-manager # namespaceの削除 kubectl delete namespace cert-manager # 古いカスタムリソースの削除 kubectl delete -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.12/deploy/manifests/00-crds.yaml # カスタムリソースの作成 kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.7.1/cert-manager.crds.yaml # cert-managerのインストール helm install -n cert-manager jetstack/cert-manager --namespace cert-manager --version v1.7.1 # 関連するCRDオブジェクト( `Certificate`と`Issuer` )のAPIバージョンなどを適切に書き換えてから helm upgrade
手順自体は公式のreinstall手順を修正したもので、解説は省きます。
ポイント
CRDオブジェクトの書き換え
v0.12.0とv1.7.1では書き方が大きく異なりますが、 cmctl convertという便利コマンドで書き換えられます。
cmctl convert -f your-certificate.yaml
helmを利用している場合はテンプレート文字列部分を一時的にダミー文字列で置き換えてから実行します。
v1.0.0以前からv1.8など最新版への直接更新は複雑
直接更新する方法はありますが、 リスクを考慮すると削除+新規作成のほうが断然楽です。
CRDオブジェクトより先にカスタムリソースAPIを削除するとリカバリが困難
helm upgradeは直前のリリースとの差分をもとにクラスタへ更新をかけます(新たなリリースを作成します)。 そのため、「直前のリリースを解釈」できる必要があります。
よって、CRDオブジェクトが古いAPI versionを利用している状態でAPIを先に削除すると、
helm upgrade
がCRDオブジェクトのマニフェストを解釈できず失敗します。
その場合次のようなログが出力されます。
Error: current release manifest contains removed kubernetes api(s) for this kubernetes version and it is therefore unable to build the kubernetes objects for performing the diff. error from kubernetes: [ unable to recognize "": no matches for kind "Certificate" in version "cert-manager.io/v1alpha2", unable to recognize "": no matches for kind "Issuer" in version "cert-manager.io/v1alpha2" ]
この状態になるとhelmではリカバリできず、手動での煩雑なリカバリが必要です*2。
... when Kubernetes removes an API version, the Kubernetes Go client library can no longer parse the deprecated objects and Helm therefore fails when calling the library. Helm unfortunately is unable to recover from this situation and is no longer able to manage such a release.
私は開発環境で起こしてしまったので諦めてhelm install
し直しました。。
コマンドが正常に通らないことがあった
kubectl delete namespace cert-manager
がスタックするとき、
webhook APIの削除
またはfinalizersを手で空にして適用が参考になります。
finalizersを空にする方法は
# これはうろ覚えです kubectl describe namespace cert-manager -o json > cert-manager.json # 適用 kubectl replace --raw "/api/v1/namespaces/cert-manager/finalize" -f ./cert-manager.json
最後に
セキュリティ面もそうですが大量のリリースノートを一気に精査するのがつらかったので、今後は早め早めに移行しようと思います。
本記事は副業メンバーの @hide04241990 さんにも協力いただきました。ありがとうございました!!
なお、FRONT-END.AIを運営するTsunagu.AIでは正社員・副業・フリーランスエンジニアを積極的に募集しています。 本記事はインフラについてでしたが、Vue.js / TypeScript / Python / 自動化あたりに関心がある方だとより楽しめるかと思います。
※もちろんインフラまわりも希望に応じて担当したり一緒に進められます! 応募は↓