6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Antrea Cluster Network Policy を使う (2021年版)

Last updated at Posted at 2021-04-15

Antrea とは

Antrea とは、オープンソースの Kubernetes CNI で、L3/4 のネットワーキングの機能とセキュリティを Kubernetes クラスターに提供するものです。オープンな仮想スイッチとして長い実績を誇る Open vSwitch をデータプレーンに利用しています。

Antrea では標準的な Kubernetes クラスターネットワーキングではサポートされない様々な機能の実装が試みられていますが、ネットワークセキュリティの観点で興味深いのが Antrea Cluster Network Policy (ACNP) です。
Antrea は標準的な NetworkPolicy もサポートしていますが、ACNP ではクラスター管理者の要求によりよく答えれるように以下のような機能を提供しています。

  • ポリシーの階層化と優先度設定
  • Namespace に限定されない、クラスターレベルのセキュリティ設定
  • アクションルールのサポート: Allow, Drop, Reject のアクションを指定可能

本記事では、Antrea Cluster Network Policy に注目して機能の確認をしていきたいと思います。

余談ですが、本記事執筆中の2021年4月10日に Antrea は 1.0.0 に到達しました。以下は Antrea 1.0.0 をベースに記載しております。
また、上記の Project Antrea のページ以外に以下の記事も参考にさせていただきました。
https://blog.shin.do/2020/01/antrea-yet-another-cni-plugin-for-kubernetes/

Antrea クラスターの準備

新しい K8s クラスタを準備

今回は kubeadm を使って Antrea 用の Kubernetes クラスターを新たに準備しました。このあたりを参考にしています。
https://thinkit.co.jp/article/18188

Master 1台と Worker 2台を構成しましたが、CNI を適用する前は以下のように NotReady となります。

$ kubectl get node
NAME          STATUS     ROLES                  AGE     VERSION
k8s-master    NotReady   control-plane,master   1d      v1.20.5
k8s-worker1   NotReady   <none>                 44m     v1.20.5
k8s-worker2   NotReady   <none>                 2m41s   v1.20.5

クラスターに Antrea を適用

CNI として Calico ではなく Antrea を適用します。Antrea の初期セットアップについてはこちらもご参照下さい:
https://github.com/vmware-tanzu/antrea/blob/main/docs/getting-started.md

今回は Antrea v1.0.0 を使うので、以下のように指定して適用します。

$ kubectl apply -f https://github.com/vmware-tanzu/antrea/releases/download/v1.0.0/antrea.yml

Latest を適用したい場合は以下でも構いません。

$ kubectl apply -f https://raw.githubusercontent.com/vmware-tanzu/antrea/main/build/yamls/antrea.yml

Antrea CNI を適用すると Node が Ready になりました。

$ kubectl get node
NAME          STATUS   ROLES                  AGE   VERSION
k8s-master    Ready    control-plane,master   1d    v1.20.5
k8s-worker1   Ready    <none>                 57m   v1.20.5
k8s-worker2   Ready    <none>                 15m   v1.20.5

antctl のインストール

antctl は Controller を介して Antrea の設定や状態を確認するためのコマンドラインツールです。今後必要になるかもしれないので最新バージョンをインストールしておきます。以下は 1.0.0 Linux 版の場合です。

$ curl -Lo ./antctl "https://github.com/vmware-tanzu/antrea/releases/download/v1.0.0/antctl-linux-x86_64"
$ chmod +x ./antctl
$ mv ./antctl /usr/local/bin
$ antctl version
antctlVersion: v1.0.0
controllerVersion: v1.0.0

設定の確認

Antrea を展開した段階で、Antrea の configmap が作成されています。現在の設定がどうなっているかを確認することができます。antrea-config-xxxxxxxxxが作成されているので表示してみます。

$ kubectl get configmap antrea-config-5ct9ktdt77 -n kube-system -o yaml

