DUICUO

CiliumでKubernetesネットワークセキュリティを強化する

要約

ネットワーク ポリシーを通じてネットワーク セキュリティを強化すると、システムにほとんど影響を与えることなく、実装および保守のコストを大幅に削減できます。

特に、eBPF テクノロジーをベースとする Cilium は、カーネルのスケーラビリティ不足の問題を解決し、カーネル レベルでのワークロードに対して安全で信頼性が高く、監視可能なネットワーク接続を提供します。

背景

Kubernetes ネットワークにセキュリティリスクが伴うのはなぜでしょうか? クラスター内のポッドはデフォルトでは分離されていないため、ポッドはネットワークを介して相互に通信できます。

これは問題を引き起こします。例えば、データの機密性により、サービスBはサービスAなどの特定のサービスからのアクセスのみを許可し、サービスCはサービスBにアクセスできない場合があります。サービスCがサービスBにアクセスできないようにするための解決策はいくつかあります。

  • SDKは、ホワイトリスト機能を実装するための一般的なソリューションを提供します。まず、リクエストにはソース識別子が含まれている必要があります。これにより、サーバーは特定の識別子を持つリクエストを許可し、それ以外のリクエストを拒否するルールを受信できます。
  • クラウドネイティブソリューションは、サービスメッシュのRBACとmTLS機能を活用します。RBACの実装原理はアプリケーション層SDKソリューションと類似していますが、インフラストラクチャ層の抽象的な汎用ソリューションに属します。一方、mTLSはより複雑で、接続ハンドシェイクフェーズで認証を実行し、証明書の発行、検証、その他の操作を伴います。

上記の両方のオプションには、それぞれ長所と短所があります。

  • SDK ソリューションは実装が簡単ですが、大規模なシステムでは、アップグレードやプロモーションの難しさ、多言語サポートに関連する高コストなどの課題に直面する可能性があります。
  • サービスメッシュソリューションは、インフラストラクチャ層向けの汎用ソリューションであり、本質的に複数の言語をサポートしています。しかし、サービスメッシュソリューションを実装したことのないユーザーにとって、アーキテクチャの変更は大きく、コストも高くなります。セキュリティ問題の解決のみを目的とした場合、サービスメッシュソリューションの使用は費用対効果が高くありません。既存のサービスメッシュソリューションの実装の難しさや、その後の運用・保守にかかるコストの高さは言うまでもありません。

ネットワーク層から始めて、インフラの下位層におけるソリューションの探求を続けましょう。KubernetesはNetworkPolicy[1]を提供しており、「ネットワークレベルの分離」を実現できます。

アプリケーション例

NetworkPolicyスキームの詳細なデモンストレーションを行う前に、デモンストレーションに使用したサンプルアプリケーションを紹介しましょう。Ciliumのインタラクティブチュートリアル「Cilium入門」[2]で使用されている「スターウォーズ」シナリオを使用します。

スターウォーズファンならおそらくご存知の3つのアプリケーションをご紹介します。

  • Death Star: ポート 80 で Web サービスを提供しており、レプリカが 2 つあり、Kubernetes Service による負荷分散を通じて帝国軍戦闘機に「ログイン」サービスを提供しています。
  • TIE ファイター: ログイン要求を実行しています。
  • X ウイング戦闘機: ログイン要求を実行しています。

図に示すように、3つのアプリケーションを識別するために、orgとclassというラベルを使用しました。これら2つのラベルは、ネットワークポリシーを適用する際に負荷を識別するために使用されます。

 # アプリ.yaml
---
apiバージョン: v1
種類:サービス
メタデータ
名前デススター
ラベル:
アプリ.kubernetes .io /名前: deathstar
仕様:
タイプ: ClusterIP
ポート:
-ポート: 80
セレクター:
組織帝国
クラス:デススター
---
apiバージョン:アプリ/ v1
種類:デプロイメント
メタデータ
名前デススター
ラベル:
アプリ.kubernetes .io /名前: deathstar
仕様:
レプリカ 2
セレクター:
マッチラベル
組織帝国
クラス:デススター
テンプレート
メタデータ
ラベル:
組織帝国
クラス:デススター
アプリ.kubernetes .io /名前: deathstar
仕様:
コンテナ
-名前デススター
画像: docker.io/cilium/starwars
---
apiバージョン: v1
種類:ポッド
メタデータ
名前タイファイター
ラベル:
組織帝国
クラス:タイファイター
アプリ.kubernetes .io /名前: tiefighter
仕様:
コンテナ
-名前宇宙船
イメージ: docker .io / tgraf / netperf
---
apiバージョン: v1
種類:ポッド
メタデータ
名前: xwing
ラベル:
アプリ.kubernetes .io /名前: xwing
組織アライアンス
クラス: xwing
仕様:
コンテナ
-名前宇宙船
イメージ: docker .io / tgraf / netperf

Kubernetes ネットワークポリシー

より詳細な情報は公式ドキュメント[3]から入手できます。ここでは設定を直接示します。

 # ネイティブ/ ネットワークポリシー.yaml
