本記事には広告(アフィリエイトリンク)が含まれます。

K8s全体像とkind軽量クラスタ入門【CKAD第5回】

広告
広告

第5回スコープ・学習目標・今ここマップ

動作確認バージョン: kind v0.31.0 / kindest/node:v1.35.0 / kubectl v1.35.0 / Docker CE 29.4.3 / containerd 2.2.3 / AlmaLinux 10.1(kernel 6.12.0-124.55.3.el10_1)(2026-05-10 時点・k8s-ops 実機検証済・SP_vol1-pre-07 起点)

本回は Kubernetes 実践教科書 第1巻(CKAD 対応・全 19 回)の第5回です。第2部「Kubernetes 基礎」の開幕回として、なぜ Kubernetes が必要か・Kubernetes の内部構造はどうなっているか・ローカル学習環境 kind をどう構築するか を扱います。

CKAD D1(Application Design and Build・20 %)の前提知識と、D2(Application Deployment・20 %)の起点となるクラスタ操作の基礎を習得します。

第4回からの継承状態確認(SP_vol1-pre-07 状態):

項目状態
k8s-ops Docker CE29.4.3 稼働中
k8s-registry Docker Registryregistry:2 コンテナ稼働中・fanclub-backend:0.2.0 格納済み
kind未インストール(type kind → not found)
kubectl未インストール(type kubectl → not found)
ディスク空き(/ パーティション)27 GB(df -h / 確認済み)
メモリ空き4.8 GiB available(free -h 確認済み)

今ここマップ(第1巻 19 回中の現在位置):

第1部 コンテナとDocker
    第1回: コンテナ技術概念 + Docker環境準備  [完了]
    第2回: Docker基本操作  [完了]
    第3回: Dockerfile + マルチステージビルド + JDK 25/Payara Micro  [完了]
    第4回: コンテナレジストリ + イメージタグ戦略 + Trivy スキャン  [完了]

第2部 Kubernetes基礎
  ★ 第5回: K8s全体像 + kind で軽量K8s  ← 今ここ
    第6回: kubectl基本操作 + Observability・Debug

第3部 アプリリソース(第7〜11回)
第4部 ワークロード戦略(第12〜14回)
第5部 セキュリティ基礎(第15〜16回)
第6部 パッケージ管理 + HTTPS公開(第17〜19回)

第5回を終えると、以下を習得した状態になります。

  • Docker 単体の限界を「スケーリング・自己回復・複数ホスト跨ぎ」の観点で説明できる
  • Kubernetes アーキテクチャ(Control Plane Node の 4 コンポーネント・Workload Node の 3 コンポーネント)を図解で説明できる
  • kind と kubeadm(第2巻)の役割の違いを「学習用 vs 本番用」の観点で説明できる
  • kind v0.31.0 と kubectl v1.35.0 をバイナリ取得でインストールし、動作確認できる
  • kind create cluster --image docker.io/kindest/node:v1.35.0 でクラスタを起動し、kubectl get nodes で初接続を確認できる

模擬アプリ進捗(第5回):第5回は kind クラスタの基盤構築回のため、fanclub-api のデプロイ作業はありません。k8s-registry に push 済みの fanclub-backend:0.2.0 を K8s の Pod として動かすのは第7回からです。

Docker 単独の限界とオーケストレーターの必要性

第1〜4回で Docker の基本操作・Dockerfile 作成・レジストリ運用を学びました。docker run でコンテナを起動し、docker stop で停止し、docker push でイメージをレジストリに登録する一連の流れを体験しました。ここで問いを立てます。

fanclub-api を 10 台のサーバーに 50 個のコンテナで動かすには、どうすればよいでしょうか。

Docker 単体でこれを実現しようとすると、次のような問題が次々と現れます。

問題1: スケーリングの手動管理

トラフィックが増えてきたとします。コンテナを 5 個から 20 個に増やしたい場合、Docker 単体では docker run を 15 回手動で実行するしかありません。

増やす先のサーバーを決め、SSH でログインし、docker run を叩き、終わったら次のサーバーへ移動する。この作業を夜間のアクセス集中時に手動でやれるでしょうか。逆にトラフィックが減ったときにコンテナを減らすのも、すべて手動です。

Docker Compose を使えば複数コンテナをまとめて操作できますが、これは 1 台のホスト上でのみ有効です。複数サーバーに分散するスケーリングは Docker Compose の設計範囲外です。

問題2: 自己回復の欠如

稼働中のコンテナが OOM(Out of Memory)でクラッシュしたとします。docker run には --restart=always オプションがあり、同じホスト上であればコンテナを自動再起動できます。しかしこれは「1 台のホスト上の Docker デーモンが管理できる範囲」に限られます。

ホスト自体がダウンした場合には --restart=always は何もできません。別のホストにコンテナを移して再起動するには、誰かが手動で気づいてコマンドを実行する必要があります。この「誰か」が深夜 3 時に対応できるかどうかは、Docker 自体には関係のない問題です。

問題3: 複数ホスト跨ぎの複雑性

10 台のサーバーで動くコンテナの状態を確認したい場合、docker ps は 1 台ごとに SSH で接続して実行するしかありません。どのサーバーのどのコンテナが動いていて、どれが止まっているかを把握するには、10 台分のコマンド結果を目視で確認する必要があります。

コンテナのバージョンを新しいものに更新する場合も同様です。10 台に SSH して docker pulldocker stop / docker run を順番に実行する。サーバーが増えれば増えるほど、作業量は線形に増加します。

問題4: サービスディスカバリの欠如

コンテナの IP アドレスは、コンテナを再起動するたびに変わります。fanclub-api の frontend コンテナが backend コンテナに HTTP リクエストを送るには「接続先の IP アドレス」が必要ですが、backend が再起動するたびに IP が変わるため、frontend はどの IP に接続すればよいか分からなくなります。