ここでは AntreaPolicy の設定を確認してみます。antrea-agent.conf および antrea-controller.conf 設定の中に AntreaPolicy: True で設定されていますが、コメントアウトされています。Antrea 1.0 からデフォルトで Antrea Network Policy が enable になっているので、この状態ですでに有効になっています。

apiVersion: v1
data:
  antrea-agent.conf: |
    # FeatureGates is a map of feature names to bools that enable or disable experimental features.
    featureGates:
    # Enable AntreaProxy which provides ServiceLB for in-cluster Services in antrea-agent.
    # It should be enabled on Windows, otherwise NetworkPolicy will not take effect on
    # Service traffic.
    #  AntreaProxy: true

    # Enable EndpointSlice support in AntreaProxy. Don't enable this feature unless that EndpointSlice
    # API version v1beta1 is supported and set as enabled in Kubernetes. If AntreaProxy is not enabled,
    # this flag will not take effect.
    #  EndpointSlice: false

    # Enable traceflow which provides packet tracing feature to diagnose network issue.
    #  Traceflow: true

    # Enable NodePortLocal feature to make the pods reachable externally through NodePort
    #  NodePortLocal: false

    # Enable Antrea ClusterNetworkPolicy feature to complement K8s NetworkPolicy for cluster admins
    # to define security policies which apply to the entire cluster, and Antrea NetworkPolicy
    # feature that supports priorities, rule actions and externalEntities in the future.
    #  AntreaPolicy: true

(snip...)

  antrea-controller.conf: |
    # FeatureGates is a map of feature names to bools that enable or disable experimental features.
    featureGates:
    # Enable traceflow which provides packet tracing feature to diagnose network issue.
    #  Traceflow: true

    # Enable Antrea ClusterNetworkPolicy feature to complement K8s NetworkPolicy for cluster admins
    # to define security policies which apply to the entire cluster, and Antrea NetworkPolicy
    # feature that supports priorities, rule actions and externalEntities in the future.
    #  AntreaPolicy: true

(snip...)

Antrea Cluster Network Policy を試す

では実際に Antrea Cluster Network Policy を使ってみます。K8s 標準の NetworkPolicy との動作の違いも見てみたいと思います。

サンプルアプリのデプロイ

まず、動作確認のために使用するアプリケーションをデプロイします。default namespace に Guestbook アプリをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-controller.json
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-service.json
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-controller.json
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-service.json
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-controller.json
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-service.json

guestbook, redis-master, redis-slave の三種類のサービスとコンテナが作成されます。

$ kubectl get all -n default
NAME                     READY   STATUS    RESTARTS   AGE
pod/guestbook-hmsrw      1/1     Running   0          23h
pod/guestbook-nl7xv      1/1     Running   0          23h
pod/guestbook-s9spp      1/1     Running   0          23h
pod/redis-master-z2vjh   1/1     Running   0          23h
pod/redis-slave-cplgv    1/1     Running   0          23h
pod/redis-slave-r2tmz    1/1     Running   0          23h

NAME                                 DESIRED   CURRENT   READY   AGE
replicationcontroller/guestbook      3         3         3       23h
replicationcontroller/redis-master   1         1         1       23h
replicationcontroller/redis-slave    2         2         2       23h

NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/guestbook      LoadBalancer   10.109.117.193   <pending>     3000:30731/TCP   23h
service/kubernetes     ClusterIP      10.96.0.1        <none>        443/TCP          2d
service/redis-master   ClusterIP      10.98.195.90     <none>        6379/TCP         23h
service/redis-slave    ClusterIP      10.109.248.115   <none>        6379/TCP         23h

guestbook サービスは LoadBalancer タイプですが、この環境には Provider LB がまだ存在しないため、EXTERNAL-IPPending になっています。とりあえず、 NodePort を使って以下の URL にアクセスすると Guestbook の UI が表示されます。192.168.110.91 は Worker ノードの IP アドレスです。

http://192.168.110.91:30731/

image.png

