kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Pluto : Kubernetes apiVersion の「非推奨と削除」を検出する

Pluto を使うと Kubernetes マニフェストの apiVersion に対して deprecated(非推奨)removed(削除)を検出できる.警告自体は Deprecated API Migration Guide | Kubernetes を見れば確認できるし,kubectl apply コマンドを実行したときにも表示されるけど,Pluto は実行前に確認できて便利!パイプラインに組み込むのも良し!

github.com

セットアップ

Pluto CLI は macOS なら Homebrew を使えば簡単にセットアップできる.今回は現時点で最新となる Pluto v5.10.2 を前提とする.

$ brew install FairwindsOps/tap/pluto

$ pluto version
Version:5.10.2 Commit:0070fa703641a58ec339a9675aa214ba080ad5d3

$ pluto help
A tool to detect Kubernetes apiVersions

Usage:
  pluto [flags]
  pluto [command]

Available Commands:
  completion    Generate the autocompletion script for the specified shell
  detect        Checks a single file or stdin for deprecated apiVersions.
  detect-files  detect-files
  detect-helm   detect-helm
  help          Help about any command
  list-versions Outputs a JSON object of the versions that Pluto knows about.
  version       Prints the current version of the tool.

Flags:
  -f, --additional-versions string       Additional deprecated versions file to add to the list. Cannot contain any existing versions
      --columns strings                  A list of columns to print. Mandatory when using --output custom, optional with --output markdown
      --components strings               A list of components to run checks for. If nil, will check for all found in versions.
  -h, --help                             help for pluto
      --ignore-deprecations              Ignore the default behavior to exit 2 if deprecated apiVersions are found.
      --ignore-removals                  Ignore the default behavior to exit 3 if removed apiVersions are found.
  -r, --only-show-removed                Only display the apiVersions that have been removed in the target version.
  -o, --output string                    The output format to use. (normal|wide|custom|json|yaml|markdown|csv) (default "normal")
  -t, --target-versions stringToString   A map of targetVersions to use. This flag supersedes all defaults in version files. (default [])
  -v, --v Level                          number for the log level verbosity

Use "pluto [command] --help" for more information about a command.

pluto.docs.fairwinds.com

Pluto を実行する

さっそく Pluto CLI を試す.個人的によく使っている Kubernetes マニフェストの一部を抜粋して pluto detect-files コマンドを実行してみた.すると CronJobPodDisruptionBudgetdeprecated(非推奨)が検出された.なお,Pluto はデフォルトで「Kubernetes v1.22」を検出対象にしている.

$ pluto detect-files -d .
NAME         KIND                  VERSION          REPLACEMENT   REMOVED   DEPRECATED
my-cronjob   CronJob               batch/v1beta1    batch/v1      false     true
my-pdb       PodDisruptionBudget   policy/v1beta1   policy/v1     false     true

kubectl コマンドのように -o オプションも使える.-o wide オプションだと該当するバージョンも表示できて便利!他にも -o json-o yaml も使える.

$ pluto detect-files -d . -o wide
NAME         NAMESPACE   KIND                  VERSION          REPLACEMENT   DEPRECATED   DEPRECATED IN   REMOVED   REMOVED IN
my-cronjob   <UNKNOWN>   CronJob               batch/v1beta1    batch/v1      true         v1.21.0         false     v1.25.0
my-pdb       <UNKNOWN>   PodDisruptionBudget   policy/v1beta1   policy/v1     true         v1.21.0         false     v1.25.0

さらに --target-versions オプションを使うと検出対象にする Kubernetes バージョンを変更できる.--target-versions k8s=v1.23.0 オプションを使うと HorizontalPodAutoscaler でも deprecated(非推奨)が検出された.明示的に指定しておくのが良さそう.

