とりあえずkubeadm試してみたい人向けハンズオン

# Abstract
ちょっとk8s環境構築を体験してみたいけど、そのためだけに複数vps借りたりするのはハードルが高いな、という人のためにUbuntu上でvm立ててプライベートネットワークのみからアクセスできるk8sクラスタ構築ハンズオンを作ってみました。

# 注意
記事中のenp4s0はあなたの環境の物理NICの名前で読み替えてください。

# 環境
OS: Ubuntu 20.04

# ネットワーク図

<img width="960" alt="network.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663506/d3a7b042-7d61-058e-2eab-d345eeb33dd1.png">


# 手順

1. [ubuntuのdocumentation][1]に従ってkvmをインストール
2. kvmのvmとホスト間をブリッジ接続にする
3. vmを2つ作成する(一つはmaster, もう一つはworker用)
4. masterにkubernetesを導入
5. workerにkubernetesを導入

## kvmのvmとホスト間をブリッジ接続にする
以下は[ここ][2]の内容ママです。

まずはパフォーマンス上の理由からnetfilterを無効にします。
/etc/sysctl.d/bridge.confを次の内容で作成:

```
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0
```

さらに、/etc/udev/rules.d/99-bridge.rulesを次の内容で作成:

```
ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/sbin/sysctl -p /etc/sysctl.d/bridge.conf"
```

設定を有効にするためにここでいったん再起動が必要です。

次にkvmのインストール時に勝手に作られたnetwork interfaceを削除します。```ip link```コマンドで確認すると```virbr0```と```virbr0-nic```というinterfaceが確認できるので、これらを削除します。

```
virsh net-destroy default
virsh net-undefine default
```

再度```ip link```を実行すると削除されていることが確認できるはずです。

次に仮想ブリッジのセットアップをします。こういう時新しいubuntuだと基本的にnetplanでやることになります。
```/etc/netplan/```内のどのファイルよりも辞書順で後ろに来るであろうファイル名で設定ファイルを作ります。ここでは```99_config.yaml```とすることにします。内容は次の通り:

```
network:
  ethernets:
    enp4s0:
      dhcp4: false
      dhcp6: false
  bridges:
    br0:
      interfaces: [ enp4s0 ]
      addresses: [ 192.168.100.225/24 ]
      gateway4: 192.168.100.1
      mtu: 1500
      nameservers:
        addresses: [ 8.8.8.8 ]
      parameters:
        stp: true
        forward-delay: 4
      dhcp4: false
      dhcp6: false
  version: 2
```

作り終えたら```sudo netplan apply```を実行してください。
タイポなどがあるとエラーメッセージが出ます。
うまくできていればipコマンドでbr0が作られていることが確認できるはずです。

次に、kvmの方にこのブリッジの存在を教えてあげる必要があります。適当な場所に```host-bridge.xml```を次の内容で作成してください。

```
<network>
  <name>host-bridge</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>
```

次のコマンドを実行しましょう。

```
virsh net-define host-bridge.xml
virsh net-start host-bridge
virsh net-autostart host-bridge
```

反映までにすこし時間がかかりますが、しばらくまつと```virsh net-list --all```コマンドで先ほど作成した```host-bridge```が確認できるようになります。


## vmを2つ作成する(一つはmaster, もう一つはworker用)

まず、VMの作成前に念のためPCのメモリサイズとhddの空き容量を確認します。

```
~/temp$ free
              total        used        free      shared  buff/cache   available
Mem:        8094608     1500404     4875980      103292     1718224     6183576
Swap:       2097148           0     2097148

~/temp$ df -BG /usr
Filesystem     1G-blocks  Used Available Use% Mounted on
/dev/sdb2           916G  243G      626G  28% /
```

ここではメモリが約8G, hddの空きがざっくり600Gくらいのようです。kubernetesはメモリが2GB以上必要なようなので試しにそれぞれ3GBで２つvmを作ってみることにします。

[参考にしたサイト][2]だとコンソール上から```virt-install```を利用してネットワーク上からisoを引っ張ってきているのですが、どうもうまくいかなかったのでvirt-managerを入れてGUIで導入しました。vmの設定は以下の通り、

OS: ubuntu20.04
CPU: 2
ram: 3072MB
disk size: 25GB

