【Kubernetes】NetworkPolicyについてざっくり理解して試してみる

スポンサーリンク

はじめに

KubernetesのNetwork Policyについて、ざっくり理解して、実際に動かしてみたいと思います。

NetworkPolicy

NetworkPolicyは、IPアドレスもしくはポートレベルでトラフィックを制御するリソースです。

利用するためには、networkプラグインが必要になります。

トラフィックの制御は下記3つの組み合わせで設定できます。

  • Pod
  • Namespace
  • IPアドレス

これらとポート番号によって、トラフィックを制御します。

マニフェスト

kubectl expalinでマニフェストの内容を確認してみます。

❯ kubectl explain netpol --recursive
KIND:     NetworkPolicy
VERSION:  networking.k8s.io/v1

DESCRIPTION:
     NetworkPolicy describes what network traffic is allowed for a set of Pods

FIELDS:
   apiVersion   <string>
   kind <string>
      :
      :
   spec <Object>
      egress    <[]Object>
         ports  <[]Object>
            endPort     <integer>
            port        <string>
            protocol    <string>
         to     <[]Object>
            ipBlock     <Object>
               cidr     <string>
               except   <[]string>
            namespaceSelector   <Object>
               matchExpressions <[]Object>
                  key   <string>
                  operator      <string>
                  values        <[]string>
               matchLabels      <map[string]string>
            podSelector <Object>
               matchExpressions <[]Object>
                  key   <string>
                  operator      <string>
                  values        <[]string>
               matchLabels      <map[string]string>
      ingress   <[]Object>
         from   <[]Object>
            ipBlock     <Object>
               cidr     <string>
               except   <[]string>
            namespaceSelector   <Object>
               matchExpressions <[]Object>
                  key   <string>
                  operator      <string>
                  values        <[]string>
               matchLabels      <map[string]string>
            podSelector <Object>
               matchExpressions <[]Object>
                  key   <string>
                  operator      <string>
                  values        <[]string>
               matchLabels      <map[string]string>
         ports  <[]Object>
            endPort     <integer>
            port        <string>
            protocol    <string>
      podSelector       <Object>
         matchExpressions       <[]Object>
            key <string>
            operator    <string>
            values      <[]string>
         matchLabels    <map[string]string>
      policyTypes       <[]string>

下記はサンプルのNetworkPolicyです。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector: # NetworkPolicyを適用するPod
    matchLabels:
      netpol-myproject: allow
  policyTypes: # NetworkPolicyが外向きか内向きか
  - Ingress
  - Egress
  ingress: # 内向きのトラフィック(fromとportsに一致するトラフィックを許可)
  - from:
    - ipBlock: # IPアドレスでの制御
        cidr: 192.168.1.0/24
        except:
        - 192.168.1.1/32
    - namespaceSelector: # Namespaceでの制御
        matchLabels:
          project: myproject
    - podSelector: # Podでの制御
        matchExpressions:
          - key: role
            operator: In
            values: [app]
    ports:
    - protocol: TCP
      port: 8080
  egress: # 外向きのトラフィック(toとportsに一致するトラフィックを許可)
  - to:
    - ipBlock:
        cidr: 192.168.2.0/24
    - namespaceSelector: # NamespaceとPodでの制御(書き方に注意)
        matchLabels:
          project: yourproject
      podSelector:
        matchExpressions:
          - key: role
            operator: In
            values: [app]
    ports:
    - protocol: TCP
      port: 8080

ingressとegressの設定

ingressegressでは下記4つのセレクターでトラフィックを制御します。

  • podSelector
  • namespaceSelector
  • podSelectornamespaceSelector
  • ipBlock

podSelectornamespaceSelectorの組み合わせのパターンはyamlの書き方に気をつける必要があります。

実際に試してみる

実際にNetworkPolicyを設定して、トラフィックが制御されているのを確認してみたいと思います。

minikubeの準備

下記のコマンドでminikubeを起動して、NetworkPolicyを使えるようにします。

minikube start --network-plugin=cni --cni=calico

リソースの準備

準備するのは2つのPodと2つのNetworkPolicyです。