$ pluto detect-files -d . -o wide --target-versions k8s=v1.23.0
NAME         NAMESPACE   KIND                      VERSION               REPLACEMENT      DEPRECATED   DEPRECATED IN   REMOVED   REMOVED IN
my-cronjob   <UNKNOWN>   CronJob                   batch/v1beta1         batch/v1         true         v1.21.0         false     v1.25.0
my-hpa       <UNKNOWN>   HorizontalPodAutoscaler   autoscaling/v2beta2   autoscaling/v2   true         v1.23.0         false     v1.26.0
my-pdb       <UNKNOWN>   PodDisruptionBudget       policy/v1beta1        policy/v1        true         v1.21.0         false     v1.25.0

Pluto を GitHub Actions に組み込む

次は Pluto を GitHub Actions に組み込む.ドキュメントに載っている YAML を使えば簡単に実行できる!

pluto.docs.fairwinds.com

name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  pluto:
    name: pluto
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Download Pluto
        uses: FairwindsOps/pluto/github-action@master
      - name: Run Pluto
        run: pluto detect-files -d . -o wide --target-versions k8s=v1.23.0

しかし Pluto は実行時に以下のリターンコードを返す.よって,deprecated(非推奨)removed(削除)が検出されると落ちてしまう.もし「検出はするけど CI は継続する」場合は --ignore-deprecations オプションと --ignore-removals オプションを併用する.そうすれば「リターンコード 0」を返せるようになる.

  • リターンコード 1 : エラー
  • リターンコード 2 : deprecated(非推奨)あり
  • リターンコード 3 : removed(削除)あり
name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  pluto:
    name: pluto
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Download Pluto
        uses: FairwindsOps/pluto/github-action@master
      - name: Run Pluto
        run: pluto detect-files -d . -o wide --target-versions k8s=v1.23.0 --ignore-deprecations --ignore-removals

まとめ

Kubernetes マニフェストの apiVersion に対して deprecated(非推奨)removed(削除)を検出できる Pluto を試した.日常的に使っているマニフェストリポジトリの GitHub Actions に Pluto を設定したので,継続的に使ってみようと思う.

CKS 対策にもおすすめ /「Docker/Kubernetes 開発・運用のためのセキュリティ実践ガイド」を読んだ

コンテナワークロードにおけるセキュリティ対策の理解を深めるため「Docker/Kubernetes 開発・運用のためのセキュリティ実践ガイド」を読んだ.実は本書は 2021年7月頃 に1度読み終わっていたけど,実際に気になった部分を試したり,CKS (Certified Kubernetes Security Specialist) を受験 しながら読み直していたら書評記事をまとめるのが遅れてしまった (;・∀・)

本書を読んで1番良かったと感じるのは「セキュリティに関して "知らなかったことに気付けた"」ことだと思う.苦手意識のあるセキュリティ領域に対して「視野を広げる」ことができた.本当に読んで良かったと思うし,何よりも「日本語で」読めることに感謝しかない!本書は 2020年2月 に出版されていて,Kubernetes 1.16.1 を前提にしていたり,ランタイムなども含めて多少のアップデートはあると思うので,もし今後「第2版」で更新されるなら絶対に読み直したい!

