27
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

こちらはAWS Containers Advent Calendar 2020の20日目の記事です。
本記事は個人の意見であり、所属する組織の見解とは関係ありません。

1年半程前、私もラズパイでKubernetesクラスタを作成しました。

pi-k8s.jpg

使用したのは3台のRaspberry Pi 3 Model B+で、その頃のKubernetesのバージョンは1.13でした。このラズパイクラスタはその後ほとんど活用されていないので、今回はこのラズパイクラスタでEKS Distroを動かしてみたいと思います。

EKS Distroとは何か、についてはFAQがわかりやすいです。日本語です。

方針

公式ドキュメントにはkopsを使ったデプロイ手順があります。パートナーがそれぞれのサービスのKubernetesクラスターでEKS Distroを使う方法を用意しています。例えば、CanonicalのSnapパッケージを使うと簡単にラズパイでもEKS Distroが動くようです。これはMicroK8sのKubernetes部分をEKS Distroに置き換えているようです。

Snapではなくkubeadmを使った手順を探していたところ、同僚に以下のブログ記事を教えてもらいました。

今回はこのブログ記事を参考にして、ラズパイに「kubeadm」で「EKS Distro」をデプロイし、「ラズパイEKSクラスタ」を作成したいと思います。ブログ記事ではコントロールプレーンを冗長化していますが、私はシングルコントロールプレーンのクラスターを作成します。

ラズパイクラスタの準備

実は最初、以前作成したラズパイクラスタを流用し、一度Dockerやらkubeadmやらを削除してきれいにした上で、EKS Distroをデプロイしようとしました。しかし私のラズパイは32bitのarmv7互換のOSで動いており、一方、EKS Distroのバイナリやイメージはarm64版しか提供されていないため失敗しました。

頑張れば自分でarmv7版のバイナリとイメージをビルドすることも可能かもしれませんが、OSを64bit版に入れ替える方が簡単そうなので、OSを入れ替えました。しかし、64bit OSはメモリー消費量が多いのか、あるいは以前よりKubernetesのバージョンが上がってメモリー消費量が多くなったのか、メモリーが1GBしかないRaspberry Pi 3 Model B+ではkubeadm initを実行するとハングしてしまうという自体に陥りました。

結局、Raspberry Pi 4 Model B (4GB RAM)を追加で購入し、Masterノードとして利用することにしました。

したがって、新しいラズパイ4Bと既存のラズパイ3B+に64bit版のOSを入れるところからはじめます。RaspbianはRaspberry Pi OSに名前が変わったのですね。64bit版はまだbetaテスト版で、以下にイメージがあります。

Ubuntuも64bit版があるようです。

今回はRaspberry Pi OSの64bit版を使うことにします。イメージをSDカードに焼くツールは、今回はRaspberry Pi Imagerを使いました。とても簡単です。

ラズパイクラスタの基本的なセットアップについては、以下の以前の記事を参照下さい。

こちらの記事にしたがって、SSHログインができるところまで進めて下さい。

なお、以前の記事ではクラスターの上部に配置した小型のWiFiルーターを使って上流のWiFiネットワークに接続する構成で、ラズパイのIPアドレスは192.11.13.101192.11.13.103でした。しかしこの構成だと小型のWiFiルーターの速度が遅いので、今回は家庭内LANに有線で直接繋がるようにしています。ラズパイのIPアドレスは192.11.11.101192.11.11.104です。

ホスト名 IPアドレス 役割 ハードウェア メモリー
k8s-master 192.168.11.101 Master Raspberry Pi 4 Model B 4GB
k8s-node1 192.168.11.102 Worker Raspberry Pi 3 Model B+ 1GB
k8s-node2 192.168.11.103 Worker Raspberry Pi 3 Model B+ 1GB
k8s-node3 192.168.11.104 Worker Raspberry Pi 3 Model B+ 1GB

手順

では、ここからクラスターの作成に取りかかります。

cgroupの有効化

起動する前にSDカードの中のcmdline.txtを編集しなかった場合は、/boot/cmdline.txtを編集して行の末尾にcgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1を追加して再起動します。

/boot/cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=af570baa-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

