一文搞懂Kubernetes网络策略(下)

2021-02-01 12:16:57 浏览数 (1)

今天zouyee为大家带来《一文搞懂Kubernetes网络策略(下)》,其中《kuberneter调度由浅入深:框架》预期周五出,敬请期待,当前涉及版本均为1.20. ,该篇承接一文搞懂Kubernetes网络策略(上)

注:如果关心各CNI插件的能力评比,可查看第四节。

三、应用场景

外网流量

代码语言:javascript复制
kubectl run web --image=nginx --labels=app=web --port 80
kubectl expose pod/web --type=LoadBalancer
kubectl get svc web
NAME   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
web    LoadBalancer   10.233.54.206   <pending>     80:32548/TCP   40s
直至EXTERNAL-IP分配IP为止

创建网络策略

代码语言:javascript复制
# cat web-allow-external.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-external
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - ports:
    - port: 80
    from: []
# kubectl apply -f web-allow-external.yaml

高级功能

a. 允许应用固定端口流量
代码语言:javascript复制
# kubectl run busybox -ti --image=busybox --labels=app=apiserver /bin/sh
If you don't see a command prompt, try pressing enter.
# nohup python3 -m http.server 8001 &
# nohup python3 -m http.server 5001 &
# exit
# kubectl create service clusterip apiserver 
    --tcp 8001:8000 
    --tcp 5001:5000

创建网络策略

代码语言:javascript复制
# cat api-allow-5000.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow-5000
spec:
  podSelector:
    matchLabels:
      app: apiserver
  ingress:
  - ports:
    - port: 5000
    from:
    - podSelector:
        matchLabels:
          role: monitoring
# kubectl apply -f api-allow-5000.yml

访问测试

代码语言:javascript复制
# 启动pod未携带指定label时,访问受限
# kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://apiserver:8001
wget: download timed out

/ # wget -qO- --timeout=2 http://apiserver:5001/metrics
wget: download timed out

# 启动pod携带指定label时,访问不受限
$ kubectl run busybox --rm -ti --image=busybox --labels=role=monitoring /bin/sh
/ # wget -qO- --timeout=2 http://apiserver:8001
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...

/ # wget -qO- --timeout=2 http://apiserver:5001/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...
b. 多标签限制

说明:Network Policy定义一组微服务访问某一应用,如下述示例中,一组微服务共享redis服务

代码语言:javascript复制
kubectl run db --image=redis:4 --port 6379 --expose 
    --labels app=bookstore,role=db

以下服务共享redis服务

代码语言:javascript复制
app=bookstore role=search

创建网络策略

代码语言:javascript复制
# cat redis-allow-services.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: redis-allow-services
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: db
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: bookstore
          role: search
    - podSelector:
        matchLabels:
          app: bookstore
          role: api
    - podSelector:
        matchLabels:
          app: inventory
          role: web
# kubectl apply -f redis-allow-services.yaml

访问测试

代码语言:javascript复制
$ kubectl run busybox --rm -ti --image=curl --labels=app=inventory,role=web /bin/sh
/ # nc -v -w 2 db 6379
db (10.233.27.143:6379) open

(works)

$ kubectl run busybox --rm -ti --image=curl --labels=app=other /bin/sh

/ # nc -v -w 2 db 6379
nc: db (10.233.27.143:6379): Operation timed out

(访问受限)

控制出口流量

a. 禁止应用的出口流量
代码语言:javascript复制
kubectl run web --image=nginx --labels app=web --expose --port 80

创建网络策略

代码语言:javascript复制
# cat foo-deny-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: foo-deny-egress
spec:
  podSelector:
    matchLabels:
      app: foo
  policyTypes:
  - Egress
  egress: []
# kubectl apply -f foo-deny-egress.yaml

说明:

代码语言:javascript复制
    policyTypes: ["egress"] 该策略类型为出口流量
代码语言:javascript复制
    egress: [] 策略为空说明出口流量全部禁止
b. 禁止命名空间非白名单流量

创建网络策略

代码语言:javascript复制
# cat default-deny-all-egress.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all-egress
  namespace: default
spec:
  policyTypes:
  - Egress
  podSelector: {}
  egress: []
# kubectl apply -f default-deny-all-egress.yaml
说明:
  • podSelector为空,说明匹配所有pod
  • egress为空数组,说明禁止所有符合podSelector的出口流量

四、开发

实现一个支持 Network Policy 的网络扩展需要至少包含两个组件

  • CNI 网络插件:负责给 Pod 配置网络接口
  • Policy controller:监听 Network Policy 的变化,并将 Policy 应用到相应的网络接口

性能测试

下图基于Kubernetes 1.19版本测试了以下特性(后续接一篇译文):

1)MTU auto config

2)带宽性能: Pod to Pod、Pod to Service(TCP、UDP)

3)资源消耗: Pod to Pod、Pod to Service(TCP、UDP)

4)安全特性:Network Policies、 Encryption等

calico其他详细的能力说明,可参看官网。

五、展望

a. SCTP特性

支持版本:Kubernetes v1.19 [beta]

作为一个 Beta 特性,SCTP 默认是被启用的。要在集群层面禁用 SCTP,需要为 kube-apiserver关闭特性--feature-gates=SCTPSupport=false,... 以禁用 SCTP 。启用该特性后,用户可以将 NetworkPolicy 的 protocol字段设置为 SCTP。

⚠️ CNI插件需要支持SCTP协议

b. 待开发

截止Kubernetes v1.20 ,NetworkPolicy API 还不支持下述功能。

  • 强制集群内部流量经过某公用网关(可通过服务网格或其他代理来实现)
  • 与 TLS 相关的场景(可使用服务网格或者 Ingress 控制器)
  • 实现适用于所有名字空间或 Pods 的默认策略(如calico)
  • 高级的策略查询或者策略验证相关工具(如calico)
  • 在同一策略声明中选择目标端口范围的能力
  • 生成网络安全事件日志的能力(例如,被阻塞或接收的连接请求)
  • 禁止本地回路或指向宿主的网络流量(Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。

上述需求可以通过操作系统组件(如 SELinux、OpenVSwitch、IPTables 等) 或者七层技术(Ingress 控制器、服务网格实现)及准入控制器进行功能增强,当然有兴趣的可以参考calico及OPA项目。

参考资料

1. Kubernetes 官网:https://kubernetes.io/docs/concepts/services-networking/network-policies/

2. Declare Network Policy: https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/

3. Securing Kubernetes Cluster Networking: https://ahmet.im/blog/kubernetes-network-policy/

4. fesikyer network policy: https://github.com/feiskyer/kubernetes-handbook/blob/master/concepts/network-policy.md

END

往期 · 精选

1、干货分享 | 一文搞懂Kubernetes网络策略(上)

2、干货分享 | CloudEvents三部曲:实践篇

3、干货分享 | K8S调度系统由浅入深:简介

0 人点赞