目次

  • 第1章「Docker/Kubernetes のおさらい」
    • 1.1 Docker の復習
    • 1.2 Kubernetes の復習
  • 第2章「コンテナ運用における脅威の事例」
    • 2.1 API エンドポイントの設定ミス
    • 2.2 ランタイムやカーネルの脆弱性
    • 2.3 イメージの脆弱性
  • 第3章「ランタイムのセキュリティ Tips」
    • 3.1 Docker API エンドポイントを保護する
    • 3.2 コンテナ実行ユーザを変更する
    • 3.3 ケーパビリティやシステムコールを制限する
    • 3.4 ファイルアクセスを制御する
    • 3.5 リソースを制限する
    • 3.6 代替ランタイムを利用する
    • 3.7 コンテナを監視する
    • 3.8 設定を検証する
  • 第4章「イメージのセキュリティTips」
    • 4.1 Dockerfile からプライベートな Git や S3 にアクセスする
    • 4.2 コンテナ内で安全にイメージをビルドする
    • 4.3 イメージの脆弱性を検査する
    • 4.4 改竄されたイメージのデプロイを防ぐ
    • 4.5 プライベートレジストリを構築する (Harbor)
  • 第5章「Kubernetes クラスタのセキュリティ Tips」
    • 5.1 クラスタを最新の状態に保つために
    • 5.2 ミスや攻撃から守る API のアクセス制御
    • 5.3 認証モジュールの選び方と使い方
    • 5.4 Service Account によるサービス認証とアカウント管理
    • 5.5 認可モジュールの種類と利用方法
    • 5.6 Admission コントローラによる柔軟なアクセス制御
    • 5.7 Webhook で独自の Admission Control を追加する
    • 5.8 システムコンポーネント間通信の保護
    • 5.9 スケジューラによる割り当てノードの制御
    • 5.10 秘密情報を管理する
    • 5.11 GitOps のための Secret 管理
  • 第6章「アプリケーション間通信を守る」
    • 6.1 Network Policy を使って Pod の通信を制御する
    • 6.2 Istio を使って Pod 間の通信を守る
    • 6.3 SPIFFE によるアプリケーションの認証
    • 6.4 クラスタ外部との通信を守る

正誤表は以下に載っている.

book.mynavi.jp

第1章「Docker/Kubernetes のおさらい」

第1章では Docker と Kubernetes の基本的な仕組みを学べる.cgroupnamespace など理解があやふやになっている部分を重点的に読んだ.また個人的に苦手意識のある TLS (Transport Layer Security) の復習にもなって良かった.例えば CKS (Certified Kubernetes Security Specialist) を受験するときに CSR (Certificate Signing Requests) 関連も出題されるし,本書の「第5章」にも関連する内容が出てくる.

👉 試した記事 📝

第2章「コンテナ運用における脅威の事例」

第2章ではコンテナワークロードでのさまざまな「セキュリティ脅威」を学べる.実際に「CVE 識別番号」も載っていて,被害を想像すると怖い〜😱となった.例えば Docker / Kubernetes の設定ミスもあれば,コンテナランタイムや Kubernetes コンポーネントの脆弱性もある.改めて,セキュリティ意識を高めておこう!と思える「第2章」だった.

第3章「ランタイムのセキュリティ Tips」

第3章では Docker コンテナや Kubernetes Pod を安全に実行するための Tips を学べる.具体的には「seccomp(不要なシステムコールを制限する)」「AppArmor(ファイル操作などを制限する)」「Falco(コンテナワークロードの脅威を検出する)」などなど.他にも Security Context に関連する Tips もあり,気になった点は積極的に試して理解を深めた.

kubernetes.io

👉 試した記事 📝

第4章「イメージのセキュリティTips」

第4章ではコンテナイメージに特化した Tips を学べる.ビルドツールの「BuildKit」や脆弱性検査ツールの「Clair」「Trivy」などが紹介されている.日頃からDockerfile ベストプラクティスは意識しているけど,今まで使ったことがなかったツールなども知れて良かった.本書に載っていないけど関連する話題としては「ヒアドキュメント構文」のサポートや「hadolint」を使った Dockerfile の静的解析もあるかなーと.

👉 試した記事 📝

第5章「Kubernetes クラスタのセキュリティ Tips」

第5章では Kubernetes クラスタに関連するセキュリティを学べる.とは言っても内容は本当に幅広く,Cloud Native Security の「4C (Cloud / Clusters / Containers / Code)」という多層防御アプローチの説明もあるし,「認証・認可・Admission Controller」「Service Account」「秘密情報 (Secrets / CSI : Container Storage Interface)」なども詳細に解説されている.トピックはまだまだ他にもあって目次を見てもらえればと!個人的に苦手意識のある「認証・認可」の理解を深められた点と,多すぎて全体把握ができていなかった「Admission Controller」を整理できた点は「第5章」を読んだメリットとして印象に残っている.

kubernetes.io

👉 試した記事 📝

第6章「アプリケーション間通信を守る」

