kubeadmを使用してkubernetes環境を構築してみました。
基本的に以下の公式ドキュメントに従って進めていきます。
環境情報
CPU | Mem | OS | hostname | IP | |
---|---|---|---|---|---|
コントロールプレーン(1台) | 2vcpu | 4GiB | ubuntu 20.04 | MyVMmaster | 10.0.0.5 |
ワーカーノード(3台) | 2vcpu | 4GiB | ubuntu 20.04 | MyVMworker1~3 | 10.0.0.6~8 |
※VMはAzure Virtual Machineで作成
- kubeadm:v1.30.0
- kubectl:v1.30.0
- Kubernetes:v1.30.0
基盤準備
swapの無効化
swap…メモリが不足した際にディスクのswap領域を使用する機能。
OS側で予期せぬ動き(swapへの読み書き)があると、kubernetesの世界でコンテナのメモリの管理が出来なくなってしまうから無効化するのかな?みたいな理解。
# swap領域の確認
azureuser@MyVMworker1:~$ sudo swapon --show
azureuser@MyVMworker1:~$ cat /etc/fstab
# CLOUD_IMG: This file was created/modified by the Cloud Image build process
UUID=xxx / ext4 defaults,discard 0 1
UUID=xxx /boot/efi vfat umask=0077 0 1
/dev/disk/cloud/azure_resource-part1 /mnt auto defaults,nofail,x-systemd.requires=cloud-init.service,_netdev,comment=cloudconfig 0 2
→swap領域が存在しないようなのでここはスキップ。
MACアドレスとproduct_uuidの確認
MACアドレスとproduct_uuidがクラスタを構成する全ノードでユニークであることを確認。
ip link
cat /sys/class/dmi/id/product_uuid
ポートの解放
各ノードで使われるポートを解放しないといけない。
対象のポートは以下を確認。
今回はNSGやファイアウォールでポートの制限等かけているわけではないので、問題無さそう。
ちなみに確認方法は以下。
# 確認対象サーバ:6443ポートでLISTENしておく
azureuser@MyVMmaster:~$ nc -l -k -p 6443
# 別サーバ:確認対象サーバへ接続確認
azureuser@MyVM:~$ nc -v MyVMmaster 6443
Connection to MyVMmaster 6443 port [tcp/*] succeeded!
コンテナランタイムのインストール
今回はコンテナランタイムとしてdockerを使用。
dockerエンジンのインストール手順に従い、全ノードでdockerエンジンのインストールを行う。
※説明は割愛
以上で基盤の準備は完了。
kubelet、kubeadm、kubectlのインストール
※全ノードで実施
※実行ユーザはあまり考慮していない
手順
- kubernetesリポジトリを利用するために必要なパッケージのインストール
- kubernetesリポジトリ用のGPGキーをダウンロード
- kubernetesリポジトリの追加
- kubelet、kubeadm、kubectlのインストール
# 必要なパッケージのインストール
root@MyVMmaster:~# apt-get install -y apt-transport-https ca-certificates curl gpg
Reading package lists... Done
Building dependency tree
Reading state information... Done
...
Unpacking apt-transport-https (2.0.10) ...
Setting up apt-transport-https (2.0.10) ...
# GPGキーのダウンロード
# /etc/apt/keyringsフォルダはdockerインストール時に作成済
root@MyVMmaster:~# curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
root@MyVMmaster:~# ls /etc/apt/keyrings
docker.asc kubernetes-apt-keyring.gpg
# kubernetesリポジトリの追加
azureuser@MyVMmaster:~$ echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /
# kubelet、kubeadm、kubectlのインストール
azureuser@MyVMmaster:~$ sudo apt-get update
azureuser@MyVMmaster:~$ sudo apt-get install -y kubelet kubeadm kubectl
azureuser@MyVMmaster:~$ sudo apt-mark hold kubelet kubeadm kubectl
# kubeadmバージョン確認
azureuser@MyVMmaster:~$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"30", GitVersion:"v1.30.0", GitCommit:"xxx", GitTreeState:"clean", BuildDate:"2024-04-17T17:34:08Z", GoVersion:"go1.22.2", Compiler:"gc", Platform:"linux/amd64"}
# kubeletステータス確認
azureuser@MyVMmaster:~$ systemctl status kubelet -n0
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor pr>
Drop-In: /usr/lib/systemd/system/kubelet.service.d
mq10-kubeadm.conf
Active: inactive (dead)
Docs: https://kubernetes.io/docs/
# kubectlバージョン確認
azureuser@MyVMmaster:~$ kubectl version --client
Client Version: v1.30.0
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
kubeadm実行
準備が出来たので、いよいよkubeadmを実行してクラスタを構築していく。
※全ノードで実施
kubeadm init実行
※この段階では実施していないが、kube initコマンドでpodのネットワークcidrの引数指定が必要のため注意。(後述のpodのネットワークプラグインのインストール参照)
root@MyVMmaster:~# kubeadm init
[init] Using Kubernetes version: v1.30.0
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR CRI]: container runtime is not running: output: time="2024-04-29T17:01:17Z" level=fatal msg="validate service connection: validate CRI v1 runtime API for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
エラー発生。
調べると、以下の方法で対応が必要とのこと。
containerdの設定ファイルを削除して再起動。
root@MyVMmaster:~# rm /etc/containerd/config.toml
root@MyVMmaster:~# systemctl restart containerd
再度kubeadm init実行。
root@MyVMmaster:~# kubeadm init
[init] Using Kubernetes version: v1.30.0
...
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/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.0.5:6443 --token xxx \
--discovery-token-ca-cert-hash sha256:xxx
今度は成功。
ここで出力されたtokenを用いて、後ほどworkerノードを追加する形となる。
(workerノードのjoin参照)
出力にもある通り、設定ファイルをホームディレクトリに配置する。
root@MyVMmaster:~# mkdir -p $HOME/.kube
root@MyVMmaster:~# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# KUBECONFIG定義
root@MyVMmaster:~# export KUBECONFIG=/etc/kubernetes/admin.conf
podのネットワークプラグインのインストール
pod同士を通信させるために、podネットワークアドオンのインストールが必要。
これが無いと、以下のようにCoreDNSと呼ばれるクラスタ内の名前解決をしてくれるリソースが立ち上がらない。
root@MyVMmaster:~# kubectl get pod -A | grep coredns
kube-system coredns-7db6d8ff4d-mklkh 0/1 Pending 0 83m
kube-system coredns-7db6d8ff4d-pddv8 0/1 Pending 0 83m
今回は以下を参考に、Calicoをインストール。
※control-planeのみで実施
# calico公式から引っ張ってきたマニフェストを使用し、kubernetesリソース作成
root@MyVMmaster:~# kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/tigera-operator.yaml
namespace/tigera-operator created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
...
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created
root@MyVMmaster:~# kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/custom-resources.yaml
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created
# リソース確認
root@MyVMmaster:~# watch kubectl get pods -n calico-system
→calico-systemというnamespaceにpodが立ち上がるはず・・・
Every 2.0s: kubectl get pods -n cali... MyVMmaster: Mon Apr 29 19:11:53 2024
No resources found in calico-system namespace.
だが、いつまで待っても立ち上がらない。
よく調べると、calicoではデフォルトのpodのネットワークcidrが以下のように192.168.0.0/16となっているため、kubeadm init で指定した引数--pod-network-cidrと同じものに変えないといけないらしい。
# マニフェストをローカルにダウンロード
root@MyVMmaster:~# wget https://projectcalico.docs.tigera.io/manifests/custom-resources.yaml
# カスタムリソース確認
# podのネットワークcidrが192.168.0.0/16になっている
root@MyVMmaster:~# cat custom-resources.yaml
# This section includes base Calico installation configuration.
# For more information, see: https://projectcalico.docs.tigera.io/master/refe rence/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
# Configures Calico networking.
calicoNetwork:
# Note: The ipPools section cannot be modified post-install.
ipPools:
- blockSize: 26
cidr: 192.168.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
...
しかし先ほど実行したkubeadm initではそのような引数は指定しておらず・・・
構築したクラスタのpodネットワークcidrがどうなっているか、見方も分からず。
結局kubeadmをアンインストールし、再度ネットワークcidrを設定してインストールし直すことにした。
kubeadm reset
sudo apt-get purge kubeadm kubectl kubelet kubernetes-cni kube*
sudo apt-get autoremove
sudo rm -rf ~/.kube
※このあたりは「kubernetes アンインストール」で調べて出てきた手順を適当に実行しただけなので、消し忘れの設定等あるかも。
アンインストールが済んだら、kubelet、kubeadm、kubectlのインストールから実施。
その後、今度はpodネットワークcidrを指定してkubeadm init 実行。
kubeadm init \
--pod-network-cidr 192.168.0.0/16
そして再びcalicoをインストールし、確認。
root@MyVMmaster:~# watch kubectl get pods -n calico-system
Every 2.0s: kubectl get pods -n cali... MyVMmaster: Mon Apr 29 19:51:54 2024
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-7569b96694-qt7wm 1/1 Running 0 4m23s
calico-node-zz8cv 1/1 Running 0 4m23s
calico-typha-7bdc59757b-2gdlc 1/1 Running 0 4m23s
csi-node-driver-7cfhw 2/2 Running 0 4m23s
今度は上手くいった。
corednsのpodも全てRunningになっていることを確認。
root@MyVMmaster:~# kubectl get pod -A | grep coredns
kube-system coredns-7db6d8ff4d-b4s88 1/1 Running 0 8m37s
kube-system coredns-7db6d8ff4d-cn9p9 1/1 Running 0 8m37s
workerノードのjoin
最後に、workerノードをクラスタにjoinさせる。
※workerノード全てで実施
root@MyVMworker1:~# kubeadm join 10.0.0.5:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx
~kubeadm init時と同様のエラーが出たため対処~
root@MyVMworker1:~# rm /etc/containerd/config.toml
root@MyVMworker1:~# systemctl restart containerd
# join
root@MyVMworker1:~# kubeadm join 10.0.0.5:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx
[preflight] Running pre-flight checks
...
This node has joined the cluster:
* Certificate signing request was sent to apiserver 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.
最後に、control-planeでノードの確認。
root@MyVMmaster:~# kubectl get node
NAME STATUS ROLES AGE VERSION
myvmmaster Ready control-plane 30m v1.30.0
myvmworker1 Ready <none> 3m23s v1.30.0
myvmworker2 Ready <none> 66s v1.30.0
myvmworker3 Ready <none> 18s v1.30.0
全てのノードが認識されており、ステータスもReadyになっているのでOK!
動作確認
最後に軽くクラスタの動作確認。
# pod作成
root@MyVMmaster:~# kubectl run nginx --image=nginx --port=80
pod/nginx created
# 作成したpodの状態確認
root@MyVMmaster:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 9s 192.168.235.6 myvmworker2 <none> <none>
# 作成したpodのserviceのタイプをNodePortにする
root@MyVMmaster:~# kubectl expose pod nginx --type=NodePort
service/nginx exposed
# serviceが作成されたことを確認
root@MyVMmaster:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 121m
nginx NodePort 10.105.194.131 <none> 80:31681/TCP 6m5s
# 疎通確認
root@MyVMmaster:~# curl -I http://10.0.0.7:31681/
HTTP/1.1 200 OK
Server: nginx/1.25.5
Date: Mon, 29 Apr 2024 21:44:32 GMT
まとめ
今まで業務でkubernetesは触ってきましたが、実際に環境を一から作るのは初めてだったので良い勉強になりました。
次はこの一連の流れをansible化してみたいです。