网络策略(Network Policy
)是Kubernetes
提供的一种规范,它描述了一组Pod
是如何被允许相互通信的,以及和其他端点是如何通信的。Kubernetes
只提供了这样的机制,具体功能由网络插件(Network Plugins
)实现,流行的网络插件有很多,但并不是所有的网络插件都提供了网络策略功能,如flannel
就没有提供这样的功能,目前已知的支持网络策略的有Calico
, Cilium
, Kube-router
, Romana
, Weave Net
, Canal
。
网络策略的应用和Kubernetes
中很多操作类似,是通过labels
来选取一组Pods
的,然后再配置具体的规则(目前的实现都是通过配置iptables rule
)来控制什么流量被允许发送到这组选取的Pods
。
注: 笔者使用的Kubernetes 1.6版本中网络策略还处于beta
状态,其配置和Kubernetes 1.7中网络策略正式版略有差异。这里略作批注。
网络策略
使用网络策略的一般步骤如下(以Calico
为例):
配置网络策略
- 修改
kube-apiserver
的配置文件,添加配置项--runtime-config=extensions/v1beta1/networkpolicies=true
,表示启用网络策略(Kubernetes 1.6版本中) - 修改
kubelet
的配置文件,添加配置项--network-plugin=cni
,表示使用CNI网络插件 - 根据
calico
相应版本的安装文档,安装calico
插件,Calico Kubernetes Hosted Install方式比较简单。
使用网络策略
kubernetes
官方文档有详细的说明,这里简要列一下几个关键配置。
-
默认配置下,
Pods
是不做隔离的,即集群内所有Pod
之间都是互通的。
a. Kubernetes 1.6版本中在使用网络策略之前,需要先配置namespace
为默认隔离,配置如下:{
"metadata": {
"name": "mynamespace",
"labels": {
"name": "mynamespace"
},
"annotations": {
"net.beta.kubernetes.io/network-policy": "{\"ingress\": {\"isolation\": \"DefaultDeny\"}}"
}
}
}此时,该
namespace
下的所有Pod
都是隔离状态的,不接收任何来源的流量。b. Kubernetes 1.7版本中直接通过网络策略配置,即配置网络策略的应用网络策略规则,未配置网络策略的还是未隔离状态。
-
使用标签选择器配置一组
Pod
的网路策略,即接收哪些来源的流量, 示例如下(Kubernetes 1.6版本apiVersion
不同),该配置表示:- 在名为
default
的命名空间中隔离所有标签为role=db
的Pod
, 如果没有隔离的话(Kubernetes 1.7版本)。 - 允许标签为
project=myproject
的命名空间中的所有Pod
通过TCP
连接该default
命令空间里的标签为role=db
的Pod
的6379
端口。 - 允许标签为
role=frontend
的defult
命名空间中的所有Pod
通过TCP
连接该default
命令空间里的标签为role=db
的Pod
的6379
端口。
{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": "test-network-policy",
"namespace": "default"
},
"spec": {
"podSelector": {
"matchLabels": {
"role": "db"
}
},
"ingress": [
{
"from": [
{
"namespaceSelector": {
"matchLabels": {
"project": "myproject"
}
}
},
{
"podSelector": {
"matchLabels": {
"role": "frontend"
}
}
}
],
"ports": [
{
"protocol": "TCP",
"port": 6379
}
]
}
]
}
} - 在名为
-
同样的,Kubernetes 1.7版本中,也提供了默认策略
a. 默认全隔离策略,类似于Kubernetes 1.6版本对namespace
的配置,作用的命名空间下所有Pod
在未应用其他网络策略的情况下是隔离状态。{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": "default-deny"
},
"spec": {
"podSelector": null
}
}b. 全通策略,作用的命名空间下所有
Pod
可接收任何流量,无视其上配置的其他网络策略。{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": "allow-all"
},
"spec": {
"podSelector": null,
"ingress": [
{
}
]
}
}
多网络策略
在文章[kubernetes之多网络支持]中,以flannel
为例讲述了多网络的配置方法。由于flannel
不支持网络策略,这里使用Huawei-PaaS/CNI-Genie插件为例,CNI-Genie
也是集成引导插件,本身不做具体功能,由引用的插件完成网络功能,其支持Calico
, Weave Net
, Canal
, Romana
等。
配置多插件
在前述配置网络策略的基础上,再安装CNI-Genie
, Weave Net
, Canal
, Romana
等插件,以上插件官方都有Kubernetes Hosted Install
的安装脚本,直接下载应用即可。这里CNI-Genie
的配置文件是00-**.conf
,而其他插件的配置文件是10-**.conf
,所以按优先级默认加载的插件是CNI-Genie
。
使用多网络
CNI-Genie
使用动态选择插件的策略,即每次部署都可以指定不同的插件,通过Kubernetes
的annotations
实现,示例如下:
apiVersion: extensions/v1beta1 |
这里annotations
添加了两个字段,cni
表示该部署使用的网络插件,如这里使用的是Calico
和Weave Net
。multi-ip-preferences
字段用于反填网络插件配置的ip地址和网络编号,以ip1
, ip2
, … 命名。
注: Calico
由于本身实现的问题,笔者在验证时不能作为非第一网络使用,具体参看github issue
多网络策略
网络策略的实现都是以Kubernetes
里的PodIP
为入参施加网络规则的,但在多网络配置下只有第一网络的ip被上报给Kubernetes
,作为PodIP
。也就是说我们无法通过Kubernetes
存储的数据获取到多网络地址。这里我们可以利用multi-ip-preferences
字段的值来满足定制化需求。
以Weave Net
为例,需要定制其npc
实现,所有获取PodIP
的地方替换成如下方式获取的ip(获取第二网络地址,这里示例不具有灵活性,可考虑在multi-ip-preferences
添加一个字段表示该ip属于哪个插件)。
func getIPFromAnnotation(pod *coreapi.Pod) string { |
至此,我们的多网络配置下,可以使网络策略作用于所有配置网络。