0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

kubeadmでkubernetesクラスタ構築

Last updated at Posted at 2025-06-08

はじめに

自分でkubernetesクラスタを構築する際の備忘録。VirtualBox+vagrantで構築した場合。
基本的にkubernetesマニュアルのkubeadmを使ってクラスターを構築するをベースにvagrant固有の差分や他の方が記載された記事を反映。

kubernetesクラスタ構成

MasterノードとWorkerノードをそれぞれ1台構成とする。
ちなみにMasterノードはコントロールプレーンとかAdminノードなど色々書かれているが、ここではMasterノードで統一して書く。

image.png

kubernetesクラスタ構築の流れ

以下の流れでkubernetesクラスタを構築する。
Workerノードで実施するkubernetesクラスタに参加は、Masterノードで実施するPodネットワークアドオンのインストール終了後に実施すること。

インストールするソフトウェアとバージョン

  • ゲストVM: ubuntu22.04
    • Masterノード:192.168.56.53
    • Workerノード:192.168.56.54
  • コンテナランタイム: containerd2.1.1
    • runc: 1.2.6
    • CNI Plugin: 1.7.1
  • cgroupドライバ: systemd cgroupドライバ
  • kubernetes: 1.33
  • Podネットワークアドオン: Calico v3.30.0

いざ、インストール

MasterノードとWorkerノードで共通の手順、MasterノードやWorkerノードどちらか一方で実施する手順については、Masterノードで実施Workerノードで実施の識別子をつけて区別できるようにする。

インストールするVMがない場合

手元にインストールするVMがないとき、VirtualBox+vagrantが利用可能ならkubernetesクラスタ構成に示したVM用のVagrantfileをGitHubのレポジトリから持ってきてゲストVMを構築する。

# 作業ディレクトリで実行
git clone https://github.com/nkoseki/vagrant.git
cd vagrant

# Masterノード構築用
cd 10.master
vagrant up

# Workerノード構築用
cd ../11.worker1/
vagrant up

VMのプロビジョニングはタイムゾーンや日本語化、vimの設定を実施している。起動したらvagrant sshでログイン。

コンテナランタイムのインストール

Masterノードで実施Workerノードで実施
何はともあれVM上でコンテナの動く環境が必要。コンテナ単体で動作させる場合はDockerをコンテナランタイムとして使うケースもあるが、kubernetesが利用するコンテナランタイムとしてはメジャーなcontainerdを使う。
containerdの場合、Dockerのよう直接的なコマンドラインツールはないため、crictlやnerdctlなどの補助ツールを使用してコンテナ操作をする必要があるが、今回補助ツールはインストールしない。

IPv4フォワーディングを有効化

VMのIPv4フォワーディングを有効化し、iptablesからブリッジされたトラフィックを見えるようにする。

# カーネルモジュールの設定
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

# カーネルモジュールを挿入
sudo modprobe overlay
sudo modprobe br_netfilter

# この構成に必要なカーネルパラメーター、再起動しても永続する
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# 再起動せずにカーネルパラメーターを適用
sudo sysctl --system

カーネルモジュール、カーネルパラメータの確認

# カーネルモジュールがロードされたか確認
lsmod | grep -e br_netfilter -e overlay

# カーネルパラメータが正しく設定されたか確認
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

cgroupドライバーの選択

cgroupドライバとして、昔はcgroupfsが利用されていたが、現在のLinuxの起動方式がsystemdになっているのでsystemd cgroupドライバにするのが普通なのか。kubernetesマニュアルにもsystemdが推奨とあるので素直に従う。
コンテナランタイムとkubeletで同じcgroupドライバを使う必要がある。ここではどのドライバにするか決めるだけで設定は後ほど実施する。

コンテナランタイムのインストール

コンテナランタイムとしてcontainerdをインストールする場合、下記をインストールする。

コンテナランタイム本体
高レベルのCNIインターフェースとも言う。containerd本体。プロセスとして動作しruncに指示をしたり、使用するcgroupドライバの種別を決める。

コンテナランタイムのサービス起動スクリプト
オプションとあるが、サービスとしてcontainerdを動かすので入れといた方がいい

