kubeadmを使ったKubernetesクラスター構築:マスター&ワーカーノード設定

はい、承知いたしました。kubeadm を用いたKubernetesクラスターの構築について、マスターノードとワーカーノードの設定を詳細に説明する約5000語の記事を作成します。


kubeadm を使ったKubernetesクラスター構築:マスター&ワーカーノード設定

はじめに:Kubernetesとkubeadmがもたらす革新

現代のソフトウェア開発において、コンテナ技術はデプロイ、スケーリング、管理の方法に革命をもたらしました。Dockerに代表されるコンテナは、アプリケーションとその依存関係を一つの独立した実行単位にパッケージ化し、環境間の差異を吸収します。しかし、単一のコンテナは強力なツールである一方で、複数のコンテナから構成される複雑なアプリケーションを管理し、それらを大規模に展開する際には、新たな課題が浮上します。例えば、コンテナ間の通信、ロードバランシング、ストレージの永続化、障害発生時の自動復旧、スケーリングなどです。

これらの課題を解決するために登場したのが、「コンテナオーケストレーション」という概念であり、そのデファクトスタンダードとして君臨しているのが Kubernetes です。Kubernetesは、コンテナ化されたワークロードとサービスを宣言的に管理するためのポータブルで拡張可能なオープンソースプラットフォームです。これにより、開発者はインフラストラクチャの詳細に煩わされることなく、アプリケーションの開発に集中できるようになります。

Kubernetesクラスターを構築する方法はいくつかありますが、公式が推奨し、最も一般的に利用されているツールの一つが kubeadm です。kubeadm は、最小限の労力で堅牢なKubernetesクラスターをセットアップするためのコマンドラインツールです。手動で各コンポーネントを設定するよりもはるかに簡単かつ迅速に、ベストプラクティスに従ったクラスターを構築できます。本記事では、この kubeadm を利用して、マスターノード1台とワーカーノード複数台からなるKubernetesクラスターをゼロから構築する手順を、詳細な解説とともに提供します。

このガイドは、Kubernetesの基礎知識がある方を対象としていますが、各ステップの背景にある理由や注意点についても深く掘り下げて説明することで、単なる手順書に留まらない実践的な知識を提供することを目指します。

本ガイドで構築するクラスターの概要

本記事では、以下のようなシンプルな構成のKubernetesクラスターを構築します。

  • マスターノード (Master Node): 1台
    • Kubernetesのコントロールプレーン(APIサーバー、スケジューラー、コントローラーマネージャー、etcd)を実行します。クラスターの状態を管理し、ワーカーノード上のワークロードをオーケストレーションします。
  • ワーカーノード (Worker Node): 複数台
    • コンテナ化されたアプリケーション(Pod)が実際に動作するノードです。kubelet、kube-proxy、コンテナランタイムが動作します。
  • コンテナランタイム (Container Runtime): containerd を使用します。
  • ネットワークプラグイン (CNI Plugin): Calico を使用します。Pod間のネットワークを確立し、ネットワークポリシーを適用します。

前提条件:構築を始める前に確認すべきこと

Kubernetesクラスターを安定して動作させるためには、各ノードが特定の要件を満たしている必要があります。以下の項目を慎重に確認し、準備を整えてください。

1. ハードウェア要件

各ノード(マスター、ワーカー共通)について、以下の最小要件を満たすことを推奨します。

  • CPU: 2コア以上 (マスターノードは特に重要。ワーカーノードも複数のPodを動かすなら2コア以上が望ましい)
  • RAM: 2GB以上 (マスターノードは4GB以上を推奨。etcdとコントロールプレーンの負荷を考慮)
  • ディスクスペース: 20GB以上 (OS、Kubernetesコンポーネント、コンテナイメージ、Podデータ用。本番環境ではより大容量が必須)
  • ネットワーク: 安定したネットワーク接続。有線接続を強く推奨。

2. オペレーティングシステム (OS)

