k8s网络策略

环境说明

操作系统版本 内核版本 Docker版本 Kubernetes版本
7.6.1810 4.19.12 19.03.13 v1.18.18

操作系统版本

$ cat /etc/redhat-release 
CentOS Linux release 7.6.1810 (Core) 

内核版本

$ uname -r
4.19.12-1.el7.elrepo.x86_64

Docker版本

$ docker --version
Docker version 19.03.13, build 4484c46

Kubernetes版本

$ kubectl get node
NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    <none>   7d22h   v1.18.18
k8s-node01   Ready    <none>   7d22h   v1.18.18
k8s-node02   Ready    <none>   7d22h   v1.18.18
k8s-node03   Ready    <none>   7d22h   v1.18.18

此实验参考 kubernetes官网calico官网

web命名空间跑业务容器,client命名空间跑测试业务容器,以下是容器的运行情况

$ kubectl get pod -n web -owide 
NAME                    READY   STATUS    RESTARTS   AGE    IP             NODE         NOMINATED NODE   READINESS GATES
http-647dffb4db-vwxmf   1/1     Running   0          17s    20.0.58.213    k8s-node02   <none>           <none>
nginx-5cd55947c-jfgpd   1/1     Running   1          6h8m   20.0.235.233   k8s-master   <none>           <none>

$ kubectl get pod -n client -owide    
NAME                       READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
busybox-5778d9f5ff-dsfxd   1/1     Running   1          5h50m   20.0.135.156   k8s-node03   <none>           <none>
centos-6774cc9984-84wlh    1/1     Running   0          6m45s   20.0.85.222    k8s-node01   <none>           <none>

限制任何pod进入web命名空间的任何pod,下面的实验都基于这个限制。

$ cat > web-np-deny.yaml <<-EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-deny
  namespace: web
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Ingress
EOF

$ kubectl apply -f web-np-deny.yaml
networkpolicy.networking.k8s.io/web-deny created

网络策略分类

ipBlock

# 不同IP段,设置前验证
$ kubectl exec -it busybox-5778d9f5ff-dsfxd -n client -- wget -q --timeout=3 http.web.svc.cluster.local -O -
wget: download timed out
command terminated with exit code 1

$ kubectl exec -it centos-6774cc9984-84wlh -n client -- wget -q --timeout=3 http.web.svc.cluster.local -O -
wget: download timed out
command terminated with exit code 1

$ cat > web-np-ipblock.yaml<<-EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-ipblock
  namespace: web
spec:
  podSelector:
    matchLabels:
      app: httpd
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 20.0.0.0/16
        except:
        - 20.0.135.0/24
    ports:
    - port: 80
      protocol: TCP
EOF

$ kubectl apply -f web-np-ipblock.yaml 
networkpolicy.networking.k8s.io/web-ipblock created

# 设置后验证
$ kubectl exec -it centos-6774cc9984-84wlh -n client -- wget -q --timeout=3 http.web.svc.cluster.local -O -
<html><body><h1>It works!</h1></body></html>

$ kubectl exec -it busybox-5778d9f5ff-dsfxd -n client -- wget -q --timeout=3 http.web.svc.cluster.local -O -
wget: download timed out
command terminated with exit code 1

注意: ingress下的字段。如果是 与 的关系,那么不需要用 - 。如果是 或 的关系,请使用 -
上面的示例是 20.0.0.0/16 网段,除了 20.0.135.0/24 之外,在这个范围的所有IP地址都可以访问 web 命名空间下带有 app=httpd 标签pod的 80 端口。

namespaceSelector

# 不同命名空间,设置前测试
$  kubectl -n web exec -it busybox-5778d9f5ff-dsfxd -- curl --connect-time 3 http.web.svc.cluster.local
curl: (28) Connection timed out after 3001 milliseconds
command terminated with exit code 28

$ cat > web-np-web-allow.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-allow
  namespace: web
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          role: client
EOF

