Plutoとnovaでdeprecated/removedなKubernetes API利用を検出/対応してKubernetesのバージョンアップに備える
はじめに
Kubernetesをインフラに採用してからしっかりと4ヶ月に1回のマイナーリリース適用だけでなく、日々のパッチリリース適用も抜け目なく続けるやり手インフラ担当の方も増えてきた昨今だと思います。
さて、マイナーリリースの適用のときに困る問題があると思いますが、今回はFairwinds Ops社のOSS, plutoを利用してKubernetes APIの非推奨(deprecate)化と削除(remove)をマイナーリリース適用前に検知、同novaでHelm Chartの新バージョンを提案してもらう方法を取り上げます。
先にテスト環境などのマイナーリリース適用を行ってデプロイ物が動かなくなったら対応する、などといったポリシーを変えて検証環境や手数を減らす一助になるかもしれません。
準拠バージョン
本記事では
- pluto v5.19.0
- nova v3.7.0
を用います
Plutoをざっくり紹介
Plutoは米国企業Fairwinds Ops社のOSSで、Apache-2.0 licenseで提供されています。
plutoが提供する機能としては
- Kubernetesで利用するYAML定義ファイルにdeprecated/removedなKubernetes APIが含まれていないかチェックする
- Helmでデプロイしたリソースにdeprecated/removedなKubernetes APIが含まれていないかチェックする
- 標準入力でYAML定義を受け付け、deprecated/removedなKubernetes APIが含まれていないかチェックする
- helm templateコマンドの出力を流したりすると便利
- Kubernetesにdeprecated/removedなKubernetes APIを使っているリソースがないかチェックする
- GitHub ActionsでGitHubリポジトリ中にdeprecated/removedなKubernetes APIが含まれていないかチェックする
があります。
某漫画、アニメ作品他、様々なものと名前が競合するのでweb検索する際には「pluto kubernetes」などで行うと良い結果が得られやすいです。
公式ドキュメント: https://pluto.docs.fairwinds.com/
GitHubリポジトリ: https://github.com/FairwindsOps/pluto
Novaもざっくり紹介
Novaも米国企業Fairwinds Ops社のOSSで、Apache-2.0 licenseで提供されています。
novaの提供する機能はシンプルで、
- Kubernetes内で古いHelm Chart/コンテナイメージが利用されていないかチェック、最新バージョンを提示する
だけです。
しっかりとメンテナンスされているHelm Chartであれば最新バージョンにするだけでdeprecated/removedなKubernetes APIの利用を解消できる可能性があり、deprecated/removed検出後の対応作業で役立ちます。
こちらも名前の競合が多いので、web検索する際は工夫が必要です。
公式ドキュメント: https://nova.docs.fairwinds.com/
GitHubリポジトリ: https://github.com/FairwindsOps/Nova
検証
注意事項
今回の検証では検証用に古いKubernetesクラスタを構築する他、古いソフトウェアをデプロイしますが、これらをインターネット上に公開することはセキュリティ上のリスクになります。
この記事と同じような検証を行う際には隔離環境に構築するなど十分に対策を行ってから実行してください。
また、今回の検証はKubernetes v1.29.x系統まで最終的に上げることを想定して行いますが、検証バージョンのKubernetes v1.23.x系統からワンステップで一気にKubernetes v1.29.x系統までバージョンアップする事を推奨する意図はありません。
検証の目標
今回の検証では一刻も早くKubernetesのバージョンを上げる必要がある切羽詰まった状況(KubernetesリソースやIaCリポジトリの中身を確認している余裕がない状況)を想定します。
検証の目標は
- Plutoを用いて古いHelm Chartを用いて構築されたfluentdのyaml定義に含まれるdeprecated/removedなKubernetes API利用を検出
- Novaを用いて最新のHelm Chartを提案してもらい、それを適用することでdeprecated/removedなKubernetes API利用を解消する
にしました。
Plutoのインストール
公式ドキュメントの手順に従い、各種パッケージマネージャ経由のインストール、もしくはバイナリの取得を行ってください。
https://pluto.docs.fairwinds.com/installation/#asdf
ちなみにArch Linuxから利用する場合にはAURからパッケージの作成が可能です。
https://aur.archlinux.org/packages/pluto
https://aur.archlinux.org/packages/pluto-bin
Novaのインストール
こちらも公式ドキュメントの手順に従い、各種パッケージマネージャ経由のインストール、もしくはバイナリの取得を行ってください。
https://nova.docs.fairwinds.com/installation/
Arch Linux利用の場合はこちらもAURにビルドスクリプトが用意されています。(上記手順で入れたものとファイル名が異なるので、実行時はnova-helmコマンドに読み替えてください)
https://aur.archlinux.org/packages/nova
準備編: 古いKubernetesクラスタの構築
こちらは本筋ではないので、お好きな方法で構築していただいて良いと思います。
今回は例として検証用にkind 0.22.0を用いてKubernetes 1.23.17のクラスタを構築します。
kindを導入済みであればコマンド1行で構築が可能です。
> kind create cluster --image kindest/node:v1.23.17
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.23.17)
✓ Preparing nodes
✓ Writing configuration
✓ Starting control-plane
✓ Installing CNI
✓ Installing StorageClass
Set kubectl context to "kind-kind"
You can now use your cluster with:
kubectl cluster-info --context kind-kind
Thanks for using kind!
これで検証用Kubernetesクラスタの構築ができました。
準備編: 古いfluentdの構築
Helmを用いて古いfluentdのyaml定義を適用します。
> helm install fluentd fluent/fluentd \
--set kind=Deployment \
--set autoscaling.enabled=true \
--version 0.5.1 \
--namespace fluent \
--create-namespace
W0319 12:55:01.512789 71764 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0319 12:55:01.521627 71764 warnings.go:70] autoscaling/v2beta2 HorizontalPodAutoscaler is deprecated in v1.23+, unavailable in v1.26+; use autoscaling/v2 HorizontalPodAutoscaler
W0319 12:55:01.562122 71764 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0319 12:55:01.588818 71764 warnings.go:70] autoscaling/v2beta2 HorizontalPodAutoscaler is deprecated in v1.23+, unavailable in v1.26+; use autoscaling/v2 HorizontalPodAutoscaler
NAME: fluentd
LAST DEPLOYED: Tue Mar 19 12:55:01 2024
NAMESPACE: fluent
STATUS: deployed
REVISION: 1
NOTES:
Get Fluentd build information by running these commands:
export POD_NAME=$(kubectl get pods --namespace fluent -l "app.kubernetes.io/name=fluentd,app.kubernetes.io/instance=fluentd" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace fluent port-forward $POD_NAME 24231:24231
curl http://127.0.0.1:24231/metrics
これで古いAPIを利用するfluentdのyaml定義がhelm経由で展開できました。
既にWarnでdeprecated/removedなAPI利用が警告されていますが、読み飛ばしたりしてしまったケースと想定して無視してください。
IaCでhelm installを代替する場合など、読み飛ばす/表示されないケースも実際に想定されます。
実践編: plutoを用いてKubernetesクラスタ上にdeprecated/removedなAPI利用がないか確認する
detect-all-in-clusterコマンドを利用します。
これは
- Helmでデプロイしたリソースにdeprecated/removedなKubernetes APIが含まれていないかチェックする
- Kubernetesにdeprecated/removedなKubernetes APIを使っているリソースがないかチェックする
の2つを行うコマンドで、コマンド一発で現状Kubernetesクラスタ上にあるものの確認が可能です。
> pluto detect-all-in-cluster --output wide
NAME NAMESPACE KIND VERSION REPLACEMENT DEPRECATED DEPRECATED IN REMOVED REMOVED IN REPL AVAIL REPL AVAIL IN
fluentd/fluentd fluent PodSecurityPolicy policy/v1beta1 true v1.21.0 true v1.25.0 true
fluentd/fluentd fluent HorizontalPodAutoscaler autoscaling/v2beta2 autoscaling/v2 true v1.23.0 false v1.26.0 true
Want more? Automate Pluto for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/pluto
outputオプションを変えることでJSONやYAMLに出力することも可能です。
処理結果をパイプする時などに役立ちます。
> pluto detect-all-in-cluster --output yaml
items:
- name: fluentd/fluentd
namespace: fluent
api:
version: policy/v1beta1
kind: PodSecurityPolicy
deprecated-in: v1.21.0
removed-in: v1.25.0
replacement-api: ""
replacement-available-in: ""
component: k8s
deprecated: true
removed: true
replacementAvailable: true
- name: fluentd/fluentd
namespace: fluent
api:
version: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
deprecated-in: v1.23.0
removed-in: v1.26.0
replacement-api: autoscaling/v2
replacement-available-in: ""
component: k8s
deprecated: true
removed: false
replacementAvailable: true
target-versions:
cert-manager: v1.5.3
istio: v1.11.0
k8s: v1.25.0
Want more? Automate Pluto for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/pluto
これでdeprecated/removedなKubernetes API利用が検出できました。
実践編: novaを用いて古いHelm Chartを検出し最新化、deprecated/removedなKubernetes API利用の解消を試みる
ここまででdeprecated/removedなKubernetes APIを利用しているリソースがあることが確認できました。
具体的にどうやってインストールされたのか知らない体で探っていこうと思います。
plutoで検出されたリソースの定義をコマンドで見てみると
> kubectl get horizontalpodautoscalers.autoscaling --namespace fluent fluentd -o yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
annotations:
meta.helm.sh/release-name: fluentd
meta.helm.sh/release-namespace: fluent
labels:
app.kubernetes.io/instance: fluentd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: fluentd
app.kubernetes.io/version: v1.16.2
helm.sh/chart: fluentd-0.5.1
name: fluentd
namespace: fluent
…
annotationsやlabelからHelmでインストールされたことが推測できます。
ここで「Helm Chartが古い場合は最新化すれば解消するかも...」という発想に至ります。
リリースが一個であればArtifact HubやGitHubリポジトリ等を調べて解消しますが、大量にリソースがあると手間がかかります。
ここでnovaを用いると、
> nova find --format table
Release Name Installed Latest Old Deprecated
============ ========= ====== === ==========
fluentd 0.5.1 0.5.2 true false
Want more? Automate Nova for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/nova
といったように古いHelm Chartを利用していたことが分かります。
余談ですがcontainersオプションで古いコンテナイメージも検出できます。
> nova find --containers --format table
Container Name Current Version Old Latest Latest Minor Latest Patch
============== =============== === ====== ============= =============
registry.k8s.io/coredns/coredns v1.8.6 true v1.11.1 v1.11.1 v1.8.6
registry.k8s.io/etcd 3.5.6-0 true 3.5.12-0 3.5.6-0 3.5.6-0
registry.k8s.io/kube-proxy v1.23.17 true v1.29.3 v1.29.3 v1.23.17
registry.k8s.io/kube-controller-manager v1.23.17 true v1.29.3 v1.29.3 v1.23.17
registry.k8s.io/kube-scheduler v1.23.17 true v1.29.3 v1.29.3 v1.23.17
registry.k8s.io/kube-apiserver v1.23.17 true v1.29.3 v1.29.3 v1.23.17
fluent/fluentd-kubernetes-daemonset v1.16.2-debian-elasticsearch7-1.0 true v1.16.3-debian-s3-arm64-2.1 v1.16.2-debian-elasticsearch7-1.0 v1.16.2-debian-elasticsearch7-1.0
Want more? Automate Nova for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/nova
# JSON出力だとどこで利用されているかも分かる
> nova find --containers | jq '.container_images[0]'
Want more? Automate Nova for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/nova
{
"name": "registry.k8s.io/coredns/coredns",
"current_version": "v1.8.6",
"latest_version": "v1.11.1",
"latest_minor_version": "v1.11.1",
"latest_patch_version": "v1.8.6",
"outdated": true,
"affectedWorkloads": [
{
"name": "coredns",
"namespace": "kube-system",
"kind": "Deployment",
"container": "coredns"
}
]
}
本筋に戻りますが、fluentdのHelm Chartが古いことがここまでで判明したので、最新版にアップグレードします。
まずは、アップグレードで解消するのかを確認します。
# 現行のHelm Chartで古いAPIを利用するリソースが展開されることを確認
> helm template fluentd fluent/fluentd --set kind=Deployment --set autoscaling.enabled=true --version 0.5.1 --namespace fluent --create-namespace | pluto detect -
NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED REPL AVAIL
fluentd HorizontalPodAutoscaler autoscaling/v2beta2 autoscaling/v2 false true true
Want more? Automate Pluto for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/pluto
#新しいHelm Chartで古いAPI利用が解消されるか確認
> helm template fluentd fluent/fluentd --set kind=Deployment --set autoscaling.enabled=true --version 0.5.2 --namespace fluent --create-namespace | pluto detect -
There were no resources found with known deprecated apiVersions.
Want more? Automate Pluto for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/pluto
最新版へのアップグレードで解消されそうなので、helm upgradeコマンドで解消を試みます。
> helm upgrade fluentd fluent/fluentd --set kind=Deployment --set autoscaling.enabled=true --version 0.5.2 --namespace fluent --create-namespace
W0319 18:45:55.010891 41838 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0319 18:45:55.012097 41838 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0319 18:45:55.017270 41838 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
Release "fluentd" has been upgraded. Happy Helming!
NAME: fluentd
LAST DEPLOYED: Tue Mar 19 12:45:54 2024
NAMESPACE: fluent
STATUS: deployed
REVISION: 2
NOTES:
Get Fluentd build information by running these commands:
export POD_NAME=$(kubectl get pods --namespace fluent -l "app.kubernetes.io/name=fluentd,app.kubernetes.io/instance=fluentd" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace fluent port-forward $POD_NAME 24231:24231
curl http://127.0.0.1:24231/metrics
新しいリリースに更新できました。もう一度plutoでスキャンを仕掛けてみます。
> pluto detect-all-in-cluster -o wide
NAME NAMESPACE KIND VERSION REPLACEMENT DEPRECATED DEPRECATED IN REMOVED REMOVED IN REPL AVAIL REPL AVAIL IN
fluentd/fluentd fluent PodSecurityPolicy policy/v1beta1 true v1.21.0 true v1.25.0 true
Want more? Automate Pluto for free with Fairwinds Insights!
https://fairwinds.com/insights-signup/pluto
対応する項目が減りました。
ちなみに残りのPodSecurityPolicyリソースはKubernetesのバージョンアップに合わせて解消されるようなので、対応不要でした。
これでKubernetesのバージョンアップで動かなくなるリソースがなくなり、安全にバージョンアップできるようになりました。
おわりに
安全にKubernetesをアップグレードする準備段階をシミュレートし、
- Plutoを用いて古いHelm Chartを用いて構築されたfluentdのyaml定義に含まれるdeprecated/removedなKubernetes API利用を検出
- Novaを用いて最新のHelm Chartを提案してもらい、それを適用することでdeprecated/removedなKubernetes API利用を解消する
を達成する事ができたと思います。
今すぐKubernetesをアップグレードしたいという切羽詰まった状況でも、作業前に一回はplutoを実行することで不要なトラブル対応や問題の検出にかかる時間を短縮する事ができるのではないでしょうか。
これからもインフラ関連作業は安全第一で行いましょう!