Docker ネットワークの同一ネットワーク内ではコンテナ名で名前解決できますが、これも 1 台のホスト上の Docker ネットワーク内に限定された仕組みです。複数ホストに分散したコンテナ間での名前解決は、Docker 単体では解決できません。

オーケストレーターが解決すること

上記の問題を「宣言的に解決」するのがコンテナオーケストレーターです。「宣言的(declarative)」とは、「何をしてほしいか」を定義するだけで、「どうやって実現するか」はシステムが判断することを意味します。

たとえば「fanclub-backend のコンテナを常時 3 個動かし続けてほしい」と宣言します。オーケストレーターは次のことを自動で行います。

  • 3 個のコンテナをどのホストに配置するかを判断して起動する
  • コンテナが 1 個クラッシュしたら別のホストに 1 個新たに起動して「3 個」を維持する
  • コンテナの IP が変わっても名前で接続できるよう、ロードバランサのルールを自動更新する
  • 新バージョンのイメージに更新する際、ダウンタイムなしにローリングアップデートする

現時点では「そんな便利なものがあるのか」という認識で十分です。H2-4 以降でその仕組みを詳しく見ていきます。

Kubernetes とは何か — 歴史・概念・現在の標準性

Kubernetes(クーバネティス)は、コンテナ化されたアプリケーションのデプロイ・スケーリング・管理を自動化する OSS のコンテナオーケストレーターです。

Google Borg から Kubernetes へ

Kubernetes の原型は Google 社内の Borg(ボーグ)と呼ばれる大規模コンテナ管理システムです。Google は 2000 年代初頭から Borg を使って検索・Gmail・YouTube などのサービスを大量のサーバー上で管理してきました。Borg で培ったノウハウを再設計・OSS 化したものが Kubernetes であり、2014 年に公開されました。

2016 年には CNCF(Cloud Native Computing Foundation)—Linux Foundation 配下のベンダー中立な財団—に Kubernetes プロジェクトが寄贈されました。CNCF への寄贈により、特定の企業(Google)が開発をコントロールする状況を脱し、業界全体が関与するプロジェクトになりました。

名称の由来はギリシャ語で「船の操舵手(helmsman)」を意味する語です。ロゴにある舵(helm)もここから来ています。略称 K8s は “K” と “s” の間に 8 文字 “ubernete” があることに由来します。本シリーズでは「Kubernetes」と「K8s」を混用します。

現在の業界標準としての立ち位置

現在、主要なクラウドプロバイダーはすべて Kubernetes のマネージドサービスを提供しています。

クラウドサービス名
AWSAmazon EKS(Elastic Kubernetes Service)
Google CloudGKE(Google Kubernetes Engine)
Microsoft AzureAKS(Azure Kubernetes Service)

CNCF は Kubernetes エンジニアの技術力を認定する資格を提供しており、CKAD / CKA / CKS はその代表的な実技資格です。本シリーズ第1巻は CKAD(Certified Kubernetes Application Developer)の全 Competency を網羅することをゴールとしています。

クラウドネイティブの定義

CNCF が定義するクラウドネイティブとは、コンテナ・マイクロサービス・動的オーケストレーション・DevOps が揃った設計思想を指します。Kubernetes はこの「動的オーケストレーション」を担う中核コンポーネントとして位置づけられています。

他のオーケストレーターとの関係

Docker Swarm(Docker 社純正のオーケストレーター)や HashiCorp Nomad など、他のコンテナオーケストレーターも存在します。ただし、クラウドネイティブ業界の事実上の標準として Kubernetes が選択されています。本シリーズは Kubernetes のみを扱い、他のオーケストレーターとの詳細比較はスコープ外です。

Kubernetes アーキテクチャ全体像

Kubernetes クラスタは大きく 2 種類のノードから構成されます。

  • Control Plane Node:クラスタ全体を管理・制御するノード。クラスタの「頭脳」に相当します
  • Workload Node:アプリケーションコンテナ(Pod)を実際に動かすノード。クラスタの「腕」に相当します

本シリーズでは「Control Plane Node」と「Workload Node」という呼称を使います。古い書籍や記事では「Master Node / Worker Node」と書かれている場合がありますが、Kubernetes v1.20 以降の公式呼称は Control Plane Node / Workload Node です。

まず全体図(図解 05-01)を確認します。各コンポーネントが何をするかの 1 行概要は表で確認し、詳細説明は次の H2-5(Control Plane Node)と H2-6(Workload Node)で扱います。

Kubernetes アーキテクチャ全体図 - 左側 Control Plane Node に kube-apiserver・etcd・kube-scheduler・kube-controller-manager の 4 コンポーネント。右側 Workload Node に kubelet・kube-proxy・containerd の 3 コンポーネント。kubectl から kube-apiserver への HTTPS 矢印。kube-apiserver から etcd への双方向矢印。kube-scheduler と kube-controller-manager から kube-apiserver への矢印。kube-apiserver から Workload Node の kubelet への矢印。kubelet から containerd への矢印。

コンポーネント 1 行概要

コンポーネント所属ノード1 行概要
kube-apiserverControl Plane Nodeすべての API 通信の入口。kubectl / kubelet / Scheduler / Controller Manager はすべて API Server を経由して状態を読み書きする
etcdControl Plane Nodeクラスタ状態を保存する分散 KV ストア。唯一の真実のソース(SSOT)
kube-schedulerControl Plane Node新しい Pod をどの Workload Node に配置するかを決定する
kube-controller-managerControl Plane NodeDeployment / ReplicaSet / Node 等の各コントローラを内包し、「宣言した状態」と「実際の状態」の差異を解消し続ける
kubeletWorkload NodeControl Plane からの指示(Pod Spec)を受け取り containerd にコンテナ起動を依頼する
kube-proxyWorkload NodeService の ClusterIP から Pod の IP への転送ルールを iptables / ipvs で管理する
containerdWorkload Node実際にコンテナを起動・停止する OCI 準拠のランタイム(第1回既習)

