跳转至

SecurityGroup 使用

Kube-OVN 支持安全组来控制一组 Pod 的网络访问规则。

Warning

Kube-OVN 同时支持 NetworkPolicyNetwork Policy APISubnet ACL 和 Security Group 四种类型的访问控制,其底层都是通过 OVN ACL 来实现。其中 NetworkPolicy 和 NetworkPolicy API 在设计时考虑了规则分层,可以做到优先级不冲突,其他类型的访问控制方式混用都可能导致优先级冲突。我们推荐不要同时使用多种访问控制规则,以避免优先级冲突带来的规则混乱。

安全组示例

apiVersion: kubeovn.io/v1
kind: SecurityGroup
metadata:
  name: sg-example
spec:
  allowSameGroupTraffic: true
  egressRules:
  - ipVersion: ipv4
    policy: allow
    priority: 1
    protocol: all
    remoteAddress: 10.16.0.13 # 10.16.0.0/16 配置网段
    remoteType: address
  ingressRules:
  - ipVersion: ipv4
    policy: deny
    priority: 1
    protocol: icmp
    remoteAddress: 10.16.0.14
    remoteType: address

安全组各字段的具体含义,可以参考 Kube-OVN 接口规范

Pod 通过添加 ovn.kubernetes.io/security_groups annotation 来绑定安全组:

    ovn.kubernetes.io/security_groups: sg-example

关于端口安全(Port Security)功能的说明,请参考端口安全文档

分层安全组

安全组支持通过可选的 tier 字段进行多层 ACL 处理。这允许您堆叠多个安全组以执行分层 ACL 评估。

  • tier:整数值,取值为 01(默认为 0)。tier 0 中的规则最先被评估。如果 tier 0 中的规则匹配且策略为 policy: pass,则 ACL 处理将继续到 tier 1
  • policy: pass:除 allowdeny 之外的策略动作,它将数据包评估转发到下一层,而不做最终决定。当安全组的 tier 设置为最大值(1)时,不能使用 pass 策略,因为没有后续层可以传递。

如果流量被传递到更高层级,但没有匹配任何规则,则默认会被丢弃。

这使得以下场景成为可能:例如,一个宽泛的 tier-0 安全组将某些流量传递给更具体的 tier-1 安全组进行进一步过滤。

分层安全组示例

创建两个安全组,每个层一个:

apiVersion: kubeovn.io/v1
kind: SecurityGroup
metadata:
  name: sg-tier0
spec:
  tier: 0
  allowSameGroupTraffic: true
  ingressRules:
  - ipVersion: ipv4
    policy: pass
    priority: 1
    protocol: tcp
    remoteAddress: 10.16.0.0/16
    remoteType: address
  - ipVersion: ipv4
    policy: deny
    priority: 2
    protocol: all
    remoteAddress: 0.0.0.0/0
    remoteType: address
---
apiVersion: kubeovn.io/v1
kind: SecurityGroup
metadata:
  name: sg-tier1
spec:
  tier: 1
  allowSameGroupTraffic: true
  ingressRules:
  - ipVersion: ipv4
    policy: allow
    priority: 1
    protocol: tcp
    remoteAddress: 10.16.0.0/16
    remoteType: address
    portRangeMin: 80
    portRangeMax: 443

在此示例中,sg-tier0 将来自 10.16.0.0/16 的所有 TCP 流量传递到 tier 1,并拒绝其他所有流量。sg-tier1 然后仅允许来自该网段的 80-443 端口的 TCP 流量。

要将两个安全组同时应用到 Pod,请在 annotation 中以逗号分隔的形式列出它们:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: web
  annotations:
    ovn.kubernetes.io/security_groups: 'sg-tier0,sg-tier1'
  name: multi-tier-pod
  namespace: default
spec:
  nodeName: kube-ovn-worker
  containers:
  - image: docker.io/library/nginx:alpine
    imagePullPolicy: IfNotPresent
    name: nginx

本地地址和源端口过滤

安全组规则支持可选的 localAddress 和源端口范围字段,以实现更细粒度的匹配:

  • localAddress:要匹配的本地 IP 地址或 CIDR。此字段允许规则仅在本地(出方向为源地址,入方向为目的地址)地址匹配时生效。
  • sourcePortRangeMin / sourcePortRangeMax:定义要匹配的源端口范围(1-65535)。仅适用于 TCP 和 UDP 协议。

本地地址过滤示例

apiVersion: kubeovn.io/v1
kind: SecurityGroup
metadata:
  name: sg-local-filter
spec:
  allowSameGroupTraffic: true
  ingressRules:
  - ipVersion: ipv4
    policy: allow
    priority: 1
    protocol: tcp
    remoteAddress: 10.16.0.0/16
    remoteType: address
    portRangeMin: 8080
    portRangeMax: 8080
    localAddress: 10.16.0.100
    sourcePortRangeMin: 1024
    sourcePortRangeMax: 65535

此规则允许从 10.16.0.0/1610.16.0.100 的 8080 端口的入站 TCP 流量,源端口范围为 1024-65535。

