k8s容器

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

2021-07-17  本文已影响0人  sknfie

一、calico网络策略原理

1. 值

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

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

2. 功能

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

3. 概念

  1. 名称空间和全局网络策略
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-tcp-6379
  namespace: production
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网络政策规范定义了以下行为:

为了和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
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 支持如下功能:

2. 概念

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

3. 动作

  1. 创建ingress policies

案例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

案例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
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
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
kubectl run --namespace=policy-demo nginx --replicas=2 --image=nginx
kubectl expose --namespace=policy-demo deployment nginx --port=80
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 nginx -O -
  1. 开启隔离
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进入的连接,并不是所有。
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
kubectl run --namespace=policy-demo access --rm -ti --image busybox /bin/sh
wget -q --timeout=5 nginx -O -
kubectl run --namespace=policy-demo cant-access --rm -ti --image busybox /bin/sh

wget -q --timeout=5 nginx -O -
kubectl delete ns policy-demo

六、kubernetes策略高级案例

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

1. 先决条件

我们经过以下步骤测试:

  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
kubectl run --namespace=advanced-policy-demo access --rm -ti --image busybox /bin/sh
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

(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
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
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
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
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. 开启隔离
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
  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
上一篇 下一篇

猜你喜欢

热点阅读