Raspberrypi 上に Kubernetes クラスタを構築した話 その１


## 準備
![IMG_9471[8].jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177247/c9effb3f-1388-263f-03af-45339b0b9fc3.jpeg)

+ Raspberrypi x3
+ MicroSDカード x3
+ PoE Hat x3 
+ PoEスイッチ

PoE関係は配線を少なくするために利用しました。
【6/21 追記】Buster を利用した構築手順に順次書き換えています。

## Raspbian Lite インストール
本項目は全Raspberrypiに対して実行します。

### OSインストール
[ここ](https://www.raspberrypi.org/downloads/raspbian/)からダウンロードしてMicroSDカードにインストールしてください。
【注意】新バージョンのBusterが出ていますが、自分は眠っていた RaspberryPi3 ModelB+ を使ったので古いRaspbian Liteを使っています。
おそらくBusterでも同様の手順で行けると思いますが、適宜読み替えてください。

### SSH 有効化
リモートで作業できるように、SSHを有効化します。
Raspbianでは/boot/の下にsshという名前のファイルもしくはディレクトリがある事で、起動時にSSHが有効化されます。

##### raspberrypi 起動後に実施する場合

```
sudo mkdir /boot/ssh
shutdown -r now
```

##### Windows上からbashを使って実施する場合。
<ドライブレター>は適宜読み替えること

```
sudo mount -t drvfs <ドライブレター>: /mnt/<ドライブレター>
mkdir -p /mnt/<ドライブレター>/ssh
sudo umount /mnt/<ドライブレター>
```

### cgroup 有効化

```
sudo sed -ie 's/rootfstype=ext4/rootfstype=ext4 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory/g' /boot/cmdline.txt
```

### WiFi & Bluetooth 無効化 (Raspberry pi 3 Model B+)
Kubernetes Cluster として使う場合、この2つは不要なので無効化します。

```
cat <<_EOF_ | sudo tee -a /boot/config.txt

[pi3]
# Disable WiFi and Bluetooth
dtoverlay=pi3-disable-wifi
dtoverlay=pi3-disable-bt
_EOF_
```

### OS update
まずはOSのアップデートから。

```
sudo apt update
sudo apt full-upgrade
sudo apt autoremove
sudo apt clean
```

### 作業に便利なツールのインストール
この辺は好みでインストールしてください。
自分はnanoよりvimの方が使いやすいので、vimを入れています。

```
sudo apt-get install -y vim
```

#### vimでウザいマウスの無効化

```
cat <<'_EOF_' | sudo tee /etc/vim/vimrc.local
" This file loads the default vim options at the beginning and prevents
" that they are being loaded again later. All other options that will be set,
" are added, or overwrite the default settings. Add as many options as you
" whish at the end of this file.

" Load the defaults
source $VIMRUNTIME/defaults.vim

" Prevent the defaults from being loaded again later, if the user doesn't
" have a local vimrc (~/.vimrc)
let skip_defaults_vim = 1


" Set more options (overwrites settings from /usr/share/vim/vim80/defaults.vim)
" Add as many options as you whish

" Set the mouse mode to 'r'
if has('mouse')
  set mouse=r
endif
_EOF_
```

### ホスト名の変更
この辺も好みで変えてください。
今回はKubernetesクラスタとして使うため、k8s-0〜2 と名前を付けました

```
sudo vim /etc/hostname
sudo vim /etc/hosts
```
以下は hosts の例になります。
Endpoint は Kubernetes Cluster を組む際に使うため、追加しています。
> 192.168.0.10 k8s-0.example.com k8s-0
> 192.168.0.11 k8s-1.example.com k8s-1
> 192.168.0.12 k8s-2.example.com k8s-2
> 192.168.0.10 k8s-endpoint.example.com k8s-endpoint


### IPアドレスの変更
固定IPアドレスにします。

```
sudo vim /etc/dhcpcd.conf
```

> interface eth0
> static ip_address=192.168.0.10/24
> static routers=192.168.0.1
> static domain_name_servers=8.8.8.8 4.4.4.4

### swap の無効化
~~この辺も好みですが、microSDカードを長持ちさせるために実行しています。~~
Kubernetes用に構築する場合、SWAP無効化は必須です。

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

### iptables-legacy への変更 (Buster+)
最近の Debian 系では iptables のラッパーとして ufw を利用しています。
ですが、Dockerではこれを利用できません。
Podどうしが通信ができなくなる為、iptables-legacy へ変更します。
正直な話、Rasupbian BusterやUbuntuでKubernetesを組むにあたり、これに一番ハマりました。

```
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
```

### 再起動
変更を有効化するために、再起動を実施します。

```
sudo shutdown -r now
```

## Kubernetes インストール
本項目は全Raspberrypiに対して実行します。

### Docker インストール

##### 最新版のインストール
ただ最新版をインストールするだけであれば、次のコマンドで問題ありません。

```
sudo apt -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common
curl -sSL https://get.docker.com | sh
```

##### バージョンを指定してインストール (example: 5:19.03.11~3-0~raspbian-buster)
Docker のバージョンを指定してインストールする必要がある場合があります。
その場合は、次の手順でインストールします。

```
sudo apt -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common
curl -fsSL https://download.docker.com/linux/raspbian/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
cat <<_EOF_ | sudo tee /etc/apt/sources.list.d/docker.list
deb [arch=armhf] https://download.docker.com/linux/raspbian $(lsb_release -cs) stable
_EOF_
sudo apt update
sudo apt -y install \
    docker-ce=5:19.03.11~3-0~raspbian-buster \
    docker-ce-cli=5:19.03.11~3-0~raspbian-buster \
    containerd.io
```

###### バージョンの調査方法
```
sudo apt-cache madison docker-ce
```

> docker-ce | 5:19.03.11~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.10~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.9~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.8~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.7~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.6~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.5~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.4~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.3~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.2~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages
> docker-ce | 5:19.03.1~3-0~raspbian-buster | https://download.docker.com/linux/raspbian buster/stable armhf Packages


##### Docker インストール後の設定
```
sudo apt-mark hold docker-ce docker-ce-cli

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_
sudo mkdir -p /etc/systemd/system/docker.service.d
# sudo usermod -aG docker zabbix # Required if monitoring with Zabbix.
sudo usermod -aG docker pi
sudo systemctl daemon-reload
sudo systemctl restart docker.service
```



Kubernetes は前提となるDockerの[バージョンの指定](https://kubernetes.io/docs/setup/production-environment/)があります。

```
docker -v
```
> Docker version 19.03.8, build afacb8b

19.03.8 であれば問題ありません。
2020/06/15 追記: 対応バージョンが上がっており、19.03.11(最新版)でも大丈夫です。

### kubelet kubeadm kubectl インストール

```
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-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
kubeadm version -o yaml
```
> clientVersion:
  buildDate: "YYYY-MM-DDTHH:MM:SSZ"
  compiler: gc
  gitCommit: 52c56ce7a8272c798dbc29846288d7cd9fbae032
  gitTreeState: clean
  gitVersion: v1.18.2
  goVersion: go1.13.9
  major: "1"
  minor: "18"
  platform: linux/arm

## クラスター作成
本項目はマスターノード（自分の場合はk8s-0）で行うものとメンバーノード（自分の場合はk8s-1,k8s-2）で行うものがあります。

### クラスターの作成
マスターノードで実行します。

#### iptables の確認

```
cat /proc/sys/net/bridge/bridge-nf-call-iptables
```
> 1

1が返ってくれば問題ありません

#### マスターサーバの初期化

```
sudo kubeadm init --control-plane-endpoint=k8s-endpoint --pod-network-cidr=10.244.0.0/16
```
> kubeadm join <IPアドレス>:6443 --token xxxxxx.xxxxxx \
    --discovery-token-ca-cert-hash sha256:xxxxxxxxx

PODネットワークのCIDRは `10.244.0.0/16` を指定します。これは今回 Pod Network にFlannelを使うためです。
Flannelを使わない場合（例えばWeave Netを使うなど）は、CIDRの指定は不要です。
ここで出力したものは後で使いますから、メモしておいてください。

#### 作業ユーザに対するコンフィグファイルの適用

```
mkdir -p ~/.kube
sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
```

#### マスターサーバの確認

```
kubectl get nodes
```
> NAME    STATUS     ROLES    AGE     VERSION
> k8s-0   NotReady   master   3m16s   v1.18.2

#### kubectlコマンドの自動補完設定

```
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
```

#### Pod Network のインストール
ここではFlannelを使って仮想ネットワークを構築します。

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

### クラスターへの参加
各メンバーノードで実行します。

```
sudo kubeadm join <IPアドレス>:6443 --token xxxxxx.xxxxxx \
   --discovery-token-ca-cert-hash sha256:xxxxxxxxxx
```
ここで指定するIPアドレスやトークン、ハッシュキーは[ここ](#マスターサーバの初期化)で出力されたものになります。

### クラスターの確認
マスターサーバで実行します。

```
kubectl get nodes
```
> NAME    STATUS   ROLES    AGE     VERSION
> k8s-0   Ready    master   16m     v1.18.2
> k8s-1   Ready    \<none>   3m11s   v1.18.2
> k8s-2   Ready    \<none>   2m5s    v1.18.2

長くなったので、その１はここまで。
次は[metrics-server](https://github.com/kubernetes-sigs/metrics-server)や[kubernetes-dashboard](https://github.com/kubernetes/dashboard)をインストールします。