BGPを使ってExternalNetworkを構築する¶
Juneauでは、Podに外部到達可能なIPアドレス(ElasticIP)を割り当て、その経路をBGPで上流ルータに広報することで、クラスター外部からPodへの直接疎通を実現できます。このガイドはその一連のリソースをゼロから組み立てる手順を示します。
このガイドで構築するもの¶
- 外部へ広報するアドレス範囲
10.225.51.0/24を持つAddressPool - 外部ルータ (AS 65002,
10.225.32.1) とのBGPピアリング - EIP対象Pod用の専用Vpc/Subnet (
10.60.0.0/24) とInternetGateway経路 - ElasticIPをnginx Podに割り当て、クラスター外から
curl http://<elasticIP>/で到達確認
前提条件¶
- Juneauのcontroller/daemon/bgp-speakerが動作しているクラスター
- クラスターのAS番号(本ガイドでは 65001)
- 上流BGPルータ側でJuneauクラスターを受け入れる設定(AS 65002、Juneauノード各IPとのピアリング)
- 広報に使うCIDRが上流ネットワークで未使用であること(本ガイドでは
10.225.51.0/24)
手順¶
1. AddressPoolを作成¶
外部広報に使うCIDR範囲を定義します。
apiVersion: juneau.loutres.me/v1alpha1
kind: AddressPool
metadata:
name: ext-pool
spec:
advertiseMode: bgp
addresses:
- 10.225.51.0/24
advertiseMode: bgp は変更不可です。詳細はAddressPoolを参照してください。
2. BGPPeerを作成¶
上流ルータを宣言します。
apiVersion: juneau.loutres.me/v1alpha1
kind: BGPPeer
metadata:
name: upstream
spec:
myASN: 65001
peerASN: 65002
peerAddress: 10.225.32.1
この時点で各Nodeのbgp-speakerが 10.225.32.1 にBGPセッションを張りに行きます。詳細はBGPPeerを参照してください。
3. BGPAdvertisementを作成¶
どのAddressPoolを広報するかを指定します。
apiVersion: juneau.loutres.me/v1alpha1
kind: BGPAdvertisement
metadata:
name: ext-adv
spec:
addressPools:
- ext-pool
詳細はBGPAdvertisementを参照してください。
4. BGPセッションの確立を確認¶
BGPNodeStateでセッションの状態を確認します。
$ kubectl get bgpnodestate
NAME READY BIRD BMP AGE
worker-1 True True True 2m
worker-2 True True True 2m
すべての列がTrueなら、そのNode上でbgp-speakerが正常に動作し、直近のreconcileも成功している状態です。詳細は以下で確認します。
$ kubectl get bgpnodestate worker-1 -o yaml
...
status:
bgpSessions:
- peerAddress: 10.225.32.1
peerName: upstream
state: Up
upSince: "2026-04-24T10:00:00Z"
advertisements:
- addressPool: ext-pool
prefixes: ["10.225.51.0/24"]
lastSyncedAt: "2026-04-24T09:59:58Z"
conditions:
- type: Ready
status: "True"
reason: Healthy
...
bgpSessions[0].stateがUpにならない場合は、上流ルータ側のピア設定や経路の疎通を疑ってください。bgpSessions[0].lastErrorに直近のPeerDown理由が出ます。詳細はBGPNodeStateを参照してください。
5. ExternalNetworkを作成¶
AddressPoolを1つの論理的な外部ネットワークとしてまとめます。
apiVersion: juneau.loutres.me/v1alpha1
kind: ExternalNetwork
metadata:
name: ext-net
spec:
type: bgp
addressPools:
- ext-pool
type: bgpの場合、参照するAddressPoolはadvertiseMode: bgpである必要があります。詳細はExternalNetworkを参照してください。
6. EIP対象Pod用のVpc/Subnetを作成¶
ElasticIPを付与するPodは、default以外のSubnetに配置する必要があります。専用Vpcとそこに属するSubnetを用意します。
apiVersion: juneau.loutres.me/v1alpha1
kind: Vpc
metadata:
name: ext-vpc
---
apiVersion: juneau.loutres.me/v1alpha1
kind: Subnet
metadata:
name: ext-subnet
spec:
vpc: ext-vpc
cidr: 10.60.0.0/24
7. RouteTableにInternetGatewayルートを追加¶
VpcのメインRouteTableは自動生成されますが、EIP egress (Pod → 外部) に必要なInternetGateway向けデフォルトルートはデフォルトでは含まれません。手動で追記します。
apiVersion: juneau.loutres.me/v1alpha1
kind: RouteTable
metadata:
name: ext-vpc
spec:
vpc: ext-vpc
routes:
- dst: 0.0.0.0/0
via:
type: internetGateway
RouteTableのメタ名はVpc名と同じです。このルートがないと、Podから外部への通信経路が成立しません。詳細はRouteTableを参照してください。
8. ElasticIPを作成¶
ExternalNetworkから1つのアドレスを払い出します。
apiVersion: juneau.loutres.me/v1alpha1
kind: ElasticIP
metadata:
name: nginx-eip
spec:
externalNetwork: ext-net
$ kubectl get elasticip nginx-eip
NAME EXTERNALNETWORK ADDRESS ATTACHMENT PHASE ALLOCATED ATTACHED
nginx-eip ext-net 10.225.51.5 Available True False
PHASE: AvailableでADDRESSが埋まればアドレス確保完了です。この時点ではまだどのPodにもひもづいていません。
9. Podをデプロイ¶
対象のPodを、手順6で作ったSubnetに配置します。juneau.loutres.me/subnet annotationで明示します。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
annotations:
juneau.loutres.me/subnet: ext-subnet
spec:
containers:
- name: nginx
image: nginx:1.27
$ kubectl get networkinterface
NAME ...
nginx.eth0 ...
NetworkInterface名はデフォルトで <Pod名>.eth0 です。
10. ElasticIPAttachmentでひもづけ¶
ElasticIPをPodのNetworkInterfaceに関連付けます。
apiVersion: juneau.loutres.me/v1alpha1
kind: ElasticIPAttachment
metadata:
name: nginx-eip-attach
spec:
elasticIPRef:
name: nginx-eip
targetRef:
networkInterfaceName: nginx.eth0
$ kubectl get elasticipattachment
NAME ELASTICIP NETWORKINTERFACE EIP PODIP NODE PHASE READY
nginx-eip-attach nginx-eip nginx.eth0 10.225.51.5 10.16.0.12 worker-1 Attached True
PHASE: AttachedかつREADY: Trueになれば、該当Node上でElasticIPがPodに関連付けられた状態です。詳細はElasticIPAttachmentを参照してください。
11. 外部からの疎通を確認¶
上流ルータ側、または上流ルータから到達可能な任意のホストから:
$ curl -sS http://10.225.51.5/
<!DOCTYPE html>
...
<h1>Welcome to nginx!</h1>
レスポンスが返れば、BGP広報 → 上流ルータの経路学習 → Nodeへの転送 → Pod、の経路が通っています。
うまくいかないとき¶
kubectl get bgpnodestateのREADYがFalseBirdRunning: Falseならbgp-speaker Podが起動していない、またはBGPセッション処理が起動していない可能性。Pod ログを確認BMPConnected: Falseならbgp-speakerのBGPセッション状態の監視経路が一時的に切れている。設定の反映待ちかポート競合の可能性
bgpSessions[].stateがUpにならないlastErrorを確認。administrative-shutdown系なら対向側の設定、remote-system-no-notification系なら対向へのTCP到達性を疑うspec.peerAddressと上流ルータのIPが一致しているか、AS番号が両側で揃っているかを確認
advertisements[]が空、または期待CIDRが無い- BGPAdvertisementの
spec.addressPoolsの綴りとAddressPool名が一致しているか - 参照先AddressPoolの
spec.advertiseMode: bgpか status.errors[]にreconcile時の不整合が記録されていないか
- BGPAdvertisementの
- BGPは張れているのにcurlが通らない
elasticipattachment.status.conditions[?(@.type=="Ready")].statusがTrueになっているか。関連付けがまだ完了していない可能性- 上流ルータで経路が学習されているか(
show ip route 10.225.51.0/24) - 対象Podがdefault以外のSubnetに属しているか。default SubnetのPodはElasticIPの対象にできません
- Podが属するVpcのRouteTableに
type: internetGatewayのルートがあるか。無いと外部疎通が成立しません - NodeとPodの間はクラスター内通信と同じ経路なので、通常のPod到達性テストで切り分け可能