Ubuntu 22.04 LTS を使用することを強く推奨します。kubeadm は様々なLinuxディストリビューションをサポートしていますが、UbuntuはKubernetesコミュニティで最も広く利用されており、豊富なドキュメントとコミュニティサポートがあります。

  • 推奨OS: Ubuntu 22.04 LTS (Jammy Jellyfish)
  • 互換性のあるOS: CentOS/RHEL 8+, Debian 11+, Fedora 37+, openSUSE Leap 15.x, SLES 15.x など。
    • 注意: SELinuxを使用するOSの場合、Kubernetesの動作に影響を与える可能性があるため、無効化またはPermissiveモードに設定する必要があります。本記事ではUbuntuを前提とするため、SELinuxに関する詳細な手順は割愛します。

3. ネットワーク要件

Kubernetesクラスター内の通信は非常に重要です。以下の点を確認してください。

  • 固定IPアドレス: 各ノードには静的IPアドレスを設定してください。DHCPを使用すると、IPアドレスが変更される可能性があり、クラスターの安定性に影響します。
  • ホスト名 (Hostname) の設定: 各ノードに一意で分かりやすいホスト名を設定してください。
    • 例: k8s-master-01, k8s-worker-01, k8s-worker-02
  • DNS解決: 各ノードが自身および他のノードのホスト名をIPアドレスに解決できることを確認してください。/etc/hosts ファイルにエントリを追加するか、適切なDNSサーバーを設定します。
  • ファイアウォール設定: Kubernetesの動作に必要なポートが開放されていることを確認してください。詳細なポートリストは後述します。
  • SSHアクセス: 各ノードにSSHでアクセスできること。以降のほとんどの作業はSSH経由で行います。

ネットワーク設計の例:

ノードの種類 ホスト名 IPアドレス 役割
マスター k8s-master-01 192.168.1.10 Kubernetesコントロールプレーン
ワーカー k8s-worker-01 192.168.1.11 アプリケーションPodの実行
ワーカー k8s-worker-02 192.168.1.12 アプリケーションPodの実行 (追加の例)

4. ユーザー権限

  • sudo 権限を持つユーザーで作業を行います。

ステップ1:全ノード共通の初期設定 (マスター&ワーカー)

このセクションでは、マスターノードとすべてのワーカーノードの両方に適用される共通の初期設定を行います。SSHで各ノードにログインし、以下の手順を実行してください。

1. OSの更新と必須パッケージのインストール

最新のセキュリティパッチとソフトウェアアップデートを適用し、後続のインストールに必要なパッケージを準備します。

“`bash

パッケージリストを更新

sudo apt update -y

システムのパッケージをアップグレード

sudo apt upgrade -y

必要なパッケージのインストール (ca-certificates, curl, gnupg, lsb-release)

ca-certificates: SSL/TLS 証明書を検証するために必要

curl: URLからデータを転送するためのコマンドラインツール

gnupg: GPGキーの管理に必要 (ソフトウェアリポジトリの認証に使用)

lsb-release: ディストリビューションの情報を取得するために必要 (リポジトリ設定用)

sudo apt install -y ca-certificates curl gnupg lsb-release
“`

2. Swapの無効化

Kubernetesは、パフォーマンスと安定性の理由から、ノード上でSwapが有効になっていることを許容しません。Swapは予測不能なパフォーマンスの低下を引き起こし、クラスターの挙動に悪影響を与える可能性があるため、完全に無効化する必要があります。

“`bash

一時的にswapを無効化 (再起動すると元に戻る可能性がある)

sudo swapoff -a

/etc/fstab を編集して永続的にswapを無効化

sedコマンドで/etc/fstab内の’swap’という行をコメントアウトする

sudo sed -i ‘/ swap / s/^(.*)$/#\1/g’ /etc/fstab

swapが完全に無効化されたか確認

free -h

Swap行が0Bになっていることを確認

“`

3. ファイアウォール (UFW) の設定

UbuntuではデフォルトでUFW (Uncomplicated Firewall) が利用できます。Kubernetesコンポーネント間の通信に必要なポートを開放します。

マスターノードで開放する必要があるポート:

プロトコル ポート範囲 説明 コンポーネント
TCP 6443 Kubernetes APIサーバー kube-apiserver
TCP 2379-2380 etcdサーバークライアントAPI etcd
TCP 10250 Kubelet API kubelet
TCP 10259 kube-schedulerのHTTPポート kube-scheduler
TCP 10257 kube-controller-managerのHTTPポート kube-controller-manager

ワーカーノードで開放する必要があるポート:

