Arch Linux に kubeadm で開発用 Kubernetes クラスタを構築してみる

# はじめに
最近お仕事で Kubernetes クラスタをぼちぼち触り始めました。そういうわけで手元にも開発用に Kubernetes クラスタがほしくなってくるわけですが、いつも使っているのは Arch Linux です。そこで、今回は Arch Linux に kubeadm を使って Master と Worker が同居する1台構成の Kubernetes クラスタを作る方法を紹介します。

# インストール前の準備
もちろん Arch Linux のインストールが必要ですが、下記の点によく注意してください。

## Swap の無効化
Swap が有効化されていると kubeadm は動かすことができません。最近マシンスペック向上のおかげで Swap を作る機会は減っているかもしれませんが、もし有効にしているのであれば無効化しておいてください。

## ファイルシステムについて
kubeadm では btrfs をサポートしていません。もし btrfs でディスクをフォーマットしてしまっていたら、ext4 で作り直す必要があります。要するに、クリーンインストールです......

## AUR について
今回紹介する方法は AUR にしか存在していないパッケージを利用します。AUR の利用を容易にするために AUR が扱えるパッケージマネージャー (yayなど) を導入しておくことをオススメします。

# Docker のインストール
何はともあれコンテナ基板として Docker をインストールします。

## Docker パッケージのインストール
ひとまずリポジトリからインストールして、sudo コマンドなしでも動くように設定しておきます。`usermod` コマンドを実行したら一度ログアウトして再ログインします。

```bash
$ yay -S docker
$ sudo usermod -a -G docker ${USER}
```

## 設定の変更
`/etc/docker/daemon.json` ファイルを新規生成して、以下の内容を書き込んでください。特にストレージドライバの設定は重要です。

```bash
$ sudo mkdir /etc/docker
$ sudo vim /etc/docker/daemon.json
```

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

## Docker デーモンの起動
あとはさっくりと systemd で Docker デーモンを起動しておきましょう。

```bash
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now docker
```

# Kubernetes のインストール
さて、準備が済んだのでいよいよ Kubernetes をインストールしていきます。

## 必要なパッケージの導入
Kubernetes そのものの動作や操作に必要な `kubectl` `kubelet` `kubeadm` を AUR からインストールします。また、後ほどクラスタ内ネットワークの構築に必要となる `cni-plugins` もここで入れておきます。

```bash
$ yay -S kubectl-bin kubelet-bin kubeadm-bin cni-plugins-bin
```

また、Kubernetes が必要とするネットワーク関連のパッケージを追加でインストールしてください。

```bash
$ yay -S ethtool ebtables socat conntrack-tools
```

## kubelet の起動
ここまで終わったら kubelet を起動する設定を有効化します。

```bash
$ sudo systemctl enable --now kubelet
```

## Master node の初期化
いよいよ Master node を初期化して、動作できるようにします。下記コマンドを流し込んで数分待つとできあがりです。なお `pod-network-cidr` に渡している IP アドレスですが、後ほど flannel (内部ネットワーク) を有効化する際に必要なものです。また、flannel のドキュメントによるとこの IP アドレスで固定されているようですので、他のものに変えたりはしないでください。

```bash
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
```

構築が終わったら表示されたコマンドを使って管理者として `kubectl` コマンドを実行できるようにしていきます。

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

最後に Master node にコンテナを建てられるように設定を変更します。通常はセキュリティ面から Master node にユーザーがコンテナを建てることはできませんが、今回は手元開発用の1台構成ですので、それを許可するようにしておきます。もちろん、本番環境で使う Master node ではこの設定を有効にしないでください。

```bash
$ kubectl taint nodes --all node-role.kubernetes.io/master-
```

## Flannel のインストール
クラスタ内部ネットワークを構築するため Flannel をインストールします。以下のコマンドを流し込んでください。

```bash
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
```

## 動作テスト
Nginx のコンテナを建てて、クラスタが動作しているかどうか確認してみましょう。適当なディレクトリに `nginx.yaml` を下記の内容で用意してください。

```bash
$ vim nginx.yaml
```

yamlファイルの中身をざっくり説明すると、Nginx のコンテナを2個立てて、8080番ポートを露出させるという設定になっています。

```yaml:nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - name: nginx
      port: 8080
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
```

ファイルが書けたらクラスタにデプロイしてみましょう。

```bash
$ kubectl apply -f nginx.yaml
```

数分待って Pod と Service の一覧を取得します。定義通り Nginx のコンテナが2つ `READY` 状態になっており、 `service/nginx` ができあがっていることが確認できます。

```shell-session
$ kubectl get pods,services
NAME                        READY   STATUS    RESTARTS   AGE
pod/nginx-d46f5678b-sm685   1/1     Running   0          3m18s
pod/nginx-d46f5678b-whdbn   1/1     Running   0          3m18s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP          15m
service/nginx        LoadBalancer   10.111.243.255   <pending>     8080:30044/TCP   4m14s
```

Nginx にアクセスしたいときは `localhost` から `PORT(S)` 欄の右側に表示されている方のポート（今回であれば30044）にアクセスしてあげると繋がります。ここまで確認できればOKです。

```bash
$ curl http://localhost:30044/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<!-- 後略 -->
```

# おわりに
この記事では Arch Linux に kubeadm を使って Kubernetes クラスタを構築する方法を紹介してきました。kubeadm を使えばこうして簡単に開発用のクラスタも構築できます。また、公式ドキュメントではサポートされていない Arch Linux でも以外と平気で動かせてしまうということも明らかになりました。皆さんもぜひご自分の Arch Linux 環境に Kubernetes 開発環境を用意して快適な開発者生活を送ってください。