阿里云容器计算服务ACS基于Kubernetes网络策略(Network Policy)提供策略级别的网络控制。如果您希望在IP地址或者端口层面控制网络流量,您可以为集群中特定应用使用网络策略。本文介绍如何使用ACS集群的网络策略及常用的使用场景。
适用范围
仅支持计算类型为通用型和性能型的CPU Pod。
仅支持用于IPv4,不支持IPv6。
注意事项
NetworkPolicy规则允许通过LabelSelector选择Namespace或者Pod。但当Pod中的NetworkPolicy数量增大时,不仅会使规则生效时间延长,而且大量的NetworkPolicy规则也会对您的集群管理、问题排查带来困扰,因此建议您集群内的NetworkPolicy数量小于40个。
步骤一:开启网络策略
安装组件Poseidon。
登录容器计算服务控制台,在左侧导航栏选择集群列表。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理。
在组件管理页面,单击网络页签,在Poseidon组件所在卡片的右下方,单击安装。
在安装组件 Poseidon页面,选中启用 NetworkPolicy,然后单击确认。

组件安装成功后,会在卡片右上角出现已安装字样。
在Pod annotation配置启用NetworkPolicy。
对需要使用NetworkPolicy的容器,必须配置下面annotation中的注解
network.alibabacloud.com/enable-network-policy-agent: "true",示例如下:apiVersion: v1 kind: Pod metadata: annotations: network.alibabacloud.com/enable-network-policy-agent: "true" name: example namespace: default spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: example
步骤二:创建可以被其他Pod正常访问的Nginx测试应用
kubectl
创建一个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=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /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
步骤三:使用网络策略
以下几种场景均支持使用网络策略,您可以按需选择。
场景一:通过网络策略限制服务只能被带有特定标签的应用访问
kubectl
使用以下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=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /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=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /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网段
kubectl
为上述名为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=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /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只能访问指定地址
kubectl
获取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=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /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公网访问权限
此操作有可能影响线上正在访问公网的服务,建议在一个空的命名空间中进行以下操作。
kubectl
创建一个测试的命名空间来验证限制的能力。
创建一个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=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 busybox-intranetping aliyun.com预期输出:
PING aliyun.com (106.11.2xx.xxx): 56 data bytes ^C --- 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 registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 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 ^C --- 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可以访问公网。