プロトコル ポート範囲 説明 コンポーネント
TCP 10250 Kubelet API kubelet
TCP 30000-32767 NodePort Services (アプリケーション用) kube-proxy

全ノード共通のポート:

  • SSH: TCP 22 (SSHアクセス用)
  • Pod間通信: CalicoなどのCNIプラグインが使用するポート。CalicoはデフォルトでIP-in-IP (IP protocol 4) とUDP 4789 (VXLAN) を使用します。

以下のコマンドを 各ノードで 実行します。

“`bash

SSHポートの許可

sudo ufw allow 22/tcp

Kubelet APIの許可

sudo ufw allow 10250/tcp

マスターノードにのみ追加するポート

(マスターノードで実行)

sudo ufw allow 6443/tcp

sudo ufw allow 2379:2380/tcp

sudo ufw allow 10259/tcp

sudo ufw allow 10257/tcp

ワーカーノードにのみ追加するポート

(ワーカーノードで実行)

sudo ufw allow 30000:32767/tcp

UFWを有効化

sudo ufw enable

状態を確認

sudo ufw status verbose
``
**注意:** UFWを有効にするとSSHセッションが切断される可能性があります。
sudo ufw allow 22/tcpsudo ufw enableの前に実行することを忘れないでください。
また、CNIプラグイン(Calicoなど)が使用するプロトコル(IP-in-IP: プロトコル番号4、またはUDP 4789)もファイアウォールで許可する必要がありますが、通常は
kubeadmとCNIの設定によって適切に処理されるか、ufw`がこれらのプロトコルに対して自動的に許可しないため、OSレベルのファイアウォールよりも、クラウドプロバイダのセキュリティグループやネットワークACLで管理する方が一般的です。ここでは基本的なTCPポートに絞ります。

4. Bridgeネットワークのフィルタリング有効化

KubernetesのPodネットワークは、Linuxブリッジングとiptablesに依存しています。sysctlパラメータを設定して、ブリッジされたトラフィックがiptablesによって正しく処理されるようにします。これは、CNIプラグインがPod間のネットワークを確立するために不可欠です。

“`bash

net.bridge.bridge-nf-call-iptables を有効化 (IPv4)

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

モジュールのロード

sudo modprobe br_netfilter

sysctl設定の反映

sudo sysctl –system
``
*
br_netfilterモジュール: ブリッジされたネットワークトラフィックがiptablesを通過できるようにするために必要です。
*
net.bridge.bridge-nf-call-iptables = 1: IPv4トラフィックがブリッジを通過する際にiptablesのルールが適用されるようにします。
*
net.bridge.bridge-nf-call-ip6tables = 1: IPv6トラフィックの場合。
*
net.ipv4.ip_forward = 1`: IPフォワーディングを有効にし、ノードがルーターとして機能できるようにします。これはPodが外部と通信するために必要です。

5. コンテナランタイムのインストール (Containerd)

Kubernetesはコンテナの実行にCRI (Container Runtime Interface) 準拠のランタイムを必要とします。Dockerも利用可能ですが、軽量でKubernetesとの統合がより最適化された containerd を使用します。

“`bash

Dockerの公式GPGキーを追加

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg –dearmor -o /etc/apt/keyrings/docker.gpg

Dockerのリポジトリを追加

echo \
“deb [arch=$(dpkg –print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable” | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

パッケージリストを更新

sudo apt update -y

containerdのインストール

sudo apt install -y containerd.io

containerdのデフォルト設定ファイルを生成

sudo containerd config default | sudo tee /etc/containerd/config.toml >/dev/null

systemd cgroup driver を使用するように設定を変更

Kubernetesとcontainerdは同じcgroup driverを使用する必要がある

config.toml内の “SystemdCgroup = false” を “SystemdCgroup = true” に変更

sudo sed -i ‘s/SystemdCgroup = false/SystemdCgroup = true/g’ /etc/containerd/config.toml

containerdサービスを再起動して設定を適用

sudo systemctl restart containerd

containerdサービスが有効になっていることを確認 (OS起動時に自動起動するように)

sudo systemctl enable containerd
``
**Cgroup Driverの重要性:**
Kubernetesの
kubeletとコンテナランタイム(この場合はcontainerd)は、**同じcgroup driver** を使用するように設定されている必要があります。デフォルトでは、kubeadmkubeletsystemdcgroup driverを使用するように設定します。したがって、containerdsystemdcgroup driverを使用するように設定する必要があります。もしこれが一致しない場合、kubeletcontainerdと通信できず、ノードがNotReady`状態になるなど、クラスターの起動に失敗します。

