1
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?

Ubuntu 24.04 に k8s を入れてみる

Last updated at Posted at 2025-04-30

はじめに

kubernetes(以下 k8s)の Network がどうなっているか、試したい。GNS3 上で Master/Worker VMを構築し、外部の VyOSと eBGP接続することを目指す。
「なんで動くのか?」の言語化とエビデンスの確認が目的のため、少し冗長かもしれない。

動作環境

Master x1, Worker x2の基本的な構成。vCPU/メモリ/ディスクは最小推奨構成。最初これより少ないメモリで試したら、そもそもインストールできなかった。

Host名 OS vCPU メモリ ディスクサイズ NICのアドレス
k8s-master ubuntu 24.04.2 4 8192MB 40GB 192.168.11.121/24
k8s-worker1 ubuntu 24.04.2 4 8192MB 40GB 192.168.11.122/24
k8s-worker2 ubuntu 24.04.2 4 8192MB 40GB 192.168.11.123/24

ターゲットk8s

2025年4月末時点での最新安定版を使用。

ソフトウェア Version コメント
k8s 1.33
containerd 1.7.24-0 dockerを利用しない
calico 3.29.3

事前準備(Master/Workerノードとも)

SWAPを無効にする

ubuntu@k8s-master:~$ sudo swapon --show
ubuntu@k8s-master:~$

試した環境では 最初からSWAP は有効にされていなかった。

/etc/hosts の編集

/etc/hostsにMaster/Workerを追加しておく

ubuntu@k8s-master:~$ cat /etc/hosts
192.168.11.121 k8s-master
192.168.11.122 k8s-master
192.168.11.123 k8s-worker

カーネルモジュールの追加

ubuntu@k8s-master:~$ sudo modprobe overlay
ubuntu@k8s-master:~$ sudo modprobe br_netfilter

overlay:
コンテナのファイルシステム(Unionファイルシステム)を支えるカーネルモジュール。
これがないと、コンテナのレイヤー管理が動かない。

br_netfilter:
Linuxカーネルで「bridgeネットワーク越しのパケット」もiptablesなどでフィルタできるようにするモジュール。
KubernetesではPod-to-Pod通信などでbridgeを使うので、これがないとNetworkPolicyやiptables制御が効かない。

永続化対応

VM再起動時に読み込まれるよう、modules.confに設定を追加。

ubuntu@k8s-master:~$ sudo tee /etc/modules-load.d/k8s.conf <<EOF
overlay
br_netfilter
EOF

カーネルパラメータの設定

ubuntu@k8s-master:~$ 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 で設定を反映させる。k8s では仮想 Bridgeを利用しているが、仮想 Bridge間通信で iptables を有効にするためにはnet.bridge.bridge-nf-call-iptablesnet.bridge.bridge-nf-call-ip6tables が必要。
Pod間 Routing を行うためにnet.ipv4.ip_forwardを有効にする。

正常性確認

ubuntu@k8s-master:~$ sudo sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1
ubuntu@k8s-master:~$ sudo sysctl net.bridge.bridge-nf-call-ip6tables
net.bridge.bridge-nf-call-ip6tables = 1
ubuntu@k8s-master:~$ sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

すべて1であれば正しく設定されている。

コンテナエンジンのインストール

sudo apt install -y containerd

k8s推奨のcontainerdを使用する。docker はk8s 1.20 以降では非推奨。

containerd設定ファイル作成

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

Systemd Cgroupにする

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

Podのコンテナプロセスを管理するために cgroup(コントロールグループ)を使ってる。cgroupとは、LinuxでCPU、メモリ、ネットワーク帯域などのリソース制御をする仕組み。
containerd 自体でCgroupを管理する行うか、Systemdでシステム一括とするかがある。k8s では後者が推奨されており、かならず SystemdCgroup = trueとする必要がある。
公式情報は以下。

containerd 再起動と有効化

ubuntu@k8s-master:~$ sudo systemctl restart containerd
ubuntu@k8s-master:~$ sudo systemctl enable containerd

k8s のインストール

これでk8s をインストールする準備ができた。k8s のパッケージは ubuntu の標準リポジトリには存在しないため、公開鍵をインポートし、k8s リポジトリを登録する。

そしてインストール。k8s 1.33においてはkuelet, kubeadm, kubectl は別パッケージ。
それぞれの役割は、公式ページによるとざっくり以下。

コマンド名 概要
kubeadm クラスターを起動するコマンド
kubelet クラスター内のすべてのマシンで実行されるコンポーネント。Podやコンテナの起動などを行う
kubectl クラスターにアクセスするためのコマンドラインツール

