kubeadmでシングルクラスタ環境を構築


はじめに

今回は、kubeadmによるクラスタ環境構築(マスター1台、ワーカー1台)をやってみました。
vagrant+ansibleによるクラスタ環境の自動構築を実施するソースコードもありますが、
手動でクラスタ環境を構築することで、クラスタの構築の仕方とその仕組みが理解できるようになります。
是非、一度、やってみてください。CKA資格取得にも役立つと思います。

公式ドキュメントをもとに、実施しましたが、
初心者の方でも躓かないように、記載しました。
(公式ドキュメント通りにやると躓くと思います)

どなたかのお役に立てれば幸いです。

実施の流れ

  • 公式ドキュメントの手順に従い、構築していきます

  • CRIのインストール【対象:マスター、ワーカー】

  • Kkubeadm、kubelet、kubectlのインストール【対象:マスター、ワーカー】

  • kubeadmを使用したシングルコントロールプレーンクラスターの作成【対象:マスター】

  • クラスタにノードの追加【対象:ワーカー】

インストール環境

  • OS:CentOS Linux release 7.6.1810
  • kubeadm:v1.20.2
  • kubectl:v1.20.2
  • kubelet:v1.20.2
  • CRI=containerd:v1.4.3
  • CNI=Calico:v3.11

CRIのインストール【対象:マスター、ワーカー】

  • Podのコンテナを実行するために、コンテナランタイムをインストールします。
  • CRIは、containerdとCRI-Oの2択です。(v1.20以降、dockershimは非推奨となったため)
  • 今回は、containerdをインストールしてみます。
  • ちなみに、systemdとcgroupfsを併用することは推奨していない。

kubeletとDockerに cgroupfs を使用し、ノード上で実行されている残りのプロセスに systemd を使用するように設定されたノードが、 リソース圧迫下で不安定になる場合があります。

事前準備【対象:マスター、ワーカー】

swapoff -a

cat > /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

# 必要なカーネルパラメータの設定をします。これらの設定値は再起動後も永続化されます。
cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sysctl --system

containerdのインストール【対象:マスター、ワーカー】

## リポジトリの設定
### 必要なパッケージのインストール
yum install -y yum-utils device-mapper-persistent-data lvm2
## Dockerのリポジトリの追加
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
## containerdのインストール
yum update -y && yum install -y containerd.io
## containerdの設定
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# containerdの再起動
systemctl restart containerd

systemd

systemdのcgroupドライバーを使うには、/etc/containerd/config.toml内でplugins.cri.systemd_cgroup = trueを設定してください。

/etc/containerd/config.toml
[plugins]
  [plugins."io.containerd.grpc.v1.cri"]
    systemd_cgroup = true

kubeadm、kubelet、kubectlのインストール【対象:マスター、ワーカー】

こちらのサイトを実施します。

ポート開放

以下のポートを解放する必要があります。

コントロールプレーンノード

ワーカーノード

iptablesがブリッジを通過するトラフィックを処理できるようにする【対象:マスター、ワーカー】

cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

参考:コンテナランタイム

kubeadmはよく知られたUnixドメインソケットのリストをスキャンすることで、インストールされたコンテナランタイムの検出を試みます。 次の表がコンテナランタイムと関連するソケットのパスリストです。

ランタイム Unixドメインソケットのパス
- Docker /var/run/docker.sock
- containerd /run/containerd/containerd.sock
- CRI-O /var/run/crio/crio.sock

Dockerとcontainerdの両方が同時に検出された場合、Dockerが優先されます。Docker 18.09にはcontainerdが同梱されており、両方が検出可能であるため、この仕様が必要です。他の2つ以上のランタイムが検出された場合、kubeadmは適切なエラーメッセージで終了します。
kubeletは、組み込まれたdockershimCRIを通してDockerと連携します。

実際にインストールしていきます【対象:マスター、ワーカー】

要は、マイナーバージョンまで含めて、一致させた方がいいよ。ということを言っています。

kubeadmはkubeletやkubectlをインストールまたは管理しないため、kubeadmにインストールするKubernetesコントロールプレーンのバージョンと一致させる必要があります。そうしないと、予期しないバグのある動作につながる可能性のあるバージョン差異(version skew)が発生するリスクがあります。ただし、kubeletとコントロールプレーン間のマイナーバージョン差異(minor version skew)は1つサポートされていますが、kubeletバージョンがAPIサーバーのバージョンを超えることはできません。たとえば、1.7.0を実行するkubeletは1.8.0 APIサーバーと完全に互換性がありますが、その逆はできません。

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