/proc/cgroupsを確認してenabledの列が1になっていればOKです。

pi@k8s-master:~ $ cat /proc/cgroups
#subsys_name	hierarchy	num_cgroups	enabled
cpuset	6	1	1
cpu	7	1	1
cpuacct	7	1	1
blkio	2	1	1
memory	9	92	1
devices	4	77	1
freezer	8	1	1
net_cls	3	1	1
perf_event	5	1	1
net_prio	3	1	1
pids	10	85	1

スワップの無効化

スワップを無効化しておきます。

sudo dphys-swapfile swapoff
sudo systemctl stop dphys-swapfile
sudo systemctl disable dphys-swapfile

freeコマンドでスワップが使われていないことを確認します。

pi@k8s-master:~ $ free
              total        used        free      shared  buff/cache   available
Mem:         934532      248860      265572        7636      420100      615608
Swap:             0           0           0

Dockerのインストール

convenience scriptを使ってインストールします。

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
コマンド出力
pi@k8s-master:~ $ sudo sh get-docker.sh
# Executing docker install script, commit: 3d8fe77c2c46c5b7571f94b42793905e5b3e42e4
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=arm64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ [ -n  ]
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sh -c docker version
Client: Docker Engine - Community
 Version:           20.10.1
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        831ebea
 Built:             Tue Dec 15 04:35:39 2020
 OS/Arch:           linux/arm64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.1
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       f001486
  Built:            Tue Dec 15 04:33:40 2020
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.4.3
  GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
 runc:
  Version:          1.0.0-rc92
  GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker your-user

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
         containers which can be used to obtain root privileges on the
         docker host.
         Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
         for more information.

20.10はまだKubernetesではサポートされていないバージョンであるため、19.03にダウングレードします。

まず利用可能なバージョンを確認します。

pi@k8s-master:~ $ apt-cache madison docker-ce
 docker-ce | 5:20.10.1~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:20.10.0~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.14~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.13~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.12~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.11~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.10~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.9~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.8~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.7~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.6~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.5~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.4~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.3~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.2~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.1~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:19.03.0~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.9~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.8~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.7~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.6~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.5~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.4~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.3~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.2~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.1~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 5:18.09.0~3-0~debian-buster | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 18.06.3~ce~3-0~debian | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 18.06.2~ce~3-0~debian | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 18.06.1~ce~3-0~debian | https://download.docker.com/linux/debian buster/stable arm64 Packages
 docker-ce | 18.06.0~ce~3-0~debian | https://download.docker.com/linux/debian buster/stable arm64 Packages

ダウングレードします。

sudo apt-get install -y --allow-downgrades --no-install-recommends \
    docker-ce=5:19.03.14~3-0~debian-buster \
    docker-ce-cli=5:19.03.14~3-0~debian-buster

バージョンは固定しておきます。

sudo apt-mark hold docker-ce docker-ce-cli

piユーザーでもdockerコマンドを実行できるようにしておきます。

sudo usermod -aG docker pi

ここからはrootユーザーで作業します。

sudo -i

Dockerのcgroupドライバーを確認します。

root@k8s-master:~# docker info | grep -i cgroup
 Cgroup Driver: cgroupfs
WARNING: No swap limit support
WARNING: No blkio weight support
WARNING: No blkio weight_device support

Kubernetesのドキュメントにしたがって、Dockerのcgroupドライバーをsystemdに変更します。log-driverとstorage-driverは既にこの指定の通りになっていますが、明示的に指定しておきます。

cat <<EOF > /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

Dockerを再起動します。

systemctl daemon-reload
systemctl restart docker

Dockerのcgroupドライバーがsystemdになったことを確認します。

root@k8s-master:~# docker info | grep -i cgroup
 Cgroup Driver: systemd
WARNING: No swap limit support

kubeadm(EKS Distro版)のインストール

rootユーザーで作業します。

kubeadmはapt-getではなくバイナリを直接ダウンロードします。まず以下のリンクに記載のkubeadmの前提条件を確認します。

iptablesがブリッジを通過するトラフィックを処理できるようにするため、net.bridge.bridge-nf-call-iptables1に設定します。この時点で既に1に設定されていますが、念のため明示的に設定します。

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

