NATGatewayでVPC外への通信を成立させる¶
Juneauでは、NATGatewayを使うことでVpc内のPodがVpc外(クラスタ外を含む)へN:1のソースNATで出ていくegress経路を構築できます。各Nodeに1つずつNAPTソースIPアドレスが払い出され、Pod がVpc外へ通信する際は配置されているNodeに対応するアドレスがソースIPとして利用されます。
このガイドでは、custom Vpcに対してBGPベースのNATGatewayを構築し、Podがクラスタ外まで疎通する手順を一通り示します。
このガイドで構築するもの¶
- NAPTソースIP用のAddressPool (
nat-pool,10.225.53.0/24) - 上流ルータ (AS 65002,
10.225.32.1) とのBGPピアリング - BGPで広報するExternalNetwork (
nat-net) - 専用Vpc (
egress-vpc) とSubnet (egress-subnet,10.90.0.0/24) - NATGateway (
egress-natgw) - VpcのRouteTableに
0.0.0.0/0をvia.type: natGatewayで追加 - Podから
curl https://1.1.1.1/cdn-cgi/traceで外部に到達し、戻ってきたip=行がNATGatewayの払い出したNAPTソースIPと一致
前提条件¶
- Juneauのcontroller/daemon/bgp-speakerが動作しているクラスター
- クラスターのAS番号(本ガイドでは 65001)
- 上流BGPルータ側でJuneauクラスターを受け入れる設定(AS 65002、Juneauノード各IPとのピアリング)
- 広報に使うCIDRが上流ネットワークで未使用であること(本ガイドでは
10.225.53.0/24) - Pod がインターネットに出るための上流側の経路設定
手順¶
1. AddressPoolを作成¶
NAPTソースIPを払い出すためのCIDRを定義します。
apiVersion: juneau.loutres.me/v1alpha1
kind: AddressPool
metadata:
name: nat-pool
spec:
advertiseMode: bgp
addresses:
- 10.225.53.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. BGPセッションの確立を確認¶
$ kubectl get bgpnodestate
NAME READY BIRD BMP AGE
worker-1 True True True 2m
worker-2 True True True 2m
すべての列がTrueになっていれば、そのNode上でbgp-speakerが正常に動作し、上流とのセッションが確立しています。詳細はBGPNodeStateを参照してください。
4. ExternalNetworkを作成¶
AddressPoolを1つの論理的な外部ネットワークとしてまとめます。
apiVersion: juneau.loutres.me/v1alpha1
kind: ExternalNetwork
metadata:
name: nat-net
spec:
type: bgp
addressPools:
- nat-pool
type: bgpの場合、参照するAddressPoolはadvertiseMode: bgpである必要があります。詳細はExternalNetworkを参照してください。
5. Vpc/Subnetを作成¶
NATGateway経由で外部に出るPodを置く専用のVpcとSubnetを用意します。
apiVersion: juneau.loutres.me/v1alpha1
kind: Vpc
metadata:
name: egress-vpc
---
apiVersion: juneau.loutres.me/v1alpha1
kind: Subnet
metadata:
name: egress-subnet
spec:
vpc: egress-vpc
cidr: 10.90.0.0/24
6. NATGatewayを作成¶
Vpcと出口となるExternalNetworkを参照するNATGatewayを作成します。
apiVersion: juneau.loutres.me/v1alpha1
kind: NATGateway
metadata:
name: egress-natgw
spec:
vpc: egress-vpc
externalNetwork: nat-net
$ kubectl get natgateway
NAME VPC EXTERNALNETWORK GATEWAYID READY
egress-natgw egress-vpc nat-net 1 True
Ready: TrueになればNATGatewayの基本的な準備は完了です。詳細はNATGatewayを参照してください。
7. RouteTableに0.0.0.0/0ルートを追加¶
VpcのメインRouteTableは自動生成されますが、Vpc外への経路はデフォルトでは含まれません。NATGateway向けのデフォルトルートを追記します。
apiVersion: juneau.loutres.me/v1alpha1
kind: RouteTable
metadata:
name: egress-vpc
spec:
vpc: egress-vpc
routes:
- dst: 0.0.0.0/0
via:
type: natGateway
natGateway: egress-natgw
RouteTableのメタ名はVpc名と同じです。このルートが無いとVpc内のPodからVpc外への経路が成立しません。詳細はRouteTableを参照してください。
8. ExternalNetworkAttachmentが払い出されたことを確認¶
NATGatewayを作成すると、対象ExternalNetworkに対してNodeごとに1つずつExternalNetworkAttachmentが自動的に作成され、それぞれにNAPTソースIPアドレスが割り当てられます。各assignedIPはBGPで上流に広報され、戻り通信が正しいNodeへ届くようになります。
$ kubectl get externalnetworkattachment
NAME EXTERNALNETWORK NODE ASSIGNEDIP READY
nat-net--worker-1 nat-net worker-1 10.225.53.5 True
nat-net--worker-2 nat-net worker-2 10.225.53.6 True
すべてのNodeに対してREADY: True、ASSIGNEDIPが埋まっていれば、NAPTソースIPの払い出しは完了です。詳細はExternalNetworkAttachmentを参照してください。
9. Podをデプロイ¶
egress-subnetにcurl用のPodを配置します。
apiVersion: v1
kind: Pod
metadata:
name: curl
annotations:
juneau.loutres.me/subnet: egress-subnet
spec:
containers:
- name: curl
image: curlimages/curl:8.7.1
command: ["sleep", "infinity"]
10. 外部からの送信元IPを確認¶
Podから外部に出るときのソースIPアドレスを、外部の応答サービスで確認します。custom VpcのPodからはCoreDNSが利用できないため、IP直指定で叩ける応答サービスを使います。
$ kubectl exec curl -- curl -sS https://1.1.1.1/cdn-cgi/trace
fl=...
h=1.1.1.1
ip=10.225.53.5
ts=...
visit_scheme=https
uag=curl/8.7.1
...
応答のip=行が、Podが動作しているNodeに対応するExternalNetworkAttachmentのstatus.assignedIPと一致していれば、NATGateway経由のN:1 NAPTで外部に出ている状態です。
うまくいかないとき¶
- NATGatewayが
Ready=Falseのままspec.vpcで参照したVpcが存在するかspec.externalNetworkで参照したExternalNetworkが存在するか
kubectl get externalnetworkattachmentが空、または対象NodeのAttachmentが無い- NATGatewayが
Ready=Trueになっているか(Attachmentは、NATGatewayから参照されているExternalNetworkに対してのみ作成されます) - 対象Nodeがクラスターに登録されているか
- NATGatewayが
- Attachmentの
assignedIPが払い出されない(READY=Falseのまま)- 参照しているAddressPoolの
advertiseModeがbgpか - AddressPoolにIP在庫が残っているか(Node数より多くのIPが必要)
- 参照しているAddressPoolの
- Podから外部に出られない
- PodのSubnetが、NATGatewayと同じVpcに属しているか
- VpcのRouteTableに
0.0.0.0/0をvia.type: natGatewayとするルートが入っているか via.natGatewayの名前が、対象NATGatewayのname と一致しているかkubectl get bgpnodestateで、各NodeのassignedIPに対応する/32がstatus.advertisements[].prefixesに乗っているか
- 送信元IPが期待値と違う
- Pod が動作しているNodeに対応するExternalNetworkAttachmentの
assignedIPを改めて確認 - 上流ルータで、該当
/32がそのNodeを次ホップに学習しているか
- Pod が動作しているNodeに対応するExternalNetworkAttachmentの