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

从CNCF基金会的成立,到Kubernetes社区蓬勃发展,历经6载,17年异军突起,在mesos、swarm等项目角逐中,拔得头筹,继而一统容器编排,其成功的关键原因可概括为以下几点:

  • 项目领导者们的坚守与远见
  • 社区的良好的运作与社区文化
  • 社区与企业落地的正反馈

今天zouyee为大家带来《一文搞懂Kubernetes网络策略(上)》,其中《kuberneter调度由浅入深:框架》正在编写中,敬请期待,当前涉及版本均为1.20.+


一、Network Policy简介

​ 随着微服务架构的日渐盛行,Serverless框架的逐步落地,应用上云后带来了模块间网络调用需求的大规模增长,Kubernetes 自 1.3 引入了 Network Policy,其提供以应用为中心, 基于策略的网络控制,用于隔离应用以减少攻击面。

​ Pod之间能否通信可通过如下三种组合进行确认:

  1. 其他被允许的 Pods(例如:Pod 无法限制对自身的访问)
  2. 被允许访问的namespace
  3. IP CIDR(例如:与 Pod 运行所在节点的通信总是被允许的)

在定义基于 Pod 或namespace的 NetworkPolicy 时,可以使用标签选择器来设定哪些流量可以进入或离开 Pod。同时,当创建基于 IP 的 NetworkPolicy 时,可以基于 IP CIDR 来定义策略。

以下结构体示意图辅助理解,后面章节有具体说明:

一文搞懂Kubernetes网络策略(上)_第1张图片

版本变迁
Kubernetes 版本 Networking API 版本 说明
v1.5-v1.6 extensions/v1beta1 需要在kube-apiserver开启 extensions/v1beta1/networkpolicies
v1.7 networking.k8s.io/v1
v1.8 networking.k8s.io/v1 新增 EgressIPBlock 的支持

二、简要介绍

默认情况下,Pod 是非隔离的,它们接受任何流量。

Pod 在被某 NetworkPolicy 选中时进入隔离状态。 一旦名字空间中有 NetworkPolicy 选择了特定的 Pod,该 Pod 会拒绝该 NetworkPolicy 所不允许的连接。 (名字空间下其他未被 NetworkPolicy 所选择的 Pod 会继续接受所有的流量)

网络策略不会冲突。 如果任何一个或多个策略选择了一个 Pod, 则该 Pod 受限于这些策略的 入站(Ingress)/出站(Egress)规则的并集。

⚠️在使用 Network Policy 时,网络插件需要支持 Network Policy,如 Calico、Romana、Weave Net 和 Trireme 等,其中Engress为 出口流量,Ingress为 入口流量。

2.1 结构体说明

staging/src/k8s.io/api/networking/v1/types.go

下面是 NetworkPolicy 的一个示例,如需完整说明,可参看结构定义文档:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: network-policy-sample
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

必需字段:与所有其他的 Kubernetes 对象一样,NetworkPolicy 需要 apiVersionkindmetadata 字段。

spec:NetworkPolicy 规约中包含了在名字空间中定义特定网络策略所需的所有信息。

podSelector:每个 NetworkPolicy 都包括一个 podSelector,它选择适用该该策略的 Pod。示例中的策略选择带有 “role=db” 标签的 Pod。 若podSelector为空的,则选择名字空间下所有 Pod。

policyTypes: 每个 NetworkPolicy 都包含一个 policyTypes 列表,其中包含 IngressEgress 或(两者亦可)。policyTypes 字段表示给定的策略是应用于 所选 Pod 的入口流量还是来出口流量(两者亦可)。 如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress; 如果 NetworkPolicy 有任何出口规则的话则设置 Egress

ingress: 每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。 每个规则都允许同时匹配 fromports 部分的流量。示例策略中包含一条 简单的规则: 它匹配某个特定端口,第一个通过 ipBlock 指定,第二个通过 namespaceSelector 指定,第三个通过 podSelector 指定。

egress: 每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。 每个规则都允许匹配 toport 部分的流量。该示例策略包含一条规则, 该规则指定端口上的流量匹配到 10.0.0.0/24 中的任何目的地。

该网络策略总结如下:

  1. 隔离 default名字空间下 role=db 的 Pod 。
  2. 出口限制:允许符合以下条件的 Pod 连接到 default名字空间下标签为 role=db的所有 Pod 的 6379 TCP 端口:
    • default名字空间下带有 role=frontend 标签的所有 Pod
    • 带有 project=myproject 标签的所有名字空间中的 Pod
    • IP 地址范围为172.17.0.0–172.17.0.255172.17.2.0–172.17.255.255(即除了 172.17.1.0/24 之外的所有 172.17.0.0/16)
  3. 入口限制:允许从带有 role=db标签的名字空间下的任何 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口。
2.2 简单示例

以 calico 为例看一下 Network Policy 的具体用法。

  1. 配置 kubelet 使用 CNI 网络插件(默认已经配置,无需更改)

kubelet --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin ...

  1. 安装 calio 网络插件
# 注意修改 CIDR,需要跟 k8s pod-network-cidr 一致,默认为 192.168.0.0/16
# 当前选择的是小于50节点的安装方式,具体安装可查看
# https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
  1. 部署应用

部署 nginx 服务

$ kubectl create deployment nginx --image=nginx
deployment "nginx" created
$ kubectl expose deployment nginx --port=80
service "nginx" exposed

测试网络

$ kubectl get svc,pod
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.233.0.1              443/TCP   186d
service/nginx        ClusterIP   10.233.27.142           80/TCP    2s

NAME                            READY   STATUS              RESTARTS   AGE
pod/nginx-f89759699-kfmbj       1/1     Running   					0          62s

$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.

/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
remote file exists
/ #

4)测试网络策略

如果只让那些拥有标签 access: true 的 Pod 访问 nginx 服务, 那么可以创建一个如下所示的 NetworkPolicy 对象:

$ cat nginx-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-nginx
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
  - from:
    - podSelector:
        matchLabels:
          access: "true"

$ kubectl create -f nginx-policy.yaml
networkpolicy "access-nginx" created

# 不带 access=true 标签的 Pod 还是无法访问 nginx 服务
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.

/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
wget: download timed out
/ #


# 而带有 access=true 标签的 Pod 可以访问 nginx 服务
$ kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.

/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
/ #
参考文档
  • Kubernetes network policies
  • Declare Network Policy
  • Securing Kubernetes Cluster Networking
  • Kubernetes Network Policy Recipes
  • fesikyer network policy

后续相关内容,请查看公众号:DCOS
一文搞懂Kubernetes网络策略(上)_第2张图片

你可能感兴趣的:(Kubernetes,Linux,kubernetes)