Azure VM に MicroK8s を入れて NIC にセカンダリ IP を追加して外部からのアクセスを試してみた

## 背景と目的

ちょっとした Kubernetes 上で動くミドルウェアの検証をやりたい場合、別途 AKS を用意してまでやる程のものではない時があったりします。そこで Azure VM に Ubuntu を用意して MicroK8s を動かし、例えば Nginx の Pod と LoadBalancer を検証するために、NIC にセカンダリ IP を追加して外部から LoadBalancer にアクセスできるように Azure CLI で構築してみました。

## 検証用の仮想マシンを作成

```bash:bash
# 環境変数をセットします
region=japaneast
prefix=mnrk8s

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# 仮想マシンにログインするための SSH キーを作成します
ssh-keygen -m PEM -t rsa -b 4096 \
  -f ${prefix}

# 仮想マシンを作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --os-disk-name ${prefix}-vmOSDisk \
  --image Canonical:0001-com-ubuntu-server-focal:20_04-lts:latest \
  --admin-username azureuser \
  --ssh-key-value ${prefix}.pub \
  --size Standard_B2s \
  --nsg-rule NONE \
  --storage-sku Standard_LRS \
  --public-ip-address-dns-name ${prefix}

# 自分の IP から SSH アクセスできるようにします
az network nsg rule create \
  --resource-group ${prefix}-rg \
  --name Allow-SSH \
  --nsg-name ${prefix}-vmNSG \
  --priority 100 \
  --source-address-prefixes $(curl -s inet-ip.info) \
  --destination-port-ranges 22 \
  --access Allow \
  --protocol Tcp

# SSH 接続します
ssh -i ${prefix} azureuser@${prefix}.japaneast.cloudapp.azure.com
```

## MicroK8s のインストールと動作確認

```bash:bash
# MicroK8s をインストールします
sudo snap install microk8s --classic

# microk8s グループに azureuser を追加します
sudo usermod -a -G microk8s $USER

# microk8s グループにログインします
newgrp microk8s

# microk8s のステータスを確認します
microk8s status --wait-ready

# node のステータスが Ready なのを確認します
microk8s kubectl get nodes

# k8s 上のリソースを確認します
microk8s kubectl get all -A

# kubectl でコマンドを実行できるようエイリアスを設定します
echo "alias kubectl='microk8s kubectl'" >> ~/.bash_aliases

# エイリアスを有効にします
source ~/.bashrc

# k8s のバージョンを確認します
kubectl version --short

# Pod 内から名前解決できるようにします
microk8s enable dns

# nginx の Pod を立ててみます
kubectl run nginx --image=nginx

# Pod のステータスが Running になるまで待ちます（Ctrl＋C で終了）
kubectl get pod -w

# Pod 内にある curl コマンドで名前解決できるか確認します
kubectl exec -it nginx -- curl inet-ip.info

# Pod を削除します
kubectl delete pod nginx
```

## 検証用の Pod を用意

```bash:bash
# microk8s の MetalLB を使用して LoadBalancer にプライベート IP を付与できるようにします
microk8s enable metallb:10.0.0.50-10.0.0.59

# LoadBalancer 込みの Nginx マニフェストを作成します
cat << EOF > nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: nginx
    port: 80
  selector:
    app: nginx
  type: LoadBalancer
EOF

# Nginx マニフェストをデプロイします
kubectl apply -f nginx.yaml

# Pod と LoadBalancer の状態を確認します
kubectl get pod,svc

# Nginx のコンテンツが取得できるか確認します
curl 10.0.0.50

# newgrp から抜けます
exit

# 仮想マシンから抜けます
exit
```

## 仮想マシンの NIC にセカンダリ IP を追加

```bash:bash
# パブリック IP を作成します
az network public-ip create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vmPublicIP2 \
  --sku Basic \
  --dns-name ${prefix}-nginx

# NIC にセカンダリ IP を追加します
az network nic ip-config create \
  --resource-group ${prefix}-rg \
  --name ipconfig${prefix}-vm2 \
  --nic-name ${prefix}-vmVMNic \
  --private-ip-address 10.0.0.50 \
  --vnet-name ${prefix}-vmVNET \
  --subnet ${prefix}-vmSubnet \
  --public-ip-address ${prefix}-vmPublicIP2

# 自分の IP から HTTP アクセスできるようにします
az network nsg rule create \
  --resource-group ${prefix}-rg \
  --name Allow-HTTP \
  --nsg-name ${prefix}-vmNSG \
  --priority 200 \
  --source-address-prefixes $(curl -s inet-ip.info) \
  --destination-port-ranges 80 \
  --access Allow \
  --protocol Tcp

# Nginx のコンテンツが取得できるか確認します
curl ${prefix}-nginx.japaneast.cloudapp.azure.com
```

![microk8s-vm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/e4e059fe-1c21-1855-5f43-b199229e6e18.png)

## 検証環境を削除

```bash:bash
# リソースグループを削除します
az group delete \
  --name ${prefix}-rg \
  --yes

# SSH キーを削除します
rm -f ${prefix}*
```

## 参考

https://microk8s.io/docs/getting-started

https://learn.microsoft.com/ja-jp/azure/virtual-network/ip-services/virtual-network-multiple-ip-addresses-cli