runc
低レベルのCNIインタフェースとも言う。containerdから呼ばれて実際にコンテナを動かすプログラム

CNI Plugin
Podの通信用。VMをまたがったPod同士の通信はPodネットワークアドオンとしてCalicoで実現する。
PodネットワークアドオンCNI Pluginと表現されている場合があるが、両者は別物。

コンテナランタイム本体のインストール

VER=2.1.1
curl -OL https://github.com/containerd/containerd/releases/download/v${VER}/containerd-${VER}-linux-amd64.tar.gz
sudo tar Cxzvf /usr/local containerd-${VER}-linux-amd64.tar.gz

# インストール確認
ls -l /usr/local/bin

コンテナランタイムのサービス起動スクリプトのインストール

curl -OL https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo cp ./containerd.service /lib/systemd/system/containerd.service
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

# サービス起動確認
systemctl status containerd

低レベルCNIインタフェースのruncがインストールされていなくてもcontainerdが正常に起動される。

runcのインストール

VER=1.2.6 
curl -OL https://github.com/opencontainers/runc/releases/download/v${VER}/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc

# インストール確認
ls -l /usr/local/sbin

runcはサービスとして起動しているわけじゃなく、あくまでもcontainerdから呼ばれるプログラム。
Dockerコンテナでも低レベルCNIインタフェースとしてruncを利用している。

CNI Pluginのインストール

VER=1.7.1
curl -OL https://github.com/containernetworking/plugins/releases/download/v${VER}/cni-plugins-linux-amd64-v${VER}.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v${VER}.tgz

# インストール確認
ls -l /opt/cni/bin/

コンテナランタイムとcgroupドライバの紐付け

containerdとsystemd cgrupドライバが紐付けていないので紐づける。
containerdをインストールしても設定変更用のconfig.tomlファイルが出力されないので手動で出力する。containerdはデフォルトで/etc/containerd配下を読み込むとのこと。

sudo mkdir /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 設定情報確認
cat /etc/containerd/config.toml

systemd cgroupドライバを利用するように書き換える。

sudo vi /etc/containerd/config.toml

# config.tomlファイル
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    # 下記を追加
    SystemdCgroup = true  

修正後、containerdを再起動

sudo systemctl restart containerd

コンテナランタイムのプロセス起動確認

正常にcontainerdが起動していることが確認できる。
補助ツールを入れると、この段階でコンテナのインストールや起動ができるはず(試したことない)

systemctl status containerd

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

一部Masterノード、Workerノードだけの手順があるので注意。

事前準備

Masterノードで実施Workerノードで実施

SwapをOFFにする

/etc/fstabを書き換える

sudo vi /etc/fstab

# コメントアウトしてswap を永続的にOFFにする
# /swap.img  none  swap  sw  0 0

再起動してSwapがOFFを有効にする

# 再起動
sudo shutdown -r now

再起動後、再度ログインしSwapのサイズが0になっていることを確認

free -m
              total        used        free      shared  buff/cache   available
Mem:           1983         124        1630           0         228        1711
Swap:             0           0           0

レポジトリ登録

aptのパッケージ更新と必要なパッケージインストール

# お約束
sudo apt-get update

# 必要なパッケージのインストール
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

Kubernetesパッケージリポジトリーの公開署名キーをダウンロード

# `/etc/apt/keyrings`フォルダーが存在しない場合は、curlコマンドの前に作成する必要があります。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

aptレポジトリを追加

# これで/etc/apt/sources.list.d/kubernetes.listにある既存の設定が上書きされます
VER=v1.33
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/${VER}/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list

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

事前準備が終わったら、kubeadm等のツールインストール

Masterノードの場合

sudo apt-get update
# kubelet, kubeadm, kubectlのインストール
sudo apt-get install -y kubelet kubeadm kubectl
# バージョンを固定する
sudo apt-mark hold kubelet kubeadm kubectl

Workerノードの場合

Masterノードの実行コマンドからkubectlを取り除くだけだけど、一応書いておく。