iptablesがnftablesをバックエンドに使用しないようにします。レガシーバージョンをインストールします。

apt-get install -y iptables arptables ebtables

レガシーバージョンに切り替えます。

update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
update-alternatives --set arptables /usr/sbin/arptables-legacy
update-alternatives --set ebtables /usr/sbin/ebtables-legacy

変更を反映するため、念のためここでラズパイを再起動します。

reboot

EKS DistroのリポジトリからCNIプラグインをダウンロードしてインストールします。

mkdir -p /opt/cni/bin
wget https://distro.eks.amazonaws.com/kubernetes-1-18/releases/1/artifacts/plugins/v0.8.7/cni-plugins-linux-arm64-v0.8.7.tar.gz
tar zxf cni-plugins-linux-arm64-v0.8.7.tar.gz -C /opt/cni/bin/

EKS Distroのリポジトリからkubeadm、kubelet、kubectlをダウンロードしてインストールします。

wget https://distro.eks.amazonaws.com/kubernetes-1-18/releases/1/artifacts/kubernetes/v1.18.9/bin/linux/arm64/kubeadm
wget https://distro.eks.amazonaws.com/kubernetes-1-18/releases/1/artifacts/kubernetes/v1.18.9/bin/linux/arm64/kubelet
wget https://distro.eks.amazonaws.com/kubernetes-1-18/releases/1/artifacts/kubernetes/v1.18.9/bin/linux/arm64/kubectl
mv kubeadm kubelet kubectl /usr/bin/
chmod +x /usr/bin/kubeadm /usr/bin/kubelet /usr/bin/kubectl

kubeletが必要とするパッケージをインストールします。

apt-get install -y conntrack ebtables socat

kubeletに引数を渡して、cgroupドライバーをsystemdに変更します。Dockerが使用するcgroupドライバーと一致する必要があります。参考にしているブログはCentOSなので、Debian(Raspberry Pi OS)とはファイルの配置場所が違うところに注意が必要です。

cat <<EOF > /etc/default/kubelet
KUBELET_EXTRA_ARGS='--cgroup-driver=systemd'
EOF

kubeadmとkubeletが使用するディレクトリを作成します。

mkdir -p /etc/kubernetes/manifests
mkdir -p /etc/systemd/system/kubelet.service.d

ブログ記事と以下のリンクも参考にしながら、kubeadmの設定ファイルとkubeletのユニット定義ファイルを作成します。

cat <<EOF > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet \$KUBELET_KUBECONFIG_ARGS \$KUBELET_CONFIG_ARGS \$KUBELET_KUBEADM_ARGS \$KUBELET_EXTRA_ARGS
EOF
cat <<EOF > /lib/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

システム起動時にkubeletが起動するようにします。

systemctl enable kubelet

Kubernetesコンポーネント(EKS Distro版)のダウンロード

コントロールプレーンに必要なDockerイメージをAmazon ECR Publicからpullします。

docker pull public.ecr.aws/eks-distro/etcd-io/etcd:v3.4.14-eks-1-18-1
docker pull public.ecr.aws/eks-distro/kubernetes/pause:v1.18.9-eks-1-18-1
docker pull public.ecr.aws/eks-distro/kubernetes/kube-scheduler:v1.18.9-eks-1-18-1
docker pull public.ecr.aws/eks-distro/kubernetes/kube-proxy:v1.18.9-eks-1-18-1
docker pull public.ecr.aws/eks-distro/kubernetes/kube-apiserver:v1.18.9-eks-1-18-1
docker pull public.ecr.aws/eks-distro/kubernetes/kube-controller-manager:v1.18.9-eks-1-18-1
docker pull public.ecr.aws/eks-distro/coredns/coredns:v1.7.0-eks-1-18-1

kubeadmにハードコードされた値に合わせる必要があるため、イメージに追加のタグを付与します。

docker tag public.ecr.aws/eks-distro/kubernetes/pause:v1.18.9-eks-1-18-1 public.ecr.aws/eks-distro/kubernetes/pause:3.2
docker tag public.ecr.aws/eks-distro/coredns/coredns:v1.7.0-eks-1-18-1 public.ecr.aws/eks-distro/kubernetes/coredns:1.6.7