kubectl からコンテナ起動までのフロー

[kubectl apply -f pod.yaml]
       | HTTPS
       v
[kube-apiserver] -- etcd に "Pod を作れ" と記録
       |
       v
[kube-scheduler] が etcd を監視 -- 配置先 Workload Node を選択
       |
       v
[kube-apiserver] -- 選ばれた Workload Node の kubelet に通知
       |
       v
[kubelet] -- containerd に "このコンテナを起動せよ" と指示
       |
       v
[containerd] -- k8s-registry から OCI イメージを pull -- コンテナ起動

このフローは第7回以降で体験します。第5回では「全体像を把握する」ことにとどめ、各コンポーネントの詳細に移ります。

コア コンポーネント詳説 — Control Plane Node

(Pod という概念が以降の説明で登場します。Pod の詳細は H2-7 で説明します。ここでは「コンテナを包む K8s の最小デプロイ単位」として読み進めてください)

Control Plane Node には以下の 4 つのコンポーネントが稼働しています。

kube-apiserver — すべての通信のゲートウェイ

kube-apiserver は、Kubernetes クラスタへのすべての API リクエストを受け付けるコンポーネントです。kubectl コマンドを実行すると、実際には kube-apiserver への HTTP/2 リクエストが送られています。

kube-apiserver の重要な性質は次の 2 点です。

  • すべての通信が kube-apiserver を経由する:kubectl / kubelet / kube-scheduler / kube-controller-manager はいずれも kube-apiserver を介して状態を読み書きします。コンポーネント間が直接通信することはありません
  • 認証・認可・バリデーションを実施してから etcd に書き込む:リクエストが正当なユーザーからのものか(認証)・そのユーザーに操作権限があるか(認可)・YAML の書式は正しいか(バリデーション)を確認してから etcd に反映します

kubectl get podskubectl apply -f manifest.yaml も、内部では kube-apiserver の REST API へのリクエストです。第6回の kubectl 基本操作では、この動作をより深く観察します。

etcd — クラスタ状態の唯一の真実のソース(SSOT)

etcd(エトシーディー)は、Raft アルゴリズムによる分散合意を持つ KV(Key-Value)ストアです。Kubernetes クラスタの「全状態」—Pod の定義・Node の情報・ConfigMap の内容・Secret・RBAC ポリシー—を etcd に保存します。

SSOT(Single Source of Truth・唯一の真実のソース)という言葉は、「クラスタの状態を知りたければ etcd を見ればよい」という意味です。他のコンポーネントが独自にクラスタ状態を持つことはなく、すべての読み書きは kube-apiserver 経由で etcd に集約されます。

etcd が壊れると、kube-apiserver は新しい状態を保存できなくなり、Scheduler と Controller Manager も機能を失います。クラスタ全体が停止します。これが 本番では etcd を奇数台(3 台または 5 台)で冗長化する理由です。第2巻では kubeadm による HA クラスタ構成と etcd バックアップ(etcdctl)を扱います。

第5回では etcd を直接操作しません。etcdctl の使い方は第2巻 CKA 編で学びます。

kube-scheduler — Pod の配置先を決定するエンジン

kube-scheduler は、「新しい Pod をどの Workload Node で動かすか」を決定するコンポーネントです。

配置先の決定には以下の情報を使います。

  • resources.requests:Pod が要求する CPU / メモリの量。ノードに余裕がなければ配置しない
  • nodeSelector:Pod が特定のラベルを持つノードにのみ配置されるよう指定する
  • Taint & Toleration:特定のノードに特定の Pod しか配置しない(第12回以降)

第5回では「配置先を決める担当者」という概念を覚えます。実際に Scheduler の動作を観察するのは第12回(Deployment)以降です。

kube-controller-manager — 制御ループのエンジン

kube-controller-manager は、Kubernetes の「制御ループ(control loop)」を担うコンポーネントです。Deployment Controller / ReplicaSet Controller / Node Controller など複数のコントローラを 1 つのバイナリに集約しています。

制御ループとは、次のサイクルを絶えず繰り返す動作です。

  • desired state(宣言した状態)を確認する:「fanclub-backend の Pod を 3 個動かしてほしい」という YAML の定義
  • actual state(実際の状態)を確認する:今 etcd に記録されている「現在動いている Pod の数」
  • 差異を解消する:desired = 3、actual = 2 なら新たに 1 個の Pod を作成する指示を kube-apiserver に送る

この仕組みが H2-2 で説明した「自己回復」を実現します。Pod が 1 個クラッシュすると actual state が 2 になり、controller が差異を検出して 3 個になるよう新しい Pod を起動します。

kind 環境での注意点:kind のシングルノードクラスタでは、Control Plane Node と Workload Node が同一のコンテナ(kindest/node)内で動作します。

本番環境では Control Plane Node と Workload Node を必ず分離します。第2巻 kubeadm HA 構成では Control Plane Node 3 台 + Workload Node 2 台の計 5 台構成を作ります。

コア コンポーネント詳説 — Workload Node

Workload Node には以下の 3 つのコンポーネントが稼働しています。

kubelet — K8s エージェント

kubelet は、各 Workload Node に常時稼働する K8s エージェントです。役割は「Control Plane(kube-apiserver)から Pod の仕様(PodSpec)を受け取り、containerd にコンテナ起動を依頼する」ことです。