第6章では「Network Policy」「Istio を使った通信制御」など,アプリケーション間通信に関するセキュリティを学べる.またアプリケーション間通信の仕様でもある SPIFFE (Secure Production Identity Framework for Everyone) も解説されている.

📝 試した記事

まとめ

「Docker/Kubernetes 開発・運用のためのセキュリティ実践ガイド」を読んだ.本書を読んで「セキュリティに関して "知らなかったことに気付けた"」ことに価値があった.コンテナワークロードにおけるセキュリティ対策の理解を深めるために本書はおすすめだし,CKS (Certified Kubernetes Security Specialist) 対策としてもおすすめ!

関連記事

CKS (Certified Kubernetes Security Specialist) を受験するなら以下の記事も合わせて読んでもらえるとー 📝

kakakakakku.hatenablog.com

Kubernetes 関連のエントリー資格 KCNA (Kubernetes and Cloud Native Associate) に合格した

CNCF (Cloud Native Computing Foundation) の Kubernetes 関連資格 KCNA (Kubernetes and Cloud Native Associate) に合格した!

ついに「4冠」になったー 🎉

まだまだ KCNA の日本語情報は少なく,資格の普及も兼ねて紹介記事としてまとめておこうと思う.

www.cncf.io

前提と結果 ☸️

僕自身は技術講師として研修で Kubernetes と Amazon EKS を教える機会があったり,既に Kubernetes 資格 CKAD (Certified Kubernetes Application Developer)CKA (Certified Kubernetes Administrator)CKS (Certified Kubernetes Security Specialist) も取得している.よって,本資格の受験対象からズレている可能性もある.資格対策はあまりしてなく,2日間ほど(実際には4,5時間)出題範囲を見直した程度だけど,そこそこ高得点が取れた.って,4問も間違えてる... (;・∀・)

受験日 試験名 得点 結果
2022/06/01 KCNA (Kubernetes and Cloud Native Associate) 93 点 合格

技術講師として,今後 Kubernetes や Cloud Native を学び始めるお客様に「おすすめできる資格なのかどうか」を確認したくて受験することにした.あと少し「資格コレクター」精神もある.

KCNA (Kubernetes and Cloud Native Associate) ☸️

KCNA2021年11月 にリリースされた資格で「Kubernetes にフォーカスした Cloud Native の概念的な理解を証明する」エントリー資格と言える.まだリリースされて半年ほどなので,CKADCKACKS と比較すると,日本での認知度は低いのかもしれない.

  • 問題数 : 60問(選択式)
  • 制限時間 : 90分
  • 合格点 : 75%
  • 言語 : 英語(あくまで 2022年6月 時点)

以下のリリース記事には「マーケティングからマネージャまで,誰もが用語とコアテクノロジーの概念を理解することにメリットがある(意訳)」「CKA / CKAD / CKS などの CNCF 資格をさらに追求するための道を開く(意訳)」と書いてある.Kubernetes や Cloud Native をより知ってもらうための資格として,従来のように Kubernetes クラスタを操作する実務試験ではなく「選択式」になっているんだと思う.

www.cncf.io

出題範囲 ☸️

カリキュラム(出題範囲)は GitHub に PDF として公開されている.

github.com

出題範囲 PDF を確認すると Kubernetes FundamentalsContainer Orchestration の比率が高いことがわかる.他にも「オブザーバビリティ」「アプリケーションデリバリー」など,概念としては幅広く出題される.よって,選択式の資格とは言え,Kubernetes やエコシステムの経験がないとそれなりに準備が必要になると思う.

Domain Detail Weight
Kubernetes Fundamentals - Kubernetes Resources
- Kubernetes Architecture
- Kubernetes API
- Containers
- Scheduling
46%
Container Orchestration - Container Orchestration Fundamentals
- Runtime
- Security
- Networking
- Service Mesh
- Storage
22%
Cloud Native Architecture - Cloud Native Architecture Fundamentals
- Autoscaling
- Serverless
- Community and Governance
- Personas
- Open Standards
16%
Cloud Native Observability - Telemetry & Observability
- Prometheus
- Cost Management
8%
Cloud Native Application Delivery - Application Delivery Fundamentals
- GitOps
- CI/CD
8%

