使用Antrea集群网络策略来应用高级网络策略
Antrea 是什么?
Antrea 是一个开源的 Kubernetes CNI,为 Kubernetes 集群提供 L3/4 网络功能和安全性。它利用具有悠久历史的 Open vSwitch 作为数据平面,充当开放的虚拟交换机。
Antrea 已尝试实现了多种扩展标准 Kubernetes 集群网络的功能。作为扩展 NetworkPolicy 的功能,Antrea 集群网络策略(ACNP)可用。Antrea 还支持标准 NetworkPolicy,但 ACNP 提供以下功能以更好地满足集群管理员的要求。
-
- ポリシーの階層化(Tier)と優先度設定(Priority)、Tier レベルの RBAC
-
- Namespace に限定されない、クラスターレベルのセキュリティ設定
-
- アクションルールのサポート: Allow, Drop, Reject のアクションを指定可能
-
- FQDN フィルタのサポート
- L7 プロトコルレベルのフィルタのサポート
在这篇文章中,我想要关注Antrea集群网络策略,并对其功能进行确认。
Antrea集群的准备工作
请参考以下文章,了解有关在 Kubernetes 集群上安装 Antrea 和 antctl 命令的示例。
https://qiita.com/ynakaoku/items/449b15d06a661fb83e91
本文假定读者使用的是Antrea 1.12.1版本进行操作。
确认设置
当部署 Antrea 时,会同时创建 Antrea 的 Configmap。您可以使用 antrea-config 命令来确认当前的配置状态。
kubectl get configmap antrea-config -n kube-system -o yaml
在这里我们将确认AntreaPolicy的设置。antrea-agent.conf和antrea-controller.conf配置文件中的AntreaPolicy已经设置为True,但被注释掉了。由于从Antrea 1.0版本开始,默认情况下Antrea网络策略已启用,所以它已经处于有效状态。
apiVersion: v1
data:
antrea-agent.conf: |
# FeatureGates is a map of feature names to bools that enable or disable experimental features.
featureGates:
# AllAlpha is a global toggle for alpha features. Per-feature key values override the default set by AllAlpha.
# AllAlpha: false
# AllBeta is a global toggle for beta features. Per-feature key values override the default set by AllBeta.
# AllBeta: false
# 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 v1 is supported and set as enabled in Kubernetes. If AntreaProxy is not enabled,
# this flag will not take effect.
# EndpointSlice: true
# Enable TopologyAwareHints in AntreaProxy. This requires AntreaProxy and EndpointSlice to be
# enabled, otherwise this flag will not take effect.
# TopologyAwareHints: true
# 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: 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-controller.conf: |
# FeatureGates is a map of feature names to bools that enable or disable experimental features.
featureGates:
# AllAlpha is a global toggle for alpha features. Per-feature key values override the default set by AllAlpha.
# AllAlpha: false
# AllBeta is a global toggle for beta features. Per-feature key values override the default set by AllBeta.
# AllBeta: false
# 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 集群网络策略
那么,让我们实际使用Antrea Cluster Network Policy来尝试一下。我也希望看看它与K8s标准的NetworkPolicy之间的区别。
部署示例应用程序
首先,我们要部署一个用于进行操作确认的应用程序。在这里,我们将使用 Kubernetes 官方教程中提供的示例应用 Guestbook,链接为https://kubernetes.io/docs/tutorials/stateless-application/guestbook/。
创建名为guestbook的命名空间,并使用以下命令展开Guestbook应用程序。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/redis-leader-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/redis-leader-service.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/redis-follower-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/redis-follower-service.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/frontend-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/frontend-service.yaml
将创建三种类型的服务和容器:前端、Redis跟随者和Redis领导者。
$ kubectl get all -n guestbook
NAME READY STATUS RESTARTS AGE
pod/frontend-767747dfdd-7sl6f 1/1 Running 0 42m
pod/frontend-767747dfdd-pqvnn 1/1 Running 0 42m
pod/redis-follower-66497dbb55-4gmqc 1/1 Running 0 42m
pod/redis-follower-66497dbb55-ksjpl 1/1 Running 0 42m
pod/redis-leader-6bfcff974b-btvr5 1/1 Running 0 42m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/frontend LoadBalancer 10.103.238.3 172.19.0.212 80:32456/TCP 42m
service/redis-follower ClusterIP 10.97.241.156 <none> 6379/TCP 42m
service/redis-leader ClusterIP 10.111.203.236 <none> 6379/TCP 42m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/frontend 2/2 2 2 42m
deployment.apps/redis-follower 2/2 2 2 42m
deployment.apps/redis-leader 1/1 1 1 42m
NAME DESIRED CURRENT READY AGE
replicaset.apps/frontend-767747dfdd 2 2 2 42m
replicaset.apps/redis-follower-66497dbb55 2 2 2 42m
replicaset.apps/redis-leader-6bfcff974b 1 1 1 42m
前端服务在教程中类型为 ClusterIP,但在这里将其修改为 LoadBalancer 类型,并通过外部负载均衡器实现从外部的连接。根据使用环境进行相应配置。
配置完成后,结构如下所示。
当您访问以下的网址时,将会显示留言板的用户界面。
http://172.19.0.212/
在这里,我会在消息栏中写一条消息。当我写下”first message”并点击提交后,Redis中存储的消息将会被显示如下。
在这里,我们将检查每个 Pod 的标签设置。前端 Pod 的标签设置为app: guestbook,即 frontend;后端的 redis-leader 和 redis-follower 的标签设置为app: redis。接下来,我们将在 NetworkPolicy 和 Antrea Network Policy 的 PodSelector 设置中使用这些标签。
$ kubectl get pod -L=app
NAME READY STATUS RESTARTS AGE APP
frontend-767747dfdd-7sl6f 1/1 Running 0 43m guestbook
frontend-767747dfdd-pqvnn 1/1 Running 0 43m guestbook
redis-follower-66497dbb55-4gmqc 1/1 Running 0 43m redis
redis-follower-66497dbb55-ksjpl 1/1 Running 0 43m redis
redis-leader-6bfcff974b-btvr5 1/1 Running 0 43m redis
网络策略
在尝试使用Antrea集群网络策略之前,我们先确认一下标准的网络策略的运行情况。
命名空间中容器之间的控制
将应用以下策略:该策略允许 app: redis Pod 与具有相同标签的其他 Pod 进行通信,但不允许与其他 Pod 进行通信。换句话说,将阻止前端前端(frontend)与后端(redis)之间在命名空间中的通信。
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: redis
$ kubectl apply -f np1.yaml
networkpolicy.networking.k8s.io/drop-access-to-redis created
当您再次访问Guestbook的URL时,不再显示以下消息。
有点难懂,但是由于无法连接到Redis后端,我们无法读取记录的消息,就像下面的图一样。
只要删除此NetworkPolicy,就可以再次从Redis中接收消息。
$ kubectl delete -f np1.yaml
networkpolicy.networking.k8s.io "drop-access-to-redis" deleted
对来自外部的命名空间访问进行控制
我們將創建並應用一個禁止訪問前端留言簿的策略。
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
然后,无法访问留言簿。
事实上,由于来自外部的连接受阻,前端服务器的外部连接已经中断。
再次删除策略后,前端也可以访问。
$ kubectl delete -f np2.yaml
networkpolicy.networking.k8s.io "drop-access-to-guestbook" deleted
命名空間之間的控制
这次我们将确认来自其他命名空间的流量控制。为了进行这个测试,我们创建了一个名为 test 的命名空间,并为其附上了项目:test 的标签。
$ kubectl create namespace test
namespace/test created
$ kubectl label namespace test project=test
namespace/test labeled
接下来,我们将在 test 命名空间内创建用于测试的 frontend 容器和服务。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/frontend-deployment.yaml -n test
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/guestbook/frontend-service.yaml -n test
$ kubectl get all -n test -L=app
NAME READY STATUS RESTARTS AGE APP
pod/frontend-7cc596bb48-dsgds 1/1 Running 0 9m24s guestbook
pod/frontend-7cc596bb48-l6wsg 1/1 Running 0 9m19s guestbook
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE APP
service/frontend LoadBalancer 10.105.1.244 172.19.0.217 80:30448/TCP 9m10s guestbook
NAME READY UP-TO-DATE AVAILABLE AGE APP
deployment.apps/frontend 2/2 2 2 9m24s
NAME DESIRED CURRENT READY AGE APP
replicaset.apps/frontend-7cc596bb48 2 2 2 9m24s guestbook
前端服务已被修改为type: LoadBalancer。
同时,已修改前端部署的环境变量,使其连接到在guestbook命名空间中创建的后端Redis,并重新启动。编辑如下所示。
(snip...)
- env:
- name: GET_HOSTS_FROM
value: env
- name: REDIS_FOLLOWER_SERVICE_HOST
value: redis-follower.guestbook.svc.cluster.local
- name: REDIS_LEADER_SERVICE_HOST
value: redis-leader.guestbook.svc.cluster.local
(snip...)
接下来,我们将创建以下策略,以允许对test命名空间的访问。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-access-from-other-ns
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
app: redis
ingress:
- from:
- namespaceSelector:
matchLabels:
project: test
$ kubectl apply -f np3.yaml -n guestbook
networkpolicy.networking.k8s.io/allow-access-from-other-ns created
在此策略中,允许从测试命名空间访问访客留言板命名空间的Redis。配置如下所示。
当你访问test命名空间中的前端服务时,将显示包含先前写入的消息的Guestbook应用程序。
http://172.19.0.217/
现在我们尝试创建以下的 NetworkPolicy,限制test命名空间中的Pod访问guestbook命名空间中的Redis。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: drop-access-from-other-ns-pod
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
app: redis
ingress:
- from:
- namespaceSelector:
matchLabels:
project: test
- podSelector:
matchLabels:
app: other
$ kubectl delete -f np3.yaml
networkpolicy.networking.k8s.io "allow-access-from-other-ns" deleted
$ kubectl apply -f np4.yaml
networkpolicy.networking.k8s.io/allow-access-from-other-ns created
我原本以为通过命名空间和 Pod 的组合来限制访问 Redis,但实际上可以像下面这样访问到 Redis。
就像这样,NetworkPolicy 可以在集群内按照每个 Namespace 进行访问控制,但不能跨越 Namespace 或集群应用相同规则。此外,策略只能允许规则,并同时记载隐式的拒绝规则。因此,它似乎不适合编写细微的拒绝规则以加强安全性。
Antrea Cluster Network Policy 可以应对这些问题。
安特蕾集群网络策略(ACNP)
现在开始设置Antrea集群网络策略。
最近的Antrea已默认启用Antrea集群网络策略,因此您可以立即开始设置,但首先我们需要了解Antrea集群网络策略的独特层级。
程序结构
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级别表示了实际处理的优先级。数字越小,优先级越高。例如,如果有一个希望最优先处理的策略,可以将其设置为”emergency”,这样它就会首先被处理。在标准的NetworkPolicy中设置的策略将在application Tier之后被处理。
可以自行创建Tier。下面将使用以下manifest文件mytier.yaml创建一个新的Tier。
apiVersion: crd.antrea.io/v1alpha1
kind: Tier
metadata:
name: mytier
spec:
priority: 10
description: "my custom tier"
$ kubectl apply -f mytier.yaml
tier.crd.antrea.io/mytier created
$
$ kubectl get tiers --sort-by=.spec.priority
mytier 10 36s
emergency 50 124d
securityops 100 124d
networkops 150 124d
platform 200 124d
application 250 124d
baseline 253 124d
应用 Antrea 集群网络策略
现在我们开始创建Antrea集群网络策略。首先,创建以下清单文件。
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: true
这与最初在 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
即使在这种状态下访问留言簿应用程序,对后端的访问也不会受阻,正常显示。
当网络策略(NetworkPolicy)生效后,隐式的Deny规则会同时生效,未被明确授权的流量将被丢弃。然而,对于集群网络策略(ACNP),除非明确编写Drop规则,否则流量将被允许通过。
需要注意的是,集群网络策略的类型是ClusterNetworkPolicy,但也可以像上述kubectl get acnp命令一样,使用acnp简写进行操作。
这次,我将修改acnp1.yaml文件并创建以下的acp11.yaml文件并应用它。我将通过podSelector明确指定源Pod,并将动作改为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: true
我們也將這個應用到同樣的情況中。
$ kubectl apply -f acnp11.yaml
clusternetworkpolicy.crd.antrea.io/acnp-drop-access-to-redis configured
然后,由于对Redis的访问受到阻碍,无法显示以下消息。
由于在上述清单中设置了 enableLogging: true,所以当与条件匹配的流量流经时,将被记录在每个节点的 /var/log/antrea/networkpolicy/np.log 中。如果登录节点并检查该文件,您会注意到最后输出了以下类似的日志。
...
2023/11/01 08:02:06.424992 AntreaPolicyIngressRule AntreaClusterNetworkPolicy:acnp-drop-access-to-redis DropFromGuestbook Drop 44900 192.168.1.97 41662 192.168.1.30 6379 TCP 60 <nil>
2023/11/01 08:02:07.438157 AntreaPolicyIngressRule AntreaClusterNetworkPolicy:acnp-drop-access-to-redis DropFromGuestbook Drop 44900 192.168.1.97 41662 192.168.1.30 6379 TCP 60 <nil>
2023/11/01 08:02:09.453315 AntreaPolicyIngressRule AntreaClusterNetworkPolicy:acnp-drop-access-to-redis DropFromGuestbook Drop 44900 192.168.1.97 41662 192.168.1.30 6379 TCP 60 <nil>
根据 DropFromGuestbook 的 Drop 规则,我们得知源 Pod 192.168.1.97 到目标 Pod 192.168.1.30 的通信以及目标端口号 6379 的通信被丢弃了。
另外,在此ACNP中,我们将tier指定为securityops,将priority指定为5。priority表示在tier内部处理的优先级。
如上所述,与标准的NetworkPolicy相比,我们指定的securityops Tier的策略将被优先处理。例如,首先应用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: true
$ kubectl apply -f np1.yaml
networkpolicy.networking.k8s.io/drop-access-to-redis created
$ kubectl apply -f acnp12.yaml
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-to-redis created
$ kubectl get netpol
NAME POD-SELECTOR AGE
drop-access-to-redis app=redis 33s
$ kubectl get acnp
NAME TIER PRIORITY DESIRED NODES CURRENT NODES AGE
acnp-allow-access-to-redis securityops 5 1 1 18s
通过使用Antrea集群网络策略,您可以更清晰地指定安全策略的发送源和目的地,比起标准的NetworkPolicy。
ACNP控制命名空间之间的控制
我們接下來要研究ACNP跨命名空間的控制。在此之前,讓我們再次確認一下K8s NetworkPolicy的行為。將剛才使用的np1.yaml拷貝並創建一個名為np11.yaml的文件,以允許Guestbook應用程序之間的流量,然後應用此文件。
kkind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-access-from-guestbook-to-redis
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
app: redis
ingress:
- from:
- podSelector:
matchLabels:
app: guestbook
$ kubectl apply -f np11.yaml
networkpolicy.networking.k8s.io/allow-access-from-guestbook-to-redis created
当前,已在guestbook和test命名空间中部署的Pod的状态如下所示。
$ kubectl get pod -L=app -n guestbook
NAME READY STATUS RESTARTS AGE APP
frontend-767747dfdd-hx7xc 1/1 Running 0 148m guestbook
frontend-767747dfdd-mngdm 1/1 Running 0 148m guestbook
redis-follower-66497dbb55-ksjpl 1/1 Running 0 4h13m redis
redis-follower-66497dbb55-vm75v 1/1 Running 0 3h16m redis
redis-leader-85f4588648-2wffl 1/1 Running 0 3h55m redis
$ kubectl get pod -L=app -n test
NAME READY STATUS RESTARTS AGE APP
frontend-7cc596bb48-dsgds 1/1 Running 0 94m guestbook
frontend-7cc596bb48-l6wsg 1/1 Running 0 94m guestbook
在这种状态下,即使访问test Namespace的Guestbook,也不允许访问Redis,因此无法获取以下消息。这是因为在K8s NetworkPolicy中,无法跨越Namespace使用podSelector。
让我们在ACNP上尝试创建相似的政策。
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: acnp-allow-access-from-guestbook-to-redis
spec:
priority: 5
tier: securityops
appliedTo:
- podSelector:
matchLabels:
app: redis
ingress:
- action: Allow
from:
- podSelector:
matchLabels:
app: guestbook
name: AllowFromGuestbook
enableLogging: true
$ kubectl apply -f acnp2.yaml
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-from-guestbook-to-redis created
与 np11.yaml 相同,同时在 appliedTo 和 from 的 podSelector 中指定了标签 app: guestbook,但未指定命名空间。同时,之前创建的 K8s NetworkPolicy 也保持不变。
$ kubectl get netpol
NAME POD-SELECTOR AGE
allow-access-from-guestbook-to-redis app=redis 11m
$
$ kubectl get acnp
NAME TIER PRIORITY DESIRED NODES CURRENT NODES AGE
acnp-allow-access-from-guestbook-to-redis securityops 5 1 1 103s
在这种情况下,如果再次访问测试方的Guestbook,将会得到以下的许可。
由于与ACNP的允许规则匹配并进行处理,因此还会输出以下类似的日志。
...
2023/11/01 08:15:34.431560 AntreaPolicyIngressRule AntreaClusterNetworkPolicy:acnp-allow-access-from-guestbook-to-redis AllowFromGuestbook Allow 44900 192.168.1.97 59608 192.168.1.41 6379 TCP 60 <nil>
在ACNP中,可以跨命名空间对PodSelector进行评估。
此外,ACNP可以同时使用podSelector和namespaceSelector来明确指定适用于每个命名空间的目标应用和源Pod。通过编辑acnp2.yaml并添加namespaceSelector条件,您可以创建一个acnp21.yaml文件。
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: acnp-allow-access-from-guestbook-to-redis
spec:
priority: 5
tier: securityops
appliedTo:
- podSelector:
matchLabels:
app: redis
namespaceSelector:
matchLabels:
project: prod
ingress:
- action: Allow
from:
- podSelector:
matchLabels:
app: guestbook
namespaceSelector:
matchLabels:
project: test
name: AllowFromGuestbook
enableLogging: true
$ kubectl apply -f acnp21.yaml
clusternetworkpolicy.crd.antrea.io/acnp-allow-access-from-to-guestbook configured
通过这个修正,接收方的命名空间标签条件中添加了 project: prod,发送方的命名空间标签条件中添加了 project: test。接收方的 Guestbook Pods 位于 guestbook 命名空间内,但因为没有标签,所以在这种状态下无法从 test 方面进行访问。
因此,在guestbook命名空间中添加一个标签。
$ kubectl label ns guestbook project=prod
namespace/guestbook labeled
$kubectl get ns -L=project
NAME STATUS AGE PROJECT
default Active 125d
guestbook Active 6d23h prod
kube-node-lease Active 125d
kube-public Active 125d
kube-system Active 125d
test Active 23h test
然后,通过测试命名空间内的Guestbook,可以访问到guestbook命名空间内的Redis。
...
2023/11/01 08:28:16.723581 AntreaPolicyIngressRule AntreaClusterNetworkPolicy:acnp-allow-access-from-guestbook-to-redis AllowFromGuestbook Allow 44900 192.168.1.71 49126 192.168.1.30 6379 TCP 60 <nil>
在Antrea Cluster Network Policy中,可以设置不限于Namespace的集群级网络策略。集群管理员可以设置与Namespace无关的集群级安全策略。
聚类群组 (jù lè zǔ)
ClusterGroup 是 ACNP 的一个特征功能,可以在 NetworkPolicy 之外创建和重复使用用于对终端点进行分组的规则。除了之前介绍的 podSelector、namespaceSelector 和熟悉的 ipBlock 外,还可以使用 serviceReference 和定义嵌套结构的 childGroups 来定义 K8s Service 的规则和分组。
在创建使用ClusterGroup的规则之前,首先删除您之前创建的所有策略。
$ kubectl get networkpolicy --no-headers | awk '{print $1}'| xargs kubectl delete networkpolicy
networkpolicy.networking.k8s.io "allow-access-from-guestbook-to-redis" deleted
$
$ kubectl get acnp --no-headers | awk '{print $1}'| xargs kubectl delete acnp
clusternetworkpolicy.crd.antrea.io "acnp-allow-access-from-guestbook-to-redis" deleted
为了禁止对guestbook命名空间内Pod的所有流量,我们创建并应用以下的acnp-dropany.yaml文件。指定将其应用于基准Tier。在这种情况下,该规则将在评估包括K8s NetworkPolicy的所有策略规则之后应用。
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: true
$ kubectl apply -f acnp-dropany.yaml
clusternetworkpolicy.crd.antrea.io/acnp-drop-any-in-production created
由于禁止了所有Pod之间的通信,因此无法进行Guestbook应用程序前端和Redis后端之间的通信。
...
2023/11/01 08:31:25.542766 IngressDefaultRule AntreaClusterNetworkPolicy:acnp-drop-any-in-production DropFromAny Drop 16 192.168.1.92 44850 192.168.1.30 6379 TCP 60 <nil>
2023/11/01 08:31:26.573559 IngressDefaultRule AntreaClusterNetworkPolicy:acnp-drop-any-in-production DropFromAny Drop 16 192.168.1.92 44850 192.168.1.30 6379 TCP 60 <nil>
2023/11/01 08:31:28.589537 IngressDefaultRule AntreaClusterNetworkPolicy:acnp-drop-any-in-production DropFromAny Drop 16 192.168.1.92 44850 192.168.1.30 6379 TCP 60 <nil>
因此,我們將記載允許前端和後端之間通訊的政策,並在此使用 ClusterGroup。我們將使用 serviceReference 和 childGroups 來對 Redis 後端服務進行分組。
apiVersion: crd.antrea.io/v1alpha3
kind: ClusterGroup
metadata:
name: cg-guestbook
spec:
podSelector:
matchLabels:
app: guestbook
---
apiVersion: crd.antrea.io/v1alpha3
kind: ClusterGroup
metadata:
name: cg-redis-leader
spec:
serviceReference:
name: redis-leader
namespace: guestbook
---
apiVersion: crd.antrea.io/v1alpha3
kind: ClusterGroup
metadata:
name: cg-redis-follower
spec:
serviceReference:
name: redis-follower
namespace: guestbook
---
apiVersion: crd.antrea.io/v1alpha3
kind: ClusterGroup
metadata:
name: cg-redis-nested
spec:
childGroups: [cg-redis-leader, cg-redis-follower]
$ kubectl apply -f cg1.yaml
clustergroup.crd.antrea.io/cg-guestbook created
clustergroup.crd.antrea.io/cg-redis-leader created
clustergroup.crd.antrea.io/cg-redis-follower created
clustergroup.crd.antrea.io/cg-redis-nested created
下一步将使用这些 ClusterGroup 创建一个名为 acnp3.yaml 的 ACNP。
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: true
---
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: true
---
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: acnp-allow-access-to-redis-follower
spec:
priority: 5
tier: securityops
appliedTo:
- group: "cg-redis-follower"
ingress:
- action: Allow
from:
- group: "cg-redis-leader"
name: AllowToRedisFollower
enableLogging: true
$ 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-follower created
当你从浏览器访问时,现在已经允许访问Redis后台,并正常返回响应。
...
2023/11/01 08:33:32.281153 AntreaPolicyIngressRule AntreaClusterNetworkPolicy:acnp-allow-access-to-redis AllowFromGuestbookToRedis Allow 44900 192.168.1.92 35194 192.168.1.30 6379 TCP 60 <nil>
您觉得如何呢?在Antrea集群网络策略中,您是否理解了可以在集群级别上实现灵活的端点分组的功能呢?
FQDN过滤
FQDN(Fully Qualified Domain Name)过滤是一种在 Pod 对外部通信中,通过指定通信目标的完全修饰域名(FQDN)来控制与特定域名的通信的机制。可以在 ACNP(Antrea Cluster Network Policy)的 egress 规则中使用。与 FQDN 进行匹配可以使用完全匹配和使用通配符的部分匹配。将 FQDN 与实际通信中使用的 IP 地址进行关联,是通过检查 Pod 的 DNS 查询来完成的。
现在让我们尝试使用 FQDN 过滤。请删除之前创建的所有 NetworkPolicy 和 ACNP。接下来,请创建并应用以下清单,以拒绝 guestbook 命名空间的所有出口流量。
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: acnp-reject-egress-in-production
spec:
priority: 100
tier: baseline
appliedTo:
- podSelector: {}
namespaceSelector:
matchLabels:
project: prod
egress:
- action: Reject
name: RejectToAny
enableLogging: true
$ kubectl apply -f acnp-reject-egress.yaml
clusternetworkpolicy.crd.antrea.io/acnp-reject-egress-in-production created
如果在这种情况下,从前端 Pod 尝试访问 www.google.com,则会被拒绝访问,拒绝的方式如下。
$ kubectl exec frontend-767747dfdd-5896s -it -- curl -o tempfile www.google.com
curl: (7) Failed to connect to www.google.com port 80: Connection refused
command terminated with exit code 7
由於在這裡應用的清單中,將操作設置為 Reject,因此TCP連接將被Antrea拒絕,連接將立即失敗。拒絕操作的詳細信息將被輸出到日誌中。
...
2023/11/01 10:41:36.949294 EgressDefaultRule AntreaClusterNetworkPolicy:acnp-reject-egress-in-production RejectToAny Reject 16 192.168.1.97 45020 172.217.26.228 80 TCP 60 <nil>
接下来,创建并应用一个类似下面的清单,以允许对google.com域名进行访问。通过在允许规则中指定fqdn: “*google.com”,将允许对google.com的所有主机和子域名进行访问。
apiVersion: crd.antrea.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: acnp-fqdn-allow-google
spec:
priority: 5
appliedTo:
- podSelector: {}
namespaceSelector:
matchLabels:
project: prod
egress:
- action: Allow
to:
- fqdn: "*google.com"
name: AllowToGoogle
enableLogging: true
$ kubectl apply -f acnp-allow-google.yaml
clusternetworkpolicy.crd.antrea.io/acnp-fqdn-allow-google created
当从前端 Pod 再次访问 www.google.com 时,将被授权如下情况。
$ kubectl exec frontend-767747dfdd-5896s -it -- curl -o tempfile www.google.com
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 19602 0 19602 0 0 98010 0 --:--:-- --:--:-- --:--:-- 98010
...
2023/11/01 10:56:56.359560 AntreaPolicyEgressRule AntreaClusterNetworkPolicy:acnp-fqdn-allow-google AllowToGoogle Allow 14500 192.168.1.97 45802 172.217.26.228 80 TCP 60 <nil>
此时,ACNP 已经处于以下状态。
$ kubectl get acnp
NAME TIER PRIORITY DESIRED NODES CURRENT NODES AGE
acnp-fqdn-allow-google application 5 1 1 6m5s
acnp-reject-egress-in-production baseline 100 1 1 26m
由于将允许连接到Google域的策略设置为比Reject策略的应用层具有更高的优先级,因此可知其将先进行评估。
我希望在接下来的会议中能够更详细地介绍Antrea集群网络策略的操作方法等内容。