kubelet は systemd サービスとして動作します(systemctl status kubelet)。kubelet が停止するとそのノードの Pod 管理が止まり、kube-controller-manager がそのノードを「NotReady」と検出して別ノードへの Pod 再配置を始めます。

第1回との再接続:第1回で「K8s は containerd を直接使用する。Docker は K8s のコンテナランタイムではない」と学びました。kubelet がその「仲介者」です。

kubelet は CRI(Container Runtime Interface)—K8s が定めたコンテナランタイムとの標準 API—を通じて containerd に指示を出します。Docker は CRI に直接対応しておらず(shimコンポーネントが必要)、K8s v1.24 以降は Docker を Container Runtime として使用できなくなっています。

kube-proxy — Service のルール管理

kube-proxy は、Kubernetes の Service リソースが機能するために必要な転送ルールを各 Workload Node の OS レベルで管理するコンポーネントです。

Service(サービス)は、Pod の IP アドレスが変わっても同じ名前・同じ仮想 IP(ClusterIP)で接続できるようにする K8s のリソースです(第8回で詳説)。kube-proxy はこの ClusterIP から実際の Pod の IP への転送ルールを、各ノードの iptables または ipvs に書き込みます。

kind 環境では kube-proxy が iptables モードで動作しています。第8回 Service 回で実際の動作を観察します。

containerd — OCI 準拠のコンテナランタイム(第1回既習との再接続)

containerd(コンテイナーディー)は、実際にコンテナを起動・停止する OCI 準拠のコンテナランタイムです。第1回で「Docker CE をインストールすると containerd も一緒にインストールされる」と学びました。K8s では kubelet が CRI 経由で containerd を直接呼び出しており、Docker デーモンは関与しません。

第4回ヒヤリハットで「kind ノード内の containerd は Docker デーモンとは別プロセス・別設定ファイルを持つ」と予告しました。

kind の各ノードコンテナ内部にも containerd が稼働しており、これは k8s-ops 上の Docker が使う containerd(containerd.sock を通じた Docker デーモン配下の containerd)とは完全に別のプロセスです。

2 つの containerd の関係を整理します。

containerd の場所役割管理するもの
k8s-ops ホスト上(Docker 配下)Docker デーモンがコンテナを起動する際に使うランタイムk8s-ops 上の Docker コンテナ(例: kind-control-plane コンテナ自体・k8s-registry の registry:2 コンテナ)
kind ノードコンテナ内部kubelet が Pod を起動する際に使うランタイムkind クラスタ内の Pod コンテナ(fanclub-api など、第7回以降でデプロイするもの)

この区別は第7回(Pod デプロイ)で k8s-registry を kind ノード内 containerd の insecure registry として設定する際に重要になります。

Pod — Kubernetes の最小デプロイ単位(概念先出し)

H2-4 の全体図から H2-6 の Workload Node 説明まで、「Pod をどの Workload Node に配置するか」「kubelet が Pod Spec を受け取る」という表現を繰り返し使いました。ここで Pod という概念を先出しで整理します。

Pod(ポッド)は、1 つ以上のコンテナを共有ネットワーク・共有ストレージで実行する K8s の最小デプロイ単位です。

なぜ「コンテナ」ではなく「Pod」が最小単位なのかは次の理由によります。

  • 1 つのサービスが「メインコンテナ + ログ収集の sidecar コンテナ」のように複数コンテナから成る場合、それらを同じネットワーク名前空間で動かす必要があります
  • Pod 内のコンテナはすべて同じ IP アドレスを共有します(localhost で相互通信できます)
  • kube-scheduler が配置先を決定する単位も「コンテナ個別」ではなく「Pod」です

第5回では Pod を直接操作しません。理由は「Pod 単独でデプロイする構成はアンチパターン」であり、本シリーズでは最初から Deployment(複数 Pod を束ねて管理するリソース)を使うためです。第7回では Pod の YAML 定義・ライフサイクル・Init Container / Sidecar パターンを本格的に学びます。

第7回(Pod + Multi-container パターン)は 第7回 Pod + Multi-container パターン です。Pod の YAML 定義・Init Container・Sidecar パターンを扱います。

kind とは — ローカル K8s 学習環境の仕組み

kind(カインド)は “Kubernetes IN Docker” の略で、Docker コンテナ自体が Kubernetes のノードになる軽量な K8s 学習環境です。

公式リポジトリは github.com/kubernetes-sigs/kind(CKAD 試験中参照可)です。なお kind.sigs.k8s.io は試験規約上の参照可否について確証がないため、CKAD 試験準備としては kubernetes.io/docs を主参照にすることを推奨します。

kind の動作原理(図解 05-02)

kind の動作原理図 - k8s-ops VM(AlmaLinux 10.1)の上に Docker CE が動く。Docker CE の中に kindest/node:v1.35.0 コンテナが動いており、コンテナ内部に kube-apiserver・etcd・kube-scheduler・kube-controller-manager・kubelet・containerd(K8s 用)が同居している。k8s-ops の kubectl がコンテナ内の kube-apiserver に kubeconfig 経由 HTTPS で接続する矢印。

動作原理を整理します。

  • k8s-ops(AlmaLinux 10.1 VM)上に Docker CE が稼働している
  • kind create cluster を実行すると、Docker コンテナ(kindest/node:v1.35.0 イメージ)が起動する
  • このコンテナ内部に Control Plane コンポーネント(kube-apiserver / etcd / kube-scheduler / kube-controller-manager)と kubelet / containerd が同居する
  • k8s-ops 上の kubectl~/.kube/config(kubeconfig)経由でこのコンテナ内の kube-apiserver に接続する

つまり 「ノード = Docker コンテナ」 が kind の本質です。docker ps を実行すると kind のノードが Docker コンテナとして表示されます。これは演習 ② で確認します。

