TT Lab
はじめる
学ぶ 学習パス コース

KCNA — Kubernetes・クラウドネイティブ入門

クラスタを手で開けてみる

TT Labで続きを見る

目標

本物のKubernetesクラスターに接続してネームスペース・ノード・APIリソースを直接調べ、ラベルセレクターと-o jsonpathで必要な値だけを取り出したうえで、同じDeploymentを命令型と宣言型の2つの方法で作り、違いを目で確認します。

なぜ重要なのか

Kubernetesを使う人は大きく2つに分かれます。毎回ドキュメントサイトを検索する人と、クラスターに直接尋ねる人です。kubectl api-resourcesとkubectl explainは、このクラスターが今実際に知っていることを教えてくれるので、ドキュメントより正確です。CRDで拡張されたリソースまで出てくるからです。

そしてラベルセレクター。Kubernetesにはオブジェクト同士の直接参照がほとんどありません。ServiceがPodを見つける方法も、ReplicaSetが自分のPodを数える方法も、すべてラベルセレクターです。この疎結合のおかげでPodを自由に入れ替えられますが、その代償として、セレクターのタイプミスはエラーなしに静かに何も見つけられません。

最後に宣言型。kubectl runは手軽ですが、何を作ったのか記録が残りません。マニフェストをファイルとして置いてapplyすれば、そのファイルがそのままこのクラスターの真実になり、レビュー・バージョン管理・ロールバックが可能になります。GitOpsという言葉は、この習慣を組織規模に広げたものにすぎません。

ステップ

  1. ネームスペースkcna-archを作成し、ラベルtier=labを付けてください。
  2. クラスターのすべてのノード名を1行に1つずつ/root/kcna-arch/nodes.txtに保存してください。名前だけを入れ、node/のような接頭辞は入れないでください。
  3. kubectl api-resourcesを見て、deploymentsのAPIVERSIONの値を/root/kcna-arch/deploy-apiversion.txtに、servicesの短縮形(SHORTNAMES)を/root/kcna-arch/svc-short.txtに、それぞれ1行で保存してください。
  4. kubectl explainで、Podをスケジューラーを介さず特定のノードに直接配置するspecフィールドを探し、そのフィールドを使ってネームスペースkcna-archにイメージがnginx:1.27-alpineのPodpinnedを作成してください。ノード名は、ステップ2の一覧にあるもののどれかにしてください。
  5. /root/kcna-arch/components.txtに次の4行をそのまま記入してください。serve-rest-api=、store-cluster-state=、watch-and-place-pods=、reconcile-desired-state=の後ろに、それぞれ適切なコンポーネント名(kube-apiserver、etcd、kube-scheduler、kube-controller-manager)を付けます。そしてkubectl get --rawでAPIサーバーの/healthzを呼び出し、その応答を/root/kcna-arch/healthz.txtに保存してください。
  6. ネームスペースkcna-archにPodを3つ作成してください。web-1(app=web,tier=front)、web-2(app=web,tier=back)、db-1(app=db,tier=back)です。次に、セレクターapp=web,tier=backで選んだPodの名前を、1行に1つずつ/root/kcna-arch/selected.txtに保存してください。
  7. kubectl create deploymentに--dry-run=client -o yamlを付けて、名前kcna-web、イメージnginx:1.27-alpine、replicas 2のDeploymentマニフェストを/root/kcna-arch/kcna-web.yamlに保存し、そのファイルをネームスペースkcna-archに宣言型で反映してください。

参考

作業用ネームスペースを作成する

ネームスペースkcna-archを作成し、ラベルtier=labを付けてください。

ネームスペースはクラスター内の名前空間です。作成するときにラベルを一緒に指定するか、作成後にkubectl labelで付けられます。ラベルのキーはtier、値はlabです。

ノード一覧をファイルに取り出す

クラスターのすべてのノード名を1行に1つずつ/root/kcna-arch/nodes.txtに保存してください。名前だけを入れ、node/のような接頭辞は入れないでください。

kubectl get nodesのデフォルト出力には、ヘッダーと複数の列が混ざっています。名前だけを1行に1つずつ取り出したいので、-oで出力形式を変えるのがすっきりします。-o nameを使うとnode/の接頭辞が付く点も確認してみてください。

api-resourcesでAPIグループと短縮形を探す

kubectl api-resourcesを見て、deploymentsのAPIVERSIONの値を/root/kcna-arch/deploy-apiversion.txtに、servicesの短縮形(SHORTNAMES)を/root/kcna-arch/svc-short.txtに、それぞれ1行で保存してください。

kubectl api-resourcesは、このクラスターが知っているすべてのリソースをNAME/SHORTNAMES/APIVERSION/NAMESPACED/KINDの列で表示します。検索はgrepで絞り込めばよいです。APIVERSIONは「グループ/バージョン」の形で、コアグループはグループ名が空である点に注意してください。

explainでフィールドを探してPodをノードに固定する

kubectl explainで、Podをスケジューラーを介さず特定のノードに直接配置するspecフィールドを探し、そのフィールドを使ってネームスペースkcna-archにイメージがnginx:1.27-alpineのPodpinnedを作成してください。ノード名は、ステップ2の一覧にあるもののどれかにしてください。

kubectl explain pod.specを実行すると、spec配下のフィールドの説明がずらりと出ます。スケジューラーを飛ばして特定のノードに直接配置するフィールドが、その中にあります。ノード名はステップ2で取り出した一覧のどれを使ってもかまいません。

コンポーネントの役割を整理してAPIサーバーの状態を取得する

/root/kcna-arch/components.txtに次の4行をそのまま記入してください。serve-rest-api=、store-cluster-state=、watch-and-place-pods=、reconcile-desired-state=の後ろに、それぞれ適切なコンポーネント名(kube-apiserver、etcd、kube-scheduler、kube-controller-manager)を付けます。そしてkubectl get --rawでAPIサーバーの/healthzを呼び出し、その応答を/root/kcna-arch/healthz.txtに保存してください。

前の読み物で扱った4つのコンポーネントの役割を、key=valueで1行ずつ書きます。そしてkubectlは--rawオプションで、APIサーバーの任意のパスをそのまま呼び出せます。ヘルスエンドポイントの応答はとても短いです。

ラベルを付けてセレクターで選び出す

ネームスペースkcna-archにPodを3つ作成してください。web-1(app=web,tier=front)、web-2(app=web,tier=back)、db-1(app=db,tier=back)です。次に、セレクターapp=web,tier=backで選んだPodの名前を、1行に1つずつ/root/kcna-arch/selected.txtに保存してください。

3つのPodに、それぞれ異なるラベルの組み合わせを付けます。次にkubectl getの-lオプションに条件をカンマでつなげて書くと、ANDとして動作します。結果をファイルに残すときは、名前だけが出るように出力形式を指定してください。

命令型で作ったYAMLを宣言型で反映する

kubectl create deploymentに--dry-run=client -o yamlを付けて、名前kcna-web、イメージnginx:1.27-alpine、replicas 2のDeploymentマニフェストを/root/kcna-arch/kcna-web.yamlに保存し、そのファイルをネームスペースkcna-archに宣言型で反映してください。

kubectl createに--dry-run=client -o yamlを付けると、クラスターに触れずにマニフェストだけを取り出せます。そのファイルをapplyで反映すると、createで作ったときにはなかったアノテーションがオブジェクトに1つ付きます。採点は、そのアノテーションの有無で2つの方式を区別します。