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-IP
は Pending
になっています。とりあえず、 NodePort
を使って以下の URL にアクセスすると Guestbook の UI が表示されます。192.168.110.91
は Worker ノードの IP アドレスです。
http://192.168.110.91:30731/
ここで各 Pod のラベル設定を確認しておきます。フロントエンドのコンテナであるguestbook
にはapp: guestbook
の、バックエンドのredis-master
とredis-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 にアクセスすると以下のように表示され、バックエンドへの接続ができないことが分かります。
この 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 を介した外部からのアクセスは可能なままです。
しかし、フロントエンドコンテナからの 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
次にテスト用コンテナをtest
namespace 内に作成します。
$ 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
このコンテナから、最初にデプロイしたdefault
namespace 内の 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
各tier
のPRIORITY
が、実際に処理される優先度を表します。小さい数値ほど優先度が高くなります。たとえば最優先で処理させたいポリシーがある場合は 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 アプリにアクセスしても、バックエンドへのアクセスは阻害されないため、正常に表示されます。
NetworkPolicy ではポリシーが反映されると同時に暗黙の Deny が有効になり許可されないトラフィックはドロップされるようになりますが、ACNP では明示的に Drop ルールが書かれない限りトラフィックは許可されます。
なお、ACNP の kind はClusterNetworkPolicy
ですが、上のkubectl get acnp
コマンドのように、acnp
という省略形で操作を行うことも可能です。
今度は、acnp1.yaml
を修正して以下のacp11.yaml
を作成し適用してみます。明示的にソースとなる Pod をpodSelector
で指定し、 action
を Drop
に変更します。
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
すると、今度はバックエンドへのアクセスが阻害されるため以下の表示に変わりました。
この ACNP では、tier
を securityops
、 priority
を 5
に指定しています。priority
は tier
の内部での処理の優先度を表します。
上述のように 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
$
現在、default
とtest
の 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
と同様に appliedTo
と from
の両方の 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 では podSelector
と namespaceSelector
を併用して、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 の外で作成し再利用することができます。これまでに紹介した podSelector
や namespaceSelector
、おなじみの 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 バックエンド間の通信もできなくなります。
そこで、 フロントエンドとバックエンド間の通信を許可するポリシーを記載していきますが、そこで ClusterGroup を使用してみます。ここでは、Redis バックエンドサービスのグルーピングに serviceReference
と childGroups
を使ってみます。
$ 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 バックエンドへのアクセスも許可されて正常に応答が返ってくるようになりました。
いかがでしたでしょうか。Antrea Cluster Network Policy では、クラスターレベルで柔軟なエンドポイントのグルーピングが可能になっていることを理解いただけたかと思います。
次回以降、Antrea Cluster Network Policy についてより詳細な操作方法などをご紹介していければと思います。