今回はRaspberry Piで、マスターノート*1 + ワーカーノート*2構成のKubernetes cluster構築の最終であるKubernetes cluster編です。
Creating a single control-plane cluster with kubeadmにあるように、kubeadmを使用してベストプラクティスに準拠する、実行可能な最小限のKubernetesクラスターをブートストラップします。
前回の記事はこちらです。
次がローカル環境です。
Client OS | Windows10 |
ネットワーク | 無線LAN・Wi-Fi |
事前チェック
kubeadmを使用してクラスターを作成する前に、Before you beginの内容をチェックします。
Ubuntu Server
ノード | 対象 |
マスターノード | 〇 |
ワーカーノード1 | 〇 |
ワーカーノード2 | 〇 |
Swapの無効
1 2 3 4 5 6 |
// typeがswapを確認 -> なし cat /etc/fstab free total used free shared buff/cache available Mem: 3884376 1059012 342564 5024 2482800 2977168 Swap: 0 0 0 |
iptablesの設定
次に、Letting iptables see bridged trafficに従って、iptablesがnftablesバックエンドを使用しないように設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
sudo apt update // br_netfilterモジュールのロードを確認 lsmod | grep br_netfilter // ロードされていなければロード sudo modprobe br_netfilter cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sudo sysctl --system ------------------------------- ・・・ net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 ・・・ ------------------------------- |
いよいよKubernetes cluster作成
いよいよ、kubeadmを使用してクラスターを作成していきます。それでは、公式のInstalling kubeadmに従って進めていきます。
dockerインストール
まず、コンテナランタイムをインストールします。ここでは、Dockerをインストールします。
ノード | 対象 |
マスターノード | 〇 |
ワーカーノード1 | 〇 |
ワーカーノード2 | 〇 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// dockerインストール sudo apt install -y docker.io // Unitファイルの一覧からdockerを検索 sudo systemctl list-unit-files | grep docker ------------------------------------------- docker.service disabled enabled docker.socket enabled enabled ------------------------------------------- // 有効化 sudo systemctl enable docker.service // デーモンをセットアップ cat <<EOF | sudo tee /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" } EOF // 現在のユーザでdockerコマンドが実行できるように権限付与 sudo gpasswd -a $(whoami) docker sudo chgrp docker /var/run/docker.sock sudo systemctl restart docker.service // sshセッションを閉じて再接続すると、現在のユーザでdockerコマンドを使用できます |
kubeadm, kubelet, kubectlインストール
次に、Installing kubeadm, kubelet and kubectlに従ってkubeadm、kubelet、kubectlをインストールします。
ノード | 対象 |
マスターノード | 〇 |
ワーカーノード1 | 〇 |
ワーカーノード2 | 〇 |
1 2 3 4 5 6 7 8 |
sudo apt-get update && sudo apt-get install -y apt-transport-https curl sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF sudo apt update sudo apt install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl |
kubeadm init
次にInitializing your control-plane nodeに従ってcontrol-plane node(マスターノード)の初期セットアップをします。
ノード | 対象 |
マスターノード | 〇 |
ワーカーノード1 | – |
ワーカーノード2 | – |
kubeadm initの引数にPodネットワークのCIDRを指定します。calicoのデフォルトは、192.168.0.0/16みたいですが、ここは以前デプロイしたAKSの設定を使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 初期セットアップ sudo kubeadm init --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: 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.13.101:6443 --token 1ncby3.kwmihywit9boxiwo --discovery-token-ca-cert-hash sha256:e2c35029e2bf18b7440ac1d8dby824b5p4a0d9779f82af99a8b82735i3eb61za |
”Your Kubernetes control-plane has initialized successfully!”と表示されると、最後にkubeadm joinのコマンドが表示されているはずです。後程、このコマンドを実行するのでメモしておいてください。仮に忘れた場合でも、トークンは再作成できるので、特に心配ありません。
kubectl
kubectlを使用できるように設定ファイルを配置します。先程のkubeadm initの実行結果にある通りに実行します。
1 2 3 4 5 6 7 8 9 |
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config // kubectlの動作確認 ※まだステータスはNotReady kubectl get node ------------------------------------ NAME STATUS ROLES AGE VERSION k8s-master-node-ubuntu NotReady master 2m19s v1.18.2 ------------------------------------ |
calico
ポッドネットワークプラグインをインストールします。Installing a Pod network add-onに人気のポッドネットワークプラグインが紹介されているのでお好みで。ここではCalicoを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// yamlファイルをダウンロード sudo wget https://docs.projectcalico.org/v3.11/manifests/calico.yaml // yamlファイルのcidr値をkubeadm initで指定した--pod-network-cidr=10.244.0.0/16の値に変更 // yamlファイルを編集したら実行 kubectl apply -f calico.yaml ------------------------------------------- configmap/calico-config created customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created clusterrole.rbac.authorization.k8s.io/calico-node created clusterrolebinding.rbac.authorization.k8s.io/calico-node created daemonset.apps/calico-node created serviceaccount/calico-node created deployment.apps/calico-kube-controllers created serviceaccount/calico-kube-controllers created ------------------------------------------------------- kubectl get node NAME STATUS ROLES AGE VERSION k8s-master-node-ubuntu Ready master 20m v1.18.2 |
ワーカーノードをKubernetes clusterに参加
ここでkubeadm initの実行結果にあったkubeadm joinコマンドを実行してワーカーノードをKubernetes clusterに参加させます。
その前に、トークンを忘れた方、若しくはkubeadm init実行から24時間以上経過した方は、トークンを再作成します。
ノード | 対象 |
マスターノード | 〇 |
ワーカーノード1 | – |
ワーカーノード2 | – |
1 2 3 4 5 6 7 8 |
// トークンの期限切れ等を確認 kubeadm token list // トークンの生成 kubeadm token create kubeadm token list // --discovery-token-ca-cert-hashを忘れた方 sudo openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \ openssl dgst -sha256 -hex | sed 's/^.* //' |
ノード | 対象 |
マスターノード | – |
ワーカーノード1 | 〇 |
ワーカーノード2 | 〇 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
sudo kubeadm join 192.168.13.101:6443 --token 1ncby3.kwmihywit9boxiwo --discovery-token-ca-cert-hash sha256:e2c35029e2bf18b7440ac1d8dby824b5p4a0d9779f82af99a8b82735i3eb61za --------------------------------------------- W0508 22:44:40.392200 9305 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set. [preflight] Running pre-flight checks [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.18" ConfigMap in the kube-system namespace [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 [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap... 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 -o wide ----------------------------------------------------------------------------------- NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-master-node-ubuntu Ready master 22h v1.18.2 192.168.13.101 <none> Ubuntu 20.04 LTS 5.4.0-1008-raspi docker://19.3.8 k8s-worker-node-01-ubuntu Ready <none> 14m v1.18.2 192.168.13.102 <none> Ubuntu 20.04 LTS 5.4.0-1008-raspi docker://19.3.8 k8s-worker-node-02-ubuntu Ready <none> 2m28s v1.18.2 192.168.13.103 <none> Ubuntu 20.04 LTS 5.4.0-1008-raspi docker://19.3.8 ----------------------------------------------------------------------------------- |
Nginxデプロイ
それでは簡単な動確です。Service typeをNodePortしてNginxデプロイします。
ノード | 対象 |
マスターノード | 〇 |
ワーカーノード1 | – |
ワーカーノード2 | – |
nginx-deployment.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 resources: limis: memory: "256Mi" requests: memory: "128Mi" --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: NodePort selector: app: nginx ports: - port: 80 targetPort: 80 |
Nginxデプロイ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
kubectl apply -f nginx-deployment.yaml --------------------------- deployment.apps/nginx-deployment created service/nginx-service created --------------------------- kubectl get deployment -o wide --------------------------- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47h <none> nginx-service NodePort 10.100.152.21 <none> 80:31594/TCP 19s app=nginx --------------------------- kubectl get pod -o wide --------------------------- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-5f58bc4c88-88l7k 1/1 Running 0 27m 10.244.37.10 k8s-worker-node-02-ubuntu <none> <none> nginx-deployment-5f58bc4c88-drk64 1/1 Running 0 27m 10.244.37.9 k8s-worker-node-02-ubuntu <none> <none> nginx-deployment-5f58bc4c88-nbvc6 1/1 Running 0 27m 10.244.244.72 k8s-worker-node-01-ubuntu <none> <none> --------------------------- kubectl get svc -o wide --------------------------- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47h <none> nginx-service NodePort 10.100.152.21 <none> 80:31594/TCP 19s app=nginx --------------------------- |
アクセス
http://192.168.13.102:31594にアクセス。

これでRaspberry Pi 4でKubernetesは完了です。よーやくスタートラインに立てた感じがします。
色々試したいことはありますが、まずは直近の目標としてService type:LoadBalancerを使いたいのでmetallbあたりを調べて適応しようかと思います。