イメージを確認します。

root@k8s-master:~# docker images
REPOSITORY                                                     TAG                  IMAGE ID       CREATED       SIZE
public.ecr.aws/eks-distro/kubernetes/pause                     3.2                  430398c8f74c   2 weeks ago   630kB
public.ecr.aws/eks-distro/kubernetes/pause                     v1.18.9-eks-1-18-1   430398c8f74c   2 weeks ago   630kB
public.ecr.aws/eks-distro/kubernetes/kube-proxy                v1.18.9-eks-1-18-1   0ff76167f898   2 weeks ago   579MB
public.ecr.aws/eks-distro/kubernetes/kube-scheduler            v1.18.9-eks-1-18-1   2f471234bdca   2 weeks ago   479MB
public.ecr.aws/eks-distro/kubernetes/kube-controller-manager   v1.18.9-eks-1-18-1   2c01694a0619   2 weeks ago   543MB
public.ecr.aws/eks-distro/kubernetes/kube-apiserver            v1.18.9-eks-1-18-1   94f388827354   2 weeks ago   553MB
public.ecr.aws/eks-distro/etcd-io/etcd                         v3.4.14-eks-1-18-1   61b76a81855c   2 weeks ago   473MB
public.ecr.aws/eks-distro/coredns/coredns                      v1.7.0-eks-1-18-1    c04916f93277   2 weeks ago   44.4MB
public.ecr.aws/eks-distro/kubernetes/coredns                   1.6.7                c04916f93277   2 weeks ago   44.4MB

etcdのイメージはこのIssueと同じエラーで起動しないため、ETCD_UNSUPPORTED_ARCH=arm64という環境変数を渡す必要があります。kubeadmの設定オプションで環境変数を渡すことができなそうだったため、環境変数を追加したイメージをビルドします。

Dockerfileを作成します。

cat <<EOF > Dockerfile
FROM public.ecr.aws/eks-distro/etcd-io/etcd:v3.4.14-eks-1-18-1
ENV ETCD_UNSUPPORTED_ARCH=arm64
EOF

イメージをビルドします。

docker build -t public.ecr.aws/eks-distro/etcd-io/etcd:v3.4.14-eks-1-18-1 .

イメージを確認します。

oot@k8s-master:~# docker images
REPOSITORY                                                     TAG                  IMAGE ID       CREATED         SIZE
public.ecr.aws/eks-distro/etcd-io/etcd                         v3.4.14-eks-1-18-1   bcc9e6b4e4d4   4 seconds ago   473MB
public.ecr.aws/eks-distro/kubernetes/pause                     3.2                  430398c8f74c   2 weeks ago     630kB
public.ecr.aws/eks-distro/kubernetes/pause                     v1.18.9-eks-1-18-1   430398c8f74c   2 weeks ago     630kB
public.ecr.aws/eks-distro/kubernetes/kube-proxy                v1.18.9-eks-1-18-1   0ff76167f898   2 weeks ago     579MB
public.ecr.aws/eks-distro/kubernetes/kube-scheduler            v1.18.9-eks-1-18-1   2f471234bdca   2 weeks ago     479MB
public.ecr.aws/eks-distro/kubernetes/kube-controller-manager   v1.18.9-eks-1-18-1   2c01694a0619   2 weeks ago     543MB
public.ecr.aws/eks-distro/kubernetes/kube-apiserver            v1.18.9-eks-1-18-1   94f388827354   2 weeks ago     553MB
public.ecr.aws/eks-distro/etcd-io/etcd                         <none>               61b76a81855c   2 weeks ago     473MB
public.ecr.aws/eks-distro/kubernetes/coredns                   1.6.7                c04916f93277   2 weeks ago     44.4MB
public.ecr.aws/eks-distro/coredns/coredns                      v1.7.0-eks-1-18-1    c04916f93277   2 weeks ago     44.4MB

ここまでの操作は全てのラズパイに対して行います。

Masterノードの初期化

以下のリンクにしたがってクラスターを作成します。