ここで各 Pod のラベル設定を確認しておきます。フロントエンドのコンテナであるguestbookにはapp: guestbookの、バックエンドのredis-masterredis-slaveにはapp: redisのラベルが設定されています。ラベルはこのあと NetworkPolicy や Antrea Network Policy の PodSelector設定で使用することになります。

$ kubectl get pod -L app
NAME                 READY   STATUS    RESTARTS   AGE     APP
guestbook-hmsrw      1/1     Running   0          23h   guestbook
guestbook-nl7xv      1/1     Running   0          23h   guestbook
guestbook-s9spp      1/1     Running   0          23h   guestbook
redis-master-z2vjh   1/1     Running   0          23h     redis
redis-slave-cplgv    1/1     Running   0          23h     redis
redis-slave-r2tmz    1/1     Running   0          23h     redis

NetworkPolicy

Antrea Cluster Network Policy を試す前に、標準の NetworkPolicy の動作を確認してみます。

namespace 内のコンテナ間制御

以下のポリシーを適用し、namespace 内のフロントエンドguestbookとバックエンドredisの通信が阻害されることを確認します。

$ cat np1.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: drop-access-to-redis
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: redis
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: other
$
$ kubectl apply -f np1.yaml
networkpolicy.networking.k8s.io/drop-access-to-redis created

再度 Guestbook の URL にアクセスすると以下のように表示され、バックエンドへの接続ができないことが分かります。

image.png

この NetworkPolicy を削除すると、再び接続できるようになります。

$ kubectl delete -f np1.yaml
networkpolicy.networking.k8s.io "drop-access-to-redis" deleted

namespace 外からのアクセスの制御

今度はフロントエンドguestbookへのアクセスを禁じるポリシーを作成して適用します。

$ cat np2.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: drop-access-to-guestbook
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: guestbook
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: other
$
$ kubectl apply -f np2.yaml
networkpolicy.networking.k8s.io/drop-access-to-guestbook created

この時、NodePort を介した外部からのアクセスは可能なままです。

image.png

しかし、フロントエンドコンテナからの ClusterIP を介したアクセスは許可されません。

$ kubectl exec guestbook-hmsrw -it -- sh