apiバージョン:ネットワーク.k8s .io / v1
種類:ネットワークポリシー
メタデータ
名前:ポリシー
名前空間:デフォルト
仕様:
ポッドセレクタ:
マッチラベル
組織帝国
クラス:デススター
ポリシータイプ:
-イングレス
入口
- から
-ポッドセレクタ:
マッチラベル
組織帝国
ポート:
-プロトコル: TCP
ポート80
  • podSelector: ネットワークポリシーを使用して適用するワークロード分散を指定します。ラベルに基づいて、deathstar から 2 つのポッドが選択されました。
  • `policyTypes`: トラフィックの種類を示します。Ingress、Egress、またはその両方を指定できます。ここでは、Ingress は、選択した Deathstar Pod への受信トラフィックにルールが適用されることを示します。
  • ingress.from: はトラフィックの送信元ワークロードを示します。これもpodSelectorとLabelを使用して選択されます。ここではorg=empireが選択されており、これはすべての「帝国の戦闘機」を意味します。
  • ingress.ports: トラフィックが入力されるポートを示します。このリストには、Deathstar のサービス ポートが表示されます。

次にテストしてみましょう。

テスト

まず環境を準備します。Kubernetes環境としてK3s[4]を使用します。ただし、K3sのデフォルトのCNIプラグインであるFlannelはネットワークポリシーをサポートしていないため、プラグインを変更する必要があります。ここでは、K3s + CalicoソリューションであるCalico[5]を選択します。

まず、単一ノード クラスターを作成します。

 curl - sfL https : // .k3s .ioを取得| K3S_KUBECONFIG_MODE = "644" INSTALL_K3S_EXEC = "--flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --disable=traefik" sh -

この時点では、Calico をまだインストールする必要があるため、すべての Pod は保留状態になっています。

 kubectl apply -f https://projectcalico.docs.tigera.io/manifests/calico.yaml

Calico が正常に実行されると、すべての Pod も正常に実行されます。

次のステップは、アプリケーションをデプロイすることです。

 kubectl apply -fアプリ.yaml

戦略を実行する前に、次のコマンドを実行して、戦闘機がデス・スターに着陸できるかどうかを確認します。

 kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
船が着陸した
kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
船が着陸した

結果は、両方のタイプの「戦闘機」(ポッド負荷)がデススター サービスにアクセスできることを示しています。

この時点で、ネットワーク ポリシーが実行されます。

 kubectl apply -fネイティブ/ネットワークポリシー.yaml

再度「ログイン」しようとすると、xwing ログイン要求はそこで停止します (終了するには ctrl+c を使用するか、要求に --connect-timeout 2 を追加する必要があります)。

考える

Kubernetesネットワークポリシーを使用し、ネットワークレベルでサービスにホワイトリスト機能を追加することで、目的を達成しました。このソリューションは変更コストを一切発生せず、システムへの影響もほとんどありませんでした。

シリウムの物語は、彼が登場する前に終わってしまった?続きを読もう。

当社のサービスでは、ホットアップデートや再起動といった管理操作を実行するためにシステムから呼び出される管理エンドポイントを公開することがあります。これらのエンドポイントは、通常のサービスから呼び出されてはなりません。そうしないと、深刻な影響が生じる可能性があります。

たとえば、次の例では、tiefighter は deathstar の管理エンドポイント /exhaust-port にアクセスします。

 kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
パニックデススターが爆発
ゴルーチン1 [実行中] :
メイン.HandleGarbage ( 0x2080c3f50 , 0x2 , 0x4 , 0x425c0 , 0x5 , 0xa )
/code/src/github.com/empire/deathstar/
temp / main.go : 9 + 0x64
メイン.main ( )
/code/src/github.com/empire/deathstar/
temp / main.go : 5 + 0x85

パニック エラーが発生しました。ポッドを確認すると、dealthstar がダウンしていることがわかります。

Kubernetes ネットワーク ポリシーはレイヤー L3 と L4 でのみ機能し、レイヤー L7 では効果がありません。

まだCiliumを取り出す必要があります。

繊毛ネットワークポリシー

CiliumはLinuxカーネル、ネットワーク、その他関連知識の多くの側面を網羅しているため、その実装原理を説明すると非常に長くなります。そのため、この記事では公式サイトからの紹介のみを抜粋しています。実装については、時間のある時に別の記事で執筆する予定です。

繊毛の紹介

Cilium[6]は、革新的なカーネルテクノロジーeBPF[7]を搭載した、コンテナワークロード(クラウドネイティブ)間のネットワーク接続を提供、保護、監視するために使用されるオープンソースソフトウェアです。

eBPF とは何ですか?

Linuxカーネルは、監視/可観測性、ネットワーク、セキュリティ機能を実装する理想的な環境として常に利用されてきました。しかし、これらのタスクにはカーネルソースコードの変更やカーネルモジュールのロードが必要であり、最終的には既存の抽象化の上に新たな抽象化が重ねられることになるため、容易ではありません。eBPFは、カーネルソースコードの変更やカーネルモジュールのロードなしに、サンドボックスプログラムをカーネル内で実行できる革新的なテクノロジーです。