注意事项

  • 安全组最后是通过设置 ACL 规则来限制访问的,OVN 文档中提到,如果匹配到的两个 ACL 规则拥有相同的优先级,实际起作用的是哪个 ACL 是不确定的。因此设置安全组规则的时候,需要注意区分优先级。
  • 配置安全组时 priority 的取值范围为 1-16384,值越小,安全组的优先级越高。通过 ACL 实现安全组时,会将安全组的优先级映射成 ACL 的优先级,具体映射关系如下:ACL 优先级 = 18484 - 安全组优先级,因此需要注意区分安全组和子网 ACL 优先级。
  • tier 字段取值为 01policy: pass 策略仅在 tier 0 中有效;在 tier 1 中使用将导致验证错误。
  • 当添加安全组的时候,要清楚的知道是在添加什么限制。Kube-OVN 作为 CNI,创建 Pod 后会进行 Pod 到网关的连通性测试,如果访问不通网关,就会导致 Pod 一直处于 ContainerCreating 状态,无法顺利切换到 Running 状态。

实际测试

利用以下 YAML 创建 Pod,在 annotation 中指定绑定示例中的安全组:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: static
  annotations:
    ovn.kubernetes.io/security_groups: 'sg-example'
  name: sg-test-pod
  namespace: default
spec:
  nodeName: kube-ovn-worker
  containers:
  - image: docker.io/library/nginx:alpine
    imagePullPolicy: IfNotPresent
    name: qatest

实际测试结果显示如下:

# kubectl get pod -o wide
NAME                   READY   STATUS              RESTARTS   AGE     IP           NODE                     NOMINATED NODE   READINESS GATES
sg-test-pod            0/1     ContainerCreating   0          5h32m   <none>       kube-ovn-worker          <none>           <none>
test-99fff7f86-52h9r   1/1     Running             0          5h41m   10.16.0.14   kube-ovn-control-plane   <none>           <none>
test-99fff7f86-qcgjw   1/1     Running             0          5h43m   10.16.0.13   kube-ovn-worker          <none>           <none>

执行 kubectl describe pod 查看 Pod 的信息,可以看到报错提示:

# kubectl describe pod sg-test-pod
Name:         sg-test-pod
Namespace:    default
Priority:     0
Node:         kube-ovn-worker/172.18.0.2
Start Time:   Tue, 28 Feb 2023 10:29:36 +0800
Labels:       app=static
Annotations:  ovn.kubernetes.io/allocated: true
              ovn.kubernetes.io/cidr: 10.16.0.0/16
              ovn.kubernetes.io/gateway: 10.16.0.1
              ovn.kubernetes.io/ip_address: 10.16.0.15
              ovn.kubernetes.io/logical_router: ovn-cluster
              ovn.kubernetes.io/logical_switch: ovn-default
              ovn.kubernetes.io/mac_address: 00:00:00:FA:17:97
              ovn.kubernetes.io/pod_nic_type: veth-pair
              ovn.kubernetes.io/port_security: true
              ovn.kubernetes.io/routed: true
              ovn.kubernetes.io/security_groups: sg-allow-reject
Status:       Pending
IP:
IPs:          <none>
·
·
·
Events:
  Type     Reason                  Age                    From     Message
  ----     ------                  ----                   ----     -------
  Warning  FailedCreatePodSandBox  5m3s (x70 over 4h59m)  kubelet  (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "40636e0c7f1ade5500fa958486163d74f2e2300051a71522a9afd7ba0538afb6": plugin type="kube-ovn" failed (add): RPC failed; request ip return 500 configure nic failed 10.16.0.15 network not ready after 200 ping 10.16.0.1

修改安全组的规则,添加到网关的访问规则,参考如下:

apiVersion: kubeovn.io/v1
kind: SecurityGroup
metadata:
  name: sg-gw-both
spec:
  allowSameGroupTraffic: true
  egressRules:
  - ipVersion: ipv4
    policy: allow
    priority: 2
    protocol: all
    remoteAddress: 10.16.0.13
    remoteType: address
  - ipVersion: ipv4
    policy: allow
    priority: 1
    protocol: all
    remoteAddress: 10.16.0.1
    remoteType: address
  ingressRules:
  - ipVersion: ipv4
    policy: deny
    priority: 2
    protocol: icmp
    remoteAddress: 10.16.0.14
    remoteType: address
  - ipVersion: ipv4
    policy: allow
    priority: 1
    protocol: icmp
    remoteAddress: 10.16.0.1
    remoteType: address

分别在入方向和出方向规则中,添加允许到网关的访问规则,并且设置该规则的优先级最高。

利用以下 yaml 绑定安全组,部署 Pod 后,确认 Pod 可以正常运行:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: static
  annotations:
    ovn.kubernetes.io/security_groups: 'sg-gw-both'
  name: sg-gw-both
  namespace: default
spec:
  nodeName: kube-ovn-worker
  containers:
  - image: docker.io/library/nginx:alpine
    imagePullPolicy: IfNotPresent
    name: qatest

部署后查看 Pod 信息:

# kubectl get pod -o wide
NAME                   READY   STATUS              RESTARTS   AGE     IP           NODE                     NOMINATED NODE   READINESS GATES
sg-test-pod            0/1     ContainerCreating   0          5h41m   <none>       kube-ovn-worker          <none>           <none>
sg-gw-both             1/1     Running             0          5h37m   10.16.0.19   kube-ovn-worker          <none>           <none>

因此对于安全组的使用,要特别明确添加的限制规则的作用。如果单纯是限制流量访问,可以考虑使用网络策略实现。

PDF Slack Support

评论