Open14

Hyper-V上のVMでkubernetesを構築する

しま🏝️しま🏝️

業務でkubernetesに触れることになりそうなので、一念発起して家のHyper-Vに環境を構築してみました。というのと、せっかくなのでChatGPT o3に手順を作ってみてもらいました。

しま🏝️しま🏝️

環境など

VM vCPU RAM OS 役割 IPアドレス
1台目 3 6GB Rocky Linux 9.5 コントロールプレーン 10.244.0.101/16
2台目 3 6GB Rocky Linux 9.5 ワーカー① 10.244.0.102/16
3台目 3 6GB Rocky Linux 9.5 ワーカー② 10.244.0.103/16
しま🏝️しま🏝️

構成

以下の構成にしました

  • Kubernetes v1.32
  • containerd
  • Flannel

Flannelにしたのは、のちのちMetalLBを使ってみたいからです

しま🏝️しま🏝️

ここからは基本的に、ChatGPT o3が出力した内容です。
変更・修正した場所は補足していますが、ほぼ修正無しでした!

しま🏝️しま🏝️

0. 前提条件とノード共通準備

項目 推奨値
OS Rocky Linux 9.5 (x86‑64)
CPU/RAM 最低 2 vCPU / 2 GiB(実運用は 4 vCPU / 8 GiB 以上推奨)
ネットワーク ノード間で L3 到達可、ポート開放は後述
権限 sudo 可能ユーザー
  1. ホスト名・ホスト間名前解決(DNS か /etc/hosts)を事前に設定します。
  2. SELinux を permissive に変更し永続化します。
    sudo setenforce 0
    sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
    
  3. swap を無効化(一時+永続)。
    sudo swapoff -a
    sudo sed -i '/swap/s/^/#/' /etc/fstab
    
  4. カーネルモジュールと sysctl(全ノード共通)。
    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
    

補足

ChatGPT o3はファイアウォール周りの設定をしませんでした。
以下のコマンドでファイアウォールを無効化しています。

sudo systemctl disable firewalld
sudo systemctl stop firewalld
しま🏝️しま🏝️

1. containerd のインストールと設定

  1. Docker CE リポジトリを追加(Rocky = RHEL 系)。
    sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sudo dnf makecache
    
  2. containerd を導入
    sudo dnf install -y containerd.io
    
  3. 既定設定ファイルを生成し SystemdCgroup を有効化
    sudo mkdir -p /etc/containerd
    sudo containerd config default | sudo tee /etc/containerd/config.toml
    sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
    
  4. サービス起動 & 自動起動化
    sudo systemctl enable --now containerd
    
しま🏝️しま🏝️

※なぜかv1.30を入れようとしていたので、読み替えてv1.32にしています。

2. Kubernetes 1.32 — リポジトリ追加とパッケージ導入

  1. 公式 rpm リポジトリ (pkgs.k8s.io) を登録
    cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/
    enabled=1
    gpgcheck=1
    gpgkey=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/repodata/repomd.xml.key
    exclude=kubelet kubeadm kubectl
    EOF
    
  2. パッケージをインストールしてバージョン固定
    sudo dnf install -y kubelet-1.32.* kubeadm-1.32.* kubectl-1.32.* --disableexcludes=kubernetes
    sudo systemctl enable --now kubelet
    
    Kubernetes v1.30 は 2025‑04‑17 リリースの最新安定版
しま🏝️しま🏝️

3. Control‑Plane ノードの初期化

sudo kubeadm init \
  --kubernetes-version 1.30.0 \
  --pod-network-cidr=10.244.0.0/16 \
  --cri-socket unix:///run/containerd/containerd.sock

Flannel の既定 CIDR に合わせ --pod-network-cidr=10.244.0.0/16 を必ず指定

初期化完了後に表示される kubeadm join ... コマンドは後で使うので控えておきます。
一般ユーザーで kubectl を使うための設定:

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

4. Flannel CNI の導入

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.7/Documentation/kube-flannel.yml

数分後に kubectl get pods -n kube-systemkube-flannel-ds-*Running になればネットワークが開通しています。


補足

kubectl get pods -n kube-systemを実行して確認しようとしていますが、実際は

# DaemonSet を確認
kubectl get ds -n kube-flannel                       
# Pod の状態を一覧
kubectl get pods -n kube-flannel -o wide
# すべてまとめて
kubectl get pods -A | grep flannel

を実行して確認しています。(DESIRED / CURRENT / READY がノード数と一致)

しま🏝️しま🏝️

5. Worker ノードをクラスターへ参加

各 Worker で、Control‑Plane で控えた join コマンドを実行:

sudo kubeadm join <control-plane-IP>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

参加後に Control‑Plane で kubectl get nodes を実行し、全ノードが Ready になることを確認します。

しま🏝️しま🏝️

6. firewalld ポート開放(必要に応じて)

※事前に無効化しているのでスキップしています。一応載せますが未確認。

Control‑Plane 用

sudo firewall-cmd --permanent --add-port=6443/tcp   # API server
sudo firewall-cmd --permanent --add-port=2379-2380/tcp # etcd
sudo firewall-cmd --permanent --add-port=10250/tcp  # kubelet
sudo firewall-cmd --permanent --add-port=10251/tcp  # scheduler
sudo firewall-cmd --permanent --add-port=10252/tcp  # controller-manager
sudo firewall-cmd --permanent --add-port=8285/udp   # Flannel udp
sudo firewall-cmd --permanent --add-port=8472/udp   # Flannel vxlan
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload

Worker 用(例)

sudo firewall-cmd --permanent --add-port=10250/tcp
sudo firewall-cmd --permanent --add-port=8285/udp
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --permanent --add-port=30000-32767/tcp # NodePort
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload
しま🏝️しま🏝️

7. 動作確認の例

kubectl get nodes
kubectl get pods -A
kubectl run --rm -i --tty busybox --image=busybox -- sh
/ # ping -c3 <別ノードの Pod IP>

すべて正常に応答すれば Rocky Linux 9.5 + Kubernetes 1.302 + containerd + Flannel クラスターの完成です。

しま🏝️しま🏝️

追加の確認

以下のようなnginx Podを作成して確認もしました。

nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx:latest
    name: nginx

(1) Podの作成

$ kubectl apply -f nginx.yaml
pod/nginx created

(2) Podの確認

$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          42s

(3) Curl実行

# PodのIPアドレスの確認
$ kubectl describe pod nginx | grep "IP"
IP:               10.244.1.2
IPs:
  IP:  10.244.1.2
$ curl 10.244.2.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

(4) Pod削除

$ kubectl delete pod nginx
pod "nginx" deleted