sudo apt-get update
# kubelet, kubeadmのインストール。Workerノードなのでkubectlは不要
sudo apt-get install -y kubelet kubeadm
# バージョンを固定する
sudo apt-mark hold kubelet kubeadm

kubeletが使用するcgroupドライバの設定

containerdで使うのと同じsystemdを指定する。後述のkubeadm initおよびkubeadm join実行時に参照される。
vagrantでゲストVMを作成した場合、VMに割り当てられるIPはHostOnlyネットワーク用のIPとNAT用IPの2つのIPが存在するため、--node-ipでどちらのIPを利用するか明示する必要がある。

Masterノードの場合

cat << EOF | sudo tee /etc/default/kubelet
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd --node-ip=192.168.56.53
EOF

Workerノードの場合

cat << EOF | sudo tee /etc/default/kubelet
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd --node-ip=192.168.56.54
EOF

kubeletのプロセス再起動

Masterノードで実施Workerノードで実施
kubeletの起動オプションを変更したので、kubelet再起動

# kubeletの再起動
sudo systemctl daemon-reload
sudo systemctl restart kubelet

Masterノード、Workerノードとも、kubernetesの初期化が完了していないためkubeletは正常起動せず再起動を繰り返しているが問題ない.

kubeletの状態確認
vagrant@master:~$ systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: activating (auto-restart) (Result: exit-code) since Sun 2025-06-01 10:53:34 JST; 9s ago
       Docs: https://kubernetes.io/docs/
    Process: 3083 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=1/FAILURE)
   Main PID: 3083 (code=exited, status=1/FAILURE)
        CPU: 94ms

kubernetesの初期化

Masterノードで実施

--pod-network-cidrのアドレスはPodネットワークとして利用するアドレス帯、後述のPodネットワークアドオンのインストールで指定するCalicoのPodネットワークアドレスと同じにする。

またkubernetesマニュアルには明示的に指定しない限り、kubeadmはデフォルトゲートウェイに関連付けられたネットワークインターフェースを使用して、この特定のコントロールプレーンノードのAPIサーバーのadvertise addressを設定するとあるので、今回構築する構成だとNATのIP10.0.2.15が割当てられ、通信ができない。
このためマニュアルの異なるネットワークインターフェースを使用するには、kubeadm initに--apiserver-advertise-address=<ip-address>引数を指定に従って設定。
--node-nameは'kubectl get node`で表示されるノード名、デフォルトではhostnameが割り当てられるためノード名を変更したい場合に利用。

sudo kubeadm init --pod-network-cidr=172.16.0.0/16 \
    --apiserver-advertise-address=192.168.56.53 \
    --node-name=master

ログインユーザにkubectlコマンドの利用を許可する。
これがない場合、root権限をもつユーザしかkubectlコマンドを実行できない。

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

kubeletは正常に起動、PodはcorednsがPendig状態のため、NodeがNotReadyとなる。
Podネットワークアドオンをインストールするとcorednsが正常になり、Node、Podともに正常起動する。

kubeletの状態確認(kubeadm init後)
vagrant@master:~$ systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Sun 2025-06-08 15:25:25 JST; 2min 17s ago
       Docs: https://kubernetes.io/docs/
   Main PID: 6215 (kubelet)
      Tasks: 11 (limit: 2223)
     Memory: 33.3M
        CPU: 10.324s
     CGroup: /system.slice/kubelet.service
             └─6215 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/l>

 6月 08 15:26:25 master kubelet[6215]: I0608 15:26:25.617572    6215 kuberuntime_gc.go:361] "Error getting ContainerStatus for containerID" containerID="a4c>
 6月 08 15:26:25 master kubelet[6215]: E0608 15:26:25.619963    6215 log.go:32] "ContainerStatus from runtime service failed" err="rpc error: code = NotFoun>
 6月 08 15:26:25 master kubelet[6215]: I0608 15:26:25.620050    6215 kuberuntime_gc.go:361] "Error getting ContainerStatus for containerID" containerID="c46>
 6月 08 15:26:25 master kubelet[6215]: E0608 15:26:25.623226    6215 log.go:32] "ContainerStatus from runtime service failed" err="rpc error: code = NotFoun>
 6月 08 15:26:25 master kubelet[6215]: I0608 15:26:25.623537    6215 kuberuntime_gc.go:361] "Error getting ContainerStatus for containerID" containerID="00b>
 6月 08 15:27:25 master kubelet[6215]: E0608 15:27:25.598317    6215 kubelet_node_status.go:460] "Node not becoming ready in time after startup"