6. kubeadm, kubelet, kubectl のインストール

Kubernetesのコアツールをインストールします。

  • kubeadm: Kubernetesクラスターを初期化またはワーカーノードをクラスターに参加させるためのコマンド。
  • kubelet: 各ノード上で動作するエージェントで、Podの実行、ノードの登録、リソース管理などを行います。
  • kubectl: Kubernetesクラスターと対話するためのコマンドラインツール。

“`bash

Kubernetesの公式GPGキーを追加

curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg –dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg

Kubernetesのリポジトリを追加

echo “deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main” | sudo tee /etc/apt/sources.list.d/kubernetes.list

パッケージリストを更新

sudo apt update -y

kubelet, kubeadm, kubectl をインストール

特定のバージョンを指定することも可能だが、今回は最新安定版をインストール

sudo apt install -y kubelet kubeadm kubectl

インストールしたKubernetesコンポーネントが自動更新されないようにする

自動更新されると、クラスターの安定性が損なわれる可能性があるため、手動でバージョンアップを行うのが一般的

sudo apt-mark hold kubelet kubeadm kubectl

kubeletサービスが有効になっていることを確認 (ただしまだ起動はしない)

sudo systemctl enable –now kubelet
``
**
apt-mark holdの重要性:**
Kubernetesクラスターでは、各コンポーネントのバージョン管理が非常に重要です。
apt upgradeなどのコマンドでkubelet,kubeadm,kubectlが意図せずアップグレードされると、クラスターが不安定になったり、互換性の問題が発生したりする可能性があります。そのため、apt-mark hold`でこれらのパッケージを固定し、アップグレードは手動で行うのがベストプラクティスです。


これで、すべてのノード共通の初期設定が完了しました。次は、マスターノードとワーカーノード固有の設定に進みます。

ステップ2:マスターノード固有の設定

ここでは、k8s-master-01 (192.168.1.10) にログインして作業を行います。

1. kubeadmによるクラスターの初期化

マスターノードで kubeadm init コマンドを実行し、Kubernetesコントロールプレーンをセットアップします。このコマンドは、APIサーバー、etcd、スケジューラー、コントローラーマネージャーなどの主要コンポーネネントをインストールし、設定します。

重要なオプション:

  • --apiserver-advertise-address: APIサーバーが他のノードと通信するために使用するマスターノードのIPアドレスを指定します。マスターノードの固定IPアドレス (192.168.1.10) を指定します。
  • --pod-network-cidr: Podに割り当てるIPアドレス範囲を指定します。これはCNIプラグインがPodネットワークを構築するために使用します。使用するCNIプラグイン(ここではCalico)のデフォルトのCIDRに合わせて 192.168.0.0/16 を指定します。これはクラスター内部のPod専用のIP空間です。
  • --control-plane-endpoint: 高可用性(HA)クラスターを構築する場合にロードバランサーのDNS名またはIPアドレスを指定しますが、今回は単一マスターのためマスターノードのIPアドレスを直接指定するか、省略しても構いません。推奨はDNS名ですが、簡単化のためIPアドレスを使用します。

“`bash

kubeadm init の実行

–upload-certs を追加することで、ワーカーノード参加時に証明書を自動でコピーできるようになる (HAクラスターで特に便利だが、単一マスターでも利用可能)

sudo kubeadm init \
–apiserver-advertise-address=192.168.1.10 \
–pod-network-cidr=192.168.0.0/16 \
–control-plane-endpoint=k8s-master-01 \
–upload-certs

コマンド実行後、成功すると以下のような出力が表示されるはずです。

This will likely take several minutes.

… (省略) …

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a Pod network to the cluster.

Run “kubectl apply -f [podnetwork].yaml” with one of the options listed at:

https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

sudo kubeadm join 192.168.1.10:6443 –token –discovery-token-ca-cert-hash sha256:

``kubeadm init`が成功すると、重要な3つの情報 が出力されます。

  1. kubectl の設定方法: クラスターを操作するための kubectl コマンドを使用するための設定手順。
  2. Podネットワーク (CNI) のインストール指示: クラスターが正しく機能するために必要なPodネットワークの導入について。
  3. ワーカーノード参加 (join) コマンド: 新しいワーカーノードをこのクラスターに参加させるための正確なコマンド。これは必ず控えておいてください。トークンとハッシュはセキュリティ上重要であり、一度失うと再生成が必要になります。

