ovn的acl用法

ovn实现ACL

第一种方法通过k8s标准资源networkpolicy实现ACL(推荐使用)

什么是网络策略?

首先NetworkPolicy是k8s的一种resource,可以通过以下三种维度对整个namespace或单一POD进行隔离:pod(允许某些pod访问)、namespace(允许某些namespace访问)、ip段(CIDR,但是pod所运行node节点始终可以访问该pod)当定义基于pod和namespace的NetworkPolicy时,需要根据标签来选择对应的pod或者namespace。

另外当需要使用NetworkPolicy资源时,k8s集群采用的网络插件必须支持,比如ovn-kubernetes等等

隔离和非隔离pod

默认情况所有的pod都是非隔离的,当pod被NetworkPolicy选择后,那么pod就是一个隔离的pod,出栈和入栈都要遵循NetworkPolicy的策略,并且如果有多个NetworkPolicy时,他们是叠加的而不是冲突的。

限制一个pod的NetworkPolicy需要从两个方向去考虑:ingress和egress。ingress表示入方向,egress表示出方向。

基于namespace的网络策略

以下yaml文件代表在app下创建一个NetworkPolicy资源,该策略作用在所有被打了app=nginx-test标签的pod,策略内容为只接受来自namespace为app的访问。

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: ns-network-policy

  namespace: app

spec: 

  #定义策略的类型:值是一个列表,支持Ingress和Egress两种,默认Egress不做任何限制

  policyTypes: [“Ingress”]

  #表示该策略作用的pod,以标签匹配,当该值是一个{}空字典时,代表所有POD

  podSelector:

    matchLabels:

      app: nginx-test

  #以下表示ingress策略

  ingress:

    - from:

       - namespaceSelector:

          matchLabels:

            kubernetes.io/metadata.name: app

基于POD的网络策略

以下yaml文件策略表示:允许带有app=nginx-test2的所有pod访问app=nginx-test的pod

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: ns-network-policy1

  namespace: app

spec:

  policyTypes: [“Ingress”]

  podSelector: 

    matchLabels:

      app: nginx-test

  ingress:

    - from:

       - podSelector: 

          matchLabels:

            app: nginx-test2

基于IP段的网络策略

以下yaml文件表示策略为:允许10.244.0.0/16段但是不包括10.244.1.0/24来访问带有app=nginx-test的pod

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: ns-network-policy

  namespace: olda

spec:

  policyTypes: [“Ingress”]

  podSelector: 

    matchLabels:

      app: nginx-test

  ingress:

    - from:

       - ipBlock: 

          cidr: 10.244.0.0/16

          except:

          - 10.244.1.0/24

关于端口号的限制

单个端口号,只允许app名称空间下的pod连接80端口,具体策略如下

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: test-network-policy

  namespace: app

spec:

  policyTypes: [“Ingress”]

  podSelector: 

    matchLabels:

      app: test

  ingress:

    - from:

       - namespaceSelector: 

          matchLabels:

            kubernetes.io/metadata.name: app

      ports:

      - protocol: TCP

        port: 80

多个端口号,在网络策略里增加3306端口

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: test-network-policy

  namespace: app

spec:

  policyTypes: [“Ingress”]

  podSelector: 

    matchLabels:

      app: test

  ingress:

    - from:

       - namespaceSelector: 

          matchLabels:

            kubernetes.io/metadata.name: app

      ports:

      - protocol: TCP

        port: 80

      - protocol: TCP

        port: 3306

常用的网络策略具体yaml文件示例

拒绝所有入站流量,具体yaml文件示例:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: default-deny-ingress

spec:

  podSelector: {}

  policyTypes:

  - Ingress

这确保即使没有被任何其他 NetworkPolicy 选择的 Pod 仍将被隔离以进行入口。 此策略不影响任何 Pod 的出口隔离。

允许所有入站流量,具体yaml文件示例:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: allow-all-ingress

spec:

  podSelector: {}

  ingress:

  - {}

  policyTypes:

  - Ingress

有了这个策略,任何额外的策略都不会导致到这些 Pod 的任何入站连接被拒绝。 此策略对任何 Pod 的出口隔离没有影响。

拒绝所有出站流量,具体yaml文件示例:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: default-deny-egress