Masterノード上でkubeadmの構成ファイルを作成します。Kubernetesの各コンポーネントの取得元のイメージリポジトリとして、EKS Distroのリポジトリを指定しています。PodネットワークアドオンはFlannelを使う想定でPodネットワークのCIDRを指定しています。Calicoだと我が家のLANのCIDRと被ってしまうためFlannelを選択しています。

cat <<EOF > kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
networking:
  podSubnet: "10.244.0.0/16"
etcd:
  local:
    imageRepository: public.ecr.aws/eks-distro/etcd-io
    imageTag: v3.4.14-eks-1-18-1
    extraArgs:
      listen-peer-urls: "https://0.0.0.0:2380"
      listen-client-urls: "https://0.0.0.0:2379"
imageRepository: public.ecr.aws/eks-distro/kubernetes
kubernetesVersion: v1.18.9-eks-1-18-1
EOF

このファイルを指定してkubeadm initを実行します。

kubeadm init --config kubeadm-config.yaml
コマンド出力
root@k8s-master:~# kubeadm init --config kubeadm-config.yaml
W1219 02:15:50.059301    1349 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.18.9-eks-1-18-1
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.11.101]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-master localhost] and IPs [192.168.11.101 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-master localhost] and IPs [192.168.11.101 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W1219 02:16:09.651280    1349 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W1219 02:16:09.655043    1349 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 39.519892 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.18" in namespace kube-system with the configuration for the kubelets in the cluster
[kubelet-check] Initial timeout of 40s passed.
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: v4aezo.0qqsig2csphtm5dj
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[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

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.11.101:6443 --token v4aezo.0qqsig2csphtm5dj \
    --discovery-token-ca-cert-hash sha256:04da2245c17641aec3cec1edc74e0ae88c7411573cc287a920c42ebba9a5c4e8

出力の最後にあるkubeadm joinコマンドを後で使います。

一般ユーザーに戻って、kubeconfigを設定します。

exit
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ですが、VERSIONはEKSっぽいバージョンになっていますね!

pi@k8s-master:~ $ kubectl get node
NAME         STATUS     ROLES    AGE    VERSION
k8s-master   NotReady   master   2m3s   v1.18.9-eks-1-18-1

Podネットワークアドオンのインストール

PodネットワークアドオンとしてFlannelをインストールします。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml

しばらくするとノードがReadyになります。

pi@k8s-master:~ $ kubectl get node
NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   4m27s   v1.18.9-eks-1-18-1

コマンドの補完とkのエイリアスを有効にしておきます(オプション)。

sudo apt-get install -y bash-completion
cat <<EOT >> ~/.bashrc

alias k="kubectl"
source <(kubectl completion bash)
complete -o default -F __start_kubectl k
EOT
source ~/.bashrc

Workerノードの追加

全てのWorkerノード上で、先ほどMasterノードでkubeadm initを実行した際に出力されていたkubeadm joinコマンドをrootユーザーで実行します。

root@k8s-node3:~# kubeadm join 192.168.11.101:6443 --token v4aezo.0qqsig2csphtm5dj \
>     --discovery-token-ca-cert-hash sha256:04da2245c17641aec3cec1edc74e0ae88c7411573cc287a920c42ebba9a5c4e8
W1219 02:22:56.373017    2477 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.

Masterノード上で、ノードが追加されReadyとなっていることを確認します。

pi@k8s-master:~ $ kubectl get node -o wide
NAME         STATUS   ROLES    AGE     VERSION              INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION   CONTAINER-RUNTIME
k8s-master   Ready    master   7m33s   v1.18.9-eks-1-18-1   192.168.11.101   <none>        Debian GNU/Linux 10 (buster)   5.4.79-v8+       docker://19.3.14
k8s-node1    Ready    <none>   66s     v1.18.9-eks-1-18-1   192.168.11.102   <none>        Debian GNU/Linux 10 (buster)   5.4.79-v8+       docker://19.3.14
k8s-node2    Ready    <none>   60s     v1.18.9-eks-1-18-1   192.168.11.103   <none>        Debian GNU/Linux 10 (buster)   5.4.79-v8+       docker://19.3.14
k8s-node3    Ready    <none>   55s     v1.18.9-eks-1-18-1   192.168.11.104   <none>        Debian GNU/Linux 10 (buster)   5.4.79-v8+       docker://19.3.14

全てのPodがRunningであることを確認します。

pi@k8s-master:~ $ kubectl get pod -A -o wide
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES
kube-system   coredns-8f7b4cf65-f4dhv              1/1     Running   0          7m40s   10.244.0.2       k8s-master   <none>           <none>
kube-system   coredns-8f7b4cf65-lgg6d              1/1     Running   0          7m40s   10.244.0.3       k8s-master   <none>           <none>
kube-system   etcd-k8s-master                      1/1     Running   0          7m46s   192.168.11.101   k8s-master   <none>           <none>
kube-system   kube-apiserver-k8s-master            1/1     Running   0          7m46s   192.168.11.101   k8s-master   <none>           <none>
kube-system   kube-controller-manager-k8s-master   1/1     Running   0          7m46s   192.168.11.101   k8s-master   <none>           <none>
kube-system   kube-flannel-ds-arm64-cfdxg          1/1     Running   0          87s     192.168.11.103   k8s-node2    <none>           <none>
kube-system   kube-flannel-ds-arm64-d7hgj          1/1     Running   0          93s     192.168.11.102   k8s-node1    <none>           <none>
kube-system   kube-flannel-ds-arm64-frcl2          1/1     Running   0          82s     192.168.11.104   k8s-node3    <none>           <none>
kube-system   kube-flannel-ds-arm64-md7gh          1/1     Running   0          3m44s   192.168.11.101   k8s-master   <none>           <none>
kube-system   kube-proxy-fcbm2                     1/1     Running   0          93s     192.168.11.102   k8s-node1    <none>           <none>
kube-system   kube-proxy-lgvw2                     1/1     Running   0          87s     192.168.11.103   k8s-node2    <none>           <none>
kube-system   kube-proxy-sbh7v                     1/1     Running   0          7m40s   192.168.11.101   k8s-master   <none>           <none>
kube-system   kube-proxy-vpgkg                     1/1     Running   0          82s     192.168.11.104   k8s-node3    <none>           <none>
kube-system   kube-scheduler-k8s-master            1/1     Running   0          7m46s   192.168.11.101   k8s-master   <none>           <none>

稼働確認

NginxをデプロイしてNodePortで公開し、クラスターが機能していることを確認しましょう。

NginxのDeploymentを作成します。

pi@k8s-master:~ $ kubectl create deployment nginx --image=nginx
deployment.apps/nginx created

DeploymentをNodePortタイプのServiceとして公開します。

pi@k8s-master:~ $ kubectl expose deployment nginx --type NodePort --port 80
service/nginx exposed

ServiceのNodePortを確認します。

pi@k8s-master:~ $ kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        10m
nginx        NodePort    10.105.150.24   <none>        80:31972/TCP   6s

ラズパイではなく手元のマシンから、いずれかのノードのIPアドレス(192.168.11.101192.168.11.104)のNodePort(上記出力の31972ポート)にアクセスして確認しましょう。

$ curl 192.168.11.103:31972
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

無事にNginxにアクセスできました。以上でラズパイEKSクラスタは完成です!

補足

クラスターの作成に失敗したり上手く動かない場合に、やり直すときは以下の手順で行います。

Masterノードでノードを削除します。

kubectl delete node k8s-node1
kubectl delete node k8s-node2
kubectl delete node k8s-node3

kubeconfigを削除します。

rm -rf $HOME/.kube

全てのノード上で、rootユーザーでkubeadm resetコマンドを実行します。

kubeadm reset -f

全てのノードを再起動します。再起動しないと、iptablesのルールや、CNIプラグインが作成したネットワークインターフェースが残っていて、クラスターを再作成した際にハマります。再起動後、以下のコマンドで不要なiptablesルールや、flannel.1cni0といったネットワークインターフェースが残っていないことを確認して下さい。

ip a
iptables -L

CNIプラグインをCalicoからFlannelに変更した場合など、以下のディレクトリ配下に設定ファイルが残っていてハマることがあるので、不要なファイルは削除して下さい。

rm -rf /etc/cni/net.d/*

参考リンク

27
24
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
27
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?