kindnet CNI

kind には kindnet という内蔵の CNI(Container Network Interface)プラグインが含まれています。CNI は Pod 間ネットワーキングを担う K8s のネットワークプラグイン仕様で、kind では追加インストール不要で kindnet が自動で設定されます。

kindnet は NetworkPolicy に対応しており(v0.20+)、第16回のネットワークポリシー演習でも使用します。

kind と本番 kubeadm の比較

観点kind(第1巻)kubeadm(第2巻〜)
用途学習・CKAD 演習本番・CKA 実技・HA クラスタ構築
ノードの実体Docker コンテナ仮想マシン(VM)
セットアップ速度数十秒(イメージ pull 済み状態)数十分(VM プロビジョニング + kubeadm init)
HA 構成不可(シングルノード)可(Control Plane Node 3 台 + Workload Node 2 台 以上)
データの永続性クラスタ削除で消えるetcd バックアップで管理
kubectl 操作感本番と同一本番と同一

kubectl の操作感は kind でも kubeadm でも完全に同じです。第5回で kind クラスタに対して kubectl get nodes を実行した経験は、第2巻の kubeadm クラスタでもそのまま使えます。

CKAD 試験との関係:CKAD 試験の実技環境は kind ではなく本番に近い構成のクラスタです。しかし kubectl コマンドの操作感・YAML 定義の書き方は種類を問わず同一のため、kind での練習が試験対策として有効です。

kind を採用する理由:k8s-ops(2 core / 5.5 GB)と k8s-registry の 2 VM 構成で kind クラスタが動作します。Docker CE は第1回で導入済みのため追加 VM は不要です。

alma-proxy 環境の制約と Docker Hub mirror 回避策

演習①(kind / kubectl インストール)と演習②(kind クラスタ起動)を実行する前に、本シリーズの検証環境における重要な制約と回避策を理解します。この内容は後述のヒヤリハット(H2-12)と対になっています。

registry.k8s.io の仕組みと HTTP 307 リダイレクト

kind create cluster をオプションなしで実行すると、デフォルトで registry.k8s.io/kindest/node:v1.35.0 のイメージを取得しようとします。

registry.k8s.io は Kubernetes 公式のイメージレジストリです。ただし、このレジストリはマニフェスト取得のリクエストに対して HTTP 307 リダイレクト で地域ごとの Google Artifact Registry(GAR)に転送する設計になっています。

東京リージョンからのアクセスでは asia-northeast2-docker.pkg.dev(asia-northeast2 = 大阪)に転送されます。

これは Google がインフラ運用コストを最適化するための設計であり、世界中のリクエストを地理的に近い GAR にルーティングします。

alma-proxy whitelist の制約

第1回で構築した alma-proxy は whitelist 方式の企業プロキシです。許可ドメインのみ通信でき、リスト外は HTTP 403(Squid ERR_ACCESS_DENIED)で拒否されます。

whitelist の状況を確認します。

  • registry.k8s.io:許可済み
  • asia-northeast2-docker.pkg.dev(registry.k8s.io の redirect 先・Google Artifact Registry):未許可

結果として、kind create cluster がデフォルトで registry.k8s.io にアクセスしても、リダイレクト先の asia-northeast2-docker.pkg.dev への通信が HTTP 403 でブロックされてイメージ取得が失敗します。

回避策 B 採用: Docker Hub mirror を明示指定

この問題には 3 つの回避策があります。

内容採否
案 Aasia-northeast2-docker.pkg.dev を alma-proxy whitelist に追加する第5回では不採用(管理者承認が必要な変更作業のため)
案 Bkind create cluster --image docker.io/kindest/node:v1.35.0 で Docker Hub mirror を明示指定する第5回採用
案 C事前に docker pull docker.io/kindest/node:v1.35.0 して別のタグ名でローカルに持つ手順が多くなるため不採用

案 B を採用する理由は、docker.io/kindest/node:v1.35.0 が Docker Hub 上のミラーイメージとして公開されており、Docker Hub の pull は registry-1.docker.io 経由で行われ、これが alma-proxy whitelist に登録済みだからです。

docker manifest inspect docker.io/kindest/node:v1.35.0 で amd64 digest(sha256:986401fce0e567a9860075ba9df8c8459bd99a35f79024d8a682773fb40f0753)が確認でき、実機検証済みです。

現場視点の補足:本番で kind を継続利用する場合は、案 A(asia-northeast2-docker.pkg.dev を whitelist に正式追加)が長期的に望ましい選択です。Docker Hub は pull レート制限があり、大規模チームでの継続利用には向きません。

第5回では教材として「管理者承認を経ずに即実行できる Docker Hub mirror」を採用しますが、現場で運用環境に kind を継続導入する場合は whitelist 追加を検討してください。

企業ネットワークでのポイント:proxy whitelist 環境では「ドメインが許可されている」だけでは不十分で、「リダイレクト先ドメインも許可されているか」まで確認する必要があります。

registry.k8s.io は通るのに pull が止まる現象は、この redirect 構造に起因します。curl -vdocker pull --verbose でリクエストの流れを追うと原因を特定できます。

やってみよう ①: kind / kubectl のインストール

演習①では kind v0.31.0 と kubectl v1.35.0 を k8s-ops にインストールします。どちらもバイナリを GitHub / dl.k8s.io から取得して /usr/local/bin に配置するだけで完了します。

前提状態:SP_vol1-pre-07(kind / kubectl 未インストール・Docker CE 29.4.3 稼働中・alma-proxy proxy 設定済み)

Step 1: 前提状態の確認

実行コマンド:

$ type kind 2>&1
$ type kubectl 2>&1
$ docker version --format '{{.Server.Version}}'

