以前Kubernetes with CALICOでコントロールノードとルータを兼用させたいといっていて、当時は結局兼用できずに仮想的に別サーバに分けることで解決したわけだが、先日再挑戦して無事できたので設定について晒す。
初めに
本記事の目的
- 稼働中の自作ルータに直接kubernetesを導入し、(マスター)ノード化する
本記事で扱うもの
本記事で扱わないもの
- CalicoやKubernetesのインストール
公式のドキュメント通りでできたので - Calicoの設定の詳細な説明
現時点で期待通り動いているだけで、なぜこの設定で動いているのか細かいところはよくわかっていないので - ファイアーウォールとしてのCalicoの設定
今回はとにかくNATとルーティングをしたかった(がなかなかうまくいかなかった)都合上、ネットワークポリシーは全部通すザル設定
構成
Nodeバージョン一覧
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
router Ready control-plane 21d v1.28.8 10.0.0.1 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-18-amd64 containerd://1.6.20
worker1 Ready <none> 206d v1.28.8 10.0.0.2 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-18-arm64 containerd://1.6.20
worker2 Ready <none> 206d v1.28.8 10.0.0.3 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-18-arm64 containerd://1.6.20
ネットワーク図
Internet
─┬────────────────────┬──────────────────────────┬─────────┬─
│ │ │ │
┌┴────────────────┐ ┌─┴───────────────────┐ ┌─┴─────┐ ┌─┴─────┐
│Rental ONU/Router│ │Jump Server │ │Client1│ │Client2│
└──────────────┬──┘ └─┬──────────────┬────┘ └────┬──┘ └┬──────┘
│ │ │ │ │
Home Network │ │ Router VPN │ Client VPN │ │
192.168.0.0/24 │ │ 10.1.0.0/24 │ 10.1.1.0/24 │ │
───────────────┼─── ─┴────────┬─── ─┴──────────────┴─────┴────────
│ │
┌──────────────┼───────────────┼──────────────────────────┐
│ Home build │ │ │
│ Router ┌─┴────────────┐ ┌┴──────────┐ ┌───────────┐ │
│ │wan0 │ │wg0 │ │lan0 │ │
│ │192.168.0.2/24│ │10.1.0.2/24│ │10.0.0.1/et│ │
│ └──────────────┘ └───────────┘ └────┬──────┘ │
│ │ │
└────────────────────────────────────────────────┼────────┘
│
Clusteer Network │
10.0.0.0/24 │
───┬────────────┬────────────────────────────────┴─────────
│ │
┌──┴─────┐ ┌─┴──────┐
│Worker1 │ │Worker 2│
└────────┘ └────────┘
以下ノードやネットワークの解説
レンタルルータ
- 普通のレンタルルータ兼ONU
- Home NetworkにDHCPやDNSを提供している
自宅ネットワーク
- 普通の家庭のネットワーク
- 自作ルータもこの配下に位置している
クラスタネットワーク
- 自作ルータの下流に位置するネットワーク
- kubernetesクラスタを構築するホスト間の物理ネットワーク
自作ルータ(ルータ兼管理ノード)
- 自宅ネットワークおよび中継サーバとクラスターネットワークの中間に位置するルータ
- デフォルトゲートウェイはレンタルルータ側で、中継ネットワークはクライアントからのアクセスのみで使う
- BGPで中継サーバと中継ネットワークとクラスターネットワークのルートの交換をしている
- クラスターネットワークにDHCPやDNSを提供している
- 実際には微妙に異なる構成の管理ノードが3台あり、keepalivedでクラスター内のデフォルトゲートウェイを冗長化したりしているが、本記事では省略して1台として扱っている
自宅ノード(ワーカーノード)
- 主にラズパイが担当
中継サーバ
- AWS Lightsail上で稼働
- 自作ルータおよび各クライアントをVPNで橋渡ししている
BGP
中継サーバとBGPでルートの共有をし、中継サーバから自宅サーバへアクセスできるようにしていた。
今回、中継サーバの構成はそのままに、自作ルータ側をCalicoを使ってクラスタネットワークのアドレス(10.0.0.0/24
)を共有する
BGP Configuration
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
bindMode: None
communities:
- name: bgp-large-community
value: 64512:000
prefixAdvertisements:
- cidr: 10.0.0.0/24
communities:
- bgp-large-community
クラスタネットワークネットワーク10.0.0.0/24
をPrefixAdvertisementsに設定することで、中継サーバにこれを広告している。
BGP Filter
クラスタネットワーク10.0.0.0/24
をエクスポート、中継ネットワーク10.1.0.0/16
をインポートするようBGPフィルターを設定する。
apiVersion: projectcalico.org/v3
kind: BGPFilter [130]
metadata:n: projectcalico.org/v3
name: bgp-filter
spec:
exportV4:
- action: Accept
matchOperator: In
cidr: 10.0.0.0/24
importV4:
- action: Accept
matchOperator: In
cidr: 10.1.0.0/16
BGP Peer
中継サーバとVPN上で隣接するノードは自作ルータのみなので、自作ルータが中継サーバとピアを組むよう設定する
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: router
spec:
peerIP: 10.1.0.1
asNumber: 65048
node: router
filters:
- bgp-filter
sourceAddress: None
keepOriginalNextHop: true
NAT
Host Endpoints
どうもCalicoではフォワーディングをホワイトリスト形式で行っているらしく、インターフェース間での転送にはそれぞれのインターフェースを設定する必要がある模様。
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: router-wan
spec:
interfaceName: wan0
node: router
expectedIPs:
- 192.168.0.2
---
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: router-vpn
labels: defaultgateway
spec:
interfaceName: wg0
node: router
expectedIPs:
- 10.1.0.2
---
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: router-cluster
labels: defaultgateway
spec:
interfaceName: lan0
node: router
expectedIPs:
- 10.0.0.1
IP Pool
IP Poolはdisabled
にすることで、kubernetes内部で使わないIPアドレスを宣言できる。ここでnatOutgoing: true
とすることで、クラスタネットワークから外部へのNATを有効にできる。
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: border-ipv4-ippool
spec:
cidr: 10.0.0.0/24
disabled: true
natOutgoing: true
GlobalNetworkPolicy
クラスター全体のネットワークポリシー
本来ならファイアーウォールとして余計な通信を除くよう設定すべきだが、今回はとりあえず通信させたいのでIngressもEgressもすべて許可している。
注意点として、DNSやDHCPといったルータとしてのサービスもクラスター内に含まれる都合上、許可する必要がある。とくにApiserverのエンドポイントをドメインにしている状態でDNSをシャットダウンすると、kubectlでドメインが見つからず詰むので要注意。
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: border-ipv4-ippool
spec:
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-forward
spec:
applyOnForward: true
types:
- Ingress
- Egress
ingress:
- action: Allow
egress:
- action: Allow
結果
中継サーバでクラスタネットワークへのルートが確認できる。
$ ip route | grep "10.0.0.0/24"
10.0.0.0/24 nhid 56 via 10.1.0.1 dev wg0 proto bgp metric 20
ワーカーノードが自作ルータ経由で外部にアクセスできることが確認できる。
$ traceroute google.com
traceroute to google.com (172.217.26.238), 30 hops max, 60 byte packets
1 10.0.0.1 (10.0.0.1) 0.288 ms 0.162 ms 0.118 ms
2 * * *
3 * * *
4 * * *
5 * * *
6 * * *
7 bom05s09-in-f14.1e100.net (172.217.26.238) 40.357 ms 108.170.242.129 (108.170.242.129) 40.114 ms nrt12s51-in-f14.1e100.net (172.217.26.238) 40.437 ms