k8sのNetworkPolicyについて入門する

4 min read読了の目安(約3900字

KubernetesのNetwork Policyを初めて使いたい人向けの入門記事です。

NetworkPolicyとは?

  • Podに対して、Pod間の通信や外部のエンドポイントへの通信を制御する為のリソース
  • labelを用いてPodを選択し、選択されたPodのtrafficのruleを設定する
    • podSelectorの指定を空にすることでNetworkPolicyが属するNamespace上の全てのPodを対象にできる
      • Namespace単位でtrafficの制御ができる

EKSにおけるNetworkPolicy

  • CalicoをインストールすることでNetworkPolicyが使えるようになる
  • Fargateではサポートされない

Calico

Ref:https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/calico.html

k apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.5/config/v1.5/calico.yaml
k get daemonset calico-node --namespace kube-system
k get daemonset calico-node --namespace kube-system
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
calico-node   2         2         2       2            2           beta.kubernetes.io/os=linux   41s
  • 使ってみるだけならこれだけで完了

NetworkPolicyを検証してみる

構成

  • layer1,2,3の3種類のnamespaceを作成する
  • nginx/busyboxのDeploymentとServiceを作成する
  • 浅いlayerから深いlayerへの通信はできるが、その逆はできないようにNetworkPolicyを設定

NetworkPolicy

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-layer1
  namespace: layer1
spec:
  # podSelecorに空の指定をすることで、NetworkPolicyが存在するnamespace内の全てのPodを対象とする
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  # namespace内の通信を許可する為に、layer1 namespaceからのtrafficをallow
  ingress:
  - from:
    # layer1からのtraficをallow
    - namespaceSelector:
        matchLabels:
          role: layer1
  # egressに空の指定をすることで全てのtrafficをallow
  egress:
  - {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-layer2
  namespace: layer2
spec:
  # podSelecorに空の指定をすることで、NetworkPolicyが存在するnamespace内の全てのPodを対象とする
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    # layer1からのtraficをallow
    - namespaceSelector:
        matchExpressions:
        - key: role
          operator: In
          values: [layer1,layer2]
  # layer3へのtrafficをallow
  egress:
  - {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-layer3
  namespace: layer3
spec:
  # podSelecorに空の指定をすることで、NetworkPolicyが存在するnamespace内の全てのPodを対象とする
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    # layer1,2からのtraficをallow
    - namespaceSelector:
        matchExpressions:
        - key: role
          operator: In
          values: [layer1,layer2]
  # egressを指定しないことで、全てのtrafficをdeny

動作検証

wget --server-response http://nginx1.layer1 -q -O -
  • layer1 -> layer1,2,3
wget --server-response http://nginx1.layer1 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9
wget --server-response http://nginx2.layer2 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9
wget --server-response http://nginx3.layer3 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9
  • layer2 -> layer1,2,3
wget --server-response http://nginx1.layer1 -q -O -
# NG
wget --server-response http://nginx2.layer2 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9
wget --server-response http://nginx3.layer3 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9
  • layer3-> layer1,2,3
wget --server-response http://nginx1.layer1 -q -O -
# NG
wget --server-response http://nginx2.layer2 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9
wget --server-response http://nginx3.layer3 -q -O -
  HTTP/1.1 200 OK
  Server: nginx/1.17.9

気づき

  • calicoをinstallするだけならまぁ簡単
  • egress厳密に絞るとkube-systemへの疎通ができなくなり名前解決ができなくなるよう
  • egressまで厳密に絞るのは困難(ipで指定すると外部に出ることができなくなる)
  • RDS/ElastiCacheなどCluster外へのアクセス制御ができない(IPアドレスでの指定になってしまう、どれだけ絞ってもサブネット単位での制御になる。NLBにSG付与できない問題と似ている)
  • やはりSG per Podが求められる