VPS(Vultr)と家のPCをVPN(WireGuard)で繋いでKubernetesクラスターの構築

# はじめに

この記事では，VPSと家のPCをVPN（WireGuard）で繋ぎ，VPSをマスターとして，家のPCをそのノードとして，Kubernetesのクラスターを構築する方法を記します．

# 構成イメージ図

![VPSと家のPC接続構成図.png](https://qiita-image-store.s3.amazonaws.com/0/249629/051836ca-abb5-3d0e-2703-9ec1d76fe5c5.png)

# 練習環境

構築の練習として[Vultr](https://www.vultr.com/?ref=7469427)上にVPSを2台用意し，片方を家のPCの代わりとして利用します．

以下に示す構成で構築した場合，Vultr側から各VPSのIPとrootのパスワードを示してくれます．
`PermitRootLogin yes`の状態になっているので，そのままrootでSSH接続して試し終わったらVPSを削除すればいいと思います．
1時間以内には終わると思います．（約4円！Wow！）

### 構成
| 項目 | 内容 |
| --- | ---- |
| Server Location | Tokyo |
| Server Type | Ubuntu 18.04 |
| Server Size | 55GB SSD / 1CPU / 2048MB Memory |

### Additional Features 

| 項目 | 内容 |
| --- | ---- |
| Enable IPv6 | no |
| Enable Private Networking | no |

### Server Hostname & Label
- Server1
- Server2

※ Server2を家のPCの代わりとして利用します

### WireGuardのネットワークについて

WireGuardを使ったVPNで利用するIPは
- Server1: 10.0.0.1
- Server2: 10.0.0.2
を利用し，ポートは33333を利用します．

# 構築手順

## 共通の手順

### VPN(WireGuard)のインストール
[WireGuard](https://www.wireguard.com/)は簡単にVPNができる技術です．
WireGuardのインストールは公式の[手順](https://www.wireguard.com/install/)と同じ感じに行います．

```
# add-apt-repository ppa:wireguard/wireguard
# apt update
# apt install wireguard
```

### Dockerのインストール

[Docker](https://www.docker.com/)はコンテナ型の仮想化環境を提供するオープンソースソフトウェアです．
Dockerのインストールも公式の[手順](https://docs.docker.com/install/linux/docker-ce/ubuntu/)と同じ感じに行います．
インストールする`dokcer-ce`はこの記事を書いた時点の`Kubernetes v1.13.4`に対応する`18.06.3~ce~3-0~ubuntu`をインストールしています．
また，`apt-mark`を使って`docker-ce`が`apt upgrade`で更新されないようにしています，

```
# apt update
# apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# apt update
# apt install docker-ce=18.06.3~ce~3-0~ubuntu
# apt-mark hold docker-ce
```

### Kubeadmのインストール

[Kubernetes](https://kubernetes.io/)はコンテナオーケストレーションシステムです．
Kubeadmは公式が提供しているkubernetesクラスターを構築するためのツールです．
Kubeadmのインストールも公式の[手順](https://kubernetes.io/docs/setup/independent/install-kubeadm/)と同じ感じに行います．

```
# apt update
# apt install apt-transport-https curl
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
# add-apt-repository "deb https://apt.kubernetes.io/ kubernetes-xenial main"
# apt update
# apt install kubelet kubeadm kubectl
# apt-mark hold kubelet kubeadm kubectl
```

## WireGuardのセットアップ

### WireGuardの秘密鍵と公開鍵の生成

各サーバーでWireGuardを使ったVPNを行うために鍵を生成します．
公式の[手順](https://www.wireguard.com/quickstart/)に従います．
片方のサーバーで二つ生成しても問題はありません．

```
# wg genkey | tee privatekey | wg pubkey > publickey
```
### WireGuardの設定ファイルの用意

WireGuradのインターフェース`wg0`の設定ファイルを用意します．
PostUpで後々Kubernetesのポッド間通信を実現するためのネットワーク設定をしています．
PostDownではその設定を消しています．

#### Server1

``` /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1
PrivateKey = {{ Server1の秘密鍵 }}
PostUp = ip route add 10.96.0.0/16 dev wg0 src 10.0.0.1
PostDown = ip route del 10.96.0.0/16 dev wg0 src 10.0.0.1
ListenPort = 33333

[Peer]
PublicKey = {{ Server2の公開鍵 }}
AllowedIps = 10.0.0.2/32
Endpoint = {{ Server2のグローバルIP }}:33333
PersistentKeepalive = 25
```

#### Server2

``` /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.2
PrivateKey = {{ Server2の秘密鍵 }}
PostUp = ip route add 10.96.0.0/16 dev wg0 src 10.0.0.2
PostDown = ip route del 10.96.0.0/16 dev wg0 src 10.0.0.2
ListenPort = 33333

[Peer]
PublicKey = {{ Server1の公開鍵 }}
AllowedIps = 10.0.0.1/32
Endpoint = {{ Server1のグローバルIP }}:33333
PersistentKeepalive = 25
```

### WireGuardのインターフェースの起動

各サーバーで`wg-quick@.service`を利用して`wg0`を起動します．
`wg-quick@.service`中では`wg-quick`コマンドでインターフェースを起動しているのですが，デフォルトで`/etc/wireguard/`を参照するようになっています．

```
# systemctl start wg-quick@wg0
# systemctl enable wg-quick@wg0
```

### WireGuardの動作確認

動作しているかは`wg`コマンドを使って確認できます．
`ping`コマンドでも確認できます．

```
# wg
interface: wg0
  public key: **************************************
  private key: (hidden)
  listening port: 33333

peer: **************************************
  endpoint: XXX.XXX.XXX.XXX:33333
  allowed ips: 10.0.0.2/32
  latest handshake: 10 seconds ago
  transfer: 5.70 MiB received, 20.25 MiB sent
  persistent keepalive: every 25 seconds
```

```
# ping 10.0.0.1 -c 3
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.068 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=1.63 ms

--- 10.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2047ms
rtt min/avg/max/mdev = 0.042/0.582/1.636/0.745 ms


# ping 10.0.0.2 -c 3
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=5.31 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=5.70 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=5.56 ms

--- 10.0.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 5.312/5.529/5.706/0.163 ms
```

## kubernetesクラスターのセットアップ

Server1をマスターとして，Server2をワーカーとしてセットアップします．
公式の[手順](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/)と同じ感じで行います．
利用する`pod network add-on`は`Weave Net`です．

### Server1のセットアップ

#### Kubernetesマスターのセットアップ

```
# kubeadm init --apiserver-advertise-address=10.0.0.1 --ignore-preflight-errors=NumCPU
...
You can now join any number of machines by running the following on each node
as root:

  kubeadm join 10.0.0.1:6443 --token ***...*** --discovery-token-ca-cert-hash sha256:***...***
```
`--ignore-preflight-errors=NumCPU`は今回練習で利用しているVPSのCPUが1個なので，そのエラーを無視するためのものです．
`kubeadm join 10.0.0.1:6443 --token ***...*** --discovery-token-ca-cert-hash sha256:***...***`はServer2のセットアップで使います

#### Weave Netのセットアップ

```
# echo "net.bridge.bridge-nf-call-iptables=1" > /etc/sysctl.d/k8s.conf
# sysctl --system
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
```

#### MasterでもPodが建てれるように設定

```
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl taint nodes --all node-role.kubernetes.io/master-
```

### Server2のセットアップ

#### クラスターへの参加

```
# kubeadm join 10.0.0.1:6443 --token ***...*** --discovery-token-ca-cert-hash sha256:***...***
```

## Kubernetesクラスターの動作確認

少しだけ時間をおいてServer1側で`kubectl node`を使って状態を確認します．

```
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl get node
NAME      STATUS     ROLES    AGE   VERSION
server1   Ready      master   **m   v1.13.4
server2   Ready      <none>   **m   v1.13.4
```

## Nodeを指定してPodを建てれるようにlabelの設定

参考記事: [kubernetes: 特定のコンテナ(Pod)だけ特定のホストで](https://qiita.com/suzukihi724/items/4c90d7e3efb8b35ab2b2)

```
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl label nodes server1 type=server1
# kubectl label nodes server2 type=server2
```

## おわり

あとは，このKubernetesクラスターを自由に使ってみればいいと思います．