注:本文基于K8S v1.21.2版本编写

1 关于网络策略

k8s的网络能力主要表现在两个方面,一个是连通性,保证pod之间能够互通,另一个就是隔离性,考虑安全、流量限制等业务需求。

而默认情况下,k8s集群的网络没任何限制,集群中的所有pod都是互通的,这对于一些业务来说是不符合安全需求的。同时如果考虑多租户的场景,这就更不能接受了,因此需要有方法能对集群网络进行限制,这就有了Network Policy。

但有一点,并不是所有网络插件都支持Network Policy,比如flannel就不支持网络策略,calico是支持的,因此我们将基于calico来测试和说明网络策略的使用。

2 K8S网络策略

虽然是基于calico网络插件,但我们现在要使用的是k8s网络策略,当然也有calico网络策略,这两者是不同的。k8s网络策略提供的是一套基础和标准的规范,而calico则是基于k8s做了一些扩展,功能也更强大。

从易到难,我们先了解下基础的k8s网络策略。

2.1 deny所有pod的流量互通

因为默认情况下所有pod都是互通的,而在K8S网络策略中,我们无法显式设置deny动作,因此为了能验证我们的策略是生效的,就需要先要创建一个默认deny所有流量的策略。

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny
  namespace: default
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Ingress
  - Egress

我们以default这个namespace为例,选择该namespace下所有pod,并将流入和流出策略置空,也就实现了deny-all的目的。

2.2 开启与某个pod的互通

首先在集群中创建两个测试pod,

[root@master network-policy]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
centos-6dc54              1/1     Running   1          24d     10.244.166.179   node1   <none>           <none>
centos-tsh95              1/1     Running   1          24d     10.244.104.29    node2   <none>           <none>

由于上一个步骤应用了deny-all的策略,因此两个pod是无法通信的,

[root@master home]# kubectl exec -ti centos-tsh95 -- /bin/bash
[root@centos-tsh95 /]# ping 10.244.166.179
PING 10.244.166.179 (10.244.166.179) 56(84) bytes of data.
^C
--- 10.244.166.179 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5003ms

然后我们针对这个pod开放access。

为了能够识别这两个pod,我们需要给它打上标签,设置color=green和color=yellow

[root@master network-policy]# kubectl label pod centos-6dc54 color=green
pod/centos-6dc54 labeled
[root@master network-policy]# kubectl label pod centos-tsh95 color=yellow
pod/centos-tsh95 labeled
[root@master network-policy]# kubectl get pod --show-labels
NAME                      READY   STATUS    RESTARTS   AGE     LABELS
centos-6dc54              1/1     Running   1          24d     app=centos,color=green,controller-revision-hash=69f7b95f44,pod-template-generation=1
centos-tsh95              1/1     Running   1          24d     app=centos,color=yellow,controller-revision-hash=69f7b95f44,pod-template-generation=1

然后我们就能通过这个label,在网络策略中匹配对应的pod,并允许它们之间的通信,

[root@master network-policy]# cat allow-same-namespace-green.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-same-namespace-green
  namespace: default
spec:
  podSelector:
    matchLabels:
      color: green
  egress:
  - to:
    - podSelector:
        matchLabels:
          color: yellow
  ingress:
  - from:
    - podSelector:
        matchLabels:
          color: yellow
root@master network-policy]# cat allow-same-namespace-yellow.yml 
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-same-namespace-yellow
  namespace: default
spec:
  podSelector:
    matchLabels:
      color: yellow
  egress:
  - to:
    - podSelector:
        matchLabels:
          color: green
  ingress:
  - from:
    - podSelector:
        matchLabels:
          color: green

需要注意的是,因为这两个pod都在default namespace中,因此要分别为这两个pod配置网络策略。同时因为我们有设置默认deny的策略,因此egress也需要配置,不然出去的包就会被默认策略丢弃。

策略应用后,这两个pod之间的通信就OK了。

[root@master network-policy]# kubectl get networkpolicy
NAME                          POD-SELECTOR   AGE
allow-same-namespace-green    color=green    6m52s
allow-same-namespace-yellow   color=yellow   5m39s
default-deny                  <none>         7m7s
[root@centos-tsh95 /]# ping 10.244.166.187
PING 10.244.166.187 (10.244.166.187) 56(84) bytes of data.
64 bytes from 10.244.166.187: icmp_seq=1 ttl=62 time=1.38 ms
^C
--- 10.244.166.187 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.382/1.382/1.382/0.000 ms

2.3 限制端口和协议

除了针对整个pod开放流量,还可以针对具体的port和protocol,

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-same-namespace-green
  namespace: default
spec:
  podSelector:
    matchLabels:
      color: green

  ingress:
  - from:
    - podSelector:
        matchLabels:
          color: yellow
    ports:
    - protocol: UDP
      port: 9999

  egress:
  - to:
    - podSelector:
        matchLabels:
          color: yellow

以上策略表示其他pod只能通过9999号端口,以UDP方式连接到该pod。


参考文档

  1. https://kubernetes.io/docs/reference/kubernetes-api/policy-resources/network-policy-v1/
  2. https://docs.projectcalico.org/security/kubernetes-network-policy
  3. https://docs.projectcalico.org/security/tutorials/kubernetes-policy-demo/kubernetes-demo
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