このブログ記事では、Kubernetesにおけるネットワークポリシーとサービスメッシュ(&Gateway API)について紹介します。

これまで、Ingressを使用したクラスターへの安全なエントリーポイントの設定、開発者とサービスによるリソース管理のための安全なアクセス制御、 そしてCI/CDパイプラインについて説明してきました。本番環境のクラスターのセットアップとしてこれで十分に思えますが、 デフォルトでは任意のサービスが他のいかなるサービスを使用できるというセキュリティ脆弱性がまだ存在し、 これはアプリケーションの悪意のあるユーザーが(メトリクスなどの)プライベート情報にアクセスしたり、 本来意図されていない決済サービスを操作したりする機会を提供してしまいます。 そのため、この記事では、クラスター内通信のこのセキュリティ脆弱性を軽減できるネットワークポリシーとサービスメッシュについて説明します。
ネットワークポリシー
Kubernetesでは、コンテナ間のネットワーキングを設定するためにコンテナネットワークインターフェース(CNI)が利用され、
MiniKubeはデフォルトでKindnetをCNIとしてインストールします。Kindnetは高性能で信頼性がありますが、
任意のサービスが他の任意のサービスと通信できるというデフォルト設定を変更するためのネットワークポリシーを設定することができません。
そのため、デフォルトのCNIを無効にして、WeavenetやCalicoなどのネットワークポリシーをサポートするCNIをインストールできます。
幸い、MiniKubeではminikube start
に--cni calico
を追加することで、簡単にCalicoに切り替えることができます。
# nginx-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx # ポリシーを適用するポッドのラベル
ingress: # `nginx`が受信するingressトラフィックに対するルール
- from:
- podSelector:
matchLabels:
access: "true" # `access:true`のラベルのついたポッドのみアクセス可能
---
# default-netpol.yaml (Calicoのネットワークポリシー)
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: default-deny
spec:
selector: projectcalico.org/namespace != "kube-system"
types:
- Ingress
- Egress
上記の例は、ラベルにaccess:true
がないポッドからnginx
ポッドへのアクセスを制限するKubernetesネットワークポリシーと、
デフォルトでkube-system
名前空間のポッド以外のトラフィックを許可しない有用なCalicoグローバルネットワークポリシーを示しており、
ゼロトラストネットワークモデルを実装しています。ご覧のとおり、これら2つは共存してレイヤー3/4でネットワークポリシーを強制でき、
様々なケースで効果的です。詳細については、記事の最後に引用されている関連リソースを確認することをお勧めします。
サービスメッシュ(Istio)
ネットワークポリシーは有用で多くのクラスターにとって十分ですが、レイヤー3/4でのみ動作するため、 より細かい制御のためのレイヤー7機能(TLS、ヘッダー、パスベースルーティング)を使用できません。 その結果、ネットワークポリシーを使用する際、開発者はセキュリティ、リトライメカニズム、 メトリクス収集などの非ビジネスロジックを自分で実装する必要があります。 そこでIstioのようなサービスメッシュは、レイヤー7で動作し、複雑なトラフィックルールの設定とサービス間の安全な通信の効率的なセットアップを可能にしています。 Istioは、カナリアデプロイメント(トラフィックがサービスの複数のバージョンに分割される)もサポートし、 本番環境対応クラスター向けにメトリクス(Prometheusをサポート)もデフォルトで追跡します。

上記のアーキテクチャは、コントロールプレーンのIstiodと、すべてのサービスのサイドカーとしてのEnvoyプロキシで構成されるIstioメッシュを示しています。 サービスメッシュを設定するには、Kubernetesリソースを定義するのと同じように、YAMLファイルを使用してIstiod用のリソースを定義できます。 例えば、AuthorizationPolicy(説明はこちら)を使用してレイヤー7でネットワークポリシーを定義し、 VirtualService(説明はこちら) を使用してトラフィックルーティング(HTTP vs HTTPS、URLリライト、カナリアデプロイメント、リトライなど)を定義し、 DestinationRule(説明はこちら)をロードバランシングの設定に利用できます。
また、クラスターの入り口をIngressコントローラーからIstio Ingress Gatewayに置き換えることで、Istioの機能をクラスターエントリに適用できます。 具体的には、Istio Ingress Gatewayのデフォルト実装を使用するIstio Gatewayを定義し、ドメイン、TLS証明書、デフォルトポリシーを担当させ、 バーチャルサービスを定義して複雑なトラフィックルーティングを設定することで(説明はこちら)、 外部と内部の両方の通信に対するトラフィックルール定義のインターフェースを統一できます。 ここで言及したすべてのリソースの定義方法の例と詳細は、上の対応するリンクからアクセスできます(それほど複雑ではありませんが、この記事には多すぎるパラメータをカバーしています)。
Gateway API
Ingress ControllerよりもIstio Ingress Gatewayを用いる利点は、インターフェースの統一だけでなく、 トラフィックルーティングに対するより大きく細かい制御と役割分担も含みます。Istioは Ingress Gatewayのデフォルト実装の提供に集中でき、 クラスターオペレーターは関連するすべてのサービスのためのIstio Gatewayの設定に集中でき、 開発者は自分のサービスのためのバーチャルサービスを設定できます。Kubernetes Gateway APIは、 標準的なGatewayとHTTPRoute(TLSRoute、GRPCRouteなど)を設定することで、 Istioの限らず多くのインフラストラクチャプロバイダーにわたってユーザーにこれらの利点を提供することを目的としています。

このモデルでは、インフラストラクチャプロバイダー(AWS、Google Cloud、Istioなど)はGatewayClass、ロードバランシングの実装に集中し、
クラスターオペレーターはGatewayClassのカスタムリソースをインストールし、(gatewayClassName
を設定することで)それを使用してドメイン、
TLS、デフォルトポリシーを管理するGatewayを定義します。その後、アプリケーション開発者は、
Gateway経由のトラフィック(parentRefs
で指定)に対する様々なトラフィックルーティング
(ヘッダーベース、パスベース、リライト、カナリアデプロイメントなど)のためのHTTPRoute(または対応するプロトコル用の他のもの)を定義できます。
Istio Gatewayの代わりに、istio
GatewayClassを使用してKubernetes Gatewayを使用し、
開発者がHTTPRouteを定義できるようにすることで、切り替えコストを大幅に削減できます。
結論
この記事では、レイヤー3/4でのネットワークポリシーとレイヤー7でのサービスメッシュ(Istio)を使用したクラスター内通信のルール定義方法、 そしてIngressコントローラーの代わりとして、より大きな制御と役割分担を伴ったクラスターエントリのメカニズムであるIstioとGateway APIについて説明しました。 これらのトピックの詳細はこの記事では大幅に省略されているため、以下に引用されているリソースから確認することをお勧めします。
リソース
- CNCF. 2022. Understanding the new Kubernetes Gateway API vs Ingress.YouTube.
- Kubernetes. n.d. Kubernetes Documentation. Kubernetes.
- minikube. n.d. Network Policy. minikube.
- Tech Tutorials with Piyush. 2024. Day 26/40 - Kubernetes Network Policies Explained. YouTube.
- TechWorld with Nana. 2021. Istio & Service Mesh - simply explained in 15 mins. YouTube.