Kubernetes 网络策略
2020-04-15 by dongnan
开始之前
在前面的三篇文章中,至此我们已经准备好了K8S
集群环境。
接下来我们将以在K8S
集群运行一个真实的项目为目标,依次介绍项目所使用的K8S
资源对象。
这个项目是一个典型的Web
系统,使用 Java Spring Boot
框架开发,需要使用 MySql
、Redis
数据库、NFS
共享存储(多个Pod
容器间共享文件)。
由于K8S
环境部署在阿里云上,所以这里使用了阿里云提供的 RDS-Mysql
、RDS-Redis
数据库服务、NAS(NFS)
网络附加存储等中间件产品,对于K8S
集群来说,我们需要将这些服务映射为K8S
的资源对象。
项目使用的K8S
的资源对象包括:
- PV&PVC,用于Pod数据卷(NFS)。
- Pod (volumeMounts、readinessProbe),挂载数据卷、健康检查。
- Secret,存储机密数据。
- Service,服务-外部域名(ExternalName)。
- NetworkPolicy,网络策略。
- LimitRange,限制资源。
- Ingress
环境
测试的k8s
集群由一个Master
管理节点、两个Worker
计算节点组成,详细请参考这里。
目标
- 使用
NetworkPolicy
隔离命名空间,例如隔离生产环境、测试环境的网络。 - 使用
NetworkPolicy
网络策略保护Pod
的网络服务 (白名单)。
举个栗子
Yaml文档
定义名称为 yyi-server-np
的网络策略:
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
namespace: yyi-prod
name: yyi-server-np
spec:
podSelector:
matchLabels:
app: yyi-server
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- protocol: TCP
port: 8080
这个NetworkPolicy
对象的作用如下:
- 使用这个
NetworkPolicy
对象,需要在yyi-prod
命名空间中,并且必须带有app: yyi-server
标签的Pod
容器组。 - 进入方向,允许来自
ingress-nginx
命名空间的Pod
(Ingress控制器),访问yyi-server
(Pod)容器的TCP
协议8080
端口。 - 进入方向,拒绝其它不符合规则的请求。
- 出方向,没有规则限制。
创建网络策略
kubectl apply -f yii-np.yaml
验证网络策略
查看 NetworkPolicy
详细信息:
kubectl -n yyi-prod describe networkpolicies yyi-server-np
Name: yyi-server-np
Namespace: yyi-prod
Labels: <none>
#...省略
Spec:
PodSelector: app=yyi-server
Allowing ingress traffic:
To Port: 8080/TCP
From:
NamespaceSelector: app.kubernetes.io/name=ingress-nginx
Not affecting egress traffic
Policy Types: Ingress
尝试使用 default
命名空间中的Pod
访问 yyi-server
容器的 8080
端口:
# 获得 Pod IP 地址
kubectl -n yyi-prod get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE #...省略
yyi-server-78df87c94d-gxt6r 1/1 Running 0 164d 172.18.xx.120 host2
# 登录 Pod 控制台
kubectl exec -ti demo-secret-cf58d4f99-8n6wj /bin/bash
# 尝试访问 yyi-server 的端口
root@demo-secret-cf58d4f99-8n6wj:/var/www/html# telnet 172.18.xx.120 8080
Trying 172.18.xx.120...
telnet: Unable to connect to remote host: Connection timed out
由于 yyi-server-np
网络策略的规则,拒绝了访问请求。
NetworkPolicy
NetworkPolicy
定义了一组Pod
是否允许相互通信,或者Pod
与网络中的其它端点通信的规则。
NetworkPolicy
对象使用标签选择Pod
,并规定选中的Pod
可以执行什么样的网络通信。
NetworkPolicy
由网络插件实现,因此使用的网络插件必须能够支持 NetworkPolicy
才可以使用此特性。
参数含义
重点看下spec
段包,含了定义网络策略的主要信息:
podSelector:
- 同名称空间中,符合此标签选择器
.spec.podSelectorr
的Pod
都将应用这个NetworkPolicy
。 - 如果该字段为空,则将对名称空间中所有的
Pod
应用这个NetworkPolicy
。
policyTypes:
- 是一个数组类型的字段,该数组中可以包含
Ingress
、Egress
中的一个,也可能两个都包含。 - 该字段默认将始终包含
Ingress
,当NetworkPolicy
中包含出方向的规则时,Egress
也将被添加到默认值。
ingress:
ingress
,代表入方向的白名单规则,每一条规则都将允许与from
和ports
匹配的入方向的网络流量发生关联。
egress:
egress
,代表出方向的白名单规则,每一条规则都将允许与to
和ports
匹配的出方向的网络流量发生。
.spec.ingress.from
和 .spec.egress.to
字段可以指定4
种类型的标签选择器:
- podSelector: 选择与
NetworkPolicy
相同名称空间中的 Pod 作为入方向访问控制规则的源或者出方向访问控制规则的目标。 - namespaceSelector: 选择某个名称空间所有的Pod 作为入方向访问控制规则的源或者出方向访问控制规则的目标。
- namespaceSelector && podSelector: 在一个
to
/from
条目中同时包含这两个选择器,将选中指定名称空间中的指定 Pod。 - ipBlock 可选择
IP
地址CIDR
范围作为入方向访问控制规则的源或者出方向访问控制规则的目标。这里应该指定的是集群外部的IP,因为集群内部 Pod 的 IP 地址是临时分配的,且不可预测。
小结
NetworkPolicy
由网络插件实现,因此使用的网络插件必须能够支持NetworkPolicy
才可以使用。- 默认情况下
Pod
都是非隔离的,可以接受来自任何请求方的网络请求。 - 如果一个
NetworkPolicy
的标签选择器选中了某个Pod
,则该Pod
将变成隔离的,并将拒绝任何不被NetworkPolicy
许可的网络连接。 NetworkPolicy
不会相互冲突,而是相互叠加的。- 如果多个
NetworkPolicy
选中了同一个Pod
,则该Pod
可以接受这些NetworkPolicy
当中任何一个NetworkPolicy
定义的规则。 - 因此,
NetworkPolicy
的顺序并不重要,因为不会影响到最终的结果。