ネットワークポリシーで通路を狭める
目標
NetworkPolicyをデフォルト拒否から始めて、6つの形に絞り込みながら、特にfrom項目のAND/OR構造を、手で区別します。
なぜ重要なのか
最初にはっきりさせておきます。このラボ環境には、ポリシーを強制するCNIのデータプレーンがありません。そのため、実際にトラフィックが遮断されるかは確認できず、採点はオブジェクトのスペックだけを見ます。この制約は、むしろ試験に似ています。CKAでも、ほとんどは、マニフェストが正確かどうかを見ます。
NetworkPolicyの考え方は、ファイアウォールとは違います。ポリシーが1つでもあるPodを選んだ瞬間、そのPodの該当する方向(Ingress/Egress)のトラフィックはデフォルト拒否に変わり、ポリシーが許可したものだけが通過します。ポリシーは互いに加算されるだけで、拒否ルールは存在しません。そのため、「デフォルト拒否のポリシー1つ + 必要なだけの許可ポリシー」が、標準的なパターンです。
egressを塞ぐときに、DNSも一緒に塞いでしまう事故もよくあります。Podがサービス名を解決できなくなると、症状がネットワークの遮断ではなく、アプリケーションのタイムアウトとして現れ、診断に時間がかかります。
ステップ
- ネームスペース
cka-netpol(ラベルtier=app)とcka-netpol-client(ラベルtier=client)を作成してください。cka-netpolにDeploymentweb(レプリカ2、イメージnginx:1.27、Podラベルapp=web)を作成してください。 cka-netpolにNetworkPolicydefault-deny-ingressを作成してください。podSelectorは空のオブジェクト、policyTypesは[Ingress]で、ingressのルールはありません。- NetworkPolicy
allow-frontendを作成してください。podSelectorapp=web、ingressのfromはpodSelectorapp=frontendだけで、ポートはTCP 80です。 - NetworkPolicy
allow-client-nsを作成してください。podSelectorapp=web、ingressのfromはnamespaceSelectortier=clientだけです(podSelectorは一緒に入れません)。 - NetworkPolicy
egress-dns-onlyを作成してください。podSelectorapp=web、policyTypesは[Egress]、egressのtoはnamespaceSelectorkubernetes.io/metadata.name=kube-systemで、ポートはUDP 53とTCP 53の2つです。 - NetworkPolicy
allow-cidrを作成してください。podSelectorapp=web、ingressのfromはipBlockのcidr10.0.0.0/16で、exceptに10.0.5.0/24を指定します。 - NetworkPolicy
web-finalを作成してください。podSelectorapp=web、policyTypesは[Ingress, Egress]です。ingressのfromは、1つの項目の中にnamespaceSelectortier=clientとpodSelectorapp=frontendを一緒に置き、ポートはTCP 8080です。egressのtoはipBlockのcidr0.0.0.0/0でexcept169.254.169.254/32、ポートはTCP 443です。
参考
- すべてのネームスペースには、
kubernetes.io/metadata.nameラベルが自動で付きます。kube-systemを選ぶときに役立ちます。 kubectl get netpol <이름> -n cka-netpol -o yamlで保存された形を読み直すと、AND/ORの構造が目に入ってきます(プレースホルダーはNetworkPolicy名です)。- よくあるミス1: ステップ7で、fromを2つの項目に分けてしまうことです。そうするとORになり、clientネームスペースのすべてのPodが通り抜けてしまいます。
- よくあるミス2:
169.254.169.254/32を、exceptではなく、別のto項目として書いてしまうことです。exceptはipBlockの中に入ります。
対象と送信元を準備する
ネームスペースcka-netpol(ラベルtier=app)とcka-netpol-client(ラベルtier=client)を作成してください。cka-netpolにDeploymentweb(レプリカ2、イメージnginx:1.27、Podラベルapp=web)を作成してください。
ネームスペースのラベルは、あとでnamespaceSelectorが選ぶための鍵です。Podのラベルも、正確に合わせておいてください。
デフォルト拒否のポリシー
cka-netpolにNetworkPolicydefault-deny-ingressを作成してください。podSelectorは空のオブジェクト、policyTypesは[Ingress]で、ingressのルールはありません。
podSelectorを空のオブジェクトにすると、そのネームスペースのすべてのPodが対象です。ルールを1つも書かなければ、すべて拒否という意味になります。
同じネームスペースのPodだけを許可する
NetworkPolicyallow-frontendを作成してください。podSelectorapp=web、ingressのfromはpodSelectorapp=frontendだけで、ポートはTCP 80です。
fromの項目にpodSelectorだけを書くと、範囲がポリシーのあるネームスペース内に限定されます。ポートも指定する必要があります。
別のネームスペース全体を許可する
NetworkPolicyallow-client-nsを作成してください。podSelectorapp=web、ingressのfromはnamespaceSelectortier=clientだけです(podSelectorは一緒に入れません)。
namespaceSelectorは、ネームスペースに付いたラベルを見ます。今回は、そのネームスペース全体を許可する必要があるので、podSelectorは一緒に入れないでください。
外向きのトラフィックをDNSだけ残して塞ぐ
NetworkPolicyegress-dns-onlyを作成してください。podSelectorapp=web、policyTypesは[Egress]、egressのtoはnamespaceSelectorkubernetes.io/metadata.name=kube-systemで、ポートはUDP 53とTCP 53の2つです。
すべてのネームスペースには、名前と同じ値のラベルが自動で付きます。DNSは、UDPだけでは足りない場合があります。
CIDRで許可し、一部の範囲だけを除く
NetworkPolicyallow-cidrを作成してください。podSelectorapp=web、ingressのfromはipBlockのcidr10.0.0.0/16で、exceptに10.0.5.0/24を指定します。
ipBlockは、cidrとexceptを持ちます。exceptの範囲は、必ずcidrの中に含まれている必要があります。
総合: AND条件とメタデータ範囲の遮断
NetworkPolicyweb-finalを作成してください。podSelectorapp=web、policyTypesは[Ingress, Egress]です。ingressのfromは、1つの項目の中にnamespaceSelectortier=clientとpodSelectorapp=frontendを一緒に置き、ポートはTCP 8080です。egressのtoはipBlockのcidr0.0.0.0/0でexcept169.254.169.254/32、ポートはTCP 443です。
fromの項目を2つに分ければOR、1つの項目の中に2つのセレクターを一緒に書けばANDです。ダッシュの位置1つが、意味を変えます。