HAProxyとminioを使って何だか高可用に見える構成を作る

# 概要

HTTPSでのリクエストをHAproxyで受けて、
バックエンドのminioにバランシングする構成の記事。
minioのストレージはNFSを使う。

イメージ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86853/9697fd66-6216-170e-486c-2c8a4865ec50.png)


補足
この構成が良いとか真っ当とかそういうのは分からないけども
思いついたのでやってみたという感じ。

# 前提

- 全部さくらのクラウドで作ります。
- OSはUbuntu 20.04.1 LTS
- ドメインは取得済み  
でもAレコードの登録はまだ。
- 証明書の更新の事は気にしない

# 下準備

## さくらのクラウドでスイッチを作る

1つ作ろう。1時間あたり11円(日割りだと110円)かかります。
公式の手順は [こちら](https://manual.sakura.ad.jp/cloud/network/switch/router-switch.html#create-switch-and-routerswitch)

## さくらのクラウドでVMを作る。
2つ作ろう。電源はOFFでOKです。
一番小さなプランでOKです。1台につき1時間あたり9円かかります。(日割りだと100円)

- 1つめのVM(HAProxyを入れる方)  
共有セグメントに接続します。
- 2つめのVM(minioを入れる方)  
作成したスイッチに接続します。  
IPアドレスは192.168.5.21/24を設定します。  
ゲートウェイは192.168.5.1を設定します。

## haproxyを入れたいサーバにnicを追加してスイッチに繋ぐ

1つ目のサーバに追加する。
コントロールパネルのMAPにてサーバにnicを追加して作成したスイッチとサーバを繋げる。
公式の手順は[この辺](https://manual.sakura.ad.jp/cloud/network/map.html)

## 確認

この時点で以下の感じになっているはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86853/b105fd7d-fdb8-e77c-b48a-e7ed98949cf0.png)

## Aレコードを登録しておく
VMを作った時点でHAProxyを動かすサーバのグローバルIPが決まっているはずなので、
Aレコードを登録しておく。ドメインを取得した事業者にUIがあるはず。



# 1つめのVMで作業する

まずは、電源を入れよう。
入れたら次へ。

## 追加したNICにIPアドレスを設定する。

ip a を実行するとeth1が認識されているはず。(eth1じゃないかもだけど、認識されててIPの設定が出来てないNICがあるはず)

/etc/netplan/01-netcfg.yaml に以下のものを追記する。
eth1が既存のeth0と同じインデントになるようにする。

```
    eth1:
      addresses:
        - 192.168.5.1/24
      dhcp4: 'no'
      dhcp6: 'no'
      nameservers:
        addresses:
          - 133.242.0.3
          - 133.242.0.4
        search:
          - localdomain
```

設定を反映させる

```shell
sudo netplan apply
```

## 証明書の取得

let's encryptで取得する。
証明書を発行するためのツールをインストール。

```shell

sudo apt update
sudo apt install certbot
```

次に証明書の発行

```shell
# まずは--dry-run をつけてパラメータなどがcertbotに渡すパラメータが正しいのかを確認
# 途中に出てくる選択肢は1を選択してstandaloneのwebサーバを使う
sudo certbot certonly --dry-run -d FQDN名
# e.g. sudo certbot certonly --dry-run -d proxy.tmktmk.work

# 問題なければ--dry-runを消してコマンドを実行する！
# 途中の選択肢はdry runの時と同じ用に選択
sudo certbot certonly -d FQDN名
```

/etc/letsencrypt/live/FQDN名/ に色々ファイルが出来ている。
READMEもあるのでそれを読むとどういったファイルなのかが分かる。

次に、それらを元にHAProxyで扱えるように証明書のファイルを作る。
(this_is_a.pem は好きなファイル名でOK)

```shell
sudo cat /etc/letsencrypt/live/FQDN名/fullchain.pem /etc/letsencrypt/live/FQDN名/privkey.pem > this_is_a.pem 
```

## HAProxyの構築

### なにはともあれインストールする。

```shell
sudo apt install haproxy
```

### 証明書のファイルを設置する

```shell
sudo mkdir /etc/haproxy/cert
sudo mv さっき作ったthis_is_a.pem /etc/haproxy/cert/
```

### configを書く

/etc/haproxy/haproxy.cfgを編集する。
以下の記述を追記する。

```vim

# ポート9000で待ち受けて来たリクエストはminio_backendで定義したサーバにバランシングする

frontend minio_front
        bind *:9000 ssl crt /etc/haproxy/cert/this_is_a.pem
        mode http
        default_backend minio_backend

# minio_backend の定義
# バランスの方式はroundrobin。サーバが5つあって、それぞれ2秒ごとにヘルスチェックをし、
# チェックが3回NGだったらそのサーバには振り分けない

backend minio_backend
        balance roundrobin
        server minio01 192.168.5.21:9000 check inter 2s fall 3
        server minio02 192.168.5.22:9000 check inter 2s fall 3
        server minio03 192.168.5.23:9000 check inter 2s fall 3
        server minio04 192.168.5.24:9000 check inter 2s fall 3
        server minio05 192.168.5.25:9000 check inter 2s fall 3
```

TIPS以下のコマンドでconfigのチェックが出来ます。
`Configuration file is valid`って最後に表示されたらとりあえずOK。

```shell
sudo haproxy -f /etc/haproxy/haproxy.cfg -c
```

以下のコマンドでconfigを読み込む

``` shell
sudo systemctl restart haproxy
```

### haproxy 配下のサーバが外と通信できるようにする。

ちょっとだけ設定しないとhaproxy配下のサーバからグローバルへの通信が通らない。

```
/etc/sysctl.conf の net.ipv4.ip_forward を 1にする
# 以下のコマンドで設定を反映する
sudo sysctl -p
```
以下のコマンドを実行する

```shell
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
```

# さくらのクラウドNFSアプライアンスを使ってNFSを作る

いわゆるネットワーク越しに使えるストレージ。minioのデータを保管する所。
公式の手順は [ここ](https://manual.sakura.ad.jp/cloud/appliance/nfs/index.html)
20GBのSSDで1時間9円かかります。1日だと99円。

注意点は

- 作成したスイッチに接続しよう。
- ゲートウェイは192.168.5.1とする。
- NFSのIPは192.168.5.100とする。

くらい。

# 2つめのVMで作業する

まず電源をいれます。

## minioサーバを作る

(ミンアイオーだと思うんだけどミニオなのかな… [minioの動画](https://www.youtube.com/channel/UCnWYd9f4il3tyshx5M9lrGw)見ているとミンアイオゥって言っている気がする。)

### 必要なものをインストールする

docker とか NFSをマウントするためのものとか色々まるっとインストールする。

```
sudo apt-get update && sudo apt upgrade -y && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release vim nfs-common && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null && sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io && sudo docker run hello-world
```

### NFSをマウントする

マウントポイントを作る

```shell
sudo mkdir /data
```

### NFSをマウントする

マウントするぞ。

```
sudo mount 192.168.5.100:/export /data

# 再起動しても大丈夫にしたい場合はfstabにも書いておきましょう。
# 192.168.5.100:/export /data nfs rw 0 0
# [公式の手順](https://manual.sakura.ad.jp/cloud/appliance/nfs/)
```

dfとかで見ると確認できる。

```shell
df -h

Filesystem             Size  Used Avail Use% Mounted on
udev                   464M     0  464M   0% /dev
tmpfs                   99M  636K   98M   1% /run
/dev/vda3               16G  4.1G   11G  27% /
tmpfs                  491M     0  491M   0% /dev/shm
tmpfs                  5.0M     0  5.0M   0% /run/lock
tmpfs                  491M     0  491M   0% /sys/fs/cgroup
tmpfs                   99M     0   99M   0% /run/user/1000
192.168.5.100:/export   20G   44M   19G   1% /data
```

### minioを起動させる

こっちはさくっとDockerで始めます。
[公式](https://docs.min.io/docs/minio-docker-quickstart-guide.html)のコマンドを参考にして、以下のコマンドで実行します。

``` shell

sudo docker run -p 9000:9000 \
  --name minio1 --restart always \
  -e "MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE" \
  -e "MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
  -v /data:/data minio/minio:RELEASE.2021-01-05T05-22-38Z server /data
```

# minioにアクセスする

FQDN:9000(e.g. proxy.tmktmk.work:9000) にアクセスしたらログイン画面になるはずなので、
`AKIAIOSFODNN7EXAMPLE`
と
`wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`
を入力してログインしてファイルをアップロードしたりしてみる。

# minioを増やす

minioを同じ手順で増やす。IPアドレスはHAProxyのkonnfigに書いたものを設定する。
そうするとHAProxyによりminioサーバはラウンドロビンでバランシングされるが、
同じNFSに接続しているのでどのminioにバランシングされても同じデータが見える。

# おわり

HAProxyはkeepalived使って冗長化したほうがいいし、
何だったらHAProxyじゃなくて、[さくらのクラウドの機能のエンハンスドロードバランサー](https://manual.sakura.ad.jp/cloud/appliance/enhanced-lb/index.html#id1)使ったほうが
冗長性を考えなくて良くなるし、証明書の自動更新含めてGUIでポチポチできて手間がない。
ちなみに冒頭にも書いた通り、思いついたのでやってみた構成なのでこれで大丈夫なのかとかそういうのは試してない。