使用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 类型,并通过外部负载均衡器实现从外部的连接。根据使用环境进行相应配置。
配置完成后,结构如下所示。

image.png

当您访问以下的网址时,将会显示留言板的用户界面。

http://172.19.0.212/
image.png

在这里,我会在消息栏中写一条消息。当我写下”first message”并点击提交后,Redis中存储的消息将会被显示如下。

image.png

在这里,我们将检查每个 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时,不再显示以下消息。

image.png

有点难懂,但是由于无法连接到Redis后端,我们无法读取记录的消息,就像下面的图一样。

image.png

只要删除此NetworkPolicy,就可以再次从Redis中接收消息。

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

对来自外部的命名空间访问进行控制

我們將創建並應用一個禁止訪問前端留言簿的策略。

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

然后,无法访问留言簿。

image.png

事实上,由于来自外部的连接受阻,前端服务器的外部连接已经中断。

image.png

再次删除策略后,前端也可以访问。

$ kubectl delete -f np2.yaml
networkpolicy.networking.k8s.io "drop-access-to-guestbook" deleted
image.png

命名空間之間的控制

这次我们将确认来自其他命名空间的流量控制。为了进行这个测试,我们创建了一个名为 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。配置如下所示。

image.png

当你访问test命名空间中的前端服务时,将显示包含先前写入的消息的Guestbook应用程序。

http://172.19.0.217/
image.png

现在我们尝试创建以下的 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。

image.png

就像这样,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

即使在这种状态下访问留言簿应用程序,对后端的访问也不会受阻,正常显示。

image.png

当网络策略(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的访问受到阻碍,无法显示以下消息。

image.png

由于在上述清单中设置了 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
image.png
image.png

通过使用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。

image.png
image.png

让我们在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,将会得到以下的许可。

image.png

由于与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>
image.png

在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 方面进行访问。

image.png

因此,在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。

image.png
... 
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后端之间的通信。

image.png
... 
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后台,并正常返回响应。

image.png
... 
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集群网络策略的操作方法等内容。

广告
将在 10 秒后关闭
bannerAds