実行結果:

bash: type: kind: 見つかりません
bash: type: kubectl: 見つかりません
29.4.3

kindkubectl どちらも「見つかりません」が返れば未インストール状態です。Docker Server Version が 29.4.3 であることも確認します。

Step 2: プロキシ環境変数の確認

実行コマンド:

$ env | grep -i proxy

実行結果:

https_proxy=http://192.168.1.121:3128
http_proxy=http://192.168.1.121:3128
no_proxy=localhost,127.0.0.1,192.168.1.0/24

https_proxy が設定されていることを確認します。curlhttps_proxy 環境変数が設定されていれば、--proxy フラグを明示しなくても自動的に alma-proxy(192.168.1.121:3128)を経由してダウンロードを行います。

Step 3: kind v0.31.0 バイナリ取得・インストール

実行コマンド:

$ curl -Lo /tmp/kind https://github.com/kubernetes-sigs/kind/releases/download/v0.31.0/kind-linux-amd64
$ sudo install -o root -g root -m 0755 /tmp/kind /usr/local/bin/kind

実行結果(curl のダウンロード進捗):

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10.5M  100 10.5M    0     0  12.4M      0 --:--:-- --:--:-- --:--:-- 12.4M

実行コマンド(バージョン確認):

$ kind version

実行結果:

kind v0.31.0 go1.25.5 linux/amd64

kind v0.31.0 と表示されれば正常です。go1.25.5 は kind v0.31.0 のビルド時の Go バージョンを示します(バイナリは AlmaLinux 10.1 のホストでも問題なく動作する Linux amd64 バイナリ)。

Step 4: kubectl v1.35.0 バイナリ取得・インストール

実行コマンド:

$ curl -Lo /tmp/kubectl https://dl.k8s.io/release/v1.35.0/bin/linux/amd64/kubectl
$ sudo install -o root -g root -m 0755 /tmp/kubectl /usr/local/bin/kubectl

実行結果(curl のダウンロード進捗):

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 55.8M  100 55.8M    0     0   937k      0  0:01:01  0:01:01 --:--:-- 1320k

実行コマンド(バージョン確認):

$ kubectl version --client

実行結果:

Client Version: v1.35.0
Kustomize Version: v5.7.1

--client フラグをつける理由は、クラスタに接続せずバイナリのバージョンのみを表示するためです。クラスタ未起動の状態でも実行できます。Kustomize Version: v5.7.1kubectl 内蔵の Kustomize バージョン(CKA D1 Kustomize で第2巻第14回に再登場します)。

なぜ v1.35.0 をピン留めするかdl.k8s.io/release/stable.txt は 2026-05-10 時点で v1.36.0 を返しますが、本シリーズは CKAD 試験(v1.35 対応)に合わせ v1.35.0 をピン留めします。kubectl のバージョンと CKAD 試験環境のクラスタバージョンを一致させることで、試験本番と同じコマンド動作を学習中に体験できます。

やってみよう ②: kind クラスタ起動 + kubectl get nodes 初接続

演習②では kind create cluster で K8s クラスタを起動し、kubectl get nodes でクラスタへの初接続を体験します。H2-9 で学んだ Docker Hub mirror 指定(--image docker.io/kindest/node:v1.35.0)を使います。

前提状態:演習①完了後(kind / kubectl インストール済み)

Step 1: kindest/node イメージを事前 pull して進捗確認

kindest/node イメージは大きなサイズのため、kind create cluster 実行中に「Ensuring node image…」の表示で長時間待機が発生することがあります(詳細は後述 H2-12 ヒヤリハット参照)。先に docker pull でイメージを取得して進捗バーで完了を確認してから、kind create cluster を実行します。

実行コマンド:

$ docker pull docker.io/kindest/node:v1.35.0

実行結果:

v1.35.0: Pulling from kindest/node
b55da17b98bb: Pull complete
cb61a4cea51e: Pull complete
Digest: sha256:4613778f3cfcd10e615029370f5786704559103cf27bef934597ba562b269661
Status: Downloaded newer image for kindest/node:v1.35.0
docker.io/kindest/node:v1.35.0

実行コマンド(イメージサイズ確認):

$ docker images kindest/node

実行結果:

IMAGE                  ID             DISK USAGE   CONTENT SIZE   EXTRA
kindest/node:v1.35.0   4613778f3cfc        1.35GB          397MB        

kindest/node イメージは Debian ベースの OS に K8s コンポーネント(kube-apiserver / etcd / kube-scheduler / kube-controller-manager / kubelet / kube-proxy / kindnet / containerd 等)を含むため、CONTENT SIZE で 397MB、DISK USAGE で 1.35GB と容量があります。

pull が完了すれば以降の kind create cluster は高速に動作します。

Step 2: kind クラスタ起動(Docker Hub mirror 明示)

実行コマンド:

$ kind create cluster --image docker.io/kindest/node:v1.35.0

実行結果:

Creating cluster "kind" ...
 • Ensuring node image (docker.io/kindest/node:v1.35.0) 🖼  ...
 ✓ Ensuring node image (docker.io/kindest/node:v1.35.0) 🖼
 • Preparing nodes 📦   ...
 ✓ Preparing nodes 📦
 • Writing configuration 📜  ...
 ✓ Writing configuration 📜
 • Starting control-plane 🕹️  ...
 ✓ Starting control-plane 🕹️
 • Installing CNI 🔌  ...
 ✓ Installing CNI 🔌
 • Installing StorageClass 💾  ...
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/

5 段階のチェックマーク(Ensuring node image → Preparing nodes → Writing configuration → Starting control-plane → Installing CNI → Installing StorageClass)が表示されれば成功です。

kindest/node イメージが pull 済みのため「Ensuring node image」は数秒で通過します。