.
├── to-dns.yml
├── deny-to-all.yml
├── pod-allow.yml
└── pod-deny.yml
  • Google Public DNS(8.8.8.8)のポート53へのトラフィックを許可するNetworkPolicy
  • デフォルトで外向き全てを拒否するNetworkPolicy
  • Google Public DNSのポート53へのトラフィックを許可するラベルがついたPod
  • ラベルがついていないPod

8.8.8.8:53だけに通信できるPod(pod-allow)と外向きの通信が全て制限されているPod(pod-deny)を作成して、トラフィックを比較してみます。

to-dns.ymlは下記の通りです。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: to-dns
  namespace: default
spec:
  podSelector:
    matchLabels:
      to-dns: allow
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: TCP
      port: 53

deny-to-all.ymlは下記の通りです。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

pod-deny.ymlは下記の通りです。

apiVersion: v1
kind: Pod
metadata:
  name: pod-deny
spec:
  containers:
  - name: net
    image: dersimn/netutils
    command:
      - sleep
      - "9999"

pod-allow.ymlは下記の通りです。

apiVersion: v1
kind: Pod
metadata:
  name: pod-allow
  labels:
    to-dns: allow
spec:
  containers:
  - name: net
    image: dersimn/netutils
    command:
      - sleep
      - "9999"

リソースを作成します。

kubectl apply -f to-dns.yml
kubectl apply -f deny-to-all.yml
kubectl apply -f pod-deny.yml
kubectl apply -f pod-allow.yml

疎通確認

pod-allowpod-denyからそれぞれ疎通確認してみたいと思います。

8.8.8.8にポート指定で疎通確認してみると、pod-allowのみ成功していることがわかります。

❯ kubectl exec pod-allow -- nc -vz 8.8.8.8 53
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!

❯ kubectl exec pod-deny -- nc -vz 8.8.8.8 53
nc: connect to 8.8.8.8 port 53 (tcp) failed: Connection timed out
command terminated with exit code 1

curlを使ってポート指定しても、pod-denyはタイムアウトになっています。pod-allowはEmpty replyになっていますが、8.8.8.8にはたどり着けているのかと思います。

❯ kubectl exec pod-allow -- curl -l 8.8.8.8:53
curl: (52) Empty reply from server
command terminated with exit code 52

❯ kubectl exec pod-deny -- curl -l 8.8.8.8:53
curl: (28) Failed to connect to 8.8.8.8 port 53: Connection timed out
command terminated with exit code 28

ポート指定していないpingで疎通確認すると、どちらもパケットが届いていないことがわかります。

❯ kubectl exec pod-allow -- ping -c 10 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

--- 8.8.8.8 ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 9281ms

command terminated with exit code 1

❯ kubectl exec pod-deny -- ping -c 10 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

--- 8.8.8.8 ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 9236ms

command terminated with exit code 1

tracerouteでも、どちらもたどり着けていません。

❯ kubectl exec pod-allow -- traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  192.168.64.3 (192.168.64.3)  0.114 ms  0.026 ms  0.013 ms
 2  * * *
    :
29  * * *
30  * * *

❯ kubectl exec pod-deny -- traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  192.168.64.3 (192.168.64.3)  0.159 ms  0.015 ms  0.015 ms
 2  * * *
    :
29  * * *
30  * * *

疎通確認については、こちらを参考にしてください。

【Linux】ネットワークのトラブルシューティング手順とコマンドまとめ
はじめにネットワークに問題が発生したときのトラブルシューティングについて、順番にコマンドで確認することで原因を特定できるようにまとめてみました。どんな問題もこれで特定できるわけではないと思いますが、どこらへんに原因があるかはある程度目処...

まとめ

  • NetworkPolicyでトラフィックの制御ができる
  • PodとNamespaceとIPアドレスで制御可能

下記もサンプルとして、NetworkPolicyを理解する助けになります。

GitHub - ahmetb/kubernetes-network-policy-recipes: Example recipes for Kubernetes Network Policies that you can just copy paste
Example recipes for Kubernetes Network Policies that you can just copy paste - GitHub - ahmetb/kubernetes-network-policy-recipes: Example recipes for Kubernetes...

参考

タイトルとURLをコピーしました