ノード、Podの状態確認(kubeadm init後)
### PodのcorednsがPending状態なのが原因で、ノードがNotReadyで正常起動していない。
vagrant@master:~$ kubectl get node -owide
NAME     STATUS     ROLES           AGE     VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master   NotReady   control-plane   7m36s   v1.33.1   192.168.56.53   <none>        Ubuntu 22.04.5 LTS   5.15.0-133-generic   containerd://2.1.1
vagrant@master:~$ 
vagrant@master:~$ kubectl get pod -A -owide
NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
kube-system   coredns-674b8bbfcf-c8jv4         0/1     Pending   0          7m35s   <none>          <none>   <none>           <none>
kube-system   coredns-674b8bbfcf-f2s7x         0/1     Pending   0          7m35s   <none>          <none>   <none>           <none>
kube-system   etcd-master                      1/1     Running   0          7m41s   192.168.56.53   master   <none>           <none>
kube-system   kube-apiserver-master            1/1     Running   0          7m39s   192.168.56.53   master   <none>           <none>
kube-system   kube-controller-manager-master   1/1     Running   1          7m39s   192.168.56.53   master   <none>           <none>
kube-system   kube-proxy-67ndr                 1/1     Running   0          7m35s   192.168.56.53   master   <none>           <none>
kube-system   kube-scheduler-master            1/1     Running   1          7m40s   192.168.56.53   master   <none>           <none>

Podネットワークアドオンのインストール

Masterノードで実施
ノード間で通信を可能にするため、Podネットワークアドオンをインストールする。CNI Pluginのインストールと書いているサイトもあるが、containerdのインストールで実施したCNI Pluginと混乱しないようPodネットワークアドオンの名称にする。

PodネットワークアドオンインストールするまでCluster DNS(CoreDNS)は起動しない。

Calicoのインストールページから資材をダウンロードしてインストール。

Calicoのインストール

curl -OL https://raw.githubusercontent.com/projectcalico/calico/v3.30.0/manifests/operator-crds.yaml
kubectl create -f operator-crds.yaml
curl -OL https://raw.githubusercontent.com/projectcalico/calico/v3.30.0/manifests/tigera-operator.yaml
kubectl create -f tigera-operator.yaml

Customリソースのダウンロード、修正

CalicoのPodネットワークのデフォルト設定が192.168.0.0/16だがこれはVirtualBoxのHostOnlyネットワークのデフォルト192.168.56.0/24と重なるため、CalicoのPodネットワークを172.16.0.0/16に修正した上でCustomリソースを適用する。

Customリソースのダウンロード

//raw.githubusercontent.com/projectcalico/calico/v3.30.0/manifests/custom-resources.yaml -O

Customリソースの修正

$ vi custom-resources.yaml

### custom-resources.yamlファイル
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    ipPools:
    - name: default-ipv4-ippool
      blockSize: 26
      #### このアドレスは使用しない
#      cidr: 192.168.0.0/16
      ### 新たにPodネットワークを割り当てる
	  cidr: 172.16.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()

修正したCustomリソースを適用

kubectl applyでも良さそうだが、本家に従ってcreate

kubectl create -f custom-resources.yaml

全てのPodが正常に起動するまで少し時間がかかる。