勉強方法 ☸️

1. 出題範囲をより深く把握する

出題範囲をより深く把握するために GitHub に公開されている情報に一通り目を通した.具体的には以下の 2 リポジトリを参考にして,特に moabukar/Kubernetes-and-Cloud-Native-Associate-KCNA はよくまとまっていた.用語集や関連リンク集やサンプル問題も載っていて参考になった.個人的には Kubernetes リソースや Kubernetes コンポーネント,そして関連するエコシステムはどれもある程度は経験があり,基本的には理解できていると感じた.

github.com

github.com

他にも CNCF Serverless Whitepaper v1.0Cloud Native Glossary も参考になる!一度読んでおくと良いと思う.

github.com

github.com

2. A Cloud Guru で模擬テストを受験する

A Cloud Guru「Kubernetes and Cloud Native Associate (KCNA)」で, Practice Exam(60 問 x 2 回)を中心に使った.最初から 90% 以上は正解できたので,間違えたり,悩んだりした問題に関連する e-Learning をザッと観た.

A Cloud Guru の e-Learning に出てきて,個人的にあまり経験がなかった技術(やサービスなど)を以下にまとめておく.

  • 環境変数を使ったサービスディスカバリ
  • Selector なし Service
  • Rook
  • FinOps(Financial Operation : 財務と運用を組み合わせた思想)

「環境変数を使ったサービスディスカバリ」に関しては実際に試してブログ記事にまとめた.

kakakakakku.hatenablog.com

英語受験 ☸️

現時点(2022年6月 時点)で KCNA「英語のみ」での受験となる.CKADCKACKS と同じく将来的には日本語もサポートされるとは思うけど,特に情報はなかった.もしかしたら「英語だから諦めよう...⚡」という人もいるかもしれないけど,個人的な感想だと「最低限読める」なら問題ないと思う!

まず,試験監督員との受験前のやり取りは全て「チャット」だった.本人確認や部屋の撮影は事前に済ませているため「飲み物を机の上に置くなら見せて?」と言われた程度だった.受験中も問題文や選択肢は比較的短く,多くは馴染みのある技術用語ということもあり,そこまで不安に感じなくて良いと思う.正直言えば,数問は英語の解釈ができずに間違えてしまった可能性もあるけど!笑

注意点は PSI Secure Browser という専用アプリを使って受験するため,Google 翻訳の Chrome 拡張を使うという従来の Tips(僕自身は未経験だけど調べると CKS などで使った人がいそうだった)は使えなかった.

受験後のフィードバックに「日本語をサポートすると受験者が増えると思うよー!」と書いておいた😃

まとめ ☸️

KCNA (Kubernetes and Cloud Native Associate) に合格した.

「4冠」になったー 🎉

CNCF のリリース記事にも載っていた通り,ソフトウェアエンジニアに限らず,最近「Kubernetes や Cloud Native という言葉をよく聞くから気になるなぁー」と感じる人におすすめできる資格だった!個人的にも「Serverless とは何?」など,改めて考え直す機会になって良かった.

もし未経験から受験を検討する場合は「Kubernetes 完全ガイド 第2版」を読むのも効果的だと思う.

おまけ : Prometheus Certified Associate (PCA) ☸️

2週間前(5月18日)にさらに新しい資格 PCA (Prometheus Certified Associate) が発表されていた!

これも気になるから受験を検討するぞー!日本語キボンヌ!

www.cncf.io

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Kubernetes の Service で「環境変数」を使ったサービスディスカバリを試す

Kubernetes の Service ドキュメントを読み直していたら「サービスディスカバリ」のモードとして「環境変数」「DNS」をサポートしていると書いてあった.一般的によく使うのは「DNS」{ServiceName}.{NamespaceName}.svc.cluster.local というレコードで名前解決できる.今回は「環境変数」を試すぞー💪

kubernetes.io

