
目前许多组织都在采用Kubernetes来运行他们的应用程序。以至于有些人将Kubernetes称为新的数据中心操作系统。因此,组织开始将Kubernetes(通常缩写为k8s)视为关键任务平台,它需要包括网络安全在内的成熟业务流程。
负责保护这个新平台的网络安全团队可能发现它出奇的不同。例如,默认的Kubernetes策略是允许任何连接。
本文提供了一些关于Kubernetes网络策略工作原理的简介,它们如何与传统防火墙策略进行比较以及一些可以帮助你保护Kubernetes应用程序的陷阱和最佳实践。
Kubernetes网络策略
Kubernetes提供了一种称为网络策略的机制,可用于对部署在平台上的应用程序实施第3层分隔。网络策略缺乏现代防火墙的高级功能,如第7层控制和威胁检测,但是它们确实提供了基本的网络安全,这是一个很好的起点。
网络策略控制Pod的通信
Kubernetes的工作负载在pod中运行,pod由一个或多个部署在一起的容器组成。Kubernetes为每个pod分配一个IP地址,这个地址可以从其他所有pod路由,甚至可以跨底层服务器。Kubernets网络策略指定pod组的访问权限,类似于云服务中的安全组用于控制对虚拟机实例的访问。
编写网络策略
与其他Kubernetes资源一样,网络策略可以使用一种称为YAML的语言定义。下面是一个简单的例子,它允许从负载均衡到postgres的访问。
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default.postgres namespace: defaultspec: podSelector: matchLabels: app: postgres ingress: - from: - podSelector: matchLabels: app: balance policyTypes: - Ingress

为了编写你自己的网络策略,你需要对yaml有基本的了解。Yaml基于缩进(使用的是空格,而不是tab)。缩进项属于其上方最接近的缩进项。连字符(破折号)开始一个新的列表项。所有其他项都是映射条目。你可以在网上找到大量关于yaml的信息。
编写完策略的YAML文件后,使用kubectl创建策略:
kubectl create -f policy.yaml
网络策略定义
网络策略定义由四个元素组成:
- podSelector:将受此策略约束的pod(策略目标)。必填
- policyType:指定哪些类型的策略包含在这个策略中,ingress或egress。该项是可选的,但建议总是明确的指定它。可选
- ingress:允许传入目标pod的流量。可选
- egress:允许从目标pod传出的流量。可选
下面这个例子是从Kubernetes官网上改编的(将“role”改为了“app”),它指定了四个元素:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: test-network-policy namespace: defaultspec: podSelector: matchLabels: app: db policyTypes: - Ingress - Egress ingress: - from: - ipBlock: cidr: 172.17.0.0/16 except: - 172.17.1.0/24 - namespaceSelector: matchLabels: project: myproject - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 6379 egress: - to: - ipBlock: cidr: 10.0.0.0/24 ports: - protocol: TCP port: 5978


注意,你不必包含所有四个元素。podSelector是必填的,其余三个是可选的。
如果你忽略了policyType,则推断如下:
- 策略总是被认为指定了一个ingress定义。如果你没有明确的定义它,它将被视为“不允许流量“。
- egress将由是否存在egress元素诱导。
为了避免错误,建议总是显式的指定policyType。
如果没有提供ingress或egress的定义,并且根据上面的逻辑假定它们存在,策略将认为它们是“不允许流量”。
默认策略是允许
当没有定义任何策略时,Kubernetes允许所有通信。所有pod都可以相互自由通信。从安全角度来看,这听起来可能有悖常理,但请记住,Kubernetes是由希望应用程序进行通信的开发人员设计的。网络策略是作为后来的增强功能添加的。
命名空间
命名空间是Kubernetes的多租户机制,旨在将命名空间环境相互隔离,但是,命名空间的通信在默认情况下仍然是被允许的。
与大多数Kubernetes实体一样,网络策略也位于特定的命名空间中。元数据头部告诉Kubernetes策略属于哪个命名空间:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: test-network-policy namespace: my-namespacespec:...
如果你没有明确指定元数据的命名空间,它将应用于kubectl提供的命名空间(默认是namespace=default)。
kubectl apply -n my-namespace -f namespace.yaml
建议显式指定命名空间,除非你正在编写的策略要统一应用在多个命名空间中。
策略中的podSelector元素将从策略所属的命名空间中选择pod(它不能从另一个命名空间选择pod)。
ingress和egress元素中的podSelector也会选择相同命名空间中的pod,除非你将它们和namespaceSelector一起使用。
策略命名约定
策略的名称在命名空间中是唯一的。一个命名空间中不能有两个同名的策略,但是不同的命名空间可以有同名的策略。当你想要在多个命名空间重复应用某个策略时,这非常方便。
我喜欢的策略命名方法之一是将命名空间与pod组合起来,例如:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default.postgres namespace: defaultspec: podSelector: matchLabels: app: postgres ingress: - from: - podSelector: matchLabels: app: admin policyTypes: - Ingress

标签
Kubernetes对象,如pod和namespace,可以附加用户自定义标签。Kubernetes网络策略依赖于标签来选择它们应用于的pod:
podSelec