AmbientとKubernetes NetworkPolicy

KubernetesのNetworkPolicyを使用すると、レイヤー4トラフィックがPodに到達する方法を制御できます。

NetworkPolicy は通常、クラスターにインストールされた CNI によって適用されます。Istio は CNI ではなく、NetworkPolicy を適用または管理しません。また、すべての場合において尊重します。アンビエントは Kubernetes NetworkPolicy の適用をバイパスすることはありませんし、今後もありません。

このことの含意として、Istio トラフィックをブロックしたり、Istio の機能を妨げたりする Kubernetes NetworkPolicy を作成できる可能性があります。そのため、NetworkPolicy とアンビエントを一緒に使用する場合は、いくつかの注意点があります。

AmbientトラフィックオーバーレイとKubernetes NetworkPolicy

アプリケーションをアンビエントメッシュに追加すると、アンビエントのセキュアな L4 オーバーレイは、ポート 15008 経由でポッド間のトラフィックをトンネリングします。セキュリティ保護されたトラフィックが宛先ポート 15008 でターゲットポッドに入ると、トラフィックは元の宛先ポートにプロキシバックされます。

ただし、NetworkPolicy はポッドの外側のホストで適用されます。つまり、たとえば、アンビエントポッドへのインバウンドトラフィックをすべてのポート(443 を除く)で拒否する既存の NetworkPolicy がある場合は、ポート 15008 の例外をその NetworkPolicy に追加する必要があります。

たとえば、次の NetworkPolicy は、ポート 15008 の my-app へのインバウンド HBONE トラフィックをブロックします

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
  ingress:
  - ports:
    - port: 9090
      protocol: TCP
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app

そして、次のように変更する必要があります

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
  ingress:
  - ports:
    - port: 8080
      protocol: TCP
    - port: 15008
      protocol: TCP
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app

my-app がアンビエントメッシュに追加された場合。

Ambient、ヘルスプローブ、およびKubernetes NetworkPolicy

Kubernetes ヘルスチェックプローブは問題を引き起こし、Kubernetes トラフィックポリシー全般で特殊なケースを作成します。これらは、クラスター内の別のポッドからではなく、ノード上でプロセスとして実行されている kubelet から発信されます。それらはプレーンテキストであり、セキュリティ保護されていません。kubelet または Kubernetes ノードのどちらも、通常、独自の暗号化 ID を持っていないため、アクセス制御は不可能です。ヘルスプローブポートですべてのトラフィックを許可するだけでは不十分です。悪意のあるトラフィックも kubelet と同じようにそのポートを簡単に使用できるからです。さらに、多くのアプリがヘルスプローブと正当なアプリケーショントラフィックに同じポートを使用するため、単純なポートベースの許可は受け入れられません。

さまざまな CNI 実装は、さまざまな方法でこれを解決し、kubelet ヘルスプローブを通常のポリシー適用から静かに除外するか、それらのポリシー例外を構成することで、問題を回避しようとしています。

Istio アンビエントでは、この問題は、iptables ルールとソースネットワークアドレス変換(SNAT)の組み合わせを使用して、ローカルノードから確実に発信されたパケットのみを固定のリンクローカル IP で書き換えることで解決されます。これにより、セキュリティ保護されていないヘルスプローブトラフィックとして Istio ポリシーの適用によって明示的に無視できます。リンクローカル IP は、通常、イングレス-エグレスコントロールでは無視され、IETF 標準ではローカルサブネットワークの外部ではルーティングできないため、デフォルトとして選択されました。

この動作は、ポッドをアンビエントメッシュに追加すると透過的に有効になり、デフォルトでは、アンビエントはリンクローカルアドレス 169.254.7.127 を使用して、kubelet ヘルスプローブパケットを識別し、正しく許可します。

ただし、ワークロード、名前空間、またはクラスターに既存のイングレスまたはエグレス NetworkPolicy がある場合、使用している CNI によっては、このリンクローカルアドレスを持つパケットが明示的な NetworkPolicy によってブロックされる可能性があり、ポッドをアンビエントメッシュに追加すると、アプリケーションポッドのヘルスプローブが失敗し始める可能性があります。

たとえば、名前空間に次の NetworkPolicy を適用すると、my-app ポッドへのすべてのトラフィック(Istio かどうかに関係なく)がブロックされます。kubelet ヘルスプローブも含まれます。CNI によっては、kubelet プローブとリンクローカルアドレスがこのポリシーによって無視されたり、ブロックされたりする可能性があります。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-ingress
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app
  policyTypes:
  - Ingress

ポッドがアンビエントメッシュに登録されると、ヘルスプローブパケットは SNAT を介してリンクローカルアドレスが割り当てられるようになるため、ヘルスプローブが CNI の NetworkPolicy 実装によってブロックされ始める可能性があります。アンビエントヘルスプローブが NetworkPolicy をバイパスできるようにするには、ホストノードからのトラフィックをポッドに許可することで、このトラフィックにアンビエントが使用するリンクローカルアドレスを許可リストに明示的に追加します。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-ingress-allow-kubelet-healthprobes
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app
  ingress:
    - from:
      - ipBlock:
          cidr: 169.254.7.127/32
この情報は役に立ちましたか?
何か改善点があれば教えてください。

フィードバックありがとうございます!