「Set kubectl context to “kind-kind”」というメッセージが表示されます。これは kubectl がこの kind クラスタに接続するための設定(kubeconfig)が自動で行われたことを意味します。

Step 3: kubeconfig の確認

実行コマンド:

$ kubectl config view

実行結果:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://127.0.0.1:36183
  name: kind-kind
contexts:
- context:
    cluster: kind-kind
    user: kind-kind
  name: kind-kind
current-context: kind-kind
kind: Config
users:
- name: kind-kind
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

kubeconfig の役割kubectl はどのクラスタに接続するかを ~/.kube/config(kubeconfig)から読み取ります。kind create cluster は自動的にこのファイルを更新し、kind-kind というコンテキスト名でクラスタへの接続情報を追記します。

出力の contexts セクションに kind-kind エントリ・current-contextkind-kind が設定されていることを確認します。serverhttps://127.0.0.1:36183 はランダムに割り当てられた kube-apiserver のポート(環境ごとに異なる値)です。

Step 4: kubectl get nodes で初接続確認

実行コマンド:

$ kubectl get nodes

実行結果:

NAME                 STATUS   ROLES           AGE   VERSION
kind-control-plane   Ready    control-plane   46s   v1.35.0

出力の読み方

内容
NAMEノード名。kind クラスタでは kind-control-plane の 1 ノードのみ
STATUSReady = 正常稼働中 / NotReady = 問題あり(kubelet が応答していない可能性がある)
ROLEScontrol-plane = Control Plane Node として機能している
AGEクラスタ起動からの経過時間
VERSIONKubernetes バージョン。v1.35.0 であることを確認する

実行コマンド(詳細表示):

$ kubectl get nodes -o wide

実行結果:

NAME                 STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION                  CONTAINER-RUNTIME
kind-control-plane   Ready    control-plane   46s   v1.35.0   172.18.0.2    <none>        Debian GNU/Linux 12 (bookworm)   6.12.0-124.55.3.el10_1.x86_64   containerd://2.2.0

注目ポイント

  • OS-IMAGEDebian GNU/Linux 12 (bookworm)。kindest/node イメージのベース OS は Debian です。k8s-ops のホスト OS(AlmaLinux 10.1)とは別の OS がコンテナ内で動いていることが確認できます
  • CONTAINER-RUNTIMEcontainerd://2.2.0。H2-6 で説明した「kind ノード内部の containerd」が実際に動作していることを確認できます。なお k8s-ops ホストの containerd は v2.2.3 ですが、kind ノードコンテナ(kindest/node)にはイメージ内に独自の containerd(v2.2.0)が同梱されているため、バージョンが異なります。これは「kind ノードコンテナ内部に完結した K8s スタック」という H2-8 の説明と整合します

Step 5: kubectl cluster-info で API Server の動作確認

実行コマンド:

$ kubectl cluster-info

実行結果:

Kubernetes control plane is running at https://127.0.0.1:36183
CoreDNS is running at https://127.0.0.1:36183/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Kubernetes control plane is running at https://127.0.0.1:3618336183 は kind が自動でランダムに割り当てたポート番号です(環境・起動ごとに異なる値)。

kube-apiserver が 127.0.0.1 のこのポートで待ち受けており、kubectl はここに接続しています。kubectl config viewserver: 値と一致することを確認できます。

Step 6: docker ps で kind ノードはコンテナであることを確認

実行コマンド:

$ docker ps

実行結果:

CONTAINER ID   IMAGE                  COMMAND                   CREATED          STATUS          PORTS                       NAMES
d57222b2a636   kindest/node:v1.35.0   "/usr/local/bin/entr…"   54 seconds ago   Up 52 seconds   127.0.0.1:36183->6443/tcp   kind-control-plane

kind-control-plane という名前のコンテナが動いていることが確認できます。これが H2-8 で説明した「Docker コンテナが K8s ノードの実体」です。kubectl get nodes で表示された kind-control-plane ノードと、docker pskind-control-plane コンテナは同一のものです。

Step 7(オプション): kind クラスタの削除確認

演習の最後に kind クラスタを一度削除して、第6回に向けてクリーンな状態に戻します。

実行コマンド:

$ kind delete cluster

実行結果:

Deleting cluster "kind" ...
Deleted nodes: ["kind-control-plane"]

実行コマンド(コンテナが消えたことを確認):

$ docker ps

実行結果:

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

kind-control-plane コンテナが消えていれば削除成功です。

重要kind delete cluster を実行すると、そのクラスタ上で稼働していたすべての K8s リソース(Pod / Service / ConfigMap 等)は削除されます。ただし k8s-registry に push したコンテナイメージ(fanclub-backend:0.2.0 等)は k8s-registry の永続 Volume に保存されているため、削除されません。

第6回は kind create cluster から始まります。

現場ヒヤリハット — whitelist proxy 環境で kind create がフリーズに見えた

H2-9 で説明した registry.k8s.io の redirect 問題を実際に踏んだ体験を紹介します。H2-11 の演習②で「Step 1 で事前に docker pull を実行する」手順を設けた理由がこのヒヤリハットから分かります。

状況

検証環境で kind create cluster を実行したところ、「Ensuring node image…」の表示でコンソールが進捗のないまま止まりました。Ctrl+C を押すべきか数分間待つべきか判断できない状況になりました。しばらく待っても進捗が止まったままのため強制終了したところ、クラスタ作成が途中で止まっていました。

原因分析