それぞれ、vmaster, vworkerと名付けました。ipアドレスはそれぞれ固定で192.168.100.256, 192.168.100.257を割り当てました。

vmが作成できたら、```ip link```からNICのMACアドレスを、```cat /sys/class/dmi/id/product_uuid```からプロダクトidが被っていないことを確認しましょう。

## masterにkubernetesを導入

[ここ][3]が参考になります。
まずはdockerを入れてサービスを立ち上げます

```
# apt-get install docker.io
# systemctl start docker
```

[```Failed to start docker.service: Unit is masked.```と表示された場合](https://forums.docker.com/t/failed-to-start-docker-service-unit-is-masked/67413)

次に必要なコンポネントをインストールします。

```
# wget https://packages.cloud.google.com/apt/doc/apt-key.gpg
# apt-key add apt-key.gpg
# apt-get install -y apt-transport-https
# echo deb https://apt.kubernetes.io/ kubernetes-xenial main > /etc/apt/sources.list.d/kubernetes.list
# apt-get update
# apt-get install kubeadm kubectl
```

そして、ファイヤウォールの設定を行います。

```
# sudo ufw enable
# sudo ufw allow 6443
# sudo ufw allow 2379
# sudo ufw allow 2380
# sudo ufw allow 10250
# sudo ufw allow 10251
# sudo ufw allow 10252
```

kubeadmの初期化をする前に、swapを無効化しておきましょう。
```swapoff -a```で無効化できます。また、再起動時のために、
```etc/fstab```から該当の行もコメントアウトしておきましょう。

さてようやく、kubeadmを呼び出します

```
kubeadm init --apiserver-advertise-address=192.168.100.226 --pod-network-cidr=10.128.0.0/16
```

apiserver-advertise-addressの部分にはそのvmのNICのアドレスを指定します。pod-network-cidrにはkubernetesのpodネットワークで使用するネットワークを使用します。ほかのネットワークとアドレスの範囲が被らないように注意が必要です。

kubeadm initが完了すると、worker nodeで実行すべきコマンドが表示されるのでメモをしておいてください。

つぎにkubectl用の設定ファイルをコピーします。

```
# mkdir -p ~＜使用するユーザー＞/.kube
# cp /etc/kubernetes/admin.conf ~＜使用するユーザー＞/.kube/config
# chown -R ＜使用するユーザー＞:＜使用するユーザー＞ ~＜使用するユーザー＞/.kube
```

ここまでくれば```kubectl get node```でmaster nodeの状態が確認できるはずです。しかし、まだネットワーク関連の設定が完了していないので、flannelを導入します。この辺りは[ここ][3]の内容がそのまま使えるのでそちらを参考にしてください。

設定が正しくできていれば、master nodeの状態がREADYになります。
ただし、これには少し時間がかかることがあるので気長に待ちましょう。


## workerにkubernetesを導入

masterの時と同様にswapを止めてdockerのサービスを起動、
必要なコンポネントをインストールしてください。

ポートの開放については以下のようにします。

```
# sudo ufw enable
# sudo ufw allow 10250
# sudo ufw allow 30000:32767/udp
# sudo ufw allow 30000:32767/tcp
```

ポートの開放ができたら、masterにノードを登録します。
ひとつ前の項で、記録しておいたコマンドをworkerで打ちます。

masterノード上で```cubectl get nodes```を実行すれば、
workerノードが登録されていることが確認できます。
readyになるまで少し時間がかかる場合がありますが、
ここも気長に待ちましょう。

以上です。

# 参考
[1]:https://help.ubuntu.com/community/KVM/Installation
[2]:https://levelup.gitconnected.com/how-to-setup-bridge-networking-with-kvm-on-ubuntu-20-04-9c560b3e3991
[3]:https://knowledge.sakura.ad.jp/20955/

1. https://help.ubuntu.com/community/KVM/Installation
2. https://levelup.gitconnected.com/how-to-setup-bridge-networking-with-kvm-on-ubuntu-20-04-9c560b3e3991
3. https://knowledge.sakura.ad.jp/20955/

# 追記
私はネットワークの専門とかでは全くないので、
誤りや誤解を招きそうな部分などあれば教えていただけると助かります。