検証環境は以下の通り.

  • Kubernetes v1.23.0

準備をする

まず準備として backend1 アプリケーション (Service + Deployment) と backend2 アプリケーション (Service + Deployment) を適当に作る.作ったら backend1 Service と backend2 Service の ClusterIP を確認しておく.

$ kubectl create deployment backend1 --image nginx:1.21 --replicas 3
$ kubectl expose deployment backend1 --port 80

$ kubectl create deployment backend2 --image nginx:1.21 --replicas 3
$ kubectl expose deployment backend2 --port 80

$ kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
backend1     ClusterIP   10.97.227.158   <none>        80/TCP    30s
backend2     ClusterIP   10.98.163.125   <none>        80/TCP    20s
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   25d

環境変数を確認する

次に frontend アプリケーション (Pod) を作る.Pod の中で printenv コマンドを使って環境変数を確認すると BACKEND1_SERVICE_HOSTBACKEND2_SERVICE_HOST などサービスディスカバリをしたサービス情報が自動的に設定されている!よって,環境変数の値を使ってサービスに接続できる💡

なるほどー!

$ kubectl run frontend --image nginx:1.21

$ kubectl exec -it frontend -- printenv | grep BACKEND | sort
BACKEND1_PORT=tcp://10.97.227.158:80
BACKEND1_PORT_80_TCP=tcp://10.97.227.158:80
BACKEND1_PORT_80_TCP_ADDR=10.97.227.158
BACKEND1_PORT_80_TCP_PORT=80
BACKEND1_PORT_80_TCP_PROTO=tcp
BACKEND1_SERVICE_HOST=10.97.227.158
BACKEND1_SERVICE_PORT=80
BACKEND2_PORT=tcp://10.98.163.125:80
BACKEND2_PORT_80_TCP=tcp://10.98.163.125:80
BACKEND2_PORT_80_TCP_ADDR=10.98.163.125
BACKEND2_PORT_80_TCP_PORT=80
BACKEND2_PORT_80_TCP_PROTO=tcp
BACKEND2_SERVICE_HOST=10.98.163.125
BACKEND2_SERVICE_PORT=80

注意点としては Service オブジェクトの「作成順序」に依存している点で,あくまで Pod を起動したときに存在するサービスディスカバリ結果を環境変数に設定する仕組みになっている.

以下に構成図をまとめた!

spec.enableServiceLinks: false で無効化する

自動的に環境変数が設定されるのは良さそうだけど,オブジェクトの「作成順序」に依存していることを考慮すると使いにくそうに感じる.実際にどういうときに積極的に使うんだろう❓

そこで,もし環境変数を使う予定がなかったり,不要な環境変数を設定したくないときは Pod の spec.enableServiceLinks: false で無効化できる.以下のように spec.enableServiceLinks: false を追加したマニフェストを作る.

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  enableServiceLinks: false
  containers:
  - name: frontend
    image: nginx:1.21

もう1度 frontend アプリケーション (Pod) を作る.Pod の中で printenv コマンドを使って環境変数を確認すると,今度は設定されていなかった.ちゃんと無効化できた💡

なるほどー!

$ kubectl apply -f frontend.yaml

$ kubectl exec -it frontend -- printenv | grep BACKEND | sort

kubectl で Taint を一覧するコマンド例

Kubernetes でノードの Taint を確認するときに「一覧する」コマンドがなくて困るときがある.--show-labels オプションのように --show-taints オプションがあったら良いのに!例えば kubectl describe node xxx | grep Taints コマンドを実行すれば「ノードごとに」確認することはできるけど,ノードが多いと面倒だったりする.今回は個人的に使っているコマンド例をまとめる.もっとイイ Tips があったら教えて欲しいのだ💡

コマンド例

最初にコマンド例をまとめておく.実際に調べると -o custom-columns を使うコマンドもあれば -o go-template-o jsonpath を使うコマンドもある.また kubectl コマンドに依存せず jq でまとめるコマンドもある.普段使いをするためにあまり複雑にしたくなく,今回は -o custom-columns を使うコマンドと jq を使うコマンドを紹介する.