原因を調べると、次の連鎖で発生していました。

  • kind create cluster(オプション未指定)はデフォルトで registry.k8s.io/kindest/node:v1.35.0 を pull しようとする
  • registry.k8s.io 自体は whitelist 許可済みのため manifest(イメージ一覧情報)の取得は成功する
  • イメージの実体(layer)は HTTP 307 で asia-northeast2-docker.pkg.dev にリダイレクトされ、そこで proxy に HTTP 403 でブロックされる
  • Docker のイメージ pull は「manifest 取得成功 → layer pull 試行 → layer pull 失敗」という順序で進むため、manifest 取得まで成功した状態で止まる。「Ensuring node image…」のまま固まって見える

回避策

実行コマンド(事前に Docker Hub mirror から pull して進捗を可視化する):

$ docker pull docker.io/kindest/node:v1.35.0

実行コマンド(pull 完了後に kind create cluster を実行する):

$ kind create cluster --image docker.io/kindest/node:v1.35.0

事前に docker pull でイメージを取得することで、進捗バー付きのダウンロード状況を確認できます。pull が完了した後に kind create cluster を実行すると「Ensuring node image」は数秒で通過します。

教育的補足

proxy whitelist 環境で「ドメインは通るのに pull が途中で止まる」現象は、redirect 先が whitelist に未登録の典型パターンです。curl -vdocker pull --verbose でリクエストの flow を追うと、どのドメインで詰まっているかを特定できます。

企業ネットワーク環境で新しい外部リソースを使うときは、接続先ドメインだけでなく「そのドメインがリダイレクトする先」まで確認する習慣をつけることが重要です。

理解度チェック + まとめ + 次回予告 + シリーズ一覧

理解度チェック(○× 形式・全 8 問)

第5回の理解度を確認します。○か×で答えてください。

問 1:Kubernetes の kube-apiserver はすべての API 通信のゲートウェイであり、kubectl や kubelet、Scheduler はすべて kube-apiserver を経由して状態を読み書きする。

問 2:etcd は Kubernetes のすべての構成データを保存するストレージであり、etcd が壊れてもクラスタは引き続き動作できる。

問 3:kube-scheduler は Pod が要求する CPU / メモリの requests やノードの状態を考慮して、Pod をどの Workload Node に配置するかを決定する。

問 4:kind クラスタでは Docker コンテナが Kubernetes のノードとして動作するため、docker ps で kind ノードを確認できる。

問 5kubectl get nodes の STATUS 列に NotReady と表示されている場合、そのノードの kubelet が正常に動作していない可能性がある。

問 6kind create cluster のデフォルト動作では registry.k8s.io から kindest/node イメージを取得しようとするが、whitelist proxy 環境では asia-northeast2-docker.pkg.dev への redirect がブロックされる場合がある。

問 7:kubectl v1.35.0 は K8s クラスタ v1.36.0 に対しても問題なく使用できる(kubectl とサーバーのバージョンスキューは ±1 マイナーバージョンまで許容される)。

問 8:kind クラスタを削除(kind delete cluster)すると、そのクラスタ上で稼働していたすべての K8s リソース(Pod / Service 等)は削除されるが、k8s-registry に push したコンテナイメージは削除されない。

解答

解答
問 1
問 2×
問 3
問 4
問 5
問 6
問 7×
問 8

解説(重要問のみ)

  • 問 2(×):etcd が壊れると kube-apiserver は新しい状態を保存できなくなり、Scheduler / Controller Manager も機能を失います。クラスタ全体が停止します。etcd の冗長化(本番は奇数台構成)が必須な理由であり、第2巻 kubeadm CKA 編で etcd バックアップ(etcdctl)を学びます。
  • 問 7(×):kubectl のバージョンスキューポリシーは「kubectl はサーバーと ±1 マイナーバージョンまでサポート」です。v1.35.0 の kubectl で v1.36.0 サーバーへの接続は -1 minor の範囲なので許容されます。ただしサーバーが v1.36 で追加された新 API を kubectl v1.35 で使おうとすると機能しない場合があります。問 7 の「問題なく使用できる」は正確ではないため × です。なお CKAD 試験では試験環境の K8s バージョンと kubectl バージョンが一致しているため実質的に問題になりません。

第5回まとめ

第5回では以下を実施しました。

  • Docker 単独の限界(スケーリング・自己回復・複数ホスト跨ぎ・サービスディスカバリ)を具体例で確認した
  • Kubernetes の歴史(Google Borg → 2014年 OSS 公開 → CNCF 寄贈)と業界標準としての立ち位置を理解した
  • Kubernetes アーキテクチャ(Control Plane Node の 4 コンポーネント・Workload Node の 3 コンポーネント)を全体図と詳説で確認した
  • Pod が K8s の最小デプロイ単位である理由を概念として把握した(詳細は第7回)
  • kind の「Docker コンテナが K8s ノードになる」仕組みを図解と docker ps の出力で確認した
  • alma-proxy whitelist 環境での kindest/node pull 制約と、Docker Hub mirror(docker.io/kindest/node:v1.35.0)を使った回避策を学んだ
  • kind v0.31.0 / kubectl v1.35.0 をバイナリ取得でインストールし、kubectl get nodes で初接続を体験した

次回予告

第6回 kubectl 基本操作 + Observability・Debug 入門では、第5回で起動した kind クラスタに対して kubectl を使い込みます。

kubectl get / describe / logs / exec / apply / diff / explain の基本コマンド・出力形式(-o yaml / -o json / -o jsonpath)・alias k=kubectl の設定を扱います。

CKAD D3(Observability and Maintenance・15 %)の全項目と、試験中の高速操作テクニック(--dry-run=client -o yaml)を習得します。

シリーズ一覧

第1部:コンテナと Docker

第2部:Kubernetes 基礎

第3部:アプリリソース

第4部:ワークロード戦略

第5部:セキュリティ基礎

第6部:パッケージ管理 + HTTPS 公開

広告
kubernetes
スポンサーリンク