Kubernetes ポリシーを使用したポッド間のトラフィックの制御
Virtual Private Cloud
Kubernetes ポリシーを使用すると、クラスター内のポッド間のネットワーク・トラフィックを制御すること、また、1 つの名前空間または複数の名前空間でアプリのマイクロサービスを互いから分離することができます。
アプリケーションのレベル: ワーカー・ノードのホスト・エンドポイント
デフォルトの動作: Kubernetes ネットワーク・ポリシーは、デフォルトでクラスター内に存在しません。 デフォルトでは、すべてのポッドに、クラスター内の他のすべてのポッドへのアクセス権限があります。 さらに、ポッドは、ポッド・ネットワークによって公開されるサービス (メトリック・サービス、クラスター DNS、API サーバー、クラスター内で手動で作成するサービスなど) にアクセスできます。
ユース・ケース: Kubernetes ネットワーク・ポリシーにより、ポッドが他のポッドおよび外部エンドポイントと通信する方法を指定します。 着信ネットワーク・トラフィックと発信ネットワーク・トラフィックの両方を、プロトコル、ポート、およびソースまたは宛先 IP アドレスに基づいて許可またはブロックできます。 トラフィックは、ポッドおよび名前空間ラベルに基づいてフィルタリングすることもできます。 Kubernetes ネットワーク・ポリシーは、適用されると自動的に Calico ネットワーク・ポリシーに変換されます。 クラスター内の Calico ネットワーク・プラグインは、ワーカー・ノード上に Linux Iptables 規則をセットアップすることによって、これらのポリシーを適用します。 iptables 規則はワーカー・ノードのファイアウォールとして機能し、ネットワーク・トラフィックがターゲット・リソースに転送されるために満たさなければならない特性を定義します。
ほとんどまたはすべてのポッドが特定のポッドまたはサービスにアクセスする必要がなく、かつそれらのポッドまたはサービスにデフォルトでポッドがアクセスできないようにする場合は、Kubernetes ネットワーク・ポリシーを作成して、それらのポッドまたはサービスへの Ingress トラフィックをブロックできます。 例えば、すべてのポッドは CoreDNS ポッド上のメトリック・エンドポイントにアクセスできるようになっています。 不必要なアクセスをブロックするために、以下のようなポリシーを適用できます。まず、TCP
と UDP のポート 53 へのすべての Ingress を許可して、ポッドが CoreDNS 機能にアクセスできるようにします。 ただし、他のすべての Ingress では CoreDNS ポッドからメトリックを収集する試みなどをブロックし、例外として、coredns-metrics-policy: allow
ラベルの付いた名前空間にあるポッドやサービス、または kube-system
ラベルの付いた coredns-metrics-policy: allow
名前空間にあるポッドからの要求を許可します。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: coredns-metrics
namespace: kube-system
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
coredns-metrics-policy: allow
- podSelector:
matchLabels:
coredns-metrics-policy: allow
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
podSelector:
matchLabels:
k8s-app: kube-dns
policyTypes:
- Ingress
Kubernetes ネットワークポリシーがポッド間のトラフィックをどのように制御するか、またポリシーの例についての詳細は 、 Kubernetes のドキュメントを参照してください。
1 つの名前空間でのアプリ・サービスの分離
以下のシナリオでは、1 つの名前空間でアプリのマイクロサービス間のトラフィックを管理する方法を説明します。
Accounts チームは、1 つの名前空間に複数のアプリ・サービスをデプロイしますが、パブリック・ネットワークによるマイクロサービス間の通信を、必要なものだけに制限するために分離を必要としています。 アプリ Srv1
については、チームにはフロントエンド・サービス、バックエンド・サービス、データベース・サービスがあります。 それぞれのサービスに app: Srv1
というラベルと tier: frontend
、tier: backend
、tier: db
というラベルを付けています。
Accounts チームは、フロントエンドからバックエンド、およびバックエンドからデータベースへのトラフィックを許可する必要があります。 そこで、ネットワーク・ポリシーでラベルを使用し、マイクロサービス間でどのトラフィック・フローを許可するかを指定することにしました。
まずは、フロントエンドからバックエンドへのトラフィックを許可する Kubernetes ネットワーク・ポリシーを作成します。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: backend-allow
spec:
podSelector:
matchLabels:
app: Srv1
tier: backend
ingress:
- from:
- podSelector:
matchLabels:
app: Srv1
Tier: frontend
spec.podSelector.matchLabels
セクションには、Srv1 バックエンド・サービスのラベルがリストされるため、このポリシーはそれらのポッド_に_のみ適用されます。 spec.ingress.from.podSelector.matchLabels
セクションには、Srv1 フロントエンド・サービスのラベルがリストされるため、それらのポッド_から_の Ingress のみが許可されます。
次に、バックエンドからデータベースへのトラフィックを許可する同じような Kubernetes ネットワーク・ポリシーを作成します。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: db-allow
spec:
podSelector:
matchLabels:
app: Srv1
tier: db
ingress:
- from:
- podSelector:
matchLabels:
app: Srv1
Tier: backend
spec.podSelector.matchLabels
セクションには、 Srv1 データベース・サービスのラベルがリストされるため、このポリシーはそれらのポッド_に_ のみ適用されます。 spec.ingress.from.podSelector.matchLabels
セクションには、Srv1 バックエンド・サービスのラベルがリストされるため、それらのポッド_から_の Ingress のみが許可されます。
これで、フロントエンドからバックエンドと、バックエンドからデータベースにトラフィックが流れるようになりました。 データベースはバックエンドに、バックエンドはフロントエンドに応答できますが、逆のトラフィック接続を確立することはできません。
複数の名前空間でのアプリ・サービスの分離
以下のシナリオでは、複数の名前空間でアプリのマイクロサービス間のトラフィックを管理する方法を説明します。
異なるサブチームが所有するサービスはコミュニケーションを取る必要があるが、サービスは同一のクラスタ内で異なるネームスペースに展開されている。 Accounts チームは、アプリ Srv1 のフロントエンド・サービス、バックエンド・サービス、データベース・サービスを accounts 名前空間にデプロイします。 Finance チームは、アプリ Srv2 のフロントエンド・サービス、バックエンド・サービス、データベース・サービスを finance 名前空間にデプロイします。 両方のチームは、それぞれのサービスに
app: Srv1
または app: Srv2
というラベルと tier: frontend
、tier: backend
、tier: db
というラベルを付けます。 また、名前空間に usage: accounts
または usage: finance
というラベルを付けます。
Finance チームの Srv2 は、Accounts チームの Srv1 のバックエンドの情報を必要とします。 そのため、Accounts チームは、ラベルを使用して、finance 名前空間から accounts 名前空間の Srv1 バックエンドへのすべてのトラフィックを許可する Kubernetes ネットワーク・ポリシーを作成します。 また、ポート 3111 を指定して、そのポートを使用するアクセスのみを分離します。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
Namespace: accounts
name: accounts-allow
spec:
podSelector:
matchLabels:
app: Srv1
Tier: backend
ingress:
- from:
- NamespaceSelector:
matchLabels:
usage: finance
ports:
port: 3111
spec.podSelector.matchLabels
セクションには、Srv1 バックエンド・サービスのラベルがリストされるため、このポリシーはそれらのポッド_に_のみ適用されます。 spec.ingress.from.NamespaceSelector.matchLabels
セクションには finance 名前空間のラベルがリストされ、その名前空間 _から_の Ingress のみが許可されます。
これで、finance マイクロサービスから accounts の Srv1 バックエンドにトラフィックが流れるようになりました。 accounts の Srv1 バックエンドは、finance マイクロサービスに応答できますが、逆のトラフィック接続を確立することはできません。
この例では、finance 名前空間のすべてのマイクロサービスからのトラフィックがすべて許可されます。 podSelector
と namespaceSelector
を組み合わせることはできないため、別の名前空間の特定のアプリ・ポッドからのトラフィックを許可することはできません。
バージョン 1.28 以降で稼働するクラスターを持つ VPC に必要なポリシー・ルール
バージョン1.27以前では、VPC クラスターはContainer Registryのプライベート・クラウド・サービス・エンドポイントを通じてIBM Cloud Container Registryからイメージを取得します。 バージョン1.28以降では、このネットワークパスが更新され、イメージはプライベートサービスのエンドポイントではなく、VPEゲートウェイを経由するようになりました。 この変更は、VPC内のすべてのクラスタに影響します。VPC内の1つのクラスタをバージョン1.28に作成または更新すると、そのVPC内のすべてのクラスタは、バージョンやタイプに関係なく、ネットワークパスが更新されます。 詳しくは、 VPC クラスターのネットワーキングの変更 を参照してください。
VPC 内にバージョン 1.28 以降を実行するクラスターがあり、 Calico ポリシーを使用してクラスター・ワーカーからのアウトバウンド接続を制限する場合は、以下のポリシー・ルールを追加して、レジストリー用の VPE ゲートウェイへの接続を許可する必要があります。 このポリシーは、VPC 内のゾーンごとに作成する必要があり、ゾーンの VPC アドレス接頭部範囲全体を宛先 CIDR として指定する必要があります。 VPC 内の各ゾーンの VPC アドレス接頭部の範囲を見つけるには、
ibmcloud is vpc-address-prefixes <vpc_name_or_id>
を実行します。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-vpe-gateway-registry
spec:
egress:
- action: Allow
destination:
nets:
- <entire-vpc-address-prefix-range> # example: 10.245.0.0/16
ports:
- 443
- 4443
protocol: TCP
source: {}
order: 500
selector: ibm.role == 'worker_private'
types:
- Egress