2. kubectl の設定

kubeadm init の出力に従い、通常のユーザーでkubectlコマンドを使えるように設定します。

“`bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

設定が正しく行われたか確認

kubectl cluster-info

Kubernetes control plane is running at https://192.168.1.10:6443

CoreDNS is running at https://192.168.1.10:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

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

kubectl get nodes

出力は以下のようになり、マスターノードが “NotReady” と表示されるはずです。

NAME STATUS ROLES AGE VERSION

k8s-master-01 NotReady control-plane 2m v1.28.0 # バージョンは異なる可能性があります

NotReadyであるのは、まだPodネットワークがデプロイされていないためです。

“`

3. Podネットワークプラグイン (Calico) のインストール

クラスターのPod間の通信を有効にするため、CNI (Container Network Interface) プラグインをインストールします。ここでは、広く利用され、ネットワークポリシー機能も充実しているCalicoを使用します。

CalicoのYAMLファイルをダウンロードし、適用します。--pod-network-cidrで指定したIPアドレス範囲とCalicoの設定が一致している必要があります。

“`bash

CalicoのYAMLマニフェストをダウンロード

バージョンは適宜最新の安定版を確認してください

curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O

ダウンロードしたYAMLファイルを適用

これにより、CalicoのPodがkube-systemネームスペースにデプロイされ、Podネットワークが構築されます。

kubectl apply -f calico.yaml

Calico Podの起動状況を確認

少し時間がかかる場合があります。STATUSが”Running”になるまで待ちます。

kubectl get pods –all-namespaces -w

出力例:

NAMESPACE NAME READY STATUS RESTARTS AGE

kube-system calico-kube-controllers-5f78c946f8-abcde 1/1 Running 0 30s

kube-system calico-node-xxxxx 1/1 Running 0 30s

kube-system coredns-5c98db65d4-abcde 1/1 Running 0 1m

kube-system coredns-5c98db65d4-vwxyz 1/1 Running 0 1m

``
すべてのCalico PodとCoreDNS Podが
Running`状態になったら、マスターノードのステータスを確認します。

“`bash
kubectl get nodes

出力例:

NAME STATUS ROLES AGE VERSION

k8s-master-01 Ready control-plane 5m v1.28.0 # STATUSが”Ready”になっていることを確認

``
マスターノードが
Ready`状態になっていれば、コントロールプレーンは正常に機能しており、Podネットワークも設定されています。

ステップ3:ワーカーノード固有の設定

ここでは、k8s-worker-01 (192.168.1.11) と k8s-worker-02 (192.168.1.12) にログインして作業を行います。

1. クラスターへの参加 (kubeadm join)

マスターノードのkubeadm initコマンドの出力に表示された kubeadm join コマンドを、各ワーカーノードで実行します。

重要な注意点:
* kubeadm joinコマンドは、root権限 で実行する必要があります。
* --token--discovery-token-ca-cert-hash は、kubeadm initコマンドの出力からコピーしたものを正確に入力してください。これらの値はクラスターごとに一意で、セキュリティのために使用されます。トークンの有効期限はデフォルトで24時間です。期限切れの場合は、マスターノードで kubeadm token create --print-join-command を実行して新しいトークンを取得できます。

ワーカーノード (k8s-worker-01, k8s-worker-02 など) で以下のコマンドを実行:

“`bash

マスターノードのkubeadm init出力からコピーしたjoinコマンドを実行

sudo kubeadm join 192.168.1.10:6443 –token –discovery-token-ca-cert-hash sha256:

成功すると以下のような出力が表示されます

This node has joined the cluster:

* Certificate signing request was sent successfully to API Server and a response was received.

* The Kubelet was informed of the new secure connection details.

Run ‘kubectl get nodes’ on the control-plane to see this node join the cluster.

“`

kubeadm join が成功したら、マスターノードに戻り、クラスターにノードが正しく参加したことを確認します。

ステップ4:クラスターの確認とテスト

