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

2022.04.16
2024.03.24
Kubernetes
NetworkPolicyPod

はじめに

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

NetworkPolicy

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

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

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

  • Pod
  • Namespace
  • IPアドレス

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

マニフェスト

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

1❯ kubectl explain netpol --recursive
2KIND:     NetworkPolicy
3VERSION:  networking.k8s.io/v1
4
5DESCRIPTION:
6     NetworkPolicy describes what network traffic is allowed for a set of Pods
7
8FIELDS:
9   apiVersion   <string>
10   kind <string>
11      :
12      :
13   spec <Object>
14      egress    <[]Object>
15         ports  <[]Object>
16            endPort     <integer>
17            port        <string>
18            protocol    <string>
19         to     <[]Object>
20            ipBlock     <Object>
21               cidr     <string>
22               except   <[]string>
23            namespaceSelector   <Object>
24               matchExpressions <[]Object>
25                  key   <string>
26                  operator      <string>
27                  values        <[]string>
28               matchLabels      <map[string]string>
29            podSelector <Object>
30               matchExpressions <[]Object>
31                  key   <string>
32                  operator      <string>
33                  values        <[]string>
34               matchLabels      <map[string]string>
35      ingress   <[]Object>
36         from   <[]Object>
37            ipBlock     <Object>
38               cidr     <string>
39               except   <[]string>
40            namespaceSelector   <Object>
41               matchExpressions <[]Object>
42                  key   <string>
43                  operator      <string>
44                  values        <[]string>
45               matchLabels      <map[string]string>
46            podSelector <Object>
47               matchExpressions <[]Object>
48                  key   <string>
49                  operator      <string>
50                  values        <[]string>
51               matchLabels      <map[string]string>
52         ports  <[]Object>
53            endPort     <integer>
54            port        <string>
55            protocol    <string>
56      podSelector       <Object>
57         matchExpressions       <[]Object>
58            key <string>
59            operator    <string>
60            values      <[]string>
61         matchLabels    <map[string]string>
62      policyTypes       <[]string>

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

1apiVersion: networking.k8s.io/v1
2kind: NetworkPolicy
3metadata:
4  name: test-network-policy
5  namespace: default
6spec:
7  podSelector: # NetworkPolicyを適用するPod
8    matchLabels:
9      netpol-myproject: allow
10  policyTypes: # NetworkPolicyが外向きか内向きか
11  - Ingress
12  - Egress
13  ingress: # 内向きのトラフィック(fromとportsに一致するトラフィックを許可)
14  - from:
15    - ipBlock: # IPアドレスでの制御
16        cidr: 192.168.1.0/24
17        except:
18        - 192.168.1.1/32
19    - namespaceSelector: # Namespaceでの制御
20        matchLabels:
21          project: myproject
22    - podSelector: # Podでの制御
23        matchExpressions:
24          - key: role
25            operator: In
26            values: [app]
27    ports:
28    - protocol: TCP
29      port: 8080
30  egress: # 外向きのトラフィック(toとportsに一致するトラフィックを許可)
31  - to:
32    - ipBlock:
33        cidr: 192.168.2.0/24
34    - namespaceSelector: # NamespaceとPodでの制御(書き方に注意)
35        matchLabels:
36          project: yourproject
37      podSelector:
38        matchExpressions:
39          - key: role
40            operator: In
41            values: [app]
42    ports:
43    - protocol: TCP
44      port: 8080

ingressとegressの設定

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

  • podSelector
  • namespaceSelector
  • podSelectornamespaceSelector
  • ipBlock

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

実際に試してみる

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

minikubeの準備

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

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

リソースの準備

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

1.
2├── to-dns.yml
3├── deny-to-all.yml
4├── pod-allow.yml
5└── 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は下記の通りです。

1apiVersion: networking.k8s.io/v1
2kind: NetworkPolicy
3metadata:
4  name: to-dns
5  namespace: default
6spec:
7  podSelector:
8    matchLabels:
9      to-dns: allow
10  policyTypes:
11  - Egress
12  egress:
13  - to:
14    - ipBlock:
15        cidr: 8.8.8.8/32
16    ports:
17    - protocol: TCP
18      port: 53

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

1apiVersion: networking.k8s.io/v1
2kind: NetworkPolicy
3metadata:
4  name: default-deny-egress
5spec:
6  podSelector: {}
7  policyTypes:
8  - Egress

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

1apiVersion: v1
2kind: Pod
3metadata:
4  name: pod-deny
5spec:
6  containers:
7  - name: net
8    image: dersimn/netutils
9    command:
10      - sleep
11      - "9999"

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

1apiVersion: v1
2kind: Pod
3metadata:
4  name: pod-allow
5  labels:
6    to-dns: allow
7spec:
8  containers:
9  - name: net
10    image: dersimn/netutils
11    command:
12      - sleep
13      - "9999"

リソースを作成します。

1kubectl apply -f to-dns.yml
2kubectl apply -f deny-to-all.yml
3kubectl apply -f pod-deny.yml
4kubectl apply -f pod-allow.yml

疎通確認

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

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

1❯ kubectl exec pod-allow -- nc -vz 8.8.8.8 53
2Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
3
4❯ kubectl exec pod-deny -- nc -vz 8.8.8.8 53
5nc: connect to 8.8.8.8 port 53 (tcp) failed: Connection timed out
6command terminated with exit code 1

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

1❯ kubectl exec pod-allow -- curl -l 8.8.8.8:53
2curl: (52) Empty reply from server
3command terminated with exit code 52
4
5❯ kubectl exec pod-deny -- curl -l 8.8.8.8:53
6curl: (28) Failed to connect to 8.8.8.8 port 53: Connection timed out
7command terminated with exit code 28

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

1❯ kubectl exec pod-allow -- ping -c 10 8.8.8.8
2PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
3
4--- 8.8.8.8 ping statistics ---
510 packets transmitted, 0 received, 100% packet loss, time 9281ms
6
7command terminated with exit code 1
8
9❯ kubectl exec pod-deny -- ping -c 10 8.8.8.8
10PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
11
12--- 8.8.8.8 ping statistics ---
1310 packets transmitted, 0 received, 100% packet loss, time 9236ms
14
15command terminated with exit code 1

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

1❯ kubectl exec pod-allow -- traceroute 8.8.8.8
2traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
3 1  192.168.64.3 (192.168.64.3)  0.114 ms  0.026 ms  0.013 ms
4 2  * * *
5    :
629  * * *
730  * * *
8
9❯ kubectl exec pod-deny -- traceroute 8.8.8.8
10traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
11 1  192.168.64.3 (192.168.64.3)  0.159 ms  0.015 ms  0.015 ms
12 2  * * *
13    :
1429  * * *
1530  * * *

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

【Linux】ネットワークのトラブルシューティング手順とコマンドまとめ

【Linux】ネットワークのトラブルシューティング手順とコマンドまとめ

:::affiliate-message 本ページはAmazonアフィリエイトのリンクを含みます。

まとめ

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

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

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

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 - ahmetb/kubernetes-network-policy-recipes

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee