VpcPeeringで2つのVPCを接続する¶
Juneauでは、VpcPeeringを使うことで2つのVpcを直接つなぎ、別々のVpcにいるPod同士を通信させることができます。
このガイドでは、2つのVpcを作ってピアリングし、双方向でPodが疎通するまでの手順を示します。
このガイドで構築するもの¶
- Vpc
shop-vpcとSubnetshop-subnet(10.70.0.0/24) - Vpc
payment-vpcとSubnetpayment-subnet(10.71.0.0/24) - 2つを接続するVpcPeering (
shop-payment) - 両VpcのメインRouteTableに、対向Subnet宛の
via.type: vpcPeeringルート shop-subnetのPodからpayment-subnetのPodへHTTPで到達
前提条件¶
- Juneauのcontroller/daemonが動作しているクラスター
- 接続する2つのVpcの間で、SubnetのCIDRが重複していないこと
手順¶
1. VpcとSubnetを作成¶
apiVersion: juneau.loutres.me/v1alpha1
kind: Vpc
metadata:
name: shop-vpc
---
apiVersion: juneau.loutres.me/v1alpha1
kind: Vpc
metadata:
name: payment-vpc
---
apiVersion: juneau.loutres.me/v1alpha1
kind: Subnet
metadata:
name: shop-subnet
spec:
vpc: shop-vpc
cidr: 10.70.0.0/24
---
apiVersion: juneau.loutres.me/v1alpha1
kind: Subnet
metadata:
name: payment-subnet
spec:
vpc: payment-vpc
cidr: 10.71.0.0/24
2. VpcPeeringを作成¶
apiVersion: juneau.loutres.me/v1alpha1
kind: VpcPeering
metadata:
name: shop-payment
spec:
requester:
vpc: shop-vpc
accepter:
vpc: payment-vpc
$ kubectl get vpcpeering
NAME REQUESTER ACCEPTER READY
shop-payment shop-vpc payment-vpc True
Ready: Trueは、両側のVpcが存在してCIDRが重複していないことを表します。ここまでではまだ通信は成立しません。詳細はVpcPeeringを参照してください。
3. 両方のRouteTableにルートを追加¶
VpcのメインRouteTableはVpc名と同じ名前で自動生成されます。それぞれに対向Subnetへのルートを追記します。どちらもcontrollerが作ったRouteTableへの追記なので、Vpcと同じマニフェストにまとめるならkubectl apply --server-sideを使ってください。詳細はRouteTableを参照してください。
apiVersion: juneau.loutres.me/v1alpha1
kind: RouteTable
metadata:
name: shop-vpc
spec:
vpc: shop-vpc
routes:
- dst: 10.71.0.0/24
via:
type: vpcPeering
vpcPeering: shop-payment
---
apiVersion: juneau.loutres.me/v1alpha1
kind: RouteTable
metadata:
name: payment-vpc
spec:
vpc: payment-vpc
routes:
- dst: 10.70.0.0/24
via:
type: vpcPeering
vpcPeering: shop-payment
dstは対向Vpcに存在するSubnetのCIDRと完全に一致させてください。10.70.0.0/16のようなスーパーネットでは宛先Subnetが定まらず、ルートは解決されません。
ルートを書いた方向にしか通らないため、双方向で通信するには両方に書く必要があります。
4. ルートが解決されたことを確認¶
$ kubectl get routetable shop-vpc -o jsonpath='{.status.routes[?(@.dst=="10.71.0.0/24")]}'
{"dst":"10.71.0.0/24","subnet":"payment-subnet","via":{"type":"vpcPeering","vpcPeering":"shop-payment"}}
subnetに対向Subnetの名前が入っていれば解決済みです。この名前をもとにデータプレーンが転送先を決めます。
5. Podをデプロイ¶
apiVersion: v1
kind: Pod
metadata:
name: payment
annotations:
juneau.loutres.me/subnet: payment-subnet
spec:
containers:
- name: nginx
image: nginx:1.27
---
apiVersion: v1
kind: Pod
metadata:
name: shop
annotations:
juneau.loutres.me/subnet: shop-subnet
spec:
containers:
- name: curl
image: curlimages/curl:8.7.1
command: ["sleep", "infinity"]
6. 疎通を確認¶
custom VpcのPodからはCoreDNSが使えないため、宛先のPod IPを直接指定します。
$ PAYMENT=$(kubectl get pod payment -o jsonpath='{.status.podIP}')
$ kubectl exec shop -- curl -sS --max-time 5 http://$PAYMENT/
<!DOCTYPE html>
...
<h1>Welcome to nginx!</h1>
SecurityGroupを併用する場合¶
SecurityGroupのpeer参照は同じVpcの中でだけ有効です。SecurityGroupの所属判定はVpc単位で行われるため、対向VpcのPodはsecurityGroupRefのルールにマッチしません。対向Vpcからの通信を許可する場合はcidrのルールを書いてください。
apiVersion: juneau.loutres.me/v1alpha1
kind: SecurityGroup
metadata:
name: payment-sg
spec:
vpc: payment-vpc
ingress:
- from:
- cidr: 10.70.0.0/24
protocol: tcp
ports:
- port: 80
別VpcのSecurityGroupをsecurityGroupRefで参照するルールはwebhookで拒否されます。
NetworkACLはアドレスベースで評価されるので、対向Vpcからの通信にもそのままルールが効きます。
3つ以上のVpcを繋ぐ場合¶
ピアリングは推移しません。shop-vpcとpayment-vpc、payment-vpcとaudit-vpcをピアリングしても、shop-vpcからaudit-vpcへは到達できません。
Vpcが増えて組み合わせを管理しきれなくなったら、TransitGatewayでハブ&スポーク構成を作るを参照してください。
うまくいかないとき¶
- VpcPeeringが
Ready=Falseのままspec.requester.vpcとspec.accepter.vpcのVpcが存在するか- 両Vpc間でSubnetのCIDRが重複していないか (
CIDRConflict)
- RouteTableが
Ready=Falseでno Subnet in Vpc ... has CIDR ...と出るdstが対向Vpcの既存SubnetのCIDRと完全に一致しているか
- 片方向しか通らない
- 戻り方向のVpcのRouteTableにもルートを書いたか
- RouteTableは解決済みなのにPodから届かない
- 宛先PodのSecurityGroupがCIDRルールで送信元Subnetを許可しているか
- 宛先SubnetにNetworkACLが付いている場合、送信元CIDRを許可しているか
- VpcPeeringを削除できない
via.vpcPeeringでこのVpcPeeringを参照しているRouteTableが残っています。先にルートを外してください