このページでは、Pod のサービス ステアリングを設定する方法について説明します。
サービス ステアリングの仕組みについては、サービス ステアリングの仕組みをご覧ください。
要件
- GKE バージョン 1.30 以降。
制限事項
ServiceFunctionChain
には、Service Function を 1 つだけ含めることができます。- 最大 100 ノードと 10 個の
ServiceFunctionChain
とTrafficSelector
のペアをおすすめします。 - GKE サービス ステアリングは、Container-Optimized OS ノードイメージを実行しているノードでのみ使用できます。
- GKE サービス ステアリングは、下り(外向き)と宛先の IP アドレスのみをサポートします。
- サービス ステアリングは、同じプレフィックス長の複数のトラフィック セレクタが同じサブジェクトに適用された場合に発生する競合を処理しません。競合を回避するには、トラフィック セレクタの設計時に、重複しない IP アドレス範囲と明確に定義された選択基準を使用してください。
サービス ステアリングを実装する
GKE サービス ステアリングを使用すると、クラスタ内のネットワーク トラフィックのフローをカスタマイズして制御できます。このセクションでは、ウェブ ゲートウェイの例を使用して、サービス ステアリングの実装方法を説明します。
エンドユーザーのクライアント デバイスからインターネットへのトラフィックを保護するウェブ ゲートウェイを作成するユースケースについて考えてみましょう。VPN ターミネーターは、セキュア トンネルを使用してトラフィックをマネージド ゲートウェイに誘導します。エンドユーザーのトラフィックはファイアウォールにリダイレクトされ、次にプロキシにリダイレクトされます。プロキシはトラフィックに送信元ネットワーク アドレス変換(SNAT)を実行し、元の送信元アドレスをマスクしてインターネットに送信します。
GKE サービス ステアリングを実装する手順は次のとおりです。
- MTU が 8896 の VPC を作成します。
- GKE クラスタを作成します。
- Service Function Pod と Service を作成します。
ServiceFunctionChain
を作成します。ServiceFunctionChain
を参照するTrafficSelector
リソースを作成します。
始める前に
作業を始める前に、次のことを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components update
を実行して最新のバージョンを取得する。
料金
次の Network Function Optimizer(NFO)機能は、GKE Enterprise が有効になっているプロジェクトのクラスタでのみサポートされます。
Google Kubernetes Engine(GKE)Enterprise エディションの有効化に適用される料金については、GKE Enterprise の料金をご覧ください。
VPC を準備する
VPC を準備します。サービス ステアリングは、カプセル化を使用して、適切な Service Function にトラフィックをリダイレクトします。カプセル化では、各パケットに追加ヘッダーが追加されるため、パケットサイズが大きくなります。サービス ステアリングを使用するために、VPC で特別な構成を行う必要はありません。VPC を準備する際は、MTU サイズを決定する際に、カプセル化のオーバーヘッドを考慮することをおすすめします。詳細については、MTU を指定した VPC ネットワークをご覧ください。
次のコマンドは、VPC の MTU サイズを設定します。
gcloud compute networks create VPC_NETWORK_NAME --mtu=8896
VPC_NETWORK_NAME
は、サブネットを含む VPC ネットワークの名前に置き換えます。
GKE クラスタを作成する
GKE でサービス ステアリングを実装するために必要な高度なネットワーク ルーティングと IP アドレス管理機能を有効にするには、次のように GKE Dataplane V2 対応の GKE クラスタを作成します。
gcloud container clusters create CLUSTER_NAME \
--network VPC_NAME \
--release-channel RELEASE_CHANNEL \
--cluster-version CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias
次のように置き換えます。
CLUSTER_NAME
: クラスタの名前。VPC_NAME
: クラスタを関連付ける VPC の名前。RELEASE_CHANNEL
: リリース チャンネルの名前。VERSION
: GKE のバージョン。1.30 以降にする必要があります。また、--release-channel
フラグを使用してリリース チャンネルを選択することもできます。リリース チャンネルを使用するには、デフォルトのバージョン 1.30 以降が必要です。
ServiceFunction
Pod を作成する
サービス チェーンを確立するには、VPN ターミネーター Pod と必要な Service Function Pod をクラスタ内にデプロイします。Pod は、ネットワーク機能を実行するコンテナ化されたアプリケーションをカプセル化します。
多くの場合、VPN ターミネーター Pod は、チェーン内の最初の Service Function であり、VPN を介してクラスタに流入するトラフィックを終端処理します。その後、ファイアウォールやロード バランシングなどの他の Service Functions に転送して、最終的な宛先に到達する前にさらに処理を行います。
次の構成ファイルの例では、クラスタ内のネットワーク トラフィック管理に不可欠な次の 3 つのコンポーネントを定義しています。
- VPN Pod: クラスタ内に仮想プライベート ネットワーク(VPN)エンドポイントを確立します。これにより、クラスタと外部ネットワーク間の安全な暗号化通信が可能になります。
- ファイアウォールのデプロイ: セキュリティとロード バランシングを提供するファイアウォール Pod の複数のレプリカをデプロイします。
- プロキシ DaemonSet: クラスタのすべてのノードにプロキシ Pod をデプロイします。これにより、ネットワーク トラフィックがファイアウォールなどの他のサービスに転送される前にローカルで処理されるようになります。
次のサンプル マニフェストを service_function.yaml
として保存します。
apiVersion: v1
kind: Pod
name: vpn
namespace: vpn
labels:
app: vpn
spec:
containers:
- name: vpn
image: openvpn
ports:
- containerPort: 51820
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: firewall
namespace: firewall
spec:
replicas: 3
selector:
matchLabels:
app: firewall
template:
metadata:
labels:
app: firewall
spec:
containers:
- name: firewall
image: firewall
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: proxy
namespace: proxy
spec:
selector:
matchLabels:
app: proxy
template:
metadata:
labels:
app: proxy
spec:
containers:
- name: proxy
image: proxy
次のようにマニフェストを適用します。
kubectl apply -f service_function.yaml
ServiceFunctionChains
を作成する
トラフィックが通過するネットワーク機能のシーケンスを定義するには、ファイアウォール、プロキシ、ロードバランサなどの各機能が特定のタスクを実行してから、次の機能にトラフィックを渡すパイプラインを作成します。
次のサンプル マニフェストを ServiceFunctionChain.yaml
として保存します。
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: firewall
spec:
sessionAffinity:
clientIpNoDestination:
timeoutSeconds: 3600 # 1hr
serviceFunctions:
- name: firewall
namespace: firewall
podSelector:
matchLabels:
app: firewall
---
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: proxy
spec:
sessionAffinity:
clientIpNoDestination: {}
serviceFunctions:
- name: proxy
namespace: proxy
podSelector:
matchLabels:
app: proxy
次のようにマニフェストを適用します。
kubectl apply -f ServiceFunctionChain.yaml
Service Function は、serviceFunctions
フィールドを使用して ServiceFunctionChain
内にインラインで定義されます。Service Function はエンドポイント セレクタです。
TrafficSelector
リソースを作成する
サービス ステアリングで選択するトラフィックの場所とトラフィックを定義するには、選択したトラフィックに適用する ServiceFunctionChains
を参照する TrafficSelector
リソースを作成します。
次のサンプル マニフェストを TrafficSelector.yaml
として保存します。
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
name: vpn-to-firewall
spec:
serviceFunctionChain: firewall
subject:
pods:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: vpn
podSelector:
matchLabels:
app: vpn
egress:
to:
ipBlock:
cidr: 0.0.0.0/0
ports:
- allPorts:
protocol: UDP
- allPorts:
protocol: TCP
---
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
name: firewall-to-proxy
spec:
serviceFunctionChain: proxy
subject:
pods:
namespaceSelector:
kubernetes.io/metadata.name: firewall
podSelector:
app: firewall
egress:
to:
ipBlock:
cidr: 0.0.0.0/0
ports:
- allPorts:
protocol: UDP
- allPorts:
protocol: TCP
次のようにマニフェストを適用します。
kubectl apply -f TrafficSelector.yaml
サービス ステアリングのトラブルシューティング
このセクションでは、GKE サービス ステアリングに関連する問題を解決する方法について説明します。
ネットワーク トラフィックが流れない
問題をデバッグするには、次の操作を行います。
ステップ 1: servicePathId
が ServiceFunctionChain
に設定されていることを確認する
servicePathId
が ServiceFunctionChain
に設定されていることを確認します。次の例に示すように、すべての ServiceFunctionChain
オブジェクトに一意の servicePathId
が割り当てられます。
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: firewall
spec:
serviceFunctions:
- name: firewall
namespace: firewall
podSelector:
matchLabels:
app: firewal
status:
servicePathId: 1
ステップ 2: Service Function ごとに Kubernetes Service が作成されていることを確認する
Service Function ごとに ClusterIP Service が自動的に作成されます。サービスのリストを表示するには、kubectl
を使用します。
kubectl get svc -A -l networking.gke.io/managed-by=service-steering-controller.gke.io
ステップ 3: Service Function ごとに、各ノードで bpf マップエントリが作成され、Service IP アドレスが保存されていることを確認する
Service Function ごとに、サービス IP アドレスを格納する bpf マップエントリが各ノードに作成されます。
anetd
Pod の名前を取得します。
kubectl get pods -n kube-system -o wide -l k8s-app=cilium
anetd
のような Pod の名前を記録します。
次のコマンドを実行します。
kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcpath list
ANETD-POD-NAME
は、anetd
Pod の名前で置き換えます。
出力は次のようになります。
PATH SERVICE FUNCTION ADDRESS
(1, 1) 10.4.10.124
ステップ 4: sfcselect
マップで bpf マップエントリが作成されていることを確認する
ノードで、TrafficSelector
によって選択された Pod がある場合、bpf マップエントリが sfcselect
マップに作成されます。次の例では、エンドポイント(Pod)3783 の任意のポートから宛先 IP アドレス 10.0.2.12 への TCP / UDP トラフィックが ServiceFunctionChain
に誘導されています。
次のコマンドを実行します。
kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcselect list
ANETD-POD-NAME
は、クラスタ内の anetd Pod の実際の名前に置き換えます。
出力は次のようになります。
SELECTOR PATH
3783, egress, 0/TCP, 10.0.2.12/32 /32 (1, 1)
3783, egress, 0/UDP, 10.0.2.12/32 /32 (1, 1)
ステップ 5: ポート 7081 で tcpdump を使用してネットワーク トラフィックをキャプチャして分析する
Service Steering は、UDP ポート 7081 で Geneve カプセル化を行います。関連するノードで tcpdump を使用してトラフィック フローを分析し、問題が発生している場所を特定できます。
次のステップ
- Pod のマルチネットワーク サポートについて確認する
- サービス ステアリングについて確認する
- Pod のマルチネットワーク サポートの設定を確認する