Unyablog.

のにれんのブログ

サポート外のリソースを含んだ Helm release を無理やり削除した

久々に 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

全く同じ内容がドキュメントにあることにその後気づいた。事故らなくてよかったですね…。

helm.sh

今回の事象は Upgrade 時に何も考えずに非互換なリソースを消して済ましたのが原因であり、教訓としては以下になる。

  • 非互換なリソースの変更を伴う Cluster upgrade は、そのリソースを触る前に Helm 配下にないか確認する
    • 配下にあった場合は Helm を使ってそのリソースをなんとかするべき