网络策略¶
策略对象¶
-
Pod
calico 支持通过
GlobalNetworkPolicy
和NetworkPolicy
对 Pod 的 Egress/Ingress 流量进行管控。特定 Namespace 的 Pod 只能与此 Namespace 下的 Pod 通信。若 namespace 具有 Label:
environment == "development
,则该 namespace 下的 Pod 只能与同一 namespace 下的 Pod 通信:apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: restrict-development-access spec: namespaceSelector: 'environment == "development"' ingress: - action: Allow source: namespaceSelector: 'environment == "development"' egress: - action: Allow destination: namespaceSelector: 'environment == "development"'
-
Service
Calico 支持对 Kubernetes Service 进行管控:
apiVersion: projectcalico.org/v3 kind: NetworkPolicy metadata: name: allow-api-access namespace: my-app spec: selector: all() egress: - action: Allow destination: services: name: kubernetes namespace: default
此处 Policy 指的是允许所有 Pod 访问 Kubernetes 这个 Service。
-
host
Calico 支持通过
GlobalNetworkPolicy
对 Kubernetes 节点进行管控。 -
VMs
-
ServiceAccount
Calico 支持用
ServiceAccount
来灵活地控制策略在 Pod 上的应用方式:-
使用
ServiceAccounts
来限制 Pod 的入口流量:当访问 namespace: prod-engineering 下具有 Label:
app == "db"
的 Pod 时,如果访问者 Pod 所使用的serviceAccounts
的 name 是api-service
或者user-auth-service
,则请求通过。 -
使用
ServiceAccount
的 Label 限制工作负载的入口流量:当访问者 Pod 所绑定的
ServiceAccounts
的 Label 满足app == "web-frontend"
, 则允许访问prod-engineering
namespace 下满足 Label: 'app == "db"' 的 Pod。 -
使用
serviceAccountSelector
筛选 Policy 的作用目标:只有
serviceAccountSelector
匹配'role == "intern"
的 Pod 之间才能互相访问:apiVersion: projectcalico.org/v3 kind: NetworkPolicy metadata: name: restrict-intern-access namespace: prod-engineering spec: serviceAccountSelector: 'role == "intern"' ingress: - action: Allow source: serviceAccounts: selector: 'role == "intern"' egress: - action: Allow destination: serviceAccounts: selector: 'role == "intern"'
-
对流量的双向管控¶
-
Egress
支持对匹配策略的 Endpoint 进行出口流量管控
-
Ingress
支持对匹配策略的 Endpoint 进行入口流量管控
支持多种管控行为¶
-
Allow
当数据包匹配定义的行为,允许其通过。
-
Deny
当数据包不匹配定义的行为,禁止其通过。
-
Log
不对数据包进行管控,只是日志记录,然后继续处理下一条规则。
-
Pass
Pass action 会跳过目前剩下的所有规则,跳转到 Calico EndPoint 分配的第一个 Profile,然后执行 Profile 定义的规则。 Calico 对于每一个 Endpoint 都会绑定两个 Profile(
kns.<namespace>
和ksa.<namespace>.default
)。 Profile 中定义了一系列的 Label 和策略(由于历史原因,Profile 中包括策略规则,先已废弃)。 如果该 Endpoint 没有绑定任何的 Profile,那么策略结果相当于 Deny。
策略优先级¶
通过 order 字段指定,如果没有指定,默认最后执行。数值越小优先级越高。如果 order 的值一样,按照 Policy 的 name 字段顺序排序。
集群及租户级别的管控¶
Kubernetes 默认采用零信任模型,即集群内所有 Pod、主机之间都可以相互访问。我们可以定义全局的策略或者租户级别的策略来管控 Pod 的入口、出口流量。
-
全局策略管控
通过
GlobalNetworkPolicy
对象作用于所有 namespace 的 Pod。例如,以下示例禁止带有 label:app=client
的 Pod 去访问带有 label:app=="server"
的 Pod:apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: deny-tcp-8080 spec: order: 1 selector: app == 'server' types: - Ingress - Egress ingress: - action: Deny metadata: annotations: from: client to: server protocol: TCP source: selector: app == 'client' destination: ports: - 8080 egress: - action: Allow
其中,
selector
:通过标签筛选此 Policy 作用于哪些 Podtypes
:管控流量的方向,Ingress
表示入口流量,Egress
表示出口流量ingress
:定义入口流量策略的内容action
:策略动作。可选值为 Allow、Deny、Log、Passmetadata
:额外信息。只是为了说明protocol
:协议。可选为"TCP"、"UDP"、"ICMP"、"ICMPv6"、"SCTP"、"UDPLite"source
:通过 label 筛选访问源destination
:筛选访问目标,这里筛选目的端口为 8080egress
:这里未做其他要求,允许所有通过calicoctl apply -f
,即可生效。
-
租户级别管控
Calico 通过
NetworkPolicy
对象管控特定 namespace 下的 Pod,与GlobalNetworkPolicy
不同的是,NetworkPolicy
作用于特定 namespace。 例如:apiVersion: projectcalico.org/v3 kind: NetworkPolicy metadata: name: allow-tcp-8080 namespace: production spec: selector: app == 'server' types: - Ingress - Egress ingress: - action: Allow metadata: annotations: from: frontend to: database protocol: TCP source: selector: app == 'client' destination: ports: - 8080 egress: - action: Allow
与上面的
GlobalNetworkPolicy
的不同之处在于:metadata
多了一个 namespace 字段,规定了这个策略作用的 namespace。
与 Kubernetes Policy 对比¶
-
支持策略优先级
-
支持 Deny 规则
-
更加灵活的匹配规则
-
支持管控更多的策略对象, Kubernetes 只支持管控 Pod
性能影响¶
Calico 的 Policy 实现依赖于 IPtables
。
当策略增多,节点对应的 iptables
数量也会增多,这会影响到性能。
以下测试展示,当策略增加时,不同模式下如 iptables
、ipset
、tc-bpf
、cilium
、calico
的性能变化(包括 CPU 开销、吞吐量、延迟)。
Note
以下测试场景旨在测试 Policy 的数量对集群内部的流量访问外部 CIDR 出口流量的影响。
其中,Calico 使用 GlobalNetworkSet API
传递想要拒绝出口的 CIDR 列表,然后通过标签选择器引用 GlobalNetworkPolicy
中的 GlobalNetworkSet
资源。
实际上,这种方式本质上使用的是 IPset
,所以可参考 IPtables
模式的数据。
性能测试结果(仅供参考):
- 当规则数增加到 1000 条以上时,
IPtables
模式下的吞吐量大幅度增加。
- 当规则数增加到 1000 条以上时,
IPtables
模式下的 CPU 使用量大幅度增加。
- 当规则数增加到 1000 条以上时,
IPtables
模式下的延迟大幅度增加。