# SELinuxをpermissiveモードに設定する(効果的に無効化する)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

systemctl enable --now kubelet

コントロールプレーンノードのkubeletによって使用されるcgroupドライバーの設定【対象:マスター、ワーカー】

CRIをDockerにした場合、kubeadmは自動的にkubelet向けのcgroupドライバーを検出し、実行時に/var/lib/kubelet/kubeadm-flags.envファイルに設定しますが、今回は、CentOSのため、cgroup-druiverの値を変更する必要があります。

/etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd
KUBELET_EXTRA_ARGS=--node-ip=10.90.3.1

このファイルは、kubeletの追加のユーザー定義引数を取得するために、kubeadm initおよびkubeadm joinによって使用されます。

以上で、kubeadm、kubelet、kubectlのインストールが完了しました。
次にkubeadmを使用して、シングルコントロールプレーンクラスタを作成していきます。
ちなみに、version1.20.2になっています。

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"}
kubectl-version
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 init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=10.90.3.1

実行すると、以下のようなメッセージが出てくる。

[ERROR CRI]: container runtime is not running: output: time="2021-02-03T06:56:58Z" level=fatal msg="getting status of runtime failed: rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.RuntimeService"
, error: exit status 1

このサイトを見て対処したところ、正常に完了しました。
※エラーが出なかった人は、この対処は不要です。

rm /etc/containerd/config.toml
systemctl restart containerd

その後、再び、以下を実行したら、成功しました。

kubeadm init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=10.90.3.1

以下は出力結果。

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.90.3.7:6443 --token xxxxx \
    --discovery-token-ca-cert-hash sha256:xxxxxxx

以下の情報については、クラスターにノードを追加する際に必要なため、どこかに控えておいてください。
kubeadm join 10.90.3.1:6443 --token xxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxx

トークンは、コントロールプレーンノードと追加ノードの間の相互認証に使用します。ここに含まれるトークンには秘密の情報が含まれます。このトークンを知っていれば、誰でもクラスターに認証済みノードを追加できてしまうため、取り扱いには注意してください。kubeadm tokenコマンドを使用すると、これらのトークンの一覧、作成、削除ができます。

先ほどの出力結果の通り、実行していきます

  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

Podネットワークアドオンのインストール【対象:マスター】

Calicoをインストールしました。

kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml

kubectl get po --all-namespacesを実行して、podのstautsがrunningになっていることを確認します。

NAMESPACE     NAME                                               READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-6b8f6f78dc-8tf24           1/1     Running   0          3m
kube-system   calico-node-ws6mn                                  1/1     Running   0          3m
kube-system   coredns-74ff55c5b-j5j5x                            1/1     Running   0          6m11s
kube-system   coredns-74ff55c5b-qg6xj                            1/1     Running   0          6m11s
kube-system   etcd-1335487-master.novalocal                      1/1     Running   0          6m13s
kube-system   kube-apiserver-1335487-master.novalocal            1/1     Running   0          6m13s
kube-system   kube-controller-manager-1335487-master.novalocal   1/1     Running   0          6m13s
kube-system   kube-proxy-5gtcg                                   1/1     Running   0          6m12s
kube-system   kube-scheduler-1335487-master.novalocal            1/1     Running   0          6m13s

ノードの追加【対象:ワーカー】

  • ワーカーノードにSSHする
  • コントロールプレーンノードで実施したことを同様の作業を実施する(kubeadm、kubelet、kubectlのインストールまで)  
  • kubeadm init実行時に出力されたコマンドを実行する。
kubeadm join --token xxxxxxx 10.90.3.1:6443 --discovery-token-ca-cert-hash sha256:xxxxxx

出力結果は以下の通り。

output
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.

コントロールプレーンノードで、kubectl get noでノードが追加されている確認します。

kubectl_get_no
NAME     STATUS    ROLES                 AGE     VERSION
master    Ready    control-plane,master   4h14m   v1.20.2
worker1   Ready    <none>                 5m46s   v1.20.2

以上で、kubeadmによるクラスタ環境構築は終了です。

これからは、このクラスタを利用して、様々なことをやっていきたいと思います。