マスターノード (k8s-master-01) にログインし、kubectlコマンドを使用してクラスターの状態を確認します。

1. ノードの状態確認

すべてのノードがReady状態になっていることを確認します。

“`bash
kubectl get nodes

出力例:

NAME STATUS ROLES AGE VERSION

k8s-master-01 Ready control-plane 15m v1.28.0

k8s-worker-01 Ready 2m v1.28.0 # k8s-worker-01が参加

k8s-worker-02 Ready 2m v1.28.0 # k8s-worker-02が参加

``STATUSReadyになっていることを確認してください。もしNotReadyであれば、ワーカーノードのkubeletログ(sudo journalctl -u kubelet -f)やマスターノードのkubectl describe node `で原因を調査してください。

2. Podの状態確認

すべてのシステムPodがRunning状態であることを確認します。

“`bash
kubectl get pods –all-namespaces

出力例:

NAMESPACE NAME READY STATUS RESTARTS AGE

kube-system calico-kube-controllers-5f78c946f8-abcde 1/1 Running 0 18m

kube-system calico-node-xxxxx 1/1 Running 0 18m

kube-system calico-node-yyyyy 1/1 Running 0 2m # worker-01のCalico

kube-system calico-node-zzzzz 1/1 Running 0 2m # worker-02のCalico

kube-system coredns-5c98db65d4-abcde 1/1 Running 0 18m

kube-system coredns-5c98db65d4-vwxyz 1/1 Running 0 18m

kube-system etcd-k8s-master-01 1/1 Running 0 18m

kube-system kube-apiserver-k8s-master-01 1/1 Running 0 18m

kube-system kube-controller-manager-k8s-master-01 1/1 Running 0 18m

kube-system kube-proxy-abcde 1/1 Running 0 18m

kube-system kube-proxy-fghij 1/1 Running 0 2m # worker-01のkube-proxy

kube-system kube-proxy-klmno 1/1 Running 0 2m # worker-02のkube-proxy

kube-system kube-scheduler-k8s-master-01 1/1 Running 0 18m

``
すべてのPodが
Running(またはCompletedEvictedなど、正常な状態) であることを確認してください。特にPendingCrashLoopBackOff`のPodがないか注意深く確認します。

3. サンプルアプリケーションのデプロイ

Nginxのデプロイメントを作成し、クラスターがアプリケーションを正しくスケジューリングして実行できるか確認します。

“`bash

Nginxデプロイメントの作成

kubectl create deployment nginx –image=nginx

デプロイメントの状態を確認

kubectl get deployment nginx

READYの列が1/1になるまで待ちます。

Podの状態を確認

kubectl get pods -l app=nginx

STATUSがRunningになることを確認

NginxサービスをNodePortとして公開

NodePortは、ワーカーノードの特定のポートを通じて外部からアプリケーションにアクセスできるようにするサービスタイプです。

kubectl expose deployment nginx –type=NodePort –port=80

サービスの状態を確認

kubectl get service nginx

出力例:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

nginx NodePort 10.96.xxx.yyy 80:3xxxx/TCP 10s

PORT(S)の3xxxxの部分がNodePortとして割り当てられたポート番号です。

Nginxへのアクセス確認

ブラウザまたはcurlコマンドで、ワーカーノードのいずれかのIPアドレスとNodePortでアクセスします。

例: curl http://192.168.1.11:3xxxx (ワーカーノードのIPアドレス)

Welcome to nginx! が表示されれば成功です。

“`
これで、基本的なKubernetesクラスターの構築と動作確認が完了しました。

トラブルシューティング:一般的な問題と解決策

Kubernetesクラスター構築中に発生しやすい一般的な問題とその解決策をまとめました。

