「Kubernetes」をUbuntu上にセットアップしました。
物理サーバー2台を用意して、マスターノード1台とワーカーノード1台の構成です。それぞれのサーバーには Ubuntu Server をインストールしました。
CRI (Container Runtime Interface) としては Containerd (※) を採用しました。
また、CNI (Container Networking Interface) として flannel を採用しました。
※CRIとしての Docker は、Kubernetes 1.20 から非奨励となっています。そこで「containerd」か「CRI-O」で迷いましたが、文献が多そうな「containerd」を選択しました。
構築環境
サーバーとして物理サーバー2台を用意して、Ubuntu Server 20.04 をセットアップしています。
Kubernetes のインストール作業は、Kubernetes 公式ページの手順に従って行いました。
Kubernetes クラスター構築にあたって使用した各コンポーネントのバージョンは以下の通りです。
OS / パッケージ | バージョン | 役割 |
---|---|---|
Ubuntu | 20.04.3 | OS |
Kubernetes | 1.22.4 | Kubernetes (kubeadm / kubectl / kubelet …) |
containerd | 1.4.12 | CRI |
flannel | 0.15.1 | CNI |
etcd | 3.5.0 | Key-Value ストア |
Ubuntu のインストール方法は以下の記事に記載しています。
Kubernetes 公式サイトにより詳細で様々な環境に適用できるインストール手順が記載されています。
前準備
Kubernetes を構築する前の準備として、以下の設定を行ってください。
Swap 機能を OFF にする
Kubernetes のシステム要件として、「Swap 機能が オフ であること。」と書いてあります。
Swapがオフであること。kubeletが正常に動作するためにはswapは必ずオフでなければなりません。
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
これに従って、Swap を利用しないように設定します。
swapoff -a
top コマンドで、Swap領域の容量が 0 になっていることを確認します。
top
top - 07:31:50 up 3 days, 12:31, 1 user, load average: 3.54, 4.90, 6.14
Tasks: 304 total, 2 running, 301 sleeping, 0 stopped, 1 zombie
%Cpu(s): 35.1 us, 5.7 sy, 0.0 ni, 54.9 id, 1.6 wa, 0.0 hi, 2.7 si, 0.0 st
MiB Mem : 7840.5 total, 455.5 free, 3843.9 used, 3541.1 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 3664.8 avail Mem
さらに、サーバー再起動をするとSwap領域が復活してしまうので、 /etc/fstab
のSwap領域の確保に関する行をコメントアウトします。
vi /etc/fstab
# /swap.img none swap sw 0 0
ホスト名で名前解決できるようにする
ノード間で通信できるように、ホスト名で名前解決できるようにしておく必要があります。内部DNSサーバにレコードを追加することでも対応できますが、ここでは /etc/hosts
で設定することにします。
vi /etc/hosts
末尾2行を追加しました。
127.0.0.1 localhost
127.0.1.1 4mo-sv10
# 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
# Settings for Kubernetes
192.168.180.10 4mo-sv10
192.168.180.30 4mo-sv30
CRI (Containerd) のインストール
公式サイトに記載の手順に従って、 Containerd をインストールしていきます。
Containerd に必要な設定の追加
カーネルモジュール overlay
br_netfilter
を読み込むように設定します。この設定は再起動後も永続化されます。
cat > /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
カーネルモジュール overlay
br_netfilter
を読み込みます。
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 のインストール
(公式サイトの手順をそのまま抜粋)
# (containerdのインストール)
## リポジトリの設定
### HTTPS越しのリポジトリの使用をaptに許可するために、パッケージをインストール
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のaptリポジトリの追加
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の設定
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# containerdの再起動
systemctl restart containerd
Containerd の起動確認
systemctl status containerd
● containerd.service - containerd container runtime
Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2021-12-07 19:02:15 UTC; 4 days ago
Docs: https://containerd.io
Main PID: 782 (containerd)
Tasks: 1482
Memory: 5.4G
CGroup: /system.slice/containerd.service
├─ 782 /usr/bin/containerd
Kubernetes のインストール
公式サイトに記載の手順に従って、 kubeadm / kubelet / kubectl をインストールします。
Kubernetes インストールで必要なパッケージのインストールを行います。
apt-get update && apt-get install -y apt-transport-https curl
GoogleのGPGキーを取得して、登録します。
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
Kubernetes のリポジトリを追加します。
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
Kubernetesのパッケージkubelet
kubeadm
kubectl
をインストールします。
apt-get update && apt-get install -y kubelet kubeadm kubectl
Kubernetes のアップデートには特別な手順が必要となります。
アップグレード (apt upgrade) によって意図せず Kubernetes パッケージが更新されてしまうことを防ぐため、パッケージの更新対象からKubernetesパッケージを除きます。
sudo apt-mark hold kubelet kubeadm kubectl
マスターノードのセットアップ
公式の手順に従って、マスターノードのセットアップを行います。
マスターノードの初期化
マスターノードの初期化を行います。
マスターノード を初期化するには kubeadm init <args>
コマンドを実行します。
公式サイトの以下の注意に従って、オプションを設定することにします。
- (推奨)シングルコントロールプレーンの
kubeadm
クラスターを高可用性クラスターにアップグレードする予定がある場合、--control-plane-endpoint
を指定して、すべてのコントロールプレーンノードとエンドポイントを共有する必要があります。エンドポイントにはDNSネームやロードバランサーのIPアドレスが使用できます。 - Podネットワークアドオンを選んで、
kubeadm init
に引数を渡す必要があるかどうか確認してください。選んだサードパーティーのプロバイダーによっては、--pod-network-cidr
をプロバイダー固有の値に設定する必要がある場合があります。詳しくは、Podネットワークアドオンのインストールを参照してください。
--control-plane-endpoint
将来的にHAクラスター(高可用性クラスター)を構築する可能性に備えてコントロールプレーンのローカルIPを指定します。--pod-network-cidr
CNI (Podネットワークアドオン) として flannel を採用するため、flannel のデフォルトのCIDRを指定します。
kubeadm init --control-plane-endpoint=192.168.180.1:6443 --pod-network-cidr=10.244.0.0/16
しばらく待っていると以下のインストール完了メッセージが表示されます。
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
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
この一番最後に表示されている kubeadm join
コマンドが重要です。この後の手順でワーカーノード(やコントロールプレーンノード)を追加する際に利用します。
<token>
やdiscovery-token-ca-cert-hash
を無くしたとしても再発行できますが、どこかに保存しておいたほうが今後の作業がスムーズに進みます。※再発行の手順はトラブルシューティングとして後述します。
Kubernetes操作環境の設定
kubectl (Kubernetesを操作するコマンド)を一般ユーザで実行できるようにするには、対象の一般ユーザーで以下のコマンドを実行します。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
一般ユーザーではなく管理者ユーザーで kubectl を実行する場合には、以下のコマンドを実行します。
export KUBECONFIG=/etc/kubernetes/admin.conf
source ~/.bashrc
flannel (CNI/Podネットワークアドオン) のインストール
以下のコマンドで最新の flannel をインストールします。
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
セットアップ後の確認
kubectl get node
コマンドでノードの状態を確認します。
kubectl get node
STATUSが Ready
になっていればマスターノードのセットアップに成功しています。
NAME STATUS ROLES AGE VERSION
4mo-sv10 Ready control-plane,master 7d11h v1.22.4
ワーカーノードのセットアップ
続いて、ワーカーノードを追加していきます。
ワーカーノードのセットアップ
マスターノードのセットアップ時に出力された kubeadm join
コマンドを実行します。
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
ノード追加完了のメッセージが表示されれば、ワーカーノードのセットアップに成功しています。
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 node
コマンドでノードの状態を確認します。
kubectl get node
STATUSが Ready
になっていれば正常です。
NAME STATUS ROLES AGE VERSION
4mo-sv10 Ready control-plane,master 7d11h v1.22.4
4mo-sv30 Ready <none> 7d11h v1.22.4
Pod の状態を kubectl get pod -A
コマンドで確認します。
kubectl get pod -A
namespace: kube-system で以下のPodのSTATUSが Running
となっていれば正常です。
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-78fcd69978-4lcjv 1/1 Running 4 (4d1h ago) 7d11h
kube-system coredns-78fcd69978-q5kfj 1/1 Running 4 (4d1h ago) 7d11h
kube-system etcd-4mo-sv10 1/1 Running 20 (4d1h ago) 7d11h
kube-system kube-apiserver-4mo-sv10 1/1 Running 20 (4d1h ago) 7d11h
kube-system kube-controller-manager-4mo-sv10 1/1 Running 21 (2d2h ago) 7d11h
kube-system kube-flannel-ds-pg7qf 1/1 Running 5 (4d1h ago) 7d11h
kube-system kube-flannel-ds-wv9bp 1/1 Running 6 (37h ago) 7d11h
kube-system kube-proxy-8xhhw 1/1 Running 6 (37h ago) 7d11h
kube-system kube-proxy-9w4vc 1/1 Running 4 (4d1h ago) 7d11h
kube-system kube-scheduler-4mo-sv10 1/1 Running 21 (2d2h ago) 7d11h
トラブルシューティング
Kubernetes のセットアップを最初からやり直したい
一度Kubernetesクラスターをリセットしてから、もう一度Kubernetesのセットアップを行いたい場合は、ワーカーノードとマスターノードの両方でkubectl reset
コマンドを実行します。
kubeadm reset
[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] are you sure you want to proceed? [y/N]: y
[preflight] running pre-flight checks
[reset] no etcd config found. Assuming external etcd
[reset] please manually reset etcd to prevent further issues
[reset] stopping the kubelet service
[reset] unmounting mounted directories in "/var/lib/kubelet"
[reset] deleting contents of stateful directories: [/var/lib/kubelet /etc/cni/net.d /var/lib/dockershim /var/run/kubernetes]
[reset] deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]
The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually.
For example:
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.
Kubernetes クラスターのリセットが完了したら、再度 Kubernetes のセットアップ を行います。
ノード追加コマンドの token や discovery-token-ca-cert-hash を忘れた
token の確認
トークンが分からない場合は、コントロールプレーンノードで kubeadm token list
コマンドを実行します。
kubeadm token list
発行済のトークンが表示されます。(表示されない場合は次を確認してください。)
TOKEN TTL EXPIRES USAGES DESCRIPTION
EXTRA GROUPS
jat85g.mtrah2hjdarj9lrk 23h 2021-12-12T20:52:06Z authentication,signing <none>
トークンの有効期限はデフォルトでは24時間です。有効期限が切れた後にクラスターにノードを参加させたい場合は、コントロールプレーンノードでkubeadm token create
コマンドを実行してトークンを生成します。
kubeadm token create
トークンが表示されます。
5didvk.d09sbcov8ph2amjw
discovery-token-ca-cert-hash の再生成
--discovery-token-ca-cert-hash
の値が分からない場合は、コントロールプレーンノードで次のコマンドを実行することで取得できます。
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
ハッシュを取得できます。
8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78
最後に
これでおうちKubernetesクラスターが完成しましたが、まだ使い勝手の良くありません。
- 永続化ボリュームが自動で作成されない
- Service で LoadBalancer が使えない
- Ingress が使えない
- …
パブリッククラウドであればクラウドが管理してくれて簡単に利用できるストレージがあったり、マネージドサービスのロードバランサーを使えたりしますが、おうち Kubernetes クラスターではそうもいきません。
また、おうち Kubernetes クラスターに限った話ではありませんが、プロダクション環境の運用には監視基盤も欲しいところです。
そこで、次回以降の記事では おうちKubernetes をより便利にするための構築手順を紹介していきます。