• 网络策略NetworkPolicy


    网络策略

    在 Kubernetes 里,网络隔离能力的定义,是依靠一种专门的 API 对象来描述的,即: NetworkPolicy。

    Kubernetes 里的 Pod 默认都是“允许所有”(Accept All)的,即:Pod 可以接收来自任何发送方的请求;或者,向任何接收方发送请求。而如果要对这个情况作出限制,就必须通过 NetworkPolicy 对象来指定。

    一个完整的NetworkPolicy对象示例如下所示:

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: test-network-policy
      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: 80
      egress:
      - to:
        - ipBlock:
            cidr: 10.0.0.0/24
        ports:
        - protocol: TCP
          port: 5978
    

    与所有其他的 Kubernetes 资源对象一样,NetworkPolicy 需要 apiVersionkindmetadata 字段,我们通过 spec.podSelector 字段定义这个 NetworkPolicy 的限制范围,因为 NetworkPolicy 目前只支持定义 ingress 规则,所以这里的 podSelector 本质上是为该策略定义 “目标pod”, 比如我们这里 matchLabels:role=db 表示的就是当前 Namespace 里携带了 role=db 标签的 Pod。而如果把 podSelector 字段留空:

    spec: 
      podSelector: {}
    

    那么这个 NetworkPolicy 就会作用于当前 Namespace 下的所有 Pod。

    每个 NetworkPolicy 包含一个 policyTypes 列表,可以是 IngressEgress 或者两者都包含,该字段表示给当前策略是否应用于所匹配的 Pod 的入口流量、出口流量或者二者都包含,如果没有指定 policyTypes,则默认情况下表示 Ingress 入口流量,如果配置了任何出口流量规则,则将指定为 Egress

    一旦 Pod 被 NetworkPolicy 选中,那么这个 Pod 就会进入“拒绝所有”(Deny All)的状态,即:这个 Pod 既不允许被外界访问,也不允许对外界发起访问。

    比如上面示例表示的是该隔离规则只对 default 命名空间下的,携带了 role=db 标签的 Pod 有效。限制的请求类型包括 ingress(流入)和 egress(流出)。

    ingress: 每个 NetworkPolicy 包含一个 ingress 规则的白名单列表。其中的规则允许同时匹配 fromports 部分的流量。比如上面示例中我们配置的入口流量规则如下所示:

    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: 80
    

    这里的 ingress 规则中我们定义了 fromports,表示允许流入的白名单和端口,Kubernetes 会拒绝任何访问被隔离 Pod 的请求,除非这个请求来自于以下“白名单”里的对象,并且访问的是被隔离 Pod 的端口。而这个允许流入的白名单中指定了三种并列的情况,分别是:ipBlocknamespaceSelectorpodSelector

    • default 命名空间下面带有 role=frontend 标签的 Pod
    • 带有 project=myproject 标签的 Namespace 下的任何 Pod
    • 任何源地址属于 172.17.0.0/16 网段,且不属于 172.17.1.0/24 网段的请求。

    egress: 每个 NetworkPolicy 包含一个 egress 规则的白名单列表。每个规则都允许匹配 toport 部分的流量。比如我们这里示例规则的配置:

    egress:
      - to:
        - ipBlock:
            cidr: 10.0.0.0/24
        ports:
        - protocol: TCP
          port: 5978
    

    表示 Kubernetes 会拒绝被隔离 Pod 对外发起任何请求,除非请求的目的地址属于 10.0.0.0/24 网段,并且访问的是该网段地址的 5978 端口。

    安装Calico

    要让网络策略生效,就需要特定的网络插件支持,目前已经实现了 NetworkPolicy 的网络插件包括 Calico、Weave 和 kube-router 等项目,但是并不包括 Flannel 项目。

    所以说,如果想要在使用 Flannel 的同时还使用 NetworkPolicy 的话,就需要再额外安装一个网络插件,比如 Calico 项目,来负责执行 NetworkPolicy。由于我们这里使用的是 Flannel 网络插件,所以首先需要安装 Calico 来负责网络策略。

    详细可以参考官方文档:https://projectcalico.docs.tigera.io/getting-started/kubernetes/flannel/flannel

    首先确定 kube-controller-manager 配置了如下的两个参数:

    ......
    spec:
      containers:
      - command:
        - kube-controller-manager
        - --allocate-node-cidrs=true
        - --cluster-cidr=10.244.0.0/16
    ......
    

    下载需要使用的资源清单文件:

    $ curl https://docs.projectcalico.org/manifests/canal.yaml -O
    

    如果之前配置的 pod CIDR 就是 10.244.0.0/16 网段,则可以跳过下面的配置,如果不同则可以使用如下方式进行替换:

    $ POD_CIDR="<your-pod-cidr>" \
    $ sed -i -e "s?10.244.0.0/16?$POD_CIDR?g" canal.yaml
    

    最后直接安装:

    $ kubectl apply -f canal.yaml
    

    测试

    首先我们准备两个待测试的Pod:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-np
    spec:
      containers:
        - name: test-np
          image: nginx:1.17.1
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: busybox
    spec:
      containers:
        - name: busybox
          image: busybox:1.30
          command: ["/bin/sh","-c","sleep 86400"]
    

    直接创建这两个pod:

    $ kubectl apply -f test-np.yaml 
    pod/test-np unchanged
    pod/busybox configured
    
    $ kubectl get pods -o wide
    NAME      READY   STATUS    RESTARTS   AGE     IP           NODE    NOMINATED  ...
    busybox   1/1     Running   0          3m38s   10.244.2.3   node1   <none>     ...      
    test-np   1/1     Running   0          3m38s   10.244.1.6   node2   <none>     ...      
    

    我们使用busybox来访问test-np,在没有加任何网路策略的情况下,测试是否能正常请求:

    $ kubectl exec -it busybox ping 10.244.1.6
    kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
    PING 10.244.1.6 (10.244.1.6): 56 data bytes
    64 bytes from 10.244.1.6: seq=0 ttl=62 time=0.642 ms
    64 bytes from 10.244.1.6: seq=1 ttl=62 time=0.536 ms
    64 bytes from 10.244.1.6: seq=2 ttl=62 time=0.981 ms
    ......
    

    这时候我们添加上面的网络策略,同时给test-np打上role=db的标签:

    $ kubectl label pod test-np role=db  --overwrite
    pod/test-np labeled
    
    $ kubectl get networkpolicy
    kubectl get networkpolicy
    NAME                  POD-SELECTOR   AGE
    test-network-policy   role=db        10s
    

    这时候test-np这个Pod就匹配了网络策略,由于匹配了网络策略的就会拒绝所有的网络请求,需要通过白名单来进行开启请求,但是busybox这个Pod 明显没有在白名单之中,所以应该会拒绝网络请求:

    kubectl exec -it busybox ping 10.244.1.6
    kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
    PING 10.244.1.6 (10.244.1.6): 56 data bytes
    ^C
    --- 10.244.1.6 ping statistics ---
    8 packets transmitted, 0 packets received, 100% packet loss
    command terminated with exit code 1
    

    那么现在我想让busybox能正常请求test-np这个pod,我们来看test-np绑定的网路策略中的白名单,第一条我们明显不符合要求,第二条将busybox转移标签 project=myproject 的 Namespace 下面,这个实现也不是特别容器,接着我们来看第三条,带有role=frontend这个标签的Pod就可以访问,那么我们就可以直接给我busybox打上这个标签:

    $ kubectl label pod busybox role=frontend --overwrite
    pod/busybox labeled
    

    接着我们继续请求test-np,这次应该可以成功:

    kubectl exec -it busybox ping 10.244.1.6
    kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
    PING 10.244.1.6 (10.244.1.6): 56 data bytes
    64 bytes from 10.244.1.6: seq=0 ttl=62 time=0.519 ms
    64 bytes from 10.244.1.6: seq=1 ttl=62 time=0.761 ms
    64 bytes from 10.244.1.6: seq=2 ttl=62 time=1.682 ms
    64 bytes from 10.244.1.6: seq=3 ttl=62 time=0.432 ms
    ......
    
  • 相关阅读:
    Linux下crontab详解
    Linux下mail/mailx命令发送邮件
    Linux下Mysql数据库备份
    Linux远程备份—ftp方式、NFS方式
    Fedora 17安装NFS
    Linux下vsftp服务器—上传、下载
    Linux中Kill进程的N种方法
    Linux命令执行顺序— ||和&&和;
    C#中override和overload的区别
    C#中派生类调用基类构造函数用法分析
  • 原文地址:https://www.cnblogs.com/huiyichanmian/p/15827780.html
Copyright © 2020-2023  润新知