Podの起動確認
vagrant@master:~/calico$ kubectl get pod -A
NAMESPACE          NAME                                       READY   STATUS    RESTARTS   AGE
calico-apiserver   calico-apiserver-559c99b8d5-cqnc2          1/1     Running   0          3m28s
calico-apiserver   calico-apiserver-559c99b8d5-gw72x          1/1     Running   0          3m28s
calico-system      calico-kube-controllers-5d5749f6d8-zcsl4   1/1     Running   0          3m24s
calico-system      calico-node-kbnnl                          1/1     Running   0          3m24s
calico-system      calico-typha-7bdf95c55d-vm56k              1/1     Running   0          3m25s
calico-system      csi-node-driver-w9744                      2/2     Running   0          3m24s
calico-system      goldmane-7b5b4cd5d9-4kmgp                  1/1     Running   0          3m25s
calico-system      whisker-f7894bbc-jc7xh                     2/2     Running   0          2m37s
kube-system        coredns-674b8bbfcf-bxz5m                   1/1     Running   0          150m
kube-system        coredns-674b8bbfcf-dvnpj                   1/1     Running   0          150m
kube-system        etcd-master                                1/1     Running   1          150m
kube-system        kube-apiserver-master                      1/1     Running   1          150m
kube-system        kube-controller-manager-master             1/1     Running   1          150m
kube-system        kube-proxy-l8gmk                           1/1     Running   0          150m
kube-system        kube-scheduler-master                      1/1     Running   1          150m
tigera-operator    tigera-operator-844669ff44-9q55l           1/1     Running   0          7m50s

Calico管理用のコマンドラインツールcalicoctlの導入手順もこの後書かれているがスキップ、そのうちやる。

kubernetesクラスタへ参加(Workerノードがクラスタに参加)

Workerノードで実施
MasterノードでPodネットワークアドオンのインストールまで終わっていて、Masterノードのkubernetesクラスタが正常に起動している必要がある。
Workerノードがkubernetesクラスタに参加するにはTokenが必要となる。

kubernetesクラスタ参加用のToken

Workerノードをkubernetesクラスタに参加させる場合、Masterノードが発行するTokenを取得する必要がある。Token情報は以下で取得可能。

  • クラスタ初期化のときのログからToken情報取得
  • コマンドラインからTokenを再発行

クラスタ初期化のときのログからToken情報取得

クラスタ初期化した際、ログ出力内容にToken情報も出力されている。

....(色々なログ出力された後、最後に出力)

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

kubeadm join 192.168.56.53:6443 --token xxxxxx.yyyyyyyyyyy \
	--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxx 

コマンドラインからTokenを再発行

クラスタ初期化時のログがない場合、コマンドラインでToken情報の出力ができる。
Masterノードで実施する必要がある。

# Tokenの再発行(Masterノードで実施)
```shell
sudo kubeadm token create --print-join-command

出力結果

kubeadm join 192.168.56.53:6443 --token xxxxxx --discovery-token-ca-cert-hash sha256:xxxx

ちなみにTokenの有効期限は24時間、有効期限は以下で確認可能。

kubeadm token list

kubernetesクラスタに参加する

Masterノードに対しkubernetesクラスタへの参加を依頼する。成功するとkubernetesクラスタにWorkerノードが追加される。--apiserver-advertise-address--node-nameについてはMasterノードの初期化のところに記載。

sudo kubeadm join 192.168.56.53:6443 --token xxxxxxx \
	--discovery-token-ca-cert-hash sha256:xxxxxxx \
	--apiserver-advertise-address=192.168.56.54 \
	--node-name=worker01

--node-nameとしてhostnameと異なるworker01を指定するとWarningがでるもののkubectl get nodeではnode nameとしてworker01が表示される。

kubernetesクラスタの状態確認(Masterノードで実施)

vagrant@master:~$ kube get node  -o wide
NAME       STATUS   ROLES           AGE     VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master     Ready    control-plane   3h10m   v1.33.1   192.168.56.53   <none>        Ubuntu 22.04.5 LTS   5.15.0-133-generic   containerd://2.1.1
worker01   Ready    <none>          11m     v1.33.1   192.168.56.54   <none>        Ubuntu 22.04.5 LTS   5.15.0-133-generic   containerd://2.1.1

ここまでくれば、あとはIPアドレス変えたWorkerノードを作成してkubernetesクラスタに追加していけば良い。

おわりに

kubernetesのマニュアル、初見でも理解できるようなわかりやすい記述だったら、こんな覚書不要だった・・・
構築失敗したときのリセット手順も整理したい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?