# -o custom-columns を使う
$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

# jq を使う
$ kubectl get nodes -o json | jq '.items[]|{name:.metadata.name, taints:.spec.taints}'

フォーラムにも関連するスレッドがあった.

discuss.kubernetes.io

動作確認

今回は kind を使って構築した Kubernetes クラスタを使う.

$ kubectl get nodes
NAME                 STATUS   ROLES           AGE   VERSION
kind-control-plane   Ready    control-plane   15m   v1.24.0
kind-worker          Ready    <none>          15m   v1.24.0
kind-worker2         Ready    <none>          15m   v1.24.0
kind-worker3         Ready    <none>          15m   v1.24.0

あくまでサンプルとして kind-worker2kind-worker3Taint を付けておく.

$ kubectl taint nodes kind-worker2 gpu=true:NoSchedule
node/kind-worker2 tainted

$ kubectl taint nodes kind-worker3 gpu=true:NoSchedule
node/kind-worker3 tainted

-o custom-columns を使うと以下のように Taint を確認できる.map 表記だったりするけど,シンプルだと思う.

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
NAME                 TAINTS
kind-control-plane   [map[effect:NoSchedule key:node-role.kubernetes.io/master] map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]]
kind-worker          <none>
kind-worker2         [map[effect:NoSchedule key:gpu value:true]]
kind-worker3         [map[effect:NoSchedule key:gpu value:true]]

jq を使うと縦長にはなるけど,結果としてはわかりやすく確認できる.やはり jq は便利!

$  kubectl get nodes -o json | jq '.items[]|{name:.metadata.name, taints:.spec.taints}'
{
  "name": "kind-control-plane",
  "taints": [
    {
      "effect": "NoSchedule",
      "key": "node-role.kubernetes.io/master"
    },
    {
      "effect": "NoSchedule",
      "key": "node-role.kubernetes.io/control-plane"
    }
  ]
}
{
  "name": "kind-worker",
  "taints": null
}
{
  "name": "kind-worker2",
  "taints": [
    {
      "effect": "NoSchedule",
      "key": "gpu",
      "value": "true"
    }
  ]
}
{
  "name": "kind-worker3",
  "taints": [
    {
      "effect": "NoSchedule",
      "key": "gpu",
      "value": "true"
    }
  ]
}

次は kind-worker3Taint を追加する.

$ kubectl taint nodes kind-worker3 spot=true:PreferNoSchedule
node/kind-worker3 tainted

-o custom-columns を使うと以下のように Taint を確認できる.右に長くなってしまうけどまだ許容範囲だと思う.

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
NAME                 TAINTS
kind-control-plane   [map[effect:NoSchedule key:node-role.kubernetes.io/master] map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]]
kind-worker          <none>
kind-worker2         [map[effect:NoSchedule key:gpu value:true]]
kind-worker3         [map[effect:PreferNoSchedule key:spot value:true] map[effect:NoSchedule key:gpu value:true]]

Taint を追加しても jq だとわかりやすく確認できる.

$ kubectl get nodes -o json | jq '.items[]|{name:.metadata.name, taints:.spec.taints}'
{
  "name": "kind-control-plane",
  "taints": [
    {
      "effect": "NoSchedule",
      "key": "node-role.kubernetes.io/master"
    },
    {
      "effect": "NoSchedule",
      "key": "node-role.kubernetes.io/control-plane"
    }
  ]
}
{
  "name": "kind-worker",
  "taints": null
}
{
  "name": "kind-worker2",
  "taints": [
    {
      "effect": "NoSchedule",
      "key": "gpu",
      "value": "true"
    }
  ]
}
{
  "name": "kind-worker3",
  "taints": [
    {
      "effect": "PreferNoSchedule",
      "key": "spot",
      "value": "true"
    },
    {
      "effect": "NoSchedule",
      "key": "gpu",
      "value": "true"
    }
  ]
}

関連記事

kakakakakku.hatenablog.com