LoginSignup
8
11

More than 3 years have passed since last update.

はじめに

昨年 CKA を取得するべく Kubernetes を勉強し無事取得することが出来ました。
体験記は以下に記事を書いているのでご参考までに。

CKA受験体験記(2020/03)

※改定前の受験内容なので、最新の情報はホームページをご確認ください。

Certified Kubernetes Administrator (CKA)

受験範囲には kubeadm の使い方も入っていました。
kubeadm は Kubernetes を構築するためのツールで、シングルノードから複数ノードのクラスタまで構築することが出来ます。
受験当時は関連する問題があったものの kubeadm の知識が薄かったため解くことが出来ず・・・
今回は復習も込めて kubeadm を使ってシングルノードのクラスタを構築しようと思います。

kubeadm の動きについては Y氏の解説記事が分かりやすいので是非。

kubeadmって何やってるの?公式ページをちゃんと読む

環境情報

今回はローカル 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)に変更しています。

Vagrant上のkubernetesでWorker Nodeのコンテナにアタッチできない問題について

Vagrantfile
# -*- 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 をインストールする準備を行います。
kubeadmkubectlkubelet をインストールします。
※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

エラーが・・・出た際は以下で対応みたいです。

参考:https://github.com/containerd/containerd/issues/4581

_/_/_/ 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/

8
11
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
8
11