やったことのまとめ
クラスタ操作の練習用にGKE
みたいなマネージドではない自前のKubernetes
クラスタがほしくて、
かつ運用の練習としてはkind
やMinikube
みたいなやつだと物足りない。
とはいえKubernetes The Hard Wayするほどじゃないんだよな…みたいな気分になったので、
おさらいも兼ねてkubeadm
でクラスタを立てることにした。
基本的にCreating a cluster with kubeadmをなぞっているだけ。
- GCPでVMとネットワークを作成した
kubeadm
を使ってKubernetes
クラスタをつくった- コンテナランタイムにはcontainerd, ネットワークアドオンはCalicoを使用した
- あまり長くつかっているとお金がかかるのでおかたづけした
つかうもの
- macOS Big Sur 11.2.3
- Google Cloud SDK 360.0.0
- GCP操作に使用
- Ubuntu 20.04.3 LTS (GNU/Linux 5.11.0-1020-gcp x86_64)
- node用のVMとして使用
- containerd 1.4.11
- コンテナランタイム
- Calico v3.20.2
- ネットワークアドオン
- Kubernetes v1.22.2
やったこと
ネットワークとVMの準備(GCP)
gcloud
のセットアップはmacOS用のクイックスタートで終わっている前提。
VPCネットワークの作成
まずはnode
同士をつなぐためのネットワークを設定する。GCP
ではVPCネットワークを使う。
# Macで実行
# VPCネットワークの作成
# サブネットのIPレンジは10.240.0.0/24(最大256node使用可能)にする
gcloud compute networks create kubernetes-vpc-network --subnet-mode=custom
gcloud compute networks subnets create kubernetes-vpc-network-subnet --range=10.240.0.0/24 --network=kubernetes-vpc-network
# ネットワークのIPレンジ内からネットワーク上の任意のnodeへの任意のプロトコルでの接続を許可(kubernetes-vpc-network-allow-internal)
# 任意の送信元からネットワーク上の任意のnodeへの特定ポートへの特定プロトコルでの接続を許可(kubernetes-vpc-network-allow-external)
# tcp:22はnodeへのSSHに, tcp:6443はkube-apiserverへのリクエストに, icmpはpingでの監視に使用
gcloud compute firewall-rules create kubernetes-vpc-network-allow-internal --network=kubernetes-vpc-network --allow all --source-ranges=10.240.0.0/24
gcloud compute firewall-rules create kubernetes-vpc-network-allow-external --network kubernetes-vpc-network --allow tcp:22,tcp:6443,icmp
VMインスタンスの作成
つぎにクラスタのnode
として使うVMインスタンスをmaster
用とworker
用にそれぞれ1台ずつ建てる。
Creating a cluster with kubeadmによるとmaster
は最低でも2GiB RAM, 2CPUsがあるといいらしいのでマシンタイプはそれを満たすように気をつける。
OSの起動imageはUbuntu 20.04 LTS
を使用した。
# Macで実行
# master(e2-medium),worker(e2-small)用インスタンスの作成
gcloud compute instances create kubernetes-master --machine-type=e2-medium --image-family=ubuntu-2004-lts --image-project=ubuntu-os-cloud --subnet=kubernetes-vpc-network-subnet
gcloud compute instances create kubernetes-worker --machine-type=e2-small --image-family=ubuntu-2004-lts --image-project=ubuntu-os-cloud --subnet=kubernetes-vpc-network-subnet
最終的に以下のようになっていればOK。
$ gcloud compute networks list --filter="name=kubernetes-vpc-network"
NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4
kubernetes-vpc-network CUSTOM REGIONAL
$ gcloud compute networks subnets list --filter="name=kubernetes-vpc-network-subnet"
NAME REGION NETWORK RANGE STACK_TYPE IPV6_ACCESS_TYPE IPV6_CIDR_RANGE EXTERNAL_IPV6_CIDR_RANGE
kubernetes-vpc-network-subnet us-central1 kubernetes-vpc-network 10.240.0.0/24 IPV4_ONLY
$ gcloud compute firewall-rules list --filter="network=kubernetes-vpc-network"
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
kubernetes-vpc-network-allow-external kubernetes-vpc-network INGRESS 1000 tcp:22,tcp:6443,icmp False
kubernetes-vpc-network-allow-internal kubernetes-vpc-network INGRESS 1000 all False
$ gcloud compute instances list
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
kubernetes-master us-central1-a e2-medium 10.240.0.4 xx.xx.xx.xxx RUNNING
kubernetes-worker us-central1-a e2-small 10.240.0.5 yy.yyy.yyy.yy RUNNING
nodeの準備
ネットワークとnode
用VM
が準備できたので、いよいよクラスタを構築していく。
# SSHするときは以下のコマンドを使う
gcloud compute ssh kubernetes-master
gcloud compute ssh kubernetes-worker
コンテナランタイム(containerd)のインストール
master
とworker
で共にPod
(コンテナ)を動かすために必要なコンテナランタイムをインストールする。
コンテナランタイムにはいくつか候補があるが、今回はcontainerdを使う。Ubuntu
でのインストール手順はInstall Docker Engine on Ubuntuを参考にする。
# master/worker両方でそれぞれ実行する
# VM起動時にkernelモジュール(overlay, br_netfilter)を読み込むための設定
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
# kernelモジュール(overlay, br_netfilter)の手動読み込み
sudo modprobe overlay && sudo modprobe br_netfilter
# kernelパラメータを変更(永続化)する設定
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# kernelパラメータの適用
sudo sysctl --system
# (ないと思うが)古いpackageを削除
sudo apt-get remove docker docker-engine docker.io containerd runc
# aptのpackage indexの更新とHTTPSでリポジトリを使うために必要なpackageのインストール
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
# Docker公式のGPG鍵追加
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Dockerのstableリポジトリ追加
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# containerdのインストール
sudo apt-get update && sudo apt-get install -y containerd.io
# containerdの設定ファイル作成(96行目付近にsystemdのcgroupドライバーを使う設定を入れる)
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo vim /etc/containerd/config.toml
# containerdの再起動
sudo systemctl restart containerd
containerd
を動かすcgroup
がsystemd
になる/etc/containerd/config.toml
の設定はUsing the systemd cgroup driverに従った。
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
base_runtime_spec = ""
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
systemd
でcontainerd
が動いていることを確認できればOK。
kubernetes-worker:~$ systemctl is-active containerd
active
kubelet,kubeadm,kubectlのインストール
コンテナランタイムがインストールできたら、次はInstalling kubeadm, kubelet and kubectlに従ってKubernetes
クラスタに必要なコンポーネントをmaster
とworker
両方にインストールする。
# master/worker両方でそれぞれ実行する
# Google CloudのGPG鍵追加
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
# Kubernetesリポジトリ追加
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# kubelet,kubeadm,kubectlのインストールとバージョン固定
sudo apt-get update && sudo apt-get install -y kubelet kubeadm kubectl && sudo apt-mark hold kubelet kubeadm kubectl
masterの起動
コンテナランタイムとkubeadm
の準備ができたらまずはmaster node (control-plane)
を作成する。
今回はネットワークアドオンにCalicoを使うため、kubeadm init
のオプションを付与する。
# masterでのみ実行する
# master nodeのセットアップ
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
# kubeconfigの準備
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# kubectlの準備
source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k
これでmaster node
が作成できた…と思いきや、
この時点ではまだネットワークアドオンが入っていないためPod
間の通信ができず、CoreDNS
が立ち上がらない。
kubernetes-master:~$ k get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-78fcd69978-dzwrb 0/1 Pending 0 3m25s
kube-system coredns-78fcd69978-ffpvj 0/1 Pending 0 3m25s
kube-system etcd-kubernetes-master 1/1 Running 0 3m33s
kube-system kube-apiserver-kubernetes-master 1/1 Running 0 3m33s
kube-system kube-controller-manager-kubernetes-master 1/1 Running 0 3m33s
kube-system kube-proxy-zk7mn 1/1 Running 0 3m25s
kube-system kube-scheduler-kubernetes-master 1/1 Running 0 3m33s
ネットワークアドオン(Calico)のインストール
kubeadm init
が終わったので、
つぎにネットワークアドオンとしてCalicoをインストールする。
# masterでのみ実行する
# Calicoのインストール
k create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml
k create -f https://docs.projectcalico.org/manifests/custom-resources.yaml
Calico
に必要なPod
の作成には時間がかかるのですこし待つ。
次のようになっていればOK。CoreDNS
も立ち上がっている。
kubernetes-master:~$ k get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
calico-apiserver calico-apiserver-6dd4bc68c6-lslcj 1/1 Running 0 12s
calico-system calico-kube-controllers-767ddd5576-64dj8 1/1 Running 0 80s
calico-system calico-node-2fx6b 1/1 Running 0 80s
calico-system calico-typha-5bf9887dd7-hrtwj 1/1 Running 0 80s
kube-system coredns-78fcd69978-dzwrb 1/1 Running 0 12m
kube-system coredns-78fcd69978-ffpvj 1/1 Running 0 12m
kube-system etcd-kubernetes-master 1/1 Running 0 12m
kube-system kube-apiserver-kubernetes-master 1/1 Running 0 12m
kube-system kube-controller-manager-kubernetes-master 1/1 Running 0 12m
kube-system kube-proxy-zk7mn 1/1 Running 0 12m
kube-system kube-scheduler-kubernetes-master 1/1 Running 0 12m
tigera-operator tigera-operator-59f4845b57-qgq6c 1/1 Running 0 111s
workerの起動
master
1台のKubernetes
クラスタができたので、
次にworker
をこのクラスタに追加する。
node
の追加に必要なトークンとCA証明書のハッシュ値はmaster
側で取得する。
# masterでのみ実行する
# 新規tokenの作成
kubernetes-master:~$ kubeadm token create
<token>
# CA証明書ハッシュの取得
kubernetes-master:~$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
<hash>
# master nodeのホストとIPを取得
kubernetes-master:~$ k cluster-info | grep control
Kubernetes control plane is running at https://<control-plane-host>:<control-plane-port>
master
で取得した情報を使ってworker
をkubeadm join
してクラスタに追加する。
# workerでのみ実行する
sudo kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
This node has joined the cluster
と表示されればworker
がクラスタに追加できている。
master
側で確認するとworker
が認識されていて、各種DaemonSet
のPod
もちゃんとworker
に配置されている。
kubernetes-master:~$ k get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kubernetes-master Ready control-plane,master 25m v1.22.2 10.240.0.4 <none> Ubuntu 20.04.3 LTS 5.11.0-1020-gcp containerd://1.4.11
kubernetes-worker Ready <none> 91s v1.22.2 10.240.0.5 <none> Ubuntu 20.04.3 LTS 5.11.0-1020-gcp containerd://1.4.11
kubernetes-master:~$ k get all -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-apiserver pod/calico-apiserver-6dd4bc68c6-lslcj 1/1 Running 0 19m 192.168.237.5 kubernetes-master <none> <none>
calico-system pod/calico-kube-controllers-767ddd5576-64dj8 1/1 Running 0 20m 192.168.237.2 kubernetes-master <none> <none>
calico-system pod/calico-node-2fx6b 1/1 Running 0 20m 10.240.0.4 kubernetes-master <none> <none>
calico-system pod/calico-node-vkmhc 1/1 Running 0 7m7s 10.240.0.5 kubernetes-worker <none> <none>
calico-system pod/calico-typha-5bf9887dd7-hrtwj 1/1 Running 0 20m 10.240.0.4 kubernetes-master <none> <none>
calico-system pod/calico-typha-5bf9887dd7-v8plr 1/1 Running 1 (6m33s ago) 7m4s 10.240.0.5 kubernetes-worker <none> <none>
kube-system pod/coredns-78fcd69978-dzwrb 1/1 Running 0 31m 192.168.237.1 kubernetes-master <none> <none>
kube-system pod/coredns-78fcd69978-ffpvj 1/1 Running 0 31m 192.168.237.3 kubernetes-master <none> <none>
kube-system pod/etcd-kubernetes-master 1/1 Running 0 31m 10.240.0.4 kubernetes-master <none> <none>
kube-system pod/kube-apiserver-kubernetes-master 1/1 Running 0 31m 10.240.0.4 kubernetes-master <none> <none>
kube-system pod/kube-controller-manager-kubernetes-master 1/1 Running 0 31m 10.240.0.4 kubernetes-master <none> <none>
kube-system pod/kube-proxy-xj444 1/1 Running 0 7m7s 10.240.0.5 kubernetes-worker <none> <none>
kube-system pod/kube-proxy-zk7mn 1/1 Running 0 31m 10.240.0.4 kubernetes-master <none> <none>
kube-system pod/kube-scheduler-kubernetes-master 1/1 Running 0 31m 10.240.0.4 kubernetes-master <none> <none>
tigera-operator pod/tigera-operator-59f4845b57-qgq6c 1/1 Running 0 20m 10.240.0.4 kubernetes-master <none> <none>
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
calico-apiserver service/calico-api ClusterIP 10.110.66.91 <none> 443/TCP 19m apiserver=true
calico-system service/calico-kube-controllers-metrics ClusterIP 10.106.106.192 <none> 9094/TCP 19m k8s-app=calico-kube-controllers
calico-system service/calico-typha ClusterIP 10.110.34.28 <none> 5473/TCP 20m k8s-app=calico-typha
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31m <none>
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 31m k8s-app=kube-dns
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
calico-system daemonset.apps/calico-node 2 2 2 2 2 kubernetes.io/os=linux 20m calico-node docker.io/calico/node:v3.20.2 k8s-app=calico-node
kube-system daemonset.apps/kube-proxy 2 2 2 2 2 kubernetes.io/os=linux 31m kube-proxy k8s.gcr.io/kube-proxy:v1.22.2 k8s-app=kube-proxy
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
calico-apiserver deployment.apps/calico-apiserver 1/1 1 1 19m calico-apiserver docker.io/calico/apiserver:v3.20.2 apiserver=true
calico-system deployment.apps/calico-kube-controllers 1/1 1 1 20m calico-kube-controllers docker.io/calico/kube-controllers:v3.20.2 k8s-app=calico-kube-controllers
calico-system deployment.apps/calico-typha 2/2 2 2 20m calico-typha docker.io/calico/typha:v3.20.2 k8s-app=calico-typha
kube-system deployment.apps/coredns 2/2 2 2 31m coredns k8s.gcr.io/coredns/coredns:v1.8.4 k8s-app=kube-dns
tigera-operator deployment.apps/tigera-operator 1/1 1 1 20m tigera-operator quay.io/tigera/operator:v1.20.4 name=tigera-operator
NAMESPACE NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
calico-apiserver replicaset.apps/calico-apiserver-6dd4bc68c6 1 1 1 19m calico-apiserver docker.io/calico/apiserver:v3.20.2 apiserver=true,pod-template-hash=6dd4bc68c6
calico-apiserver replicaset.apps/calico-apiserver-788fc95f55 0 0 0 19m calico-apiserver docker.io/calico/apiserver:v3.20.2 apiserver=true,pod-template-hash=788fc95f55
calico-system replicaset.apps/calico-kube-controllers-767ddd5576 1 1 1 20m calico-kube-controllers docker.io/calico/kube-controllers:v3.20.2 k8s-app=calico-kube-controllers,pod-template-hash=767ddd5576
calico-system replicaset.apps/calico-typha-5bf9887dd7 2 2 2 20m calico-typha docker.io/calico/typha:v3.20.2 k8s-app=calico-typha,pod-template-hash=5bf9887dd7
kube-system replicaset.apps/coredns-78fcd69978 2 2 2 31m coredns k8s.gcr.io/coredns/coredns:v1.8.4 k8s-app=kube-dns,pod-template-hash=78fcd69978
tigera-operator replicaset.apps/tigera-operator-59f4845b57 1 1 1 20m tigera-operator quay.io/tigera/operator:v1.20.4 name=tigera-operator,pod-template-hash=59f4845b57
これで1master
-1worker
のKubernetes
クラスタをつくることができた。
後はVMのリソースが尽きない限り何でも自由にやりたい放題できる。
おかたづけ
GCP
で建てたVM
は今回master
に使用したe2-medium
だけでも1ヶ月で約3000円くらいかかってしまう。
お金に余裕があればいいんだけど、練習用のクラスタなので使わなくなったらさっさと片付けるべき。
(昔デカめのKubernetes
クラスタを放置してたら無料枠$300が1ヶ月で吹き飛んた)
VM
をそのまま吹き飛ばしても良いのだが、練習としてkubeadm
を使ったお掃除をしてみる。
# masterでのみ実行する
# workerのPodを退去させる
kubectl drain kubernetes-worker --delete-local-data --force --ignore-daemonsets
# workerでのみ実行する
# kubadm joinによって設定されたものを設定前に戻す
sudo kubeadm reset
sudo rm -rf /etc/cni/net.d
# masterでのみ実行する
# workerを削除する
kubectl delete node kubernetes-worker
# kubeadm initによって設定されたものを設定前に戻す
sudo kubeadm reset
sudo rm -rf /etc/cni/net.d
あとは粛々とKubernetes
コンポーネントとコンテナランタイムを削除していく。
# master/worker両方でそれぞれ実行する
# Kubernetesコンポーネントの削除
sudo apt-get purge -y --allow-change-held-packages kubelet kubeadm kubectl
sudo apt-get purge -y --allow-change-held-packages containerd.io
最後にgcloud
で作ったリソースを削除する。
# Macで実行
# GCPリソースの削除(いきなりこれをやってもOK)
gcloud compute instances delete kubernetes-master kubernetes-worker
gcloud compute firewall-rules delete kubernetes-vpc-network-allow-internal kubernetes-vpc-network-allow-external
gcloud compute networks subnets delete kubernetes-vpc-network-subnet
gcloud compute networks delete kubernetes-vpc-network
これで綺麗さっぱりおかたづけできたのでお財布のダメージも少ないはず。
おわり
Creating a cluster with kubeadmをなぞって練習用のKubernetes
クラスタをつくった。
基本的にはドキュメントさえ見ればできるんだけど、参照するドキュメントが何枚もあったりしてたまに混乱するので具体的な手順を1枚にできてよかった。