久々に helmfile sync を行った結果、PodSecurityPolicy リソースなんか知らないという理由で Upgrade に失敗した。
$ helmfile dep && helmfile sync ... Error: UPGRADE FAILED: resource mapping not found for name: "descheduler" namespace: "" from "": no matches for kind "PodSecurityPolicy" in version "policy/v1beta1" ensure CRDs are installed first
「PSP? なにそれ CRD か何か?」と言われる有様。そういえば、k8s クラスタを最近アップグレードしたときに不要な PSP を消していた気がする。
一旦手動で helm uninstall をしようとするも、同じようなエラーが出て uninstall できない。
$ helm uninstall descheduler -n kube-system --debug uninstall.go:97: [debug] uninstall: Deleting descheduler uninstall.go:119: [debug] uninstall: Failed to delete release: [unable to build kubernetes objects for delete: resource mapping not found for name: "descheduler" namespace: "" from "": no matches for kind "PodSecurityPolicy" in version "policy/v1beta1" ensure CRDs are installed first] Error: failed to delete release: descheduler helm.go:84: [debug] failed to delete release: descheduler helm.sh/helm/v3/pkg/action.(*Uninstall).Run helm.sh/helm/v3/pkg/action/uninstall.go:120 main.newUninstallCmd.func2 helm.sh/helm/v3/cmd/helm/uninstall.go:60 github.com/spf13/cobra.(*Command).execute github.com/spf13/cobra@v1.6.1/command.go:916 github.com/spf13/cobra.(*Command).ExecuteC github.com/spf13/cobra@v1.6.1/command.go:1044 github.com/spf13/cobra.(*Command).Execute github.com/spf13/cobra@v1.6.1/command.go:968 main.main helm.sh/helm/v3/cmd/helm/helm.go:83 runtime.main runtime/proc.go:250 runtime.goexit runtime/asm_arm64.s:1172
どうやら、以前この Chart を install したときには PSP があったので、今回 uninstall するにあったっても PSP を消そうとするが、API の対応がないので落ちているらしい。
ここで、helm はインストールしたときの情報を secrets に保存している。この内容をデコードすると、インストール時の YAML がそのまま格納されている。
$ kubectl describe secret -n kube-system sh.helm.release.v1.descheduler.v15 Name: sh.helm.release.v1.descheduler.v15 Namespace: kube-system Labels: modifiedAt=1687875686 name=descheduler owner=helm status=uninstalling version=15 Annotations: <none> Type: helm.sh/release.v1 Data ==== release: 13804 bytes $ kubectl get secret -n kube-system sh.helm.release.v1.descheduler.v15 -o json | jq .data.release -r | base64 -d | base64 -d | gunzip | jq { "name": "descheduler", "info": { "first_deployed": "2021-05-25T22:28:45.6228274+09:00", ... }, ... "manifest": "---\n# Source: descheduler/templates/podsecuritypolicy.yaml\napiVersion: policy/v1beta1\nkind: PodSecurityPolicy\nmetadata:\n name: descheduler\n annotations:\n seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default'\n seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/de...(続く)" ... }
この manifest を使って uninstall しているのでは?と考えて、manifest から PodSecurityPolicy の部分を削って secrets の値を変更してみたところ、ビンゴだった。
$ gzip new_release.json --stdout | base64 -w 0 | base64 -w 0 | pbcopy $ kubectl edit secret -n kube-system sh.helm.release.v1.descheduler.v15 (コピーした内容を release に貼り付ける)
これで無事 PSP を除いた uninstall を行うことができた。
$ helm uninstall descheduler -n kube-system --debug uninstall.go:97: [debug] uninstall: Deleting descheduler client.go:478: [debug] Starting delete for "descheduler" CronJob client.go:478: [debug] Starting delete for "descheduler" ClusterRoleBinding client.go:478: [debug] Starting delete for "descheduler" ClusterRole client.go:478: [debug] Starting delete for "descheduler" ConfigMap client.go:478: [debug] Starting delete for "descheduler" ServiceAccount uninstall.go:150: [debug] purge requested for descheduler release "descheduler" uninstalled
全く同じ内容がドキュメントにあることにその後気づいた。事故らなくてよかったですね…。
今回の事象は Upgrade 時に何も考えずに非互換なリソースを消して済ましたのが原因であり、教訓としては以下になる。
- 非互換なリソースの変更を伴う Cluster upgrade は、そのリソースを触る前に Helm 配下にないか確認する
- 配下にあった場合は Helm を使ってそのリソースをなんとかするべき