spec:

  podSelector: {}

  policyTypes:

  - Egress

此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。 此策略不会更改任何 Pod 的入站流量隔离行为。

允许所有出战流量,具体yaml文件示例:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: allow-all-egress

spec:

  podSelector: {}

  egress:

  - {}

  policyTypes:

  - Egress

拒绝所有入站和出站流量,具体yaml文件示例:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: default-deny-all

spec:

  podSelector: {}

  policyTypes:

  - Ingress

  - Egress

限制特定的pod访问,具体yaml文件示例:

kind: NetworkPolicy

apiVersion: networking.k8s.io/v1

metadata:

  name: app-test

spec:

  podSelector:

    matchLabels:

      app: bookstore

      role: api

  ingress:

  - from:

      - podSelector:

          matchLabels:

            app: bookstore

允许所有的namespace访问pod,具体yaml文件示例:

kind: NetworkPolicy

apiVersion: networking.k8s.io/v1

metadata:

  namespace: default

  name: web-allow-all-namespaces

spec:

  podSelector:

    matchLabels:

      app: web

  ingress:

  - from:

    - namespaceSelector: {}

允许特定的namespace访问pod,具体yaml文件示例:

kind: NetworkPolicy

apiVersion: networking.k8s.io/v1

metadata:

  name: web-allow-prod

spec:

  podSelector:

    matchLabels:

      app: web

  ingress:

  - from:

    - namespaceSelector:

        matchLabels:

          purpose: production

根据namespace和pod相结合的策略允许pod访问,具体yaml文件示例:

kind: NetworkPolicy

apiVersion: networking.k8s.io/v1

metadata:

  name: web-allow-all-ns-monitoring

  namespace: default

spec:

  podSelector:

    matchLabels:

      app: web

  ingress:

    - from:

      - namespaceSelector:     # chooses all pods in namespaces labelled with team=operations

          matchLabels:

            team: operations  

        podSelector:           # chooses pods with type=monitoring

          matchLabels:

            type: monitoring

根据特定的pod和port结合策略允许访问pod,具体yaml文件示例:

kind: NetworkPolicy

apiVersion: networking.k8s.io/v1

metadata:

  name: api-allow-5000

spec:

  podSelector:

    matchLabels:

      app: apiserver

  ingress:

  - ports:

    - port: 5000

    from:

    - podSelector:

        matchLabels:

          role: monitoring

限制访问外部的流量,但可以访问DNS,具体yaml文件示例:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: foo-deny-egress

spec:

  podSelector:

    matchLabels:

      app: foo

  policyTypes:

  - Egress

  egress:

  # allow DNS resolution

  - to:

    - namespaceSelector:

        matchLabels:

          kubernetes.io/metadata.name: kube-system

      podSelector:

        matchLabels:

          k8s-app: kube-dns

    ports:

      - port: 53

        protocol: UDP

      - port: 53

        protocol: TCP

设置了网络策略,如何在ovn里查看是否生成相应的ACL

登录ovn-kubernetes的环境,使用如下命令登录如图的pod:

kubectl exec -it -n ovn-kubernetes ovnkube-master-788b596d78-l7gkt -c ovnkube-master – bash -il

登录之后,使用如下命令,查看ACL的数据:

Ovn-nbctl find acl

此时没有设置网络策略,就没有多余的ACL,设置一个网络策略之后就会发现多一些ACL的数据:

注意:如果针对同一个规则同时设置了deny和allow的ACL,allow的优先级会比deny优先级高,所以会允许allow。

Networkpolicy使用限制:

