美文网首页k8s容器
一文学会calico及k8s网络策略入门

一文学会calico及k8s网络策略入门

作者: sknfie | 来源:发表于2021-07-17 23:31 被阅读0次

    一、calico网络策略原理

    1. 值

    • 外部的Kubernetes network policy

    calico网络策略提供了一系列的策略能力,其中包括策略的顺序/优先级,拒绝规则和其它更灵活的匹配规则。kubernetes网络策略仅应用于Pod,而Calico网络策略可以应用于多种类型的终端,比如pods, VMs和主机接口等。 而且,当使用istio service mesh的话,那么Calico network policy还支持应用的5-7层的网络策略。

    • 写一次,应用到所有
      写一次策略,你可以应用几乎所有的云提供商中。

    • 和kubernetes 网络策略无缝的结合

    你可以使用Calico 网络策略附加到Kubernetes网络策略,也可单独使用。 比如,你可以 允许开发者针对他们的微服务定义kubernetes网络策略,而允许安全团队或ops团队定义它们的calico 网络策略。

    2. 功能

    Calico 网络策略支持以下功能:

    • 策略可以应用任何的端点: Pods/containers,VMs,and/or host interfaces.

    • 策略可以定应用于ingress,egress或两者的规则

    • 策略规则支持:

      • Actions: allow, deny, log, pass

      • Source and destination match criteria:

        • Ports: numbered, ports in a range, and Kubernetes named ports
        • Protocols: TCP, UDP, ICMP, SCTP, UDPlite, ICMPv6, protocol numbers (1-255)
        • HTTP attributes (if using Istio service mesh)
        • ICMP attributes
        • IP version (IPv4, IPv6)
        • IP or CIDR
        • Endpoint selectors (using label expression to select pods, VMs, host interfaces, and/or network sets)
        • Namespace selectors
        • Service account selectors
    • 可选的包处理控制:在DNAT前,关闭连接追踪,应用转发策略 and/or 本地流量终止。

    3. 概念

    1. 名称空间和全局网络策略
    • calico network policy是名称空间资源,它应用于那个名称空间的pods/containers/VMs。
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: allow-tcp-6379
      namespace: production
    
    • calico global network policy 是非名称空间资源,它应用于任何类型的endpoint(pods, VMs, host interfaces). 是独立于名称空间的.
    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: allow-tcp-port-6379
    
    1. kubectl vs calicoctl

    请记住一点:calico network policy和calico global network policies是使用calicoctl应用的。

    1. Ingress and egress
      从endpint的视图而言(pod,VM, host interface), ingress是进入到endpint的流量,而egress是从endpoints出去的流量 。

    下面是应用的关系表:

    Ingress rule present? Engress rule present? Value
    No No Ingress
    Yes No Ingress
    No Yes Egress
    Yes Yes Ingress, Egress
    1. 网络策略的行为: deny and allow

    Kubernetes网络政策规范定义了以下行为:

    • 如果没有网络策略应用于pod,那么从pod出去的流量或进入pod的都是允许的。

    • 如果有定义位于pod ingress rules,那么仅那些被允许的Ingress流量是放行的,其它拒绝。

    • 如果有定义位于pod egress rules,那么仅那些被允许的egress流量是放行的,其它拒绝。

    为了和kuberneres兼容,calico network policy遵循善存 kubernetes pods相同的行为。针对其它endpoints的类型(VMs, host interfaces),Calico network policy是默认的拒绝。

    二、启用默认的策略

    1. Enable default deny calico global network policy, non-namespaced
    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: default-deny
    spec:
      selector: all()
      types:
      - Ingress
      - Egress
    
    1. Enable default deny Calico network policy, namespaced
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: default-deny
      namespace: engineering
    spec:
      selector: all()
      types:
      - Ingress
      - Egress
    
    1. Enable default deny kubernetes policy, namespaced
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny
      namespace: engineering
    spec:
      podSelector: {}
      policyTypes:
      - Ingress
      - Egress
    

    三、calico网络策略案例

    4. 案例

    1. Control traffic to/from endpoints in a namespace

      • 实验环境构建
    # 创建网络名称空间
    $ kubectl create ns production
    
    # 创建默认的策略
    $ cat default-deny-for-production.yaml
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: default-deny
      namespace: production
    spec:
      selector: all()
      types:
      - Ingress
    
    # 应用默认的策略
    $ calico apply -f default-deny-for-production.yaml
    
    # 部署redis应用
    $ cat redis-rc.yaml
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: redis
      namespace: production
    spec:
       replicas: 1
       selector:
         color: red
       template:
         metadata:
           labels:
             color: red
         spec:
           containers:
           - name: redis
             image: redis
             ports:
             - containerPort: 6379
    
    • 在下面的案例中,假如来自相同的名称空间的pod,它的标签为run:access到名称空间production的标签为color:red是,且端口号为6379的是允许的。
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: allow-tcp-6379
      namespace: production
    spec:
      selector: color == 'red'
      ingress:
      - action: Allow
        protocol: TCP
        source:
          selector: run == 'access'
        destination:
          ports:
            - 6379
    
    • 使用如下进行测试
    kubectl run --namespace=production deny --rm -ti --image busybox /bin/sh
    kubectl run --namespace=production access --rm -ti --image busybox /bin/sh
    
    • 使用名称空间选择器的案例
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: allow-tcp-6379
      namespace: production
    spec:
      selector: color == 'red'
      ingress:
      - action: Allow
        protocol: TCP
        source:
          selector: run == 'access'
          namespaceSelector: name == 'zangxueyuan'
        destination:
          ports:
          - 6379
    
    # 使用如下进行测试
    $ kubectl label ns default name=zangxueyuan
    $ kubectl run --namespace=default access --rm -ti --image busybox /bin/sh
    
    1. Control traffic to/from endpoints independent of namespace

    案例如下:

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: deny-blue
    spec:
      selector: color == 'red'
      ingress:
      - action: Deny
        protocol: TCP
        source:
          selector: color == 'blue'
    
    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: deny-circle-blue
    spec:
      selector: color == 'red'
      ingress:
      - action: Deny
        protocol: TCP
        source:
          selector: color == 'blue'
          namespaceSelector: shape == 'circle'
    
    1. Control traffic to/from endpoints using IP addresses or CIDR ranges
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: allow-egress-external
      namespace: production
    spec:
      selector:
        color == 'red'
      types:
        - Egress
      egress:    
        - action: Deny
          destination:
            nets:
            - 1.2.3.4/24
    
    1. Apply network policies in specific order

    应用的顺序数字从小到大:

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: drop-other-ingress
    spec:
      order: 20
      ...deny policy rules here...
    
    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: allow-cluster-internal-ingress
    spec:
      order: 10
      ...allow policy rules here...
    
    1. 针对指定的流量产生日志
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    Metadata:
      name: allow-tcp-6379
      namespace: production
    Spec:
      selector: role == 'database'
      types:
      - Ingress
      - Egress
      ingress:
      - action: Log
        protocol: TCP
        source:
          selector: role == 'frontend'
      - action: Deny
        protocol: TCP
        source:
          selector: role == 'frontend'
    

    四、kubernetes网络策略原理

    Kubernetes网络政策允许开发人员获得和他们的应用程序使用相同的简单的语言使用部署它们。开发人员可以专注于他们的应用程序不了解底层网络的概念。使开发人员能够轻松地使用网络政策确保他们的应用程序DevOps环境。

    1. 功能

    kubernetes Network Policy API 支持如下功能:

    • 策略作用于名称空间的范围

    • 策略仅用于那些label selectors的pods.

    • 策略规则可以指定流量 to/from pods, namespaces, or CIDRs的流量 。

    • 策略规则可以指定协议(TCP,UDP,SCTP),端口的名字或端口号码

    2. 概念

    kubernetes网络策略 API提供一个方式,让用户定义网络策略去控制流量 。然后,kubernetes是没有内置的网络策略的,因此,你必须使用插件的方式,比如Calico插件。

    3. 动作

    1. 创建ingress policies
    • 允许相同名称空间的pods互访

    案例1:

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-same-namespace
      namespace: default
    spec:
      podSelector:
        matchLabels:
          color: blue
      ingress:
      - from:
        - podSelector:
            matchLabels:
              color: red
        ports:
          - port: 80
    
    • 允许不同的名称空间的pods互访

    案例2:

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-same-namespace
      namespace: default
    spec:
      podSelector:
        matchLabels:
          color: blue
      ingress:
      - from:
        - podSelector:
            matchLabels:
              color: red
          namespaceSelector:
            matchLabels:
              shape: square
        ports:
        - port: 80
    
    1. 创建egress policies
    • 允许相同名称空间的pods互访
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-egress-same-namespace
      namespace: default
    spec:
      podSelector:
        matchLabels:
          color: blue
      egress:
      - to:
        - podSelector:
            matchLabels:
              color: red
        ports:
        - port: 80
    
    • 允许egress traffic到IP地址或CIDR块
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-egress-external
      namespace: default
    spec:
      podSelector:
        matchLabels:
          color: red
      egress:
      - to:
        - ipBlock:
            cidr: 172.18.0.0/24
    

    4. 最佳实践:创建拒绝所有的默认网络策略

    1. 创建一个默认的拒绝所有的ingress和egress网络策略
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: default-deny
      namespace: policy-demo
    spec:
      podSelector:
        matchLabels: {}
      types:
      - Ingress
      - Egress
    

    五、kubernetes策略基础案例

    1. 配置名称空间
    kubectl create ns policy-demo
    
    1. 创建demo pods
    • policy-demo名称空间中创建一些nginx pods
    kubectl run --namespace=policy-demo nginx --replicas=2 --image=nginx
    
    • 通过服务暴露它们
    kubectl expose --namespace=policy-demo deployment nginx --port=80
    
    • 确定nginx的服务是可以访问的
    kubectl run --namespace=policy-demo access --rm -ti --image busybox /bin/sh
    
    Waiting for pod policy-demo/access-472357175-y0m47 to be running, status is Pending, pod ready: false
    
    If you don't see a command prompt, try pressing enter.
    
    / #
    
    • 在access的内部,尝试访问nginx服务。
    wget -q nginx -O -
    
    1. 开启隔离
    • 运行下面的命令创建一个NetworkPolicy,它在policy-demo名称空间中执行默认的行为。
    kubectl create -f - <<EOF
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: default-deny
      namespace: policy-demo
    spec:
      podSelector:
        matchLabels: {}
    EOF
    
    • 测试隔离
    kubectl run --namespace=policy-demo access --rm -ti --image busybox /bin/sh
    
    Waiting for pod policy-demo/access-472357175-y0m47 to be running, status is Pending, pod ready: false
    
    If you don't see a command prompt, try pressing enter.
    
    / #
    
    wget -q --timeout=5 nginx -O -
    
    wget: download time out
    
    1. 使用网络策略允许访问
      现在,让我们使用NetworkPolicy开启到nginx 服务的访问. 这只是允许从access pod进入的连接,并不是所有。
    • 创建网络策略access-nginx,内容如下:
    kubectl create -f - <<EOF
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: access-nginx
      namespace: policy-demo
    spec:
      podSelector:
        matchLabels:
          run: nginx
      ingress:
        - from:
          - podSelector:
              matchLabels:
                run: access
    EOF
    
    • 现在应该能够从access pod访问服务
    kubectl run --namespace=policy-demo access --rm -ti --image busybox /bin/sh
    
    • 执行如下命令进行访问测试
    wget -q --timeout=5 nginx -O -
    
    • 如果不是从access的pod的话,那么便不能访问,执行如下
    kubectl run --namespace=policy-demo cant-access --rm -ti --image busybox /bin/sh
    
    wget -q --timeout=5 nginx -O -
    
    • 清除demo的名称空间
    kubectl delete ns policy-demo
    

    六、kubernetes策略高级案例

    kubernetesNetworkPolicy API 允许用户基于 labels 和 port 定义kubernetes pods ingress 和 egress.

    1. 先决条件

    • calico v2.6.1+, kubernetes 1.8+

    • 可以使用kubectl 访问kubernetes集群

    • 你Kubernetes节点能够连接到公共Internet

    • 熟悉kubernetes NetworkPolicy

    我们经过以下步骤测试:

    1. 创建名称空间和Nginx服务

    2. 拒绝所有ingress流量

    3. 允许ingress流量到nginx

    4. 拒绝所有egress流量

    5. 允许egress流量到kube-dns

    6. 清除名称空间

    2. 创建名称空间和nginx 服务

    kubectl create ns advanced-policy-demo
    kubectl run --namespace=advanced-policy-demo nginx --replicas=2 --image=nginx
    kubectl expose --namespace=advanced-policy-demo deployment nginx --port=80
    
    • 校验访问 - 允许所有ingress和egress
    kubectl run --namespace=advanced-policy-demo access --rm -ti --image busybox /bin/sh
    
    • 访问nginx的服务进行测试
    wget -q --timeout=5 nginx -O -
    
    • 访问外网进行测试
    wget -q --timeout=5 www.baidu.com -O -
    

    3. 拒绝所有的ingress 流量

    通过部署一个默认的所有Ingress流量策略,在名称空间中开启ingress 隔离。

    kubectl create -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny-ingress
      namespace: advanced-policy-demo
    spec:
      podSelector:
        matchLabels: {}
      policyTypes:
      - Ingress
    EOF
    
    • 校验访问 - 拒绝所有ingress和允许所有egress

    (1) 访问Nginx服务

    wget -q --timeout=5 nginx -O -
    
    # 返回结果
    wget: download timed out
    

    (2)尝试访问baidu.com

    wget -q --timeout=5 www.baidu.com -O -
    
    # 返回结果
    <!doctype html><html itemscope="" item....
    

    4. 允许ingress流量到nginx

    kubectl create -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: access-nginx
      
      namespace: advanced-policy-demo
    spec:
      podSelector:
        matchLabels:
          run: nginx
      ingress:
        - from:
          - podSelector:
              matchLabels: {}
    EOF
    
    • 校验访问-- 允许nginx ingress
    wget -q --timeout=5 nginx -O -
    
    # 返回结果如下
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>...
    
    

    5. 拒绝所有egress流量

    kubectl create -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny-egress
      namespace: advanced-policy-demo
    spec:
      podSelector:
        matchLabels: {}
      policyTypes:
      - Egress
    EOF
    
    • 校验访问 - 拒绝所有egress
    nslookup nginx
    
    #  返回结果
    Server:    10.96.0.10
    Address 1: 10.96.0.10
    
    nslookup: can't resolve 'nginx'
    

    (2)尝试访问baidu.com

    wget -q --timeout=5 www.baidu.com -O -
    
    # 返回结果
    wget: bad address 'google.com'
    

    6. 允许DNS egress流量

    运行下面的命令在kube-system名称空间上创建一个name: kube-system标签, 并且创建一个网络策略允许advanced-policy-demo名称空间中的任何pods到kube-system DNS egress流量。

    kubectl label namespace kube-system name=kube-system
    kubectl create -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-dns-access
      namespace: advanced-policy-demo
    spec:
      podSelector:
        matchLabels: {}
      policyTypes:
      - Egress
      egress:
      - to:
        - namespaceSelector:
            matchLabels:
              name: kube-system
        ports:
        - protocol: UDP
          port: 53
    
    EOF
    
    • 校验访问 - 允许DNS访问
    nslookup nginx
    
    # 返回结果如下
    Server:    10.0.0.10
    Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
    
    nslookup baidu.com
    

    7. 允许egress流量到nginx

    创建egress 流量策略允许在advanced-policy-demo名称空间的任何pods到相同名称空间中的匹配标签 run: nginx的pods.

    kubectl create -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-egress-to-advance-policy-ns
      namespace: advanced-policy-demo
    spec:
      podSelector:
        matchLabels: {}
      policyTypes:
      - Egress
      egress:
      - to:
        - podSelector:
            matchLabels:
              run: nginx
    EOF
    
    • 校验访问- 允许egress访问到nginx
    wget -q --timeout=5 nginx -O -
    
    # 返回的结果
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>...
    
    wget -q --timeout=5 google.com -O -
    
    # 返回的结果
    wget: download timed out
    

    8. 清空名称空间

    kubectl delete ns advanced-policy-demo
    

    七、calico在生产情况模拟

    这包含构建fronted 和 backend service的demo,.

    1. 创建fronted, backend, client 和management-ui apps.
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/manifests/00-namespace.yaml
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/manifests/01-management-ui.yaml
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/manifests/02-backend.yaml
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/manifests/03-frontend.yaml
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/manifests/04-client.yaml
    
    1. 等待所有的pods处于运行状态:
    kubectl get pods --all-namespaces --watch
    

    此时应该可以通过http://<k8s-node-ip>:30002进行访问了。

    1. 开启隔离
    • 运行以下命令阻止所有的到fronted,backend,和client服务的访问。
    kubectl create -n stars -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/policies/default-deny.yaml
    kubectl create -n client -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/policies/default-deny.yaml
    
    • 隔离的确认

    刷新管理UI,现在我们开启隔离,这个UI将不能够再次访问。

    1. 使用网络策略允许UI的访问
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/policies/allow-ui.yaml
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/policies/allow-ui-client.yaml
    

    几秒钟后,刷新UI——它现在应该显示服务,但他们不能互相访问

    1. 创建backend-policy.yaml文件允许流量 从frontend到backend.
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/policies/backend-policy.yaml
    
    • 刷新UI,你应该能看到如下:

      • 前端现在可以访问后端(仅在TCP端口6379)。
      • 后端不能访问前端。
      • 客户端不能访问前端,也不能访问后端
    1. 暴露前端的服务给客户端名称空间
    kubectl create -f https://docs.projectcalico.org/v3.11/security/tutorials/kubernetes-policy-demo/policies/frontend-policy.yaml
    

    现在客户端可以访问前端,而不是后端。前端和后端都无法启动连接客户端。前端仍然能够访问后端。

    1. 清空demo的环境
    kubectl delete ns client stars management-ui
    

    相关文章

      网友评论

        本文标题:一文学会calico及k8s网络策略入门

        本文链接:https://www.haomeiwen.com/subject/rimgpltx.html