vxlan over wireguardでMetalLBにグローバルIPv6を付与

# 目的
KubernetesのMetalLBにLinodeで払い出してもらっているIPv6/56を割り当てる。
今回はVXLAN over Wireguardをnetplanだけで簡易的に設定する。

# 実証環境
- Ubuntu 22.04 (Linode)
- Debian 12 Bookwarm (Kubernetes worker on Proxmox)

# ネットワーク構成
LinodeのGlobal IPv6 /56をUbuntuに追加
例：`2600:3C00:1234:1100::/56`
| ノード  | WireGuard IP     | 公開IP                      |
| ------ | ---------------- | -------------------------- |
| Ubuntu | `172.16.42.1/30` |                            |
| Debian | `172.16.42.2/30` | `2600:3C00:1234:1100::/56` |

# 手元で鍵生成
```
export PRIVATE_KEY=`wg genkey | sudo tee -a /etc/wireguard/keypars/wg0.key`
export PUBLIC_KEY=`echo $PRIVATE_KEY | wg pubkey | sudo tee -a /etc/wireguard/keypars/wg0.pub`
export REMOTE_PRIVATE_KEY=`wg genkey | sudo tee -a /etc/wireguard/keypars/wg0-remote.key`
export REMOTE_PUBLIC_KEY=`echo $REMOTE_PUBLIC_KEY | wg pubkey | sudo tee -a /etc/wireguard/keypars/wg0-remote.pub`
```
OR

以下のサイトで生成しても構いません
https://wg.orz.tools/

# Ubuntu (Linode側) の設定

手元の`$PRIVATE_KEY`と`$REMOTE_PUBLIC_KEY`をコピーしておく
```bash
# 依存パッケージをインストール
sudo apt install -y iptables resolvconf wireguard openvswitch-switch

cat <<EOF | sudo tee /etc/netplan/99-wg0.yaml
network:
  version: 2
  
  bridges:
    wg0@br0:
      addresses:
      - fc00:ffff:ffff:ffff::0/127
      interfaces:
      - wg0@vxlan0
      routes:
      - to: 2600:3c00:1234:1100::/56
        via: fc00:ffff:ffff:ffff::1
        
  tunnels:
    wg0:
      mode: wireguard
      port: 51820
      key: $PRIVATE_KEY
      addresses:
      - 172.16.42.1/30
      peers:
      - allowed-ips:
        - 172.16.42.2/30
        keys:
          public: $REMOTE_PUBLIC_KEY
        keepalive: 25    
    wg0@vxlan0:
      mode: vxlan
      local: 172.16.42.1
      remote: 172.16.42.2
      id: 100
      port: 4789
      link: wg0
EOF

sudo netplan apply
```

# Debian (worker側) の設定
手元の`$PUBLIC_KEY`と`$REMOTE_PRIVATE_KEY`をコピーしておく
```bash
# 依存パッケージをインストール
sudo apt install -y iptables resolvconf wireguard openvswitch-switch

cat <<EOF | sudo tee /etc/netplan/99-wg0.yaml
network:
  version: 2

  bridges:
    wg0@br0:
      addresses:
      - fc00:ffff:ffff:ffff::1/127
      interfaces:
      - wg0@vxlan0
      routes:
      - to: ::/0
        via: fc00:ffff:ffff:ffff::0
        metric: 99

  tunnels:
    wg0:
      mode: wireguard
      key: $REMOTE_PRIVATE_KEY
      addresses:
      - 172.16.42.2/30
      peers:
      - endpoint: 172.237.20.100:51820
        keepalive: 25
        allowed-ips:
        - 172.16.42.1/30
        keys:
          public: $PUBLIC_KEY
    wg0@vxlan0:
      mode: vxlan
      local: 172.16.42.2
      remote: 172.16.42.1
      id: 100
      port: 4789
      link: wg0
EOF

sudo netplan apply
```
### ⚠️ トラブルシューティング
環境によっては`wg0@br0`のデフォルトルートがmetric負けしていることがあります。
`ip -6 route show`で確認し、もし`default via` が他にも存在する場合はそれよりも低いmetricを設定してください。
### MetalLBの設定
```bash
cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: wireguard-v6-global
  namespace: metallb-system
spec:
  addresses:
  - 2600:3c00:1234:1100::/56
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: wg0-vxlan0-l2adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - wireguard-v6-global
EOF
```