SecurityGroup 使用¶
Kube-OVN 支持安全组来控制一组 Pod 的网络访问规则。
Warning
Kube-OVN 同时支持 NetworkPolicy,Network Policy API,Subnet 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:整数值,取值为0或1(默认为0)。tier0中的规则最先被评估。如果 tier0中的规则匹配且策略为policy: pass,则 ACL 处理将继续到 tier1。policy: pass:除allow和deny之外的策略动作,它将数据包评估转发到下一层,而不做最终决定。当安全组的 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/16 到 10.16.0.100 的 8080 端口的入站 TCP 流量,源端口范围为 1024-65535。
注意事项¶
- 安全组最后是通过设置 ACL 规则来限制访问的,OVN 文档中提到,如果匹配到的两个 ACL 规则拥有相同的优先级,实际起作用的是哪个 ACL 是不确定的。因此设置安全组规则的时候,需要注意区分优先级。
- 配置安全组时
priority的取值范围为 1-16384,值越小,安全组的优先级越高。通过 ACL 实现安全组时,会将安全组的优先级映射成 ACL 的优先级,具体映射关系如下:ACL 优先级 = 18484 - 安全组优先级,因此需要注意区分安全组和子网 ACL 优先级。 tier字段取值为0或1。policy: pass策略仅在 tier0中有效;在 tier1中使用将导致验证错误。- 当添加安全组的时候,要清楚的知道是在添加什么限制。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>
因此对于安全组的使用,要特别明确添加的限制规则的作用。如果单纯是限制流量访问,可以考虑使用网络策略实现。