1. ノードが NotReady 状態のまま

  • 原因: kubeletが起動していない、コンテナランタイムが正しく動作していない、CNIプラグインがデプロイされていない、またはPodネットワークに問題がある。
  • 確認コマンド:
    • sudo journalctl -u kubelet -f (ノード上でKubeletのログを確認)
    • sudo systemctl status kubelet (Kubeletサービスの稼働状況確認)
    • sudo systemctl status containerd (Containerdサービスの稼働状況確認)
    • kubectl describe node <node_name> (マスターノードからノードの詳細な状態を確認)
    • kubectl get pods --all-namespaces -o wide (Podがどのノードで実行されているか確認。特にkube-systemの名前空間のPod)
  • 解決策:
    • Cgroup Driverの不一致: kubeletcontainerdのcgroup driver設定が一致しているか確認 (/etc/containerd/config.tomlSystemdCgroupkubeletの設定)。多くの場合、SystemdCgroup = trueにする必要があります。変更後はsudo systemctl restart containerdsudo systemctl restart kubelet
    • CNIプラグイン未インストール/問題: マスターノードにCalicoなどのCNIプラグインが正しくデプロイされているか確認。Calico PodがRunningか確認し、ログ(kubectl logs calico-node-xxxxx -n kube-system)を確認。
    • ファイアウォール: 必要なポートが開放されているか確認。
    • Swap: Swapが完全に無効化されているか再確認。

2. Podが Pending 状態のまま

  • 原因: Podをスケジューリングできるノードがない、リソース不足、Node Selector/Taints and Tolerations の問題、Podネットワークの問題。
  • 確認コマンド:
    • kubectl describe pod <pod_name> -n <namespace> (Podの詳細なイベントとエラーメッセージを確認)
    • kubectl get nodes (ノードの状態とリソースを確認)
  • 解決策:
    • リソース不足: ノードのリソース(CPU, Memory)が十分か確認。Podの要求リソースがノードのキャパシティを超えていないか確認。
    • CNI問題: CNIプラグインが正しく動作しているか確認。特にCalico Podが正常に起動しているか。
    • Taints/Tolerations: マスターノードにPodをデプロイしたい場合、デフォルトではTaintが設定されているため、kubectl taint nodes --all node-role.kubernetes.io/control-plane- でTaintを解除するか、PodにTolerationを設定する必要があります。

3. Podが CrashLoopBackOff 状態のまま

  • 原因: アプリケーションのエラー、設定ミス、イメージが見つからない、依存関係の問題。
  • 確認コマンド:
    • kubectl logs <pod_name> -n <namespace> (Podのアプリケーションログを確認)
    • kubectl describe pod <pod_name> -n <namespace> (Podの詳細イベント、イメージプルエラーなどを確認)
  • 解決策:
    • アプリケーションログの確認: 最も重要なステップ。アプリケーションのエラーメッセージから原因を特定。
    • イメージ名の確認: イメージ名が正しいか、プライベートレジストリからのプルに認証が必要な場合は設定されているか確認。
    • 設定ファイル (ConfigMap, Secret) の確認: アプリケーションが依存する設定が正しく提供されているか確認。

4. kubeadm join がうまくいかない

  • 原因: トークンの有効期限切れ、ハッシュ値の間違い、マスターノードへのネットワーク接続問題。
  • 確認コマンド:
    • ワーカーノードからマスターノードのAPIサーバーへの疎通確認: curl -k https://192.168.1.10:6443/version
  • 解決策:
    • 新しいトークンの生成: マスターノードで sudo kubeadm token create --print-join-command を実行し、新しいjoinコマンドを取得して再試行。
    • ファイアウォール: マスターノードの6443ポートが開放されているか確認。
    • ホスト名/IPアドレスの解決: 各ノードから他のノードのホスト名やIPアドレスが正しく解決できるか確認。

5. kubeadm reset で初期状態に戻す

クラスターを再構築したい場合や、特定ノードをクラスターから除外して初期状態に戻したい場合は、kubeadm resetコマンドを使用します。

“`bash

ノード上で実行

sudo kubeadm reset

もしストレージボリュームが残っている場合 (Dockerやcontainerdのボリュームなど)

それらもクリーンアップしたい場合は、以下のコマンドを参考に手動で削除

sudo rm -rf /etc/cni/net.d

sudo rm -rf ~/.kube/config

sudo systemctl stop kubelet containerd

sudo rm -rf /var/lib/kubelet

sudo rm -rf /var/lib/containerd

sudo rm -rf /etc/kubernetes/pki

sudo apt purge -y kubelet kubeadm kubectl containerd.io

sudo apt autoremove -y

``kubeadm reset` はKubernetes関連のファイルを削除しますが、コンテナランタイムやOSレベルの設定(Swap無効化など)は手動で元に戻すか、再度設定し直す必要があります。

追加設定と次のステップ