BusyBox v1.21.1 (Ubuntu 1:1.21.0-1ubuntu1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
^C
/app # 

再びポリシーを削除するとフロントエンドからもアクセスできるようになります。

$ kubectl delete -f np2.yaml
networkpolicy.networking.k8s.io "drop-access-to-guestbook" deleted
/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta charset="utf-8">
    <meta content="width=device-width" name="viewport">
    <link href="style.css" rel="stylesheet">
    <title>Guestbook</title>
  </head>
  <body>
    <div id="header">
      <h1>Guestbook</h1>
    </div>

(snip...)

このように、NodePort を用いた外部からの制御には NetworkPolicy は利用できません。

namespace 間の制御

今度は、以下のポリシーを作成して、他の namespace からのアクセスを許可します。

$ cat np3.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-access-from-other-ns
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: guestbook
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          project: test
    - podSelector:
        matchLabels:
          app: other
$
$ kubectl apply -f np3.yaml
networkpolicy.networking.k8s.io/allow-access-from-other-ns created

このテストを行うために一時的に namespace test を作成し、project: testのラベルを付けます。

$ kubectl create namespace test
namespace/test created
$ kubectl label namespace test project=test
namespace/test labeled

次にテスト用コンテナをtestnamespace 内に作成します。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-controller.json -n test
$ kubectl get pod -n test
NAME              READY   STATUS    RESTARTS   AGE
guestbook-5w6ft   1/1     Running   0          79m
guestbook-cfzfd   1/1     Running   0          79m
guestbook-jlfpw   1/1     Running   0          79m

このコンテナから、最初にデプロイしたdefaultnamespace 内の Guestbook アプリにアクセスできることを確認します。

$ kubectl exec guestbook-5w6ft -n test  -it -- sh


BusyBox v1.21.1 (Ubuntu 1:1.21.0-1ubuntu1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta charset="utf-8">
    <meta content="width=device-width" name="viewport">
    <link href="style.css" rel="stylesheet">
    <title>Guestbook</title>
  </head>
  <body>
    <div id="header">
      <h1>Guestbook</h1>
    </div>

(snip...)

このように、NetworkPolicy ではクラスターに閉じた形で namespace 毎のアクセス制御が可能ですが、namespace やクラスターを超えて同じルールを適用することはできません。また、ポリシーは allow ルールのみですが同時に暗黙の drop ルールが記述されます。そのため細やかな drop ルールを書くようなセキュリティの掛け方には向かないようです。
Antrea Cluster Network Policy はこれらの課題に対応しようとしています。

Antrea Cluster Network Policy (ACNP)

ではいよいよ Antrea Cluster Network Policy を設定していきます。
Antrea 1.0 では最初から Antrea Cluster Network Policy が enable になっていますので、すぐに設定を開始できますが、まず Antrea Cluster Network Policy 独自の Tier について確認しておきます。

Tier

Tier はポリシーを階層化して管理するための概念で、ポリシーに対して優先度をつけたい場合に有用です。初期設定では Tier は以下のように設定されています。

$ kubectl get tier --sort-by=.spec.priority
NAME          PRIORITY   AGE
emergency     50         37m
securityops   100        37m
networkops    150        37m
platform      200        37m
application   250        37m
baseline      253        37m

tierPRIORITYが、実際に処理される優先度を表します。小さい数値ほど優先度が高くなります。たとえば最優先で処理させたいポリシーがある場合は emergency に設定すれば最初に処理されるようになります。標準の NetworkPolicy で設定されたポリシーは、application Tier の後で処理されます。

Tier は自分で作成することも可能です。ここでは新しい Tier を以下のマニフェストmytier.yamlで作成してみます。

apiVersion: security.antrea.tanzu.vmware.com/v1alpha1
kind: Tier
metadata:
  name: mytier
spec:
  priority: 10
  description: "my custom tier"
$ kubectl apply -f mytier.yaml
tier.security.antrea.tanzu.vmware.com/mytier created
$
$ kubectl get tiers --sort-by=.spec.priority
NAME          PRIORITY   AGE
mytier        10         42s
emergency     50         45m
securityops   100        45m
networkops    150        45m
platform      200        45m
application   250        45m
baseline      253        45m

Antrea Cluster Network Policy の適用

では Antrea Cluster Network Policy を実際に作成していきます。まず以下のマニフェストacnp1.yamlを作成します。

apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-drop-access-to-redis
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - podSelector:
        matchLabels:
          app: redis
  ingress:
    - action: Allow
      from:
        - podSelector:
            matchLabels:
              app: other
      name: AllowFromOther
      enableLogging: false

これは NetworkPolicy のところで最初に作成したnp1.yamlによく似ていますが、実際の動作は異なります。以下のコマンドでこのマニフェストを適用します。

$ kubectl apply -f acnp1.yaml
clusternetworkpolicy.crd.antrea.io/acnp-drop-access-to-redis created
$ 
$ kubectl get acnp
NAME                        TIER          PRIORITY   DESIRED NODES   CURRENT NODES   AGE
acnp-drop-access-to-redis   securityops   5          1               1               24s

この状態で Guestbook アプリにアクセスしても、バックエンドへのアクセスは阻害されないため、正常に表示されます。

image.png

NetworkPolicy ではポリシーが反映されると同時に暗黙の Deny が有効になり許可されないトラフィックはドロップされるようになりますが、ACNP では明示的に Drop ルールが書かれない限りトラフィックは許可されます。
なお、ACNP の kind はClusterNetworkPolicyですが、上のkubectl get acnpコマンドのように、acnpという省略形で操作を行うことも可能です。

今度は、acnp1.yamlを修正して以下のacp11.yamlを作成し適用してみます。明示的にソースとなる Pod をpodSelector で指定し、 actionDrop に変更します。

apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-drop-access-to-redis
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - podSelector:
        matchLabels:
          app: redis
  ingress:
    - action: Drop
      from:
        - podSelector:
            matchLabels:
              app: guestbook
      name: DropFromGuestbook
      enableLogging: false

これを同じく適用します。

$ kubectl apply -f acnp11.yaml
clusternetworkpolicy.crd.antrea.io/acnp-drop-access-to-redis configured

すると、今度はバックエンドへのアクセスが阻害されるため以下の表示に変わりました。

image.png

この ACNP では、tiersecurityopspriority5 に指定しています。prioritytier の内部での処理の優先度を表します。
上述のように securityops Tier に指定したポリシーは標準の Network Policy よりも優先的に処理されます。例えば、np1.yamlを最初に適用してバックエンドへのアクセスが阻害されている状態を作り、その上で以下のacnp12.yamlを適用すると、ACNP の処理が優先されてバックエンドへのアクセスが許可されるようになります。

apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-allow-access-to-redis
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - podSelector:
        matchLabels:
          app: redis
  ingress:
    - action: Allow
      from:
        - podSelector:
            matchLabels:
              app: guestbook
      name: AllowFromGuestbook
      enableLogging: false

このように、Antrea Cluster Network Policy を使えば、標準の NetworkPolicy よりもより明確に送信元と宛先を指定したセキュリティポリシーの定義ができることを理解いただけたかと思います。

ACNP による namespace 間の制御

ここからは ACNP による namespace をまたいだ制御を見ていきたいと思います。その前に、もう一度 K8s NetworkPolicy ではどのような挙動になるかを確認しておきます。上で利用した np2.yaml コピーして、 Guestbook アプリ間のトラフィックを許可するように変更した np22.yaml を作成し適用します。

$ cat np22.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-access-from-to-guestbook
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: guestbook
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: guestbook
$
$ kubectl apply -f np22.yaml
networkpolicy.networking.k8s.io/allow-access-from-to-guestbook created
$ 

現在、defaulttest の namespace にデプロイ済みの Pod の状態は以下のようになっています。

$ kubectl get pod -L app -n default
NAME                 READY   STATUS    RESTARTS   AGE   APP
guestbook-hmsrw      1/1     Running   0          28d   guestbook
guestbook-nl7xv      1/1     Running   0          28d   guestbook
guestbook-s9spp      1/1     Running   0          28d   guestbook
redis-master-blz4w   1/1     Running   0          21d   redis
redis-slave-fbsz6    1/1     Running   0          21d   redis
redis-slave-rpvqt    1/1     Running   0          21d   redis
$ 
$ kubectl get pod -L app -n test
NAME              READY   STATUS    RESTARTS   AGE   APP
guestbook-5w6ft   1/1     Running   0          27d   guestbook
guestbook-cfzfd   1/1     Running   0          27d   guestbook
guestbook-jlfpw   1/1     Running   0          27d   guestbook
$ 

この状態では、test namespace 側の Guestbook pod から default namespace 側にアクセスが許可されません。K8s NetworkPolicy では namespace をまたいで podSelector を利用できないからです。実際、test namespace 側の Guestbook Pod から default namespace 側の Guestbook pod へのアクセスは以下のように許可されません。

$ kubectl exec guestbook-5w6ft -n test  -it -- sh


BusyBox v1.21.1 (Ubuntu 1:1.21.0-1ubuntu1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
wget: can't connect to remote host (10.109.117.193): Connection timed out
/app #

では、ACNP で同じようなポリシーを作成してトライしてみましょう。

$ cat acnp2.yaml
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-allow-access-from-to-guestbook
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - podSelector:
        matchLabels:
          app: guestbook
  ingress:
    - action: Allow
      from:
        - podSelector:
            matchLabels:
              app: guestbook
      name: AllowFromGuestbook
      enableLogging: false
$
$ kubectl apply -f acnp2.yaml
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-from-to-guestbook created
$ 

np22.yaml と同様に appliedTofrom の両方の podSelector でラベル app: guestbook を指定していますが、namespace は特に指定していません。また、前に作成した K8s NetworkPolicy もそのままにしてあります。

$ kubectl get networkpolicy
NAMESPACE   NAME                             POD-SELECTOR    AGE
default     allow-access-from-to-guestbook   app=guestbook   32m
$ 
$ kubectl get acnp
NAME                                  TIER          PRIORITY   DESIRED NODES   CURRENT NODES   AGE
acnp-allow-access-from-to-guestbook   securityops   5          2               2               10m

この状態で再び test 側の Pod から default 側にアクセスすると以下のように許可されます。

/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta charset="utf-8">
    <meta content="width=device-width" name="viewport">
    <link href="style.css" rel="stylesheet">
    <title>Guestbook</title>
  </head>
  <body>
    <div id="header">
      <h1>Guestbook</h1>
    </div>

(snip...)

  </body>
</html>
-                    100% |*******************************|   922   0:00:00 ETA
/app #

また、ACNP では podSelectornamespaceSelector を併用して、namespace 毎に適用対象や送信元となる pod を明示的に指定することができます。acnp2.yaml を編集して namespaceSelector 条件を追加した acnp22.yaml を作成します。

$ cat acnp22.yaml
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-allow-access-from-to-guestbook
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - podSelector:
        matchLabels:
          app: guestbook
      namespaceSelector:
        matchLabels:
          project: prod
  ingress:
    - action: Allow
      from:
        - podSelector:
            matchLabels:
              app: guestbook
          namespaceSelector:
            matchLabels:
              project: test
      name: AllowFromGuestbook
      enableLogging: false
$
$ kubectl apply -f acnp22.yaml
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-from-to-guestbook configured
$ 

この修正により、受信側 namespace のラベル条件に project: prod、送信側 namespace のラベルが条件には project: test が追加されました。しかしながら、受信側の Guestbook pod は default namespace 内にありますが、namespace にラベルをまだ追加していないため、この状態では通信は失敗します。

/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
wget: can't connect to remote host (10.109.117.193): Connection timed out
/app #

そこで、default namespace にラベルを追加します。

$ kubectl label ns default project=prod
namespace/default labeled
$ 
$ kubectl get ns --show-labels
NAME              STATUS   AGE   LABELS
default           Active   29d   project=prod
kube-node-lease   Active   29d   <none>
kube-public       Active   29d   <none>
kube-system       Active   29d   <none>
test              Active   27d   project=test

すると test namespace 内の Guestbook pod から default namespace 内の Guestbook pod にアクセスできるようになりました。

/app # wget -O - http://guestbook.default.svc.cluster.local:3000
Connecting to guestbook.default.svc.cluster.local:3000 (10.109.117.193:3000)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta charset="utf-8">
    <meta content="width=device-width" name="viewport">
    <link href="style.css" rel="stylesheet">
    <title>Guestbook</title>
  </head>
  <body>
    <div id="header">
      <h1>Guestbook</h1>
    </div>

(snip...)

  </body>
</html>
-                    100% |*******************************|   922   0:00:00 ETA
/app #

このように、Antrea Cluster Network Policy では、namespace に限定されないクラスターレベルのネットワークポリシーを設定することが可能です。クラスター管理者は namespace に依存しないクラスターレベルのセキュリティポリシーを設定することができるようになります。

ClusterGroup

ClusterGroup は ACNP の特徴的な機能の一つで、エンドポイントをグルーピングするルールを NetworkPolicy の外で作成し再利用することができます。これまでに紹介した podSelectornamespaceSelector、おなじみの ipBlock 以外に、K8s Service を利用する serviceReference やグルーピングのネスト構造を定義できる childGroups といった定義を使うことが可能です。

ClusterGroup を使ったルールを作成していく前に、これまでに作成してきたすべてのポリシーをいったん削除します。

$ kubectl get networkpolicy --no-headers | awk '{print $1}'| xargs kubectl delete networkpolicy
networkpolicy.networking.k8s.io "allow-access-from-to-guestbook" deleted
$ 
$ kubectl get acnp --no-headers | awk '{print $1}'| xargs kubectl delete acnp
clusternetworkpolicy.crd.antrea.io "acnp-allow-access-from-to-guestbook" deleted

そして default namespace 内の Pod へのすべてのトラフィックを暗黙的に不許可にするために以下の acnp-dropany.yaml を作成し適用します。適用先の Tier として baseline を指定しています。この場合、このルールは K8s NetworkPolicy を含むすべてのポリシールールが評価された後に適用されるようになります。

$ cat acnp-dropany.yaml

apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-drop-any-in-production
spec:
  priority: 100
  tier: baseline
  appliedTo:
    - podSelector: {}
      namespaceSelector:
        matchLabels:
          project: prod
  ingress:
    - action: Drop
      from:
        - podSelector: {}
      name: DropFromAny
      enableLogging: false
$
$ kubectl apply -f acnp-dropany.yaml
clusternetworkpolicy.crd.antrea.io/acnp-drop-any-in-production created
$

すべての Pod 間の通信が不許可になるため、Guestbook アプリのフロントエンドと Redis バックエンド間の通信もできなくなります。
image.png

そこで、 フロントエンドとバックエンド間の通信を許可するポリシーを記載していきますが、そこで ClusterGroup を使用してみます。ここでは、Redis バックエンドサービスのグルーピングに serviceReferencechildGroups を使ってみます。

$ cat cg1.yaml
apiVersion: crd.antrea.io/v1alpha2
kind: ClusterGroup
metadata:
  name: cg-guestbook
spec:
  podSelector:
    matchLabels:
      app: guestbook
---
apiVersion: crd.antrea.io/v1alpha2
kind: ClusterGroup
metadata:
  name: cg-redis-master
spec:
  serviceReference:
    name: redis-master
    namespace: default
---
apiVersion: crd.antrea.io/v1alpha2
kind: ClusterGroup
metadata:
  name: cg-redis-slave
spec:
  serviceReference:
    name: redis-slave
    namespace: default
---
apiVersion: crd.antrea.io/v1alpha2
kind: ClusterGroup
metadata:
  name: cg-redis-nested
spec:
  childGroups: [cg-redis-master, cg-redis-slave]
$
$ kubectl apply -f cg1.yaml
clustergroup.crd.antrea.io/cg-guestbook created
clustergroup.crd.antrea.io/cg-redis-master created
clustergroup.crd.antrea.io/cg-redis-slave created
clustergroup.crd.antrea.io/cg-redis-nested created
$ 

次にこれらの ClusterGroup を利用した ACNP を acnp3.yaml として作成していきます。

$ cat acnp3.yaml
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-allow-access-to-guestbook
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - group: "cg-guestbook"
  ingress:
    - action: Allow
      from:
        - group: "cg-guestbook"
      name: AllowToGuestbook
      enableLogging: false
---
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-allow-access-to-redis
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - group: "cg-redis-nested"
  ingress:
    - action: Allow
      from:
        - group: "cg-guestbook"
      name: AllowFromGuestbookToRedis
      enableLogging: false
---
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
  name: acnp-allow-access-to-redis-slave
spec:
  priority: 5
  tier: securityops
  appliedTo:
    - group: "cg-redis-slave"
  ingress:
    - action: Allow
      from:
        - group: "cg-redis-master"
      name: AllowToRedisSlave
      enableLogging: false
$
$ kubectl apply -f acnp3.yaml
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-to-guestbook created
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-to-redis created
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-to-redis-slave created
$ 

この状態でブラウザからアクセスすると、Redis バックエンドへのアクセスも許可されて正常に応答が返ってくるようになりました。

image.png

いかがでしたでしょうか。Antrea Cluster Network Policy では、クラスターレベルで柔軟なエンドポイントのグルーピングが可能になっていることを理解いただけたかと思います。

次回以降、Antrea Cluster Network Policy についてより詳細な操作方法などをご紹介していければと思います。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?