k8s リポジトリの追加

ubuntu@k8s-master:~$ sudo curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes.gpg
ubuntu@k8s-master:~$ echo "deb https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list

パッケージインストール

ubuntu@k8s-master:~$ sudo apt update
ubuntu@k8s-master:~$ sudo apt install -y kubelet kubeadm kubectl
ubuntu@k8s-master:~$ sudo apt-mark hold kubelet kubeadm kubectl

最後のはk8sのバージョン固定。apt upgradeでもって不用意に上げないようにするためのもの。 Version upするときには 一時的に unholdして作業を実施する。

sudo apt-mark unhold kubelet kubeadm kubectl
sudo apt update
sudo apt install kubelet=1.33.1-00 kubeadm=1.33.1-00 kubectl=1.33.1-00
sudo apt-mark hold kubelet kubeadm kubectl

ここで書いたサンプルのバージョンはあくまでも例。書いている段階ではまだ存在していない。

Master ノードでの作業

ようやっとここで Master ノードの初期化を行う。k8sのPodに割り当てるアドレスレンジ(Pod Cider)と、k8s 内部でService を識別するために使用する Cluster IPは、このタイミングでしか設定できない。 これらのアドレスは外部ネットワークと重複不可。歴史の長いオンプレミス環境ではこのアドレスをどうやって確保するかが一大事となる(溜息)

本検証でのパラメータ

Network 付与するNWアドレス
Pod CIDR 100.64.0.0/16
Cluster IP 172.16.0.0/16

なぜここまで大きなアドレスレンジにするかだが、以下の理由による模様。

  1. どちらのアドレスレンジも後から拡張できない
  2. Pod/Serviceが廃棄された後、アドレスが使いまわされるまでにはある程度の時間がかかる

実際に作成する

ubuntu@k8s-master:~$ sudo kubeadm init \
--pod-network-cidr=100.64.0.0/16 --service-cidr=172.16.0.0/16
(snip)
Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.11.121:6443 --token jkorog.c9yonl55bvubfjjm \
        --discovery-token-ca-cert-hash sha256:e4cbc98a34b42a394b24a82d63d86b9af6828b07fde5a9dd955fd84c4e00aeaf

この最後のkubeadm --join を Worker1/2でも実行することで、MasterにWorkerノードが組み込まれる。このコマンドには制限時間(24時間?)あり、失効すると Worker の登録ができない。その場合はsudo kubeadm token create --print-join-command新しい有効なjoinコマンド が出てくるのでそれを利用する。

kubectl の準備

kubectlが接続する「k8sクラスタ」「ユーザ」「利用する認証情報」を指定するため、admin.confをローカルにコピーする。

ubuntu@k8s-master:~$ mkdir -p $HOME/.kube
ubuntu@k8s-master:~$ sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
ubuntu@k8s-master:~$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

CNI のインストール

CNIもいくつかあるが、今回は Calico を採用する。
Pod 間通信するには必ず必要なので、最初に入れる。後から変えるのはかなり厄介。

ubuntu@k8s-master:~$ kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.3/manifests/calico.yaml

正常性確認

名前空間kube-system 上に calico-kube-controllers-*calico-node-* があり、STATUSがRunning であることを確認する。calico-node-*は Worker ノードが増えていけばその分だけ増えていく。

ubuntu@k8s-master:~$ kubectl -n kube-system get pod
NAME                                      READY   STATUS    RESTARTS        AGE
calico-kube-controllers-79949b87d-k488c   1/1     Running   4 (12h ago)     3d8h
calico-node-8r8kj                         1/1     Running   6 (7h13m ago)   3d8h

調べていくと、一部資料では calico.yaml をダウンロードした後、このyaml ファイル内でname: CALICO_IPV4POOL_CIDRの値を Pod CIDRと同じ値に変更するものもあった。しかし、今回試したバージョンでは no effect. This should fall within --cluster-cidr. となっており、kubeadm init で指定した値に自動で組み込まれるように変更されていた。どのバージョンから仕様が変わったかは調査しきれず。

Worker ノード側での作業

Worker ノードをjoinする。このコマンドはMaster ノードでkubeadm init実行した際、最後のほうの行に出てくるのでコピーして実行。

ubuntu@k8s-worker1:~$ kubeadm join 192.168.11.121:6443 --token jkorog.c9yonl55bvubfjjm \
        --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXX

Master ノードでの正常性確認

kubectl get nodes で確認する。STATUS が ReadyになっていればOK。

