Kubernetes网络策略Network Policy提供基于策略的网络控制。如果您希望在IP地址或者端口层面控制网络流量,您可以为集群中特定应用使用网络策略。本文介绍如何使用ASK集群的网络策略及常见的使用场景。
索引
前提条件
注意事项
ASK的Network Policy功能还在灰度中,如需使用Network Policy功能请 提交工单 申请开放。
-
Network Policy功能仅支持在ASK Pro版、ACK Pro版集群使用。
-
NetworkPolicy规则允许通过LabelSelector选择Namespace或者Pod。但当Pod中的NetworkPolicy数量增大时,不仅会使规则生效时间延长,而且大量的NetworkPolicy规则也会对您的集群管理、问题排查带来困扰,因此建议您集群内的NetworkPolicy数量小于40个。
-
ACK和ASK集群的Network Policy的实现由不同组件承载。
-
在ACK集群(非ECI实例)中,Network Policy的实现由 Terway 插件负责。详细信息,请参见 在ACK中开启网络策略 。
-
在ASK集群、ACK集群的ECI实例中,Network Policy的实现由 Poseidon 组件负责。详细信息将在本文进行介绍。
-
步骤一:开启网络策略
-
登录 容器服务管理控制台 ,在左侧导航栏选择 集群 。
-
在 集群列表 页面,单击目标集群名称,然后在左侧导航栏,选择 。
-
在 组件管理 页面,单击 其他 页签,在 Poseidon 组件所在卡片的右下方,单击 安装 。
-
在 安装组件 Poseidon 页面,选中 为ECI 实例启用 NetworkPolicy ,然后单击 确认 。
组件安装成功后,会在卡片右上角出现 已安装 字样。
步骤二:创建可以被其他Pod正常访问的nginx测试应用
通过控制台操作
-
登录 容器服务管理控制台 ,在左侧导航栏选择 集群 。
-
在 集群列表 页面,单击目标集群名称,然后在左侧导航栏,选择 。
-
在 无状态 页面,单击 使用镜像创建 。在 创建 配置向导页面中,创建一个名称为 nginx 的应用,并通过Service将其公开。配置完成后,单击 创建 。
本示例的nginx应用仅需配置以下配置项,其他配置项选择默认配置。关于更多配置说明,请参见 使用镜像创建无状态Deployment应用 。
页面
配置项
说明
示例值
应用基本信息
应用名称
自定义名称。
nginx
副本数量
按需选择。
1
容器配置
镜像名称
单击 选择镜像 ,选择所需的镜像并单击 确定 。
本例选择官方Nginx镜像,可以在 搜索 页签中,选择 Docker官方镜像 ,然后在文本框中输入 nginx 进行搜索。
高级配置
服务(Service)
在 服务(Service) 右侧,单击 创建 设置服务配置项。
名称:nginx
类型:
-
负载均衡
-
公网访问
-
新建SLB
端口映射:
-
名称:nginx
-
服务端口:80
-
容器端口:80
-
协议:TCP
-
-
再次在 无状态 页面,单击 使用镜像创建 。在 创建 配置向导页面中, 创建用于测试访问名称为 busybox 的客户端应用,用于测试访问上一步中创建的名为 nginx 的Service。
本示例的 busybox 客户端应用仅需配置以下配置项,其他配置项选择默认配置。关于更多配置说明,请参见 使用镜像创建无状态Deployment应用 。 。
页面
配置项
说明
示例值
应用基本信息
应用名称
自定义名称。
busybox
副本数量
按需取值。
1
容器启动项
镜像名称
单击 选择镜像 ,选择所需的镜像并单击 确定 。
本例选择官方busybox镜像,可以在 搜索 页签中,选择 Docker官方镜像 ,然后在文本框中输busybox进行搜索。
容器启动项
无
选中 stdin 和 tty
-
验证busybox客户端应用是否可以访问nginx Service。
-
在 无状态 页面,找到并单击busybox名称。
-
在 容器组 页签下的busybox-{hash值}容器组右侧,单击 终端 。
-
在busybox的命令行终端中执行
wget nginx测试访问nginx。
当出现以上信息时,说明您可以在busybox中访问nginx Service。
-
通过命令行操作
-
执行以下命令,创建一个nginx的应用,并通过名称为nginx的Service与其通信。
创建nginx应用:
kubectl run nginx --image=nginx预期输出:
pod/nginx created查看Pod是否启动:
kubectl get pod预期输出:
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 45s创建名为nginx的Service:
kubectl expose pod nginx --port=80预期输出:
service/nginx exposed查看Service:
kubectl get service预期输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 172.XX.XX.1 <none> 443/TCP 30m nginx ClusterIP 172.XX.XX.48 <none> 80/TCP 12s -
执行以下命令,创建名称为busybox的Pod,访问名为nginx的Service。
kubectl run busybox --rm -ti --image=busybox /bin/sh预期输出:
If you don't see a command prompt, try pressing enter. / #获取nginx:
If you don't see a command prompt, try pressing enter. / # wget nginx # wget nginx需要输入到此处。预期输出:
Connecting to nginx (172.XX.XX.48:80) saving to 'index.html' index.html 100% |****************************************************************************************************************************************************| 612 0:00:00 ETA 'index.html' saved
步骤三:使用网络策略
以下几种场景均质池使用网络策略,您可以按需选择。
场景一:通过网络策略限制服务只能被带有特定标签的应用访问
通过控制台操作
-
登录 容器服务管理控制台 ,在左侧导航栏选择 集群 。
-
在 集群列表 页面,单击目标集群名称,然后在左侧导航栏,选择 。
-
在 网络策略 页面上方,选择放置网络策略的命名空间,本示例选择 default ,然后在页面右上方,单击 创建 ,在 创建面板 中配置网络策略。
配置项
说明
示例值
名称
自定义网络策略的名称。
access-nginx
Pod选择器
单击 + 选择工作负载添加标签 ,设置使用网络策略的Pod。
说明如果Pod选择器设置为空,则对命名空间下所有Pod生效。
本文示例设置如下:
-
设置类型为: 无状态
-
设置工作负载为: nginx
-
设置标签为: app=nginx
来源
每个网络策略可包含一个来源(ingress规则)的白名单列表。 每个规则都允许同时匹配来源规则和特定端口部分的流量。
-
规则 :
-
podSelector:此选择器将在与网络策略同命名空间中选择特定的 Pod,并将其允许作为入站流量来源。
-
namespaceSelector:此选择器将选择特定的命名空间,并将所有Pod 用作其入站流量来源。
-
ipBlock:此选择器将选择特定的IP CIDR范围以用作入站流量来源。
-
-
端口 :支持TCP和UDP协议。
说明-
如果不添加任何规则,表示不允许访问任何Pod与选择的Pod进行访问。
-
如果集群启用 IPvlan ,您无法通过ipBlock来限制Pod网段流量,您需要使用podSelector。
本示例不添加任何来源规则。
去向
每个网络策略可包含一个egress规则的白名单列表。每个规则都允许匹配去向规则和特定端口部分的流量。
-
规则 :
-
podSelector:此选择器将在与网络策略同命名空间中选择特定的Pod,并将其允许作为出站流量目的地。
-
namespaceSelector:此选择器将选择特定的命名空间,并将所有Pod用作其出站流量目的地。
-
ipBlock:此选择器将选择特定的IP CIDR范围以出站流量目的地。
-
-
端口 :支持TCP和UDP协议。
说明如果集群启用 IPvlan ,您无法通过ipBlock来限制Pod网段流量,您需要使用podSelector。
本示例不添加任何去向规则。
-
-
单击 下一步 ,然后单击 确定。
-
在busybox命令行终端执行
wget nginx命令,测试与nginx Service的通信。具体操作,请参见 步骤5 。因在网络策略没有允许busybox访问,所以访问会超时。
-
修改网络策略为允许busybox的应用访问。
-
在网络策略列表中,找到access-nginx网络策略并在其右侧,单击 编辑 。
-
添加来源规则。
在 来源 右侧,单击 +添加 ,并继续以下操作:
-
在 规则 右侧,单击 +添加 。添加podSelector的访问,规则设置如下:
配置项
示例值
选择器
podSelector
类型
无状态
工作负载
busybox
标签
app=busybox
-
在 端口 右侧,单击 +添加 。端口设置如下:
配置项
示例值
协议
TCP
端口
80
-
-
单击 下一步 ,然后单击 确定 。
-
执行
wget -O /dev/null nginx命令,测试修改网络策略后busybox与nginx的通信。网络策略增加busybox应用的规则后,busybox可以正常访问nginx。
-
通过命令行操作
-
使用以下YAML模板并执行命令
vim policy.yaml,创建名为 policy.yaml 文件。vim policy.yaml以下为YAML文件内容。
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: access-nginx spec: podSelector: matchLabels: run: nginx ingress: - from: - podSelector: matchLabels: access: "true" -
执行以下命令,根据上述的 policy.yaml 文件创建网络策略。
kubectl apply -f policy.yaml预期输出:
networkpolicy.networking.k8s.io/access-nginx created -
执行以下命令,当没有定义访问标签时,测试访问名为nginx的Service,请求会超时,无法访问。
kubectl run busybox --rm -ti --image=busybox /bin/sh测试访问名为nginx的Service :
wget nginx预期输出:
Connecting to nginx (172.19.XX.XX:80) wget: can't connect to remote host (172.19.XX.XX): Connection timed out -
执行以下命令,定义访问标签。
kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh测试访问nginx Service :
wget nginx预期输出:
Connecting to nginx (172.21.XX.XX:80) saving to 'index.html' index.html 100% |****************************************************************************************************************************************************| 612 0:00:00 ETA 'index.html' saved连接nginx的进度为100%时,说明请求成功,可以正常访问nginx服务。
场景二:通过网络策略限制可访问公网服务的来源IP网段
通过控制台操作
-
为nginx Service设置网络策略。相关配置,请参见 通过网络策略限制服务只能被带有特定标签的应用访问 。
-
在服务列表中的 外部端点 列下,查看 步骤二:创建可以被其他Pod正常访问的nginx测试应用 中nginx Service的公网访问地址(47.xxx.xx.x),并在浏览器中访问该地址。
由于已为nginx添加网络策略,默认访问nginx失败。
-
通过网络策略增加允许访问的网段来允许客户端访问。
-
通过浏览器访问 myip.ipip.net 获取本机的IP地址。
-
在网络策略列表中,找到access-nginx网络策略并在其右侧,单击 编辑 ,然后在 编辑 面板中修改规则。
在 来源 右侧,单击 +添加 ,并继续以下操作:
-
在 规则 右侧,单击 +添加 。规则中增加本机的IP地址的访问:
配置项
示例值
选择器
ipBlock
cidr
<本机的IP地址>/32
例如:42.xx.xx.xx/32
-
在 规则 右侧,单击 +添加 。规则中增加阿里云SLB的健康检查网段的访问:
配置项
示例值
选择器
ipBlock
cidr
100.0.0.0/8
-
在 端口 右侧,单击 +添加 。端口设置如下:
参数
示例值
协议
TCP
端口
80
-
-
单击 下一步 ,然后单击 确定 。
-
在服务列表中的外部端点列下,单击外部端点的IP,访问nginx外部端点(47.xxx.xx.x:80)。
增加网络策略后客户端可以通过公网SLB访问nginx。
-
通过命令行操作
-
执行以下命令,为上述名为nginx的应用创建阿里云SLB服务,指定
type=LoadBalancer来向外网用户暴露nginx服务。vim nginx-service.yamlnginx-service.yaml 文件模板如下。
# 将以下YAML内容粘贴至nginx-service.yaml中。 apiVersion: v1 kind: Service metadata: labels: run: nginx name: nginx-slb spec: externalTrafficPolicy: Local ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer执行以下命令,根据上述的 nginx-service.yaml 文件创建网络策略。
kubectl apply -f nginx-service.yaml预期输出:
service/nginx-slb created查看应用是否对外暴露nginx服务:
kubectl get service nginx-slb预期输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-slb LoadBalancer 172.19.xx.xxx 47.110.xxx.xxx 80:32240/TCP 8m -
执行以下命令,访问刚刚创建的SLB的IP地址 47.110.xxx.xxx ,访问失败。
wget 47.110.xxx.xxx预期输出:
--2018-11-21 11:46:05-- http://47.110.xx.xxx/ Connecting to 47.110.XX.XX:80... failed: Connection refused.说明访问失败的原因是:
-
配置的nginx Service只能被带有特定标签即
access=true的应用访问。 -
访问SLB的IP地址,是从外部访问Kubernetes,与通过网络策略限制服务只能被带有特定标签的应用访问不同。
解决方法:修改网络策略,增加允许访问的来源IP地址段。
-
-
执行以下命令,查看本地的IP地址。
curl myip.ipip.net预期输出:
当前IP:10.0.x.x来自于:中国 北京 北京 # 此处仅为示例,具体请以实际设备为准。 -
执行以下命令,修改已经创建的 policy.yaml 文件。
vim policy.yaml将 policy.yaml 文件 修改为如下内容:
# 以下为YAML文件内容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: access-nginx spec: podSelector: matchLabels: run: nginx ingress: - from: - podSelector: matchLabels: access: "true" - ipBlock: cidr: 100.64.0.0/10 - ipBlock: cidr: 10.0.0.1/24 # 本地IP地址,此处仅为示例,具体请以实际设备为准。执行以下命令,根据policy.yaml文件创建网络策略。
kubectl apply -f policy.yaml预期输出:
networkpolicy.networking.k8s.io/access-nginx unchanged说明-
有些网络的出口有多个IP地址,这里请使用/24的地址范围。
-
SLB健康检查地址在
100.64.0.0/10地址段内,因此请务必配置100.64.0.0/10。
-
-
执行以下命令,创建nginx服务。
kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh访问nginx服务:
wget 47.110.XX.XX预期输出:
Connecting to 47.110.XX.XX (47.110.XX.XX:80) index.html 100% |***********************************************************| 612 0:00:00 ETA连接进度显示100%时,说明成功访问nginx服务。
场景三:通过网络策略限制一个Pod只能访问指定地址
通过控制台操作
本文以 www.aliyun.com 和 registry.aliyuncs.com 为例,说明通过设置网络策略一个Pod只能访问 registry.aliyuncs.com 。
-
通过Ping命令查询 registry.aliyuncs.com 地址绑定的IP地址(120.55.XXX.XXX)。
-
在网络策略中创建规则限制busybox应用只能访问 registry.aliyuncs.com 。
-
在 网络策略 页面右上角,单击 创建 ,然后在 创建 面板中配置网络策略规则。
-
设置类型为:无状态
-
设置工作负载为:busybox
-
设置标签为:app=busybox
-
选择器:ipBlock
-
cidr:120.55.XXX.XXX/32
-
在 规则 右侧,单击 +添加 ,添加命名空间选择器为全部的规则。
-
在 端口 右侧,单击 +添加 。添加UDP 53的规则用来保障应用可以解析DNS。
-
规则:
-
选择器:namespaceSelector
-
命名空间:全部
-
-
端口:
-
协议:UDP
-
端口:53
-
-
单击 下一步 ,然后单击 确定 。
-
在busybox终端执行以下命令,分别访问 www.aliyun.com 和 registry.aliyuncs.com 。
nc -vz -w 1 www.aliyunc.com 443nc -vz -w 1 registry.aliyuncs.com 443增加网络策略后,busybox应用只能访问registry.aliyuncs.com而无法访问其他地址。
关于具体的参数描述,请参见 通过网络策略限制服务只能被带有特定标签的应用访问 。示例配置如下。
配置项
说明
示例值
名称
自定义网络策略的名称。
busybox-policy
Pod选择器
单击 + 选择工作负载添加标签 ,设置使用网络策略的Pod。
说明如果Pod选择器设置为空,则对命名空间下所有Pod生效。
本文示例设置如下:
去向
在 去向 右侧,单击 +添加 ,然后在 规则 右侧,单击 +添加 。
添加ipBlock为前面获取的 registry.aliyuncs.com 的解析的IP地址(120.55.XXX.XXX)/32的规则。
在 去向 右侧,单击 +添加 ,添加命名空间选择器为全部命名空间的UDP 53端口的访问的规则,用来保障应用可以解析DNS。
-
通过命令行操作
-
执行以下命令,获取 www.aliyun.com 域名解析到的IP地址列表。
dig +short www.aliyun.com预期输出:
www-jp-de-intl-adns.aliyun.com. www-jp-de-intl-adns.aliyun.com.gds.alibabadns.com. v6wagbridge.aliyun.com. v6wagbridge.aliyun.com.gds.alibabadns.com. 106.XX.XX.21 140.XX.XX.4 140.XX.XX.13 140.XX.XX.3 -
执行以下命令,创建 busybox-policy 文件。
vim busybox-policy.yamlbusybox-policy 文件 模板如下:
# 以下为YAML文件内容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: busybox-policy spec: podSelector: matchLabels: run: busybox egress: - to: - ipBlock: cidr: 106.XX.XX.21/32 - ipBlock: cidr: 140.XX.XX.4/32 - ipBlock: cidr: 140.XX.XX.13/32 - ipBlock: cidr: 140.XX.XX.3/32 - to: - ipBlock: cidr: 0.0.0.0/0 - namespaceSelector: {} ports: - protocol: UDP port: 53说明在 busybox-policy 文件中,配置了去向规则(Egress),限制应用的对外访问。在这里需配置允许UDP请求,否则无法做DNS解析。
-
执行以下命令,根据 busybox-policy 文件创建网络策略。
kubectl apply -f busybox-policy.yaml预期输出:
networkpolicy.networking.k8s.io/busybox-policy created -
执行以下命令,创建busybox。
kubectl run busybox --rm -ti --image=busybox /bin/sh访问 www.aliyun.com 之外的网站,例如, www.taobao.com :
wget www.taobao.com预期输出:
Connecting to www.taobao.com (64.13.XX.XX:80) wget: can't connect to remote host (64.13.XX.XX): Connection timed out出现 can't connect to remote host 时,说明失败访问服务。
-
执行以下命令,访问 www.aliyun.com 。
wget www.aliyun.com预期输出:
Connecting to www.aliyun.com (140.205.XX.XX:80) Connecting to www.aliyun.com (140.205.XX.XX:443) wget: note: TLS certificate validation not implemented index.html 100% |***********************************************************| 462k 0:00:00 ETA进行显示100%,说明成功访问服务。
场景四:通过网络策略控制命名空间下Pod公网访问权限
此操作有可能影响线上正在访问公网的服务,建议在一个空的命名空间中进行以下操作。
通过控制台操作
-
在 网络策略 页面右上角,单击 创建 ,然后在 创建 面板中配置网络策略规则。
关于具体的参数描述及操作,请参见 通过网络策略限制服务只能被带有特定标签的应用访问 。示例配置如下。
配置项
示例值
名称
deny-public-net
Pod选择器
设置类型为全部。
来源
添加以下两条规则:
-
设置namespaceSelector的全部允许的规则。
-
设置ipBlock的全部允许的规则。
去向
添加只允许访问内网的规则:
-
设置 namespaceSelector 的 全部 允许的规则,允许Pod访问内网的所有Pod。
-
设置 ipBlock 的三条内网网段的规则,包括以下三个内网网段:
-
10.0.0.0/8
-
172.16.0.0/12
-
192.168.0.0/16
说明不可同时在一条ipBlock规则中同时添加多个网段。
-
-
-
单击 下一步 ,然后单击 确定 。
-
在集群详情的基本信息页签,获取内网IP和端口。
-
在busybox终端执行以下命令,分别测试Pod的公网访问权限和内网访问权限。
nc -vz -w 1 www.aliyunc.com 443nc -vz -w 1 10.xx.xx.xx:<IP端口> # 此处的IP地址为您的内网地址。Pod只能访问内网的地址而无法访问公网的地址。
通过命令行操作
-
执行以下命令,创建一个测试的命名空间来验证限制的能力。
创建一个test-np的命名空间。
kubectl create ns test-np预期输出:
namespace/test-np created -
执行以下命令,为这个命名空间设置默认的只允许主动访问私网的网络策略规则。
vim default-deny.yaml以下为default-deny.yaml文件的示例模板:
# 以下为YAML文件内容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: namespace: test-np name: deny-public-net spec: podSelector: {} ingress: - from: - ipBlock: cidr: 0.0.0.0/0 egress: - to: - ipBlock: cidr: 192.168.0.0/16 - ipBlock: cidr: 172.16.0.0/12 - ipBlock: cidr: 10.0.0.0/8查看default-deny.yaml文件是否已创建成功。
kubectl apply -f default-deny.yaml预期输出:
networkpolicy.networking.k8s.io/deny-public-net created查看网络策略:
kubectl get networkpolicy -n test-np预期输出:
NAME POD-SELECTOR AGE deny-public-net <none> 1m -
执行以下命令,为特殊标签的Pod设置允许访问公网。
vim allow-specify-label.yaml示例标签设置为
public-network=true。# 以下为YAML文件内容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-public-network-for-labels namespace: test-np spec: podSelector: matchLabels: public-network: "true" ingress: - from: - ipBlock: cidr: 0.0.0.0/0 egress: - to: - ipBlock: cidr: 0.0.0.0/0 - namespaceSelector: matchLabels: ns: kube-system执行如下命令,创建网络策略:
kubectl apply -f allow-specify-label.yaml预期输出:
networkpolicy.networking.k8s.io/allow-public-network-for-labels created查看网络策略:
kubectl get networkpolicy -n test-np预期输出:
NAME POD-SELECTOR AGE allow-public-network-for-labels public-network=true 1m deny-public-net <none> 3m -
执行以下命令验证无特殊标签的Pod不能访问公网。
kubectl run -it --namespace test-np --rm --image busybox busybox-intranetping aliyun.com预期输出:
PING aliyun.com (106.11.2xx.xxx): 56 data bytes --- aliyun.com ping statistics --- 9 packets transmitted, 0 packets received, 100% packet loss显示 0 packets received 时,说明访问失败。
说明访问失败的原因是:由于通过 deny-public-net 的网络策略规则限制了 test-np 的这个命名空间下的Pod的默认的公网访问,所以它下面启动的默认标签的Pod无法访问公网。
-
执行以下命令验证带有 public-network=true 的Pod可以访问服务。
kubectl run -it --namespace test-np --labels public-network=true --rm --image busybox busybox-internetping aliyun.com预期输出:
PING aliyun.com (106.11.1xx.xx): 56 data bytes 64 bytes from 106.11.1xx.xx: seq=0 ttl=47 time=4.235 ms 64 bytes from 106.11.1xx.xx: seq=1 ttl=47 time=4.200 ms 64 bytes from 106.11.1xx.xx: seq=2 ttl=47 time=4.182 ms --- aliyun.com ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 4.182/4.205/4.235 ms显示 0% packet loss 时,说明成功访问服务。
说明可以正常访问的原因是:由于在 allow-public-network-for-labels 的网络策略的规则中允许了带有 public-network=true 的Pod的公网访问,所以在带有这个Label的 busybox-internet 的Pod可以访问公网。