$ kubectl apply -f web-np-web-allow.yaml
networkpolicy.networking.k8s.io/web-allow created

# 设置后测试
$ kubectl -n web exec -it busybox-5778d9f5ff-dsfxd -- curl --connect-time 3 http.web.svc.cluster.local
<html><body><h1>It works!</h1></body></html>

上面的示例是允许命名空间 client 下的所有pod可以访问命名空间 web 下的所有pod。

podSelector

# 相同命名空间不同pod,设置前验证
$  kubectl -n web exec -it nginx-5cd55947c-jfgpd -- curl --connect-timeout 3 http.web.svc.cluster.local
curl: (28) Connection timed out after 3000 milliseconds
command terminated with exit code 28

$ cat > web-np-web-allow.yaml<<-EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-allow
  namespace: web
spec:
  podSelector:
    matchLabels:
      app: httpd
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: nginx
EOF

$ kubectl apply -f web-np-web-allow.yaml
networkpolicy.networking.k8s.io/web-allow created

# 设置后验证
$ kubectl -n web exec -it nginx-5cd55947c-jfgpd -- curl --connect-timeout 3 http.web.svc.cluster.local
<html><body><h1>It works!</h1></body></html>

允许命名空间 web 下,带有 app=nginx 的pod,允许访问 web 命名空间下,带有 app=httpd 的pod。

namespaceSelector 和 podSelector

# 不同命名空间下特定pod访问,设置前访问
$ kubectl -n client exec -it busybox-5778d9f5ff-dsfxd -- wget -q --timeout=3 http.web.svc.cluster.local -O -
wget: download timed out
command terminated with exit code 1

$ kubectl -n client exec -it centos-6774cc9984-84wlh -- wget -q --timeout=3 nginx.web.svc.cluster.local -O -
wget: download timed out
command terminated with exit code 1

$ cat > web-np-clientPod-allow.yaml <<-EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: clientpod-allow
  namespace: web
spec:
  podSelector:
    matchLabels:
      app: httpd
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: client
      namespaceSelector:
        matchLabels:
          role: client
    ports:
    - port: 80
      protocol: TCP
EOF

$ kubectl apply -f web-np-clientPod-allow.yaml 
networkpolicy.networking.k8s.io/clientpod-allow created

# 设置后访问
$ kubectl -n client exec -it busybox-5778d9f5ff-dsfxd -- wget -q --timeout=3 http.web.svc.cluster.local -O -
<html><body><h1>It works!</h1></body></html>

$ kubectl -n client exec -it centos-6774cc9984-84wlh -- wget -q --timeout=3 nginx.web.svc.cluster.local -O -
wget: download timed out
command terminated with exit code 1

上面的示例是允许命名空间带有 role=client 的标签 且 pod带有 app=client 的标签去访问 httpd 80 端口的服务。

扩展知识

其实上面的网络策略是由 calico 网络插件来实现的,如果上面的网络策略限制的不精准的话,可以直接查看calico生成的网络策略。

$ calicoctl get networkpolicy -n web
NAMESPACE   NAME                          
web         knp.default.clientpod-allow   
web         knp.default.web-deny

$ calicoctl get networkpolicy -n web knp.default.clientpod-allow -oyaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  creationTimestamp: "2021-08-23T01:54:45Z"
  name: knp.default.clientpod-allow
  namespace: web
  resourceVersion: "1743939"
  uid: 989ac5e1-239b-4428-a3d7-82612e642ad9
spec:
  ingress:
  - action: Allow
    destination:
      ports:
      - 80
    protocol: TCP
    source:
      namespaceSelector: role == 'client'
      selector: projectcalico.org/orchestrator == 'k8s' && app == 'client'
  order: 1000
  selector: projectcalico.org/orchestrator == 'k8s' && app == 'httpd'
  types:
  - Ingress

calico 网络策略出现两个 action 参数。那说明有两个规则生效,导致权限控制不精准。

原文地址:https://www.cnblogs.com/mycloudedu/p/15167057.html