通过网络策略(至少目前还)无法完成的工作,到 Kubernetes 1.26 为止,NetworkPolicy API 还不支持以下功能, 不过你可能可以使用操作系统组件(如 SELinux、OpenVSwitch、IPTables 等等) 或者第七层技术(Ingress 控制器、服务网格实现)或准入控制器来实现一些替代方案。 如果你对 Kubernetes 中的网络安全性还不太了解,了解使用 NetworkPolicy API 还无法实现下面的用户场景是很值得的。

  • 强制集群内部流量经过某公用网关(这种场景最好通过服务网格或其他代理来实现);

  • 与 TLS 相关的场景(考虑使用服务网格或者 Ingress 控制器);

  • 特定于节点的策略(你可以使用 CIDR 来表达这一需求不过你无法使用节点在 Kubernetes 中的其他标识信息来辩识目标节点);

  • 基于名字来选择服务(不过,你可以使用 标签 来选择目标 Pod 或名字空间,这也通常是一种可靠的替代方案);

  • 创建或管理由第三方来实际完成的“策略请求”;

  • 实现适用于所有名字空间或 Pods 的默认策略(某些第三方 Kubernetes 发行版本或项目可以做到这点);

  • 高级的策略查询或者可达性相关工具;

  • 生成网络安全事件日志的能力(例如,被阻塞或接收的连接请求);

  • 显式地拒绝策略的能力(目前,NetworkPolicy 的模型默认采用拒绝操作, 其唯一的能力是添加允许策略);

  • 禁止本地回路或指向宿主的网络流量(Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。

参考资料

++https://kubernetes.io/docs/concepts/services-networking/network-policies/++

第二种方法通过ovn-kubernetes自定义的crd并根据资源来控制实现ACL(因限制太多不推荐使用)

找到生成的crd的yaml文件k8s.ovn.org_egressfirewalls.yaml

在部署ovn的文件夹ovn/ovn-kubernetes/dist/yaml里,有一个k8s.ovn.org_egressfirewalls.yaml文件,是根据命令生成yaml文件时生产的:

./daemonset.sh –image=yusur/ovn-daemonset-f:fullmode –net-cidr=10.123.0.0/16 –svc-cidr=10.86.0.0/16 –gateway-mode=”local” –k8s-apiserver=https://192.168.122.189:6443

创建EgressFirewall资源

找到上述的yaml文件k8s.ovn.org_egressfirewalls.yaml,使用命令:

kubectl apply -f k8s.ovn.org_egressfirewalls.yaml

修改ovnkube-master.yaml里面的参数使EgressFirewall资源生效

如果在已经部署的环境中,请修改部署ovn的文件夹ovn/ovn-kubernetes/dist/yaml里的ovnkube-master.yaml,修改里面的- name: OVN_EGRESSFIREWALL_ENABLE为true

需要重新按修改后的yaml文件重新拉起这个pod

如果是即将部署的环境,请使用如下参数添加即可:

./daemonset.sh   –egress-firewall-enable=true

设置EgressFirewall规则

EgressFirewall特性允许集群管理员限制项目中的pod可以访问的外部主机。 

EgressFirewall对象规则适用于所有共享的pod带有egressfirewall对象的名称空间。仅一个名称空间,支持有一个EgressFirewallObject。

如下示例:

kind: EgressFirewall

apiVersion: k8s.ovn.org/v1

metadata:

  name: default  #该name必须设置为default,否则会创建失败

  namespace: default

spec:

  egress:

  - type: Allow

    to:

      dnsName: www.openvswitch.org

  - type: Allow

    to:

      cidrSelector: 1.2.3.0/24

  - type: Allow

    to:

      cidrSelector: 4.5.6.0/24

    ports:

      - protocol: UDP

        port: 55

  - type: Deny

    to:

      cidrSelector: 0.0.0.0/0

这个例子允许连接到默认名称空间中的Pods,www.openvswitch.org转换为的主机,任何外部主机在1.2.3.0到1.2.3.255范围内的主机,并且允许添加只有端口上的UDP协议才会将流量设置为4.5.6.0到4.5.6.255第55号,并拒绝所有其他外部主机的流量。端口是可选的,允许用户指定特定的端口To和协议允许或拒绝流量。规则的优先级由其在出口中的位置决定数组中。较早的规则在较晚的规则之前被处理。在前面的例子,如果规则颠倒过来,所有流量都被拒绝,包括到1.2.3.0/24 CIDR块中的主机的任何流量。使用DNS特性假设已定位节点和主节点 在与添加到ovn的DNS条目类似的位置数据库是由主机生成的。 注意:在deny规则中使用DNS名称时,请谨慎使用。DNS拦截器将永远不会完美地工作,并可能允许访问一个被拒绝的主机,如果节点上的DNS解析与主节点上的DNS解析不同。

使用kubectl apply -f xxx.yaml文件之后,同样会在ovn-master的pod里面看见新增加的ACL