Linux カーネルをプログラム可能にすることで、システムの複雑さを増大させたり、パフォーマンスやセキュリティを犠牲にしたりすることなく、既存の(新しい抽象化レイヤーを追加するのではなく)抽象化レイヤーに基づいて、よりスマートで機能豊富なインフラストラクチャ ソフトウェアを作成できるようになります。

Cilium のネットワーク戦略を見てみましょう。

 #cilium /ネットワークポリシー- L4.yaml
apiバージョン: "cilium.io/v2"
種類: CiliumNetworkPolicy
メタデータ
名前: "rule1"
仕様:
説明: 「特定の HTTP 呼び出しへのアクセスを制限する L7 ポリシー」
エンドポイントセレクター:
マッチラベル
組織帝国
クラス:デススター
入口
- fromEndpoints :
-マッチラベル:
組織帝国
トポート:
-ポート:
-ポート 「80」
プロトコル: TCP

ネットワーク戦略はKubernetesのネイティブネットワーク戦略とそれほど変わりませんし、前回の紹介ですでに理解しているので、直接テストに移りましょう。

テスト

Cilium自体がCNIを実装しているため、以前のクラスターは使用できなくなりました。まず、クラスターをアンインストールします。

 k3s -アンインストール.sh
# !! 以前のCNIプラグインをクリーンアップすることを忘れないでください
sudo rm -rf /etc/cni/net.d

同じコマンドを使用して、単一ノード クラスターを作成します。

 curl - sfL https : // .k3s .ioを取得| K3S_KUBECONFIG_MODE = "644" INSTALL_K3S_EXEC = "--flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --disable=traefik" sh -
# ciliumはこの変数を使用します
KUBECONFIG =/ etc / rancher / k3s / k3s.yamlをエクスポートします。

次に、Cilium CLI をインストールします。

 curl - L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --cilium-linux-amd64.tar.gz.sha256sum をチェックします
sudo tar xzvfC cilium - linux - amd64 .tar .gz / usr / local / bin
rm cilium - linux - amd64 .tar .gz { ,. sha256sum }
繊毛バージョン
cilium - cli : Linux / amd64 上でgo1 .17 .6でコンパイルされた v0 .10 .2
繊毛画像デフォルト : v1.11.1
繊毛画像安定 : v1.11.1
cilium イメージ(実行中) : 不明。cilium バージョンを取得できません名前空間「kube-system」 cilium ポッドが見つかりません。

クラスターに Cilium をインストールします。

繊毛インストール

Cilium が正常に実行されるのを待機しています:

繊毛の状態
/ ¯¯\
/ ¯¯\__ / ¯¯\ 繊毛 OK
\__ / ¯¯\__ /オペレーター OK
/ ¯¯\__ / ¯¯\ ハッブル無効
\__ / ¯¯\__ / ClusterMesh :無効
__ /
展開繊毛-オペレータ 希望 1 準備完了 1/1 利用可能 1/1
DaemonSet cilium必要: 1 準備完了: 1/1 使用可能: 1/1
容器繊毛実行 1
繊毛-演算子 実行中: 1
クラスターポッド: 3/3 ( Cilium によって管理)
イメージバージョン cilium - operator quay .io / cilium / operator - generic : v1 .11 .1 @sha256 : 977240 a4783c7be821e215ead515da3093a10f4a7baea9f803511a2c2b44a235 : 1
cilium quay .io / cilium / cilium : v1 .11 .1 @sha256 : 251 ff274acf22fd2067b29a31e9fda94253d2961c061577203621583d7e85bd2 : 1

アプリケーションの展開:

 kubectl apply -fアプリ.yaml

アプリケーションの起動後にサービス呼び出しをテストします。

 kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
船が着陸した
kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
船が着陸した

L4 ネットワーク ポリシーを実行します。

 kubectl 適用- f cilium /ネットワークポリシー- L4.yaml

デス・スターに再度「ログイン」しようとしたとき、Xウイング戦闘機はまだログインできず、L4 レイヤー ルールが有効になっていることが示されました。

レイヤー L7 のルールをもう一度試してみましょう。

 #cilium /ネットワークポリシー- L7.yaml
apiバージョン: "cilium.io/v2"
種類: CiliumNetworkPolicy
メタデータ
名前: "rule1"
仕様:
説明: 「特定の HTTP 呼び出しへのアクセスを制限する L7 ポリシー」
エンドポイントセレクター:
マッチラベル
組織帝国
クラス:デススター
入口
- fromEndpoints :
-マッチラベル:
組織帝国
トポート:
-ポート:
-ポート 「80」
プロトコル: TCP
ルール
http :
-メソッド 「POST」
パス: "/v1/request-landing"

実行ルール:

 kubectl 適用- f cilium /ネットワークポリシー- L7.yaml

今回は、Tiefighter を使用して、デス・スターの管理インターフェースを呼び出します。

 kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
アクセスが拒否されました
# ログインインターフェースは正常に動作しています
kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
船が着陸した

今回は、「アクセスが拒否されました」というメッセージが返され、レイヤー 7 のルールが有効になっていることが示されました。