こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
本記事ではubuntu22.04にkubeadmを使ってKubernetes環境を構築していきたいと思います。
master1台×worker1台で環境を作ります。
なぜkubeadmでKubernetes環境を構築するのか?
今まで散々、microk8sやRancher、GKE等を使用してKubernetes環境を構築してきましたが、これらの環境だとKubernetesのnetworkやcertificate、ETCD周りの検証がしにくいなという問題にぶつかりました。
私は近いうちにCKA(Certified Kubernetes Administrator)と呼ばれるKuberenetesの資格を取得しようと考えております。
そのためにUdemyの以下の動画(界隈では鉄板の教材であるみたい)を使用してKubernetesを勉強したりいじったりしているのですが、上記であげたETCDなどの検証がしにくいようなイメージがあります。
誤認であれば恐縮なのですが、microk8sやGKEは便利であるがゆえにブラックボックスのようになっている部分が多いように感じ、その部分が勉強をしているときに気持ち悪かったりもやもやしたり、色々調べまわったりして疲れるなと。
また、CKAの試験範囲にkubeadmはばっちり入ってるっぽいので避けては通れません汗
そのため、改めてKubernetes環境構築をすることになりました。
用語
kubeadm
Kubeadmは、Kubernetesクラスタを作成するためのベストプラクティスの「ファストパス」としてkubeadm initとkubeadm joinを提供するために構築されたツールである。
kubeadmは、最小限の実行可能なクラスタを立ち上げて実行するために必要なアクションを実行します。設計上、マシンのプロビジョニングではなく、ブートストラップのみに関心があります。同様に、Kubernetes Dashboard、監視ソリューション、クラウド固有のアドオンなど、さまざまな便利なアドオンをインストールすることも、対象外です。
その代わり、kubeadmの上に、より高レベルでよりカスタマイズされたツールが構築されることを期待しています。理想的には、すべてのデプロイの基礎としてkubeadmを使用することで、適合するクラスタを簡単に作成することができます。
EOF
ヒアドキュメントというやつを使うときに使う(?)
以下のような記述をすると、終了文字として"EOF"を指定し、"EOF"が入力されるまでファイルの入力を続ける様子。
cat > sample.txt << EOF
> text1
> text2
> text3
> EOF
containerd
Dockerから派生したソフトウェアのようです。
Docker内部で使っているやつっぽい?
以下の書籍ではそのように記載されておりました。
構築時参考にしているサイト
基本的に以下のサイト通りにやれば問題ないと思います。少なくとも私の環境は問題なかったです。
ただ、書いていないこともありそうだったのでそこを備忘録として残しておこうかなと。。。
HWスペック
参考程度に記載しておきます。
k8s-master
k8s-worker01
構築
master/worker全ノードで実行すること
まず、名前解決できるように/etc/hostsに対してデータを入れ込みます。
以下はmasterノードのhostsファイルになり、★がついているところが追記したデータとなります。
worker02や03は今後追加するものなのでここでは気になさらないでください。
127.0.0.1 localhost
127.0.1.1 k8s-master
192.168.2.30 k8s-master ★
192.168.2.31 k8s-worker01 ★
192.168.2.32 k8s-worker02 ★
192.168.2.33 k8s-worker03 ★
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
swapを無効にするために以下のコマンドを実行
root@k8s-master:~# swapoff -a
root@k8s-master:~# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
カーネルモジュールにロードする(らしい)
root@k8s-master:~# tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
root@k8s-master:~# modprobe overlay
root@k8s-master:~# modprobe br_netfilter
kubernetesのconfigにカーネルパラメータを設定
(EOFの後に">"みたいなのが出てきたらEOFを入力してエンターキーを押下すれば問題なさそうです。)
root@k8s-master:~# tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
上記変更を反映させます。バーッと出力されますが気にしなくてよいかと・・・
root@k8s-master:~# sysctl --system
containerdをインストールし、起動します。
root@k8s-master:~# apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
root@k8s-master:~# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
root@k8s-master:~# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
root@k8s-master:~# apt update
root@k8s-master:~# apt install -y containerd.io
root@k8s-master:~# containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
root@k8s-master:~# sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
root@k8s-master:~# systemctl restart containerd
root@k8s-master:~# systemctl enable containerd
Kubernetes関連のコマンドなどをインストールします。
root@k8s-master:~# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/kubernetes-xenial.gpg
root@k8s-master:~# apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
root@k8s-master:~# apt update
root@k8s-master:~# apt install -y kubelet kubeadm kubectl
root@k8s-master:~# apt-mark hold kubelet kubeadm kubectl
ここまですべてのノードで実行します。masterもworkerも関係ありません。
masterで実行すること 01
以下コマンドを実行してKubernetesクラスタを初期化していきます。
出力が長いので途中のものは省きますが、必要そうな部分は残しておきます。
また、このあたりの出力はコピーしておきましょう。
また、コマンドのendpointのオプションは各個人の環境に依存するので気を付けてください。基本的にmasterとなるノードを指定してあげればOKの認識です。
root@k8s-master:~# kubeadm init --control-plane-endpoint=k8s-master
~ 中略 ~
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
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
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/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join k8s-master:6443 --token pg46jl.pvynngmtqsrukf6l \
--discovery-token-ca-cert-hash sha256:0497a12ab9c4ff1eb3c21bf6f92d2346c3645a00f54c746a5000f1ffe9a107fc \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join k8s-master:6443 --token pg46jl.pvynngmtqsrukf6l \
--discovery-token-ca-cert-hash sha256:0497a12ab9c4ff1eb3c21bf6f92d2346c3645a00f54c746a5000f1ffe9a107fc
問題なく初期化ができたら以下のコマンドを実行します。
このコマンドを実行しないと、Kubernetesクラスタの初期化が完了した後に「やったー!試しにkubectl get podコマンドたたいてみよー!」と叩いてみても、tcp connection refused的なエラーではじかれます。(1敗)
root@k8s-master:~# mkdir -p $HOME/.kube
root@k8s-master:~# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
root@k8s-master:~# chown $(id -u):$(id -g) $HOME/.kube/config
root@k8s-master:~# kubectl cluster-info
Kubernetes control plane is running at https://k8s-master:6443
CoreDNS is running at https://k8s-master: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 nodeとget podをたたいてみます。
dnsのpodがpendingステートとなっていますが、これでいったん問題ありません。後ほどCalicoをデプロイしますがその時に稼働を開始します。(おそらくこのタイミングだとk8s内の内部ネットワークがまだない的な判断をして稼働しないのかなぁと?)
ノードもNotReadyとなっていますが同様に今は気にしないで大丈夫です。
root@k8s-master:~# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 6m11s v1.27.2
root@k8s-master:~# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-5d78c9869d-sswnk 0/1 Pending 0 6m11s
kube-system coredns-5d78c9869d-zmjp6 0/1 Pending 0 6m11s
kube-system etcd-k8s-master 1/1 Running 0 6m18s
kube-system kube-apiserver-k8s-master 1/1 Running 0 6m15s
kube-system kube-controller-manager-k8s-master 1/1 Running 0 6m20s
kube-system kube-proxy-jkfzg 1/1 Running 0 6m11s
kube-system kube-scheduler-k8s-master 1/1 Running 0 6m22s
workerで実行すること
kubeadm initで実は出力されていた"kubeadm join"コマンドを実行します。
これは個々人の環境によって異なりますので出力されたコマンドをコピペして使用してください。
microk8sを使ったことがある方ならピンとくると思いますが、microk8s add-nodeコマンドをmaster側で実行してコマンドを吐き出させて、そのコマンドをworker側で入力してクラスタ化していると思うのですが基本的にそれと同じニュアンスで問題なさそうです。
root@k8s-worker01:~# kubeadm join k8s-master:6443 --token pg46jl.pvynngmtqsrukf6l --discovery-token-ca-cert-hash sha256:0497a12ab9c4ff1eb3c21bf6f92d2346c3645a00f54c746a5000f1ffe9a107fc
master側でノードが認識されているかを確認します。
worker01となっているので問題なさそうですね。ステートがNotReadyとなっていますが、これも今は気にしないで大丈夫です。
root@k8s-master:~# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 135m v1.27.2
k8s-worker01 NotReady <none> 58s v1.27.2
masterで実行すること 02
以下のyamlファイルを実行してCalicoをローカルのKubernetes環境にデプロイしてきます。
root@k8s-master:~# kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
これを実行した後、5~10分程度待つと以下のようにpendingステートだったDNS podもrunnningになったり、NotReadyだったノードもReadyに代わるはずです。
ここまでやってKubernetes環境構築完了となります。
root@k8s-master:~# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-6c99c8747f-xhc26 1/1 Running 0 4m3s
kube-system calico-node-8lhx6 1/1 Running 0 4m3s
kube-system calico-node-w8vcl 1/1 Running 0 4m3s
kube-system coredns-5d78c9869d-sswnk 1/1 Running 0 140m
kube-system coredns-5d78c9869d-zmjp6 1/1 Running 0 140m
kube-system etcd-k8s-master 1/1 Running 0 140m
kube-system kube-apiserver-k8s-master 1/1 Running 2 (82m ago) 140m
kube-system kube-controller-manager-k8s-master 1/1 Running 4 (80m ago) 140m
kube-system kube-proxy-gjlhj 1/1 Running 0 6m15s
kube-system kube-proxy-jkfzg 1/1 Running 0 140m
kube-system kube-scheduler-k8s-master 1/1 Running 1 (90m ago) 140m
root@k8s-master:~# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 140m v1.27.2
k8s-worker01 Ready <none> 6m19s v1.27.2
2025/3/17 追記
上記手順では構築できなくなっていたので更新します。
以下をとりあえず実行。
ここまで環境用意したら、snapshotとっておいた方が無難。
sudo su -
apt update && apt upgrade -y
vi /etc/hosts
以下を記載
127.0.0.1 localhost
172.18.251.19 k8s-master
172.18.251.16 k8s-worker01
172.18.251.18 k8s-worker02
172.18.251.20 k8s-worker03
これを実行
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt update
apt install -y containerd.io
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
systemctl restart containerd
systemctl enable containerd
これを実行
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
masterで以下を実行
kubeadm init --control-plane-endpoint=k8s-master --pod-network-cidr=192.168.0.0/16
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
kubectl cluster-info
kubectl get node
workerで以下を実行
※この出力はkubeadm initコマンドで出力されている。
kubeadm join k8s-master:6443 --token mdnrvz.w6qhxk7y9owdkzh8 \
--discovery-token-ca-cert-hash sha256:8e909e6c462c1f913008fdb94f87069b128ccbc47ec7ef6faa602667623f8289
masterでkubectl get nodeコマンドを事項
workerノードが出力されればOK
root@k8s-master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 32m v1.32.3
k8s-worker01 NotReady <none> 8s v1.32.3
masterで以下を実施。実行後しばらくしないとpodとかdeployされない。10分以上待ってもいいかも?
Calico公式:
https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/custom-resources.yaml
masterで以下を実行してReadyになっていればOK
podも以下のようになる。
root@k8s-master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 13m v1.32.3
k8s-worker01 Ready <none> 12m v1.32.3
root@k8s-master:~# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
calico-apiserver calico-apiserver-7ddd789855-dv4mw 1/1 Running 0 98s
calico-apiserver calico-apiserver-7ddd789855-xpkhl 1/1 Running 0 98s
calico-system calico-kube-controllers-5f975465c6-mcxjl 1/1 Running 0 98s
calico-system calico-node-bqhjm 1/1 Running 0 98s
calico-system calico-node-xclnt 1/1 Running 0 98s
calico-system calico-typha-66dd857759-tdrln 1/1 Running 0 98s
calico-system csi-node-driver-fwq7b 2/2 Running 0 98s
calico-system csi-node-driver-qgsbv 2/2 Running 0 98s
kube-system coredns-668d6bf9bc-2f5fn 1/1 Running 0 3m54s
kube-system coredns-668d6bf9bc-jd94h 1/1 Running 0 3m54s
kube-system etcd-k8s-master 1/1 Running 2 3m59s
kube-system kube-apiserver-k8s-master 1/1 Running 2 4m1s
kube-system kube-controller-manager-k8s-master 1/1 Running 0 3m59s
kube-system kube-proxy-c99cw 1/1 Running 0 3m55s
kube-system kube-proxy-w5bhf 1/1 Running 0 3m
kube-system kube-scheduler-k8s-master 1/1 Running 2 3m59s
tigera-operator tigera-operator-ccfc44587-m6ncv 1/1 Running 0 106s