クラスター構築は第一歩に過ぎません。より実用的なクラスターにするために、いくつかの追加設定や学習を継続することを推奨します。

1. Kubernetes Dashboardのインストール

Kubernetes Dashboardは、Webベースのユーザーインターフェースで、クラスター内のリソース(デプロイメント、Pod、サービスなど)の管理や監視を視覚的に行うことができます。

“`bash

Dashboardのデプロイ

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

Dashboardへのアクセス用のServiceAccountとClusterRoleBindingを作成

(認証方法により方法は異なりますが、ここでは簡単化のためにトークン認証用の設定例)

cat <<EOF | kubectl apply -f –
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard


apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
– kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF

トークンを取得

kubectl -n kubernetes-dashboard create token admin-user

プロキシを起動

マスターノードで実行し、Webブラウザから http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ にアクセス

kubectl proxy –address=’0.0.0.0′ –accept-hosts=’.*’
“`
ブラウザでアクセスし、トークン認証でログインします。

2. Ingress Controllerのインストール

NodePortサービスはポートが動的に割り当てられるため、本番環境には向きません。Ingress Controllerは、外部からのHTTP/HTTPSトラフィックをクラスター内のサービスにルーティングするための強力な方法です。Nginx Ingress Controllerが最も一般的です。

“`bash

Nginx Ingress Controllerのデプロイ (例: bare-metal環境向け)

公式ドキュメントを参照して、お使いの環境に合ったマニフェストを適用してください

https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud-generic.yaml

“`

3. 永続ストレージのプロビジョニング (Persistent Volume)

コンテナは通常、一時的なストレージを使用します。データベースや状態を持つアプリケーションのために、永続的なストレージが必要です。

  • NFS: 共有ファイルシステムとして手軽に利用できます。NFSサーバーを別途用意し、NFS Provisionerをデプロイします。
  • Longhorn: Kubernetesネイティブな分散ブロックストレージソリューションで、デプロイが比較的簡単です。
  • クラウドプロバイダのCSI (Container Storage Interface): AWS EBS, Google Persistent Disk, Azure Diskなど。

4. 監視 (Monitoring) とログ収集 (Logging)

  • Prometheus & Grafana: クラスターのメトリクスを収集・可視化するためのデファクトスタンダード。
  • ELK Stack (Elasticsearch, Logstash, Kibana) / Grafana Loki: クラスター内のログを集約・分析するためのソリューション。

5. 高可用性 (High Availability) クラスター

本ガイドでは単一マスターノードのクラスターを構築しましたが、本番環境ではマスターノードの障害に備えて複数台のマスターノード(3台または5台)と外部/内部ロードバランサーを使用したHA構成が推奨されます。

6. セキュリティの強化

  • RBAC (Role-Based Access Control) の適切な設定
  • ネットワークポリシーによるPod間の通信制御 (Calicoで可能)
  • コンテナイメージの脆弱性スキャン
  • シークレット管理のベストプラクティス

まとめ

本記事では、kubeadm を使用してKubernetesクラスターをゼロから構築する詳細な手順を、マスターノードとワーカーノードそれぞれに分けて解説しました。Swapの無効化、ファイアウォール設定、sysctlパラメータの調整、containerdのインストールとcgroup driverの設定、kubeadm, kubelet, kubectlの導入、そしてkubeadm initkubeadm joinによるクラスターのセットアップ、さらにCalicoによるPodネットワークの確立までを網羅しました。

これにより、アプリケーションをデプロイし、実行できる基本的なKubernetes環境が手に入ります。しかし、Kubernetesは広大なエコシステムを持ち、その可能性を最大限に引き出すためには、Dashboard、Ingress、永続ストレージ、監視、ログ収集、そして高可用性といった追加の概念とツールを学習していくことが不可欠です。

このガイドが、皆さんのKubernetesジャーニーの確かな第一歩となり、コンテナ化されたアプリケーションのデプロイと管理をより効率的かつ堅牢にする手助けとなれば幸いです。Kubernetesの学習は奥深く、継続的な探求が必要ですが、その投資は間違いなく、現代のクラウドネイティブな開発において大きなリターンをもたらすでしょう。


文字数概算: 約5000語に調整しました。各ステップの説明、背景、トラブルシューティング、次のステップに詳細を加えています。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール