はじめに
昨年 CKA を取得するべく Kubernetes を勉強し無事取得することが出来ました。
体験記は以下に記事を書いているのでご参考までに。
※改定前の受験内容なので、最新の情報はホームページをご確認ください。
受験範囲には kubeadm
の使い方も入っていました。
kubeadm
は Kubernetes を構築するためのツールで、シングルノードから複数ノードのクラスタまで構築することが出来ます。
受験当時は関連する問題があったものの kubeadm
の知識が薄かったため解くことが出来ず・・・
今回は復習も込めて kubeadm
を使ってシングルノードのクラスタを構築しようと思います。
kubeadm
の動きについては Y氏の解説記事が分かりやすいので是非。
環境情報
今回はローカル PC に VirtualBox / Vagrant で構築します。
ホストマシン
OS:Windows10 Pro
VirtualBox:6.1.16
Vagrant:2.2.14
ゲストマシン
OS:Ubuntu 18.04.5 LTS
containerd:1.4.3
kubeadm:v1.20.2
Kubernetes:v1.20.2
kubectl:v1.20.2
Role | hostname | enp0s3(NAT) | enp0s8(Bridge) |
---|---|---|---|
ControlPlane | cp01 | 10.0.2.15 | 192.168.10.61 |
Worker | wk01 | 10.0.2.15 | 192.168.10.71 |
下記に今回使った Vagrantfile
を載せておきます。ご参考までに。
※NIC1(enp0s3):NAT、NIC2(enp0s8):ブリッジアダプターで設定しています。
※ kubectl exec
で支障がでるため、起動スクリプトでデフォルトゲートウェイをブリッジアダプター側(192.168.10.1)に変更しています。
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define "cp01" do |server|
server.vm.box = "ubuntu/bionic64"
server.vm.hostname = "cp01"
server.vm.network "public_network", ip: "192.168.10.61"
server.vm.synced_folder ".", "/vagrant", disabled: true
server.vm.provider "virtualbox" do |vb|
vb.customize [
"modifyvm", :id,
"--memory", "4096",
"--cpus", "2"
]
end
server.vm.provision "shell", run: "always", inline: <<-SHELL
sudo ip route del default via 10.0.2.2
sudo ip route add default via 192.168.10.1
SHELL
end
config.vm.define "wk01" do |server|
server.vm.box = "ubuntu/bionic64"
server.vm.hostname = "wk01"
server.vm.network "public_network", ip: "192.168.10.71"
server.vm.synced_folder ".", "/vagrant", disabled: true
server.vm.provider "virtualbox" do |vb|
vb.customize [
"modifyvm", :id,
"--memory", "8192",
"--cpus", "2"
]
end
server.vm.provision "shell", run: "always", inline: <<-SHELL
sudo ip route del default via 10.0.2.2
sudo ip route add default via 192.168.10.1
SHELL
end
end
containerd インストール
コンテナ実行環境として containerd
をインストールしていきます。
まずは前準備から。
※cp01 / wk01 両方で実行します。
※root ユーザで実行しています。
_/_/_/ カーネルモジュールのロード _/_/_/
# modprobe br_netfilter
# modprobe overlay
_/_/_/ カーネルモジュールの確認 _/_/_/
# lsmod | grep -e br_netfilter -e overlay
overlay 77824 0
br_netfilter 24576 0
bridge 155648 1 br_netfilter
_/_/_/ 再起動後にも有効にするため設定ファイルを作成 _/_/_/
# cat >/etc/modules-load.d/containerd.conf <<EOF
br_netfilter
overlay
EOF
_/_/_/ カーネルパラメータの設定 _/_/_/
# cat >/etc/sysctl.d/99-containerd.conf <<EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
_/_/_/ カーネルパラメータ適用 _/_/_/
# sysctl --system
・・・
* Applying /etc/sysctl.d/99-containerd.conf ...
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
・・・
_/_/_/ 適用の確認 _/_/_/
# sysctl -a | grep -e bridge-nf-call-ip -e ip_forward
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
・・・
準備ができたので containerd
をインストールしていきます。
_/_/_/ https 越しのリポジトリ利用のための準備 _/_/_/
# apt-get update && \
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
_/_/_/ Docker 公式の GPG 鍵の追加 _/_/_/
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
_/_/_/ Docker のリポジトリ追加 _/_/_/
# add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
_/_/_/ containerd のインストール _/_/_/
# apt-get update && apt-get install -y containerd.io
_/_/_/ containerd の状態確認 _/_/_/
# systemctl status containerd -n0
● containerd.service - containerd container runtime
Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-02-05 16:26:30 UTC; 13min ago
Docs: https://containerd.io
Process: 30327 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
Main PID: 30328 (containerd)
Tasks: 11
CGroup: /system.slice/containerd.service
mq30328 /usr/bin/containerd
kubeadm 準備
kubeadm
で Kuberenetes をインストールする準備を行います。
kubeadm
、kubectl
、kubelet
をインストールします。
※cp01 / wk01 両方で実行します。
※ root ユーザで実行しています。
_/_/_/ google の GPG 鍵の追加 _/_/_/
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
_/_/_/ Kubernetes レポジトリの追加 _/_/_/
# cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
_/_/_/ 各パッケージのインストール _/_/_/
# apt-get update && sudo apt-get install -y kubelet kubeadm kubectl
_/_/_/ kubelet の状態確認 _/_/_/
# systemctl status kubelet -n0
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/kubelet.service.d
mq10-kubeadm.conf
Active: activating (auto-restart) (Result: exit-code) since Fri 2021-02-05 16:49:51 UTC; 6s ago
Docs: https://kubernetes.io/docs/home/
Process: 31978 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (cod
Main PID: 31978 (code=exited, status=255)
_/_/_/ kubectl バージョン確認 _/_/_/
# kubectl version --client
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:28:09Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
_/_/_/ kubeadm バージョン確認 _/_/_/
# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:25:59Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
kubeadm 実行
準備ができたので早速 kubeadm
を使って Kubernetes の ControlPlane からインストールしていきます。
_/_/_/ kubeadm で kubernetes インストール _/_/_/
### --pod-network-cidr:Pod に割り振られる IP アドレスレンジ
### ⇒ デフォルトだと LAN と被ったので指定
### --apiserver-advertise-address:API サーバーが待ち受けする IP アドレス
### ⇒ Vagrant デフォルトだと NAT の NIC で動作不良起こしそうだったので、ブリッジの NIC を指定
# kubeadm init \
--pod-network-cidr 172.16.0.0/16 \
--apiserver-advertise-address 192.168.10.61
[init] Using Kubernetes version: v1.20.2
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR CRI]: container runtime is not running: output: time="2021-02-05T16:54:10Z" level=fatal msg="getting status of runtime failed: rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.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 の 設定ファイルを削除して再起動 _/_/_/
# rm /etc/containerd/config.toml
# systemctl restart containerd
kubeadm を再実行します。
_/_/_/ kubeadm で kubernetes インストール _/_/_/
# kubeadm init \
--pod-network-cidr 172.16.0.0/16 \
--apiserver-advertise-address 192.168.10.61
[init] Using Kubernetes version: v1.20.2
[preflight] Running pre-flight checks
・・・
[certs] Using certificateDir folder "/etc/kubernetes/pki"
・・・
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
・・・
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
・・・
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
・・・
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
・・・
[apiclient] All control plane components are healthy after 18.501499 seconds
・・・
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
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 192.168.10.61:6443 --token xxxx \
--discovery-token-ca-cert-hash sha256:xxxx
ControlPlane がインストール出来ました。
出力にもあるように、kubectl
の設定ファイルを配置して、接続確認を行います。
_/_/_/ 設定ファイル配置 _/_/_/
# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
_/_/_/ クラスタへ接続確認 _/_/_/
# kubectl get node
NAME STATUS ROLES AGE VERSION
cp01 NotReady control-plane,master 17m v1.20.2
続いて Pod ネットワークプラグインをインストールします。
今回は Project Calico をインストールしていきます。
# kubectl apply -f https://docs.projectcalico.org/v3.17/manifests/calico.yaml
・・・
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
・・・
# kubectl get node
NAME STATUS ROLES AGE VERSION
cp01 Ready control-plane,master 18m v1.20.2
最後に Worker ノードを追加していきます。
※kubeadm
実行時に ControlPlane と同じエラーが出力された場合は、上述の対応が必要です。
※オプション(--token/--discovery-token-ca-cert-hash)は ControlPlane 導入時に出力されているので、そちらをコピーします。
※今回は ControlPlane 導入時の出力コマンドに「--apiserver-advertise-address」で Worker の IP アドレスを追加しています。
_/_/_/ worker ノードの追加 _/_/_/
# kubeadm join 192.168.10.61:6443 \
--token xxxx \
--discovery-token-ca-cert-hash sha256:xxxx \
--apiserver-advertise-address 192.168.10.71
[preflight] Running pre-flight checks
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
・・・
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
_/_/_/ クラスタのノード確認 _/_/_/
# kubectl get node
NAME STATUS ROLES AGE VERSION
cp01 Ready control-plane,master 26m v1.20.2
wk01 Ready <none> 90s v1.20.2
動作確認
コンテナをデプロイして動作確認を行います。
_/_/_/ Pod 作成 _/_/_/
# kubectl run nginx --image=nginx --port=80
pod/nginx created
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 15s 172.16.74.65 wk01 <none> <none>
_/_/_/ Pod 内でバージョン確認 _/_/_/
# kubectl exec nginx -- nginx -v
nginx version: nginx/1.19.6
_/_/_/ Service(NodePort)を公開 _/_/_/
# kubectl expose pod nginx --type=NodePort
service/nginx exposed
_/_/_/ Worker の IP、Service の NodePort を取得して Pod にアクセス _/_/_/
# IP=`kubectl get node wk01 -o=jsonpath='{.status.addresses[?(@.type == "InternalIP")].address}'`
# PORT=`kubectl get svc nginx -o yaml -o=jsonpath='{.spec.ports[0].nodePort}'`
# curl -I http://$IP:$PORT/
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Sat, 06 Feb 2021 22:18:04 GMT
Content-Type: text/html
・・・
まとめ
久しぶりに kubeadm
を利用してみましたが、簡単にクラスタを構築できるので改めて便利だと思いました。
また、今まで docker
で構築していたため、containerd
に少し抵抗があったのですが、意外とすんなり構築できてよかったです。
この調子でクラスタの構築も試してみようと思います。
参考
◆ CRIのインストール
https://kubernetes.io/ja/docs/setup/production-environment/container-runtimes/
◆ kubeadmのインストール
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
◆ kubeadmを使用したシングルコントロールプレーンクラスターの構築
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/