ubuntu@k8s-master:~$ kubectl get nodes
NAME          STATUS   ROLES           AGE    VERSION
k8s-master    Ready    control-plane   4d2h   v1.33.0
k8s-worker1   Ready    <none>          3d1h   v1.33.0
k8s-worker2   Ready    <none>          3d1h   v1.33.0

Worker ノードでkubectl get nodes を実行してもこの結果は得られない。kubectl コマンドはkube-apiserverにリクエストを送るコマンドであり、workerノードでは kube-apiserverの情報がないため、localhostへ取りに行って失敗する動きになる。原理的にはMasterノードの~/.kube/configをworkerノードへコピーすればできるはずだが、kubectl は Master ノードで実行するのが基本であり、あえて行う必要はない。

切り戻し方

k8s クラスタを作ったはよいけれど、設定を間違ったから削除したい。完全削除は次のように行う。Master/Worker ノード両者で行う必要がある。

Master ノードでの完全初期化

# 1. kubeadm による初期化をリセット
ubuntu@k8s-master:~$ sudo kubeadm reset -f

# 2. 各種残存ファイルを削除(念のため)
ubuntu@k8s-master:~$ sudo rm -rf /etc/kubernetes /var/lib/etcd /var/lib/kubelet /etc/cni /opt/cni /var/lib/cni

# 3. ネットワーク設定(iptables)をクリア
ubuntu@k8s-master:~$ sudo iptables -F
ubuntu@k8s-master:~$ sudo iptables -t nat -F
ubuntu@k8s-master:~$ sudo iptables -t mangle -F
ubuntu@k8s-master:~$ sudo iptables -X

# 4. CNI のブリッジインターフェース(cni0 など)が残っていれば削除
ubuntu@k8s-master:~$ sudo ip link delete cni0 2>/dev/null
ubuntu@k8s-master:~$ sudo ip link delete flannel.1 2>/dev/null

# 5. CNI削除
ubuntu@k8s-master:~$ sudo rm -rf /etc/cni/net.d

# 6. kubeconfig 削除(kubectl 設定)
ubuntu@k8s-master:~$ rm -rf ~/.kube/config

# 7. 明示的なノード削除(kubeadm reset 後、kubectl get nodesで残っていた場合)
ubuntu@k8s-master:~$ kubectl delete node <ノード名>

CNI 設定の削除
kubeadm reset/etc/cni/net.d ディレクトリを削除しません。異なる CNI プラグインを導入する場合、前の干渉する可能性があるため、手動で削除することが推奨されている。

Worker ノードでの完全初期化

# 1. kubeadm join の設定を解除
ubuntu@k8s-worker1:~$ sudo kubeadm reset -f

# 2. 設定ディレクトリ等を削除
ubuntu@k8s-worker1:~$ sudo rm -rf /etc/kubernetes /var/lib/kubelet /etc/cni /opt/cni /var/lib/cni

# 3. ネットワーク関連を削除
ubuntu@k8s-worker1:~$ sudo iptables -F
ubuntu@k8s-worker1:~$ sudo iptables -t nat -F
ubuntu@k8s-worker1:~$ sudo iptables -t mangle -F
ubuntu@k8s-worker1:~$ sudo iptables -X

ubuntu@k8s-worker1:~$ sudo ip link delete cni0 2>/dev/null
ubuntu@k8s-worker1:~$ sudo ip link delete flannel.1 2>/dev/null

もう少し高度は k8s 構築方法

1セットの Master/Workerノードに複数のk8s context を作りたくなる時がある。試験用のクラスタを作るとか。こういった際、kubeadm init する際に --configを使用し、より詳細な設定を行うことができる。

cluster-config.yaml

ここでは k8s cluster の名前を明示してみる。色々設定できる様子だが、Pod CIDR, Cluster IP, cluster名称だけを変更する。

yaml cluster-config.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
clusterName: shakapon-lab
kubernetesVersion: "1.33.0"
networking:
  podSubnet: 100.64.0.0/16        # Calico が使用
  serviceSubnet: 172.16.0.0/16    # ClusterIP に使用

kubeadm init

cluster-config.yamlを利用して初期構築実施可能。

ubuntu@k8s-master:~$ sudo kubeadm init --config=cluster-config.yaml

これ以降の作業は特に変わらない。

正常性確認

せっかくなので context が正しく設定されていることを確認する。

ubuntu@k8s-master:~$ kubectl config current-context
kubernetes-admin@shakapon-lab
ubuntu@k8s-master:~$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@shakapon-lab shakapon-lab kubernetes-admin
1
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
1
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?