はじめに
Meadow Supply には、小さなカタログと、動作する買い物かごの見積もり機能があります。公開ページは Shop API に在庫状況を問い合わせます。API は Application Programming Interface の略で、ここでは顧客向けページと内部の在庫サービスをつなぐ、アプリケーションのリクエスト用インターフェースです。この API がページのために在庫を読み取ります。現在は、顧客プロセスと別の訪問者も在庫を直接読み取れます。公開カタログには不要な棚の詳細まで読めてしまいます。
通常の顧客操作を維持しながら、在庫への接続を、承認された名前空間の承認された API ロールに制限してください。再利用できる成果物は、保存した NetworkPolicy とそれに一致する実際の通信境界です。図の緑色表示ではなく、実際のリクエストによって裏付けます。
基本的なターミナルのパス、簡単な YAML、名前空間、Pod、Deployment、Service、ラベルを理解していることを前提とします。この実験では、ポリシーのフィールド、配布された診断コマンド、リクエスト結果を、使う前に説明します。Calico を備えた実際の単一ノード Kubernetes クラスター、アプリケーション、合成データは準備済みです。クラスターのインストール、イメージのビルド、アプリケーションのプログラミングは不要です。所要時間は作者の見積もりで、読む時間と通常の操作ミスへの対応を含みます。これは練習用の見積もりであり、注文、予約、支払いは行いません。
在庫へのアクセスを承認された経路に限定する
このステップでは、Shop API が在庫に到達できるようにしながら、顧客プロセスと訪問者プロセスが API を迂回するのを防ぎます。
Shop タブから始めます。Meadow Supply には Good things for everyday と 3 つの商品が表示されるはずです。Glass water bottle を開き、価格 $18.00 と Available · 6 in stock を確認してから、Quantity を 1 にして Try a basket quote を選びます。結果には Ready for collection と $18.00 が表示され、予約、注文、支払いは一切行われていないことが明記されるはずです。Back to product、Back to collection の順に戻ります。
実際のリクエスト経路は次のとおりです。
Customer page → Shop API → Stock service
顧客向けページは、専用の Pod で動作しています。サイトを開いても、ブラウザーがクラスターの Pod になるわけではありません。在庫へのリクエストは、準備済みのアプリケーションプロセスから送られます。API は、新しいネットワーク接続を通じて在庫を読み、承認済みのカタログ価格と組み合わせます。静的な在庫データへのフォールバックはありません。別の Reference タブには、Meadow Dispatch の集荷メモが表示されます。開いて P-104 と P-108 を読み、Workspace に切り替えます。この別サービスは、動作を維持する必要があります。
ターミナルは /home/labex/project/stock-policy から始まります。pwd は現在のディレクトリを表示し、ls はその中の項目を一覧表示します。ここに戻る必要がある場合は、絶対パスの cd コマンドを使ってください。
pwd
ls
cd /home/labex/project/stock-policy
scope.json、starter、tools があるはずです。cat は、準備済みの作業範囲ファイルを表示します。このファイルは JSON(JavaScript Object Notation)を使います。これは、名前付きの値とリストを表すテキスト形式です。架空のトポロジー状態ではなく、実際のリソース名とリクエスト対象を列挙しています。
cat scope.json
--context=labex-v135 は、準備済みの実際のクラスターを選択します。--show-labels はオブジェクトのラベルを表示します。名前空間はオブジェクトをまとめますが、それだけでネットワーク接続を遮断するわけではありません。名前空間の識別情報を読みます。
kubectl --context=labex-v135 get namespaces meadow-shop meadow-stock meadow-visitors --show-labels
各名前空間には、その名前と等しい組み込みの kubernetes.io/metadata.name ラベルがあります。-n は名前空間を選びます。Pod とそのラベルを読みます。
kubectl --context=labex-v135 -n meadow-shop get pods --show-labels
kubectl --context=labex-v135 -n meadow-stock get pods --show-labels
kubectl --context=labex-v135 -n meadow-visitors get pods --show-labels
顧客プロセスは role=customer、API は role=shop-api、在庫は role=inventory です。別の集荷サービスは role=dispatch です。訪問者は meadow-visitors にいますが、実際の API と同じ role=shop-api ラベルを意図的に持っています。したがって、ロールラベルだけでは承認された名前空間を識別できません。
Service を読みます。Service は準備済みの Pod を選び、安定したアドレスを提供します。ポートは、アプリケーションの待ち受け先を識別します。TCP(Transmission Control Protocol)は、これらの Web リクエストが使う接続を提供します。在庫プロセスは TCP ポート 8080 で待ち受けます。
kubectl --context=labex-v135 -n meadow-stock get services
配布された ./tools/network-test は、kubectl exec を使い、既存のアプリケーションの実行主体から実際のリクエストを送ります。先頭の ./ は、ツールが現在のディレクトリ内にあることを意味します。最初の引数で customer、api、visitor、stock、reference を選び、次で http、dns、dns-tcp を選び、最後に対象を指定します。ポリシーを変更したり、アプリケーションを修復したりすることはありません。http リクエストは、これらの Web/API エンドポイントで要求と応答に使うプロトコルである HTTP(Hypertext Transfer Protocol)を使います。完全な名前 stock.meadow-stock.svc.cluster.local は、Service 名をアドレスに解決するクラスター DNS(Domain Name System)を通じて、その名前空間内の在庫 Service を識別します。
まず、現在の接続と内容を確認します。分離前は、両方のリクエストが成功することを期待します。
./tools/network-test api http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
./tools/network-test customer http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
HTTP_REPLY 200 に続いて、同じ在庫データが返るはずです。bottle は棚 M-03 に 6 個、notebook は M-08 に 4 個、bag は M-12 に 0 個あります。顧客は、このように内部データを直接読むのではなく、API を通じて公開用の在庫状況を取得するべきです。このベースラインによって、制限を加える前に対象が動作していることを証明できます。
NetworkPolicy は Pod を選び、ある通信方向に対して特定の接続を許可します。Ingress は、選択した Pod に入ってくる接続を意味します。ingress ポリシーが在庫を選択すると、ノードとの通信や Pod 自身への通信など、Kubernetes の文書に記載された例外を除き、許可された着信経路だけが利用可能になります。これは Pod のネットワーク制御であり、ユーザー認証や HTTP の認可ではありません。
リリースディレクトリを作成します。mkdir -p は必要なら作成し、既存のディレクトリは維持します。次の cat コマンドは、ポリシー全体を自分のリリースファイルに書き込みます。> は出力をそのファイルにリダイレクトし、引用符付きの YAML マーカーは、単独の行にある最後のマーカーまでテキストをそのまま扱わせます。繰り返すと、この編集可能なポリシーファイルだけが置き換わります。
mkdir -p release
cat > release/stock-ingress.yaml <<'YAML'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: stock-ingress
namespace: meadow-stock
spec:
podSelector:
matchLabels:
role: inventory
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: meadow-shop
podSelector:
matchLabels:
role: shop-api
ports:
- protocol: TCP
port: 8080
YAML
適用前に、保存したファイルを読みます。
cat release/stock-ingress.yaml
外側の podSelector は在庫だけを選び、集荷サービスはこのポリシーの対象外にします。1 つの from 項目内では、namespaceSelector と podSelector の両方が一致しなければなりません。送信元は meadow-shop に存在し、かつ role=shop-api を持つ必要があります。2 つのセレクターは、同じリスト項目の下に並びます。内側の podSelector の前にハイフンをもう 1 つ追加すると、2 つ目の選択肢となって OR の意味になり、承認された名前空間内の他の Pod も許可してしまいます。ポートは、在庫 Pod が待ち受ける TCP ポートです。このルールは API の egress を制限しません。
apply -f は、保存したマニフェストを読み、その名前のポリシーを作成または更新します。アプリケーションを再起動するものではありません。
kubectl --context=labex-v135 apply -f release/stock-ingress.yaml
describe は、Kubernetes がルールをどう解釈したかを表示します。
kubectl --context=labex-v135 -n meadow-stock describe networkpolicy stock-ingress
選択された在庫のロール、送信元の名前空間と API ロール、TCP ポートを読みます。ポリシーの適用が行き渡るまで、数秒かかることがあります。まず、元の許可されたリクエストが、引き続きデータ全体を返すことを確認します。
./tools/network-test api http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
次に、送信元を拒否する必要がある 2 つの異なる理由をテストします。
./tools/network-test customer http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
./tools/network-test visitor http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
最後の 2 コマンドでは、NETWORK_TIMEOUT とゼロ以外の終了コードが期待されます。Customer は承認された名前空間にいますが、ロールが異なります。Visitor はロールが一致しますが、名前空間が異なります。接続拒否、DNS エラー、対象の停止は、分離の証拠にはなりません。同じ対象への API の成功リクエストが、動作確認の対照になります。ポリシー適用直後に繰り返したリクエストがまだ成功する場合は、数秒待って繰り返してください。実際の拒否対象の経路がタイムアウトするまでは、分離できたと判断してはいけません。
パスを打ち間違えた場合は、前述の pwd、ls、絶対パスの cd を使ってから、失敗した操作を繰り返します。YAML を解析できない場合は、リリースファイルを読み、インデントとハイフンの位置を完全な例と比較し、その編集可能なファイルを書き直して再適用してください。API も遮断された場合は、describe と、すでに表示したラベルおよびポートを調べ、保存したポリシーを修正して再適用します。元の名前空間、ラベル、ワークロード、Pod、Service、アプリケーション、ソースファイル、診断ツールを保持してください。拒否結果を作り出すために、在庫を停止したり、ラベルを変えたり、Pod IP/CIDR のルールを使ったり、ホストのネットワーク設定を変えたり、VM をリセットしたりしてはいけません。
顧客の操作経路全体を確認する
このステップでは、分離後の顧客体験全体を検証し、別の集荷サービスを利用可能に保ちます。
Workspace の /home/labex/project/stock-policy から始めます。Customer による直接の在庫リクエストは意図的に遮断されていますが、Customer は引き続き Shop API に到達できなければなりません。その元の経路を通じてカタログを要求します。
./tools/network-test customer http http://api.meadow-shop.svc.cluster.local:8080/catalogue.json
HTTP_REPLY 200 と、元の価格および数量を持つ承認済みの 3 商品が期待されます。Glass water bottle は 1800 セント / 6 個、Everyday notebook は 1400 / 4、Canvas market bag は 2400 / 0 です。API は、どの元の在庫 Pod が応答したかも報告しますが、公開ページはそのインフラ情報を表示しません。API 経路の成功と直接経路の失敗は両立します。API は、自身に許可された在庫接続を行うためです。
Shop に切り替えて再読み込みします。Glass water bottle を開き、Quantity を 2 にして、Try a basket quote を選びます。Ready for collection、Quantity 2、Total $36.00、Units available 6 が期待されます。練習用の注意書きを読み、在庫が予約されないことを確認してください。Back to product と Back to collection で戻ります。
Back soon と表示されている Canvas market bag を開き、Quantity 1 の見積もりを試します。Not enough stock、Total $24.00、Units available 0 が期待されます。これは有効な業務上の回答であり、ネットワーク障害ではありません。すべての見積もりを成功させるために在庫を変えてはいけません。Back to product、Back to collection の順に戻ります。Our approach を開き、練習用の見積もりについての説明を読んで、Back to collection で戻ります。
完成したカタログには、元の 3 商品と実際の在庫状況が表示されます。見出し、価格、在庫状況を、次の稼働例と比較してください。

Reference に切り替えて再読み込みします。P-104 · Ready と P-108 · Packed が引き続き表示される必要があります。Download notes を選び、実際にダウンロードした notes.json を開きます。在庫データではなく、変更されていない 2 件の集荷レコードが入っています。ブラウザーのダウンロード先とターミナルのワークスペースは異なる場所です。この課題では、そのファイルをワークスペースにコピーする必要はありません。
Workspace に戻り、Customer から同じ別の Service を読みます。
./tools/network-test customer http http://dispatch.meadow-stock.svc.cluster.local:8080/notes.json
HTTP_REPLY 200 と、両方の元のメモが期待されます。ポリシーが選んだのは在庫 Pod であり、在庫の名前空間全体ではありません。集荷プロセス、データ、元の Service を維持してください。停止すると、広すぎるルールを隠してしまいます。
引き渡すのは release/stock-ingress.yaml と、それに一致する実際の通信境界です。完全なカタログと 2 種類の見積もり結果は、元のアプリケーションを通じて引き続き利用でき、直接在庫を読む 2 つの迂回経路は拒否されたままである必要があります。準備されたすべてのソースファイル、アプリケーションオブジェクト、元の Pod を保持してください。ページに Live availability unavailable が表示された場合は、学んだラベル、ポリシー、リクエストの確認に戻り、リリースポリシーだけを修正して再適用します。静的な代替ページは修復ではありません。ここでのテストは、準備済みの 1 クラスター上で行う有限回の実際の TCP リクエストであり、本番環境のセキュリティや途切れない可用性の保証ではありません。
まとめ
実際の顧客 → API → 在庫という操作経路を維持しながら、ロールが異なる顧客と、別の名前空間でロールが一致する訪問者の両方から、直接在庫を読み取ることを防ぎました。保存した ingress ポリシーは、名前空間とロールの両方を満たす関係を表現しています。実際のカタログ、練習用の見積もり、別の集荷サービスも引き続き動作しています。
NetworkPolicy が制御するのは Pod のネットワーク経路であり、顧客の認証ではありません。タイムアウトは、対象と承認された接続が引き続き動作している場合にだけ、役立つ証拠になります。次の独立した実験では、逆方向である API の egress、DNS、他のポリシーによって追加される権限を考えます。



