Calico除了支持BGP网络之外还支持网络策略。
在默认情况下,k8s上的2个不同名称空间下的Pod是可以相互访问的。k8s的名称空间仅用于为资源名称提供隔离机制,而对于不同名称空间下的pod间相互访问并没有进行隔离。而Calico的网络策略则是用来管控Pod间的通信流量。
所谓的网络测略就是专用于调用节点内核上,能够实施流量控制的API从而定义规则来管控Pod间通信的一种机制。
k8s默认网络策略 网络策略是K8S上的一种标准资源。
k8s默认网络策略定义规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name <string> namespace <string> spec: podSelector <Object> policyTypes <[]string> ingress <[]Object> - from <[]Object> - ipBlock <Object> - namespaceSelector <Object> podSelector <Object> ports <[]Object> egress <[]Object> - to <[]Object> ports <[]Object>
管控入站流量 管控入站流量时有3种方式定义其来源
ipblock
namespaceSelector
podSelector
nameSpaceSelector和podSelector是同时使用的。
示例 1.创建出pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 root@k8s-master01:~/yaml/chapter08 apiVersion: apps/v1 kind: Deployment metadata: name: deployment-demo spec: replicas: 4 selector: matchLabels: app: demoapp release: stable template: metadata: labels: app: demoapp release: stable spec: containers: - name: demoapp image: ikubernetes/demoapp:v1.0 ports: - containerPort: 80 name: http root@k8s-master01:~/yaml/chapter08 deployment.apps/deployment-demo created
2.编写netpol资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 root@k8s-master01:~/yaml/chapter10 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: demoapp-ingress namespace: dev spec: podSelector: matchLabels: app: demoapp policyTypes: ["Ingress" ] ingress: - from: - namespaceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: In values: [dev,kube-system,logs,monitoring,kubernetes-dashboard,longhorn-system] - from: - namespaceSelector: matchExpressions: - {key: kubernetes.io/metadata.name, operator: NotIn, values: ["default" ]} ports: - protocol: TCP port: 80
3.应用资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 root@k8s-master01:~/yaml/chapter10 networkpolicy.networking.k8s.io/demoapp-ingress created root@k8s-master01:~/yaml/chapter10 Name: demoapp-ingress Namespace: dev Created on: 2021-08-09 08:15:42 +0000 UTC Labels: <none> Annotations: <none> Spec: PodSelector: app=demoapp Allowing ingress traffic: To Port: <any> (traffic allowed to all ports) From: NamespaceSelector: kubernetes.io/metadata.name in (dev,kube-system,kubernetes-dashboard,logs,monitoring) ---------- To Port: 80/TCP From: NamespaceSelector: kubernetes.io/metadata.name notin (default) Not affecting egress traffic Policy Types: Ingress
4.在default名称空间下使用pod进行访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 root@k8s-master01:~/yaml/chapter10 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deployment-demo-fb544c5d8-8jd62 1/1 Running 0 3d 192.168.96.1 k8s-node02 <none> <none> deployment-demo-fb544c5d8-wcdms 1/1 Running 0 3d 192.168.131.3 k8s-node01 <none> <none> deployment-demo-fb544c5d8-xvsm7 1/1 Running 0 3d 192.168.30.2 k8s-node03 <none> <none> deployment-demo-fb544c5d8-zwbhd 1/1 Running 0 3d 192.168.30.1 k8s-node03 <none> <none> root@k8s-master01:~/yaml/chapter10 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deployment-demo-fb544c5d8-frmr7 1/1 Running 0 13m 192.168.30.3 k8s-node03 <none> <none> deployment-demo-fb544c5d8-lxnvz 1/1 Running 0 13m 192.168.96.2 k8s-node02 <none> <none> deployment-demo-fb544c5d8-vqqbt 1/1 Running 0 13m 192.168.131.4 k8s-node01 <none> <none> deployment-demo-fb544c5d8-z9wfc 1/1 Running 0 13m 192.168.96.3 k8s-node02 <none> <none> root@k8s-master01:~/yaml/chapter10
注意事项:
在使用规则时,名称空间必须要存在相应的标签,否则规则将无法匹配导致不生效
定义规则时必须生效顺序,若允许的规则范围太大将会导致拒绝规则不生效。
管控出站流量 由于默认的出战规则是放行所有,所以需要先将所有的入站和出栈规则做拒绝,才能进行管控。
1.创建资源清单,拒绝所有出入站
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 root@k8s-master01:~/yaml/chapter10 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-ingress namespace: dev spec: podSelector: {} policyTypes: ["Ingress" ,"Egress" ] egress: - to: - podSelector: {} ingress: - from: - podSelector: {}
2.应用配置清单
1 2 3 4 5 6 7 8 9 10 root@k8s-master01:~/yaml/chapter10 networkpolicy.networking.k8s.io/deny-all-ingress created root@k8s-master01:~/yaml/chapter10 ;; connection timed out; no servers could be reached command terminated with exit code 1
3.定义egress的放行规则,编写资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 root@k8s-master01:~/yaml/chapter10 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: demoapp-egress namespace: dev spec: podSelector: matchLabels: app: demoapp policyTypes: ["Egress" ] egress: - to: ports: - protocol: UDP port: 53 - to: - podSelector: matchLabels: app: redis ports: - protocol: TCP port: 6379 - to: - podSelector: matchLabels: app: demoapp ports: - protocol: TCP port: 80
4.应用资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 root@k8s-master01:~/yaml/chapter10 networkpolicy.networking.k8s.io/demoapp-egress created root@k8s-master01:~/yaml/chapter10 Server: 10.96.0.10 Address: 10.96.0.10 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Name: www.a.shifen.com Address: 180.101.49.12 Name: www.a.shifen.com Address: 180.101.49.11
隔离名称空间 之前的denyall资源清单,使用后虽然能够实现隔离名称空间的效果,但是其直接拒绝了所有。而后ingress和egress的资源清单实现了流量控制的机制,但是定义网络规则时,如果定义在多个资源内很有可能资源和资源间的规则会冲突和覆盖导致无法达成目标,所以建议所有的入站和出战规则写入同一个文件中。
示例 名称空间级别出入站同一文件示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 root@k8s-master01:~/yaml/chapter10 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default namespace: stage spec: podSelector: {} policyTypes: ["Ingress" ,"Egress" ] ingress: - from: - namespaceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: In values: [stage,kube-system,logs,monitoring,kubernetes-dashboard] egress: - to: ports: - protocol: UDP port: 53 - to: - namespaceSelector: matchLabels: name: kube-apiserver podSelector: matchLabels: component: kube-apiserver ports: - protocol: TCP port: 443 - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: stage
k8s自身的networkPolicy每个名称空间都需要以当前名称空间为中心设置networkPolicy,系统上存在几个namespace就需要几个networkPolicy去应用,这管理起来十分复杂。因此Calico提供了另一种解决方案
Calico的网络策略 尽管k8s功能上日渐丰富,但k8s自己的NetworkPolicy
资源仍然具有相当的局限性,例如它没有明确的拒绝规则、缺乏对选择器高级表达式的支持、不支持应用层规则,以及没有集群范围的网络策略等。为了解决这些限制,Calico等提供了自有的策略CRD,包括NetworkPolicy
和GlobalNetworkPolicy
等,其中的NetworkPolicy CRD
比Kubernetes NetworkPolicy API
提供了更大的功能集,包括支持拒绝规则、规则解析级别以及应用层规则等,但相关的规则需要由calicoctl创建。
1 2 3 root@k8s-master01:~/yaml/chapter10 globalnetworkpolicies crd.projectcalico.org/v1 false GlobalNetworkPolicy networkpolicies crd.projectcalico.org/v1 true NetworkPolicy
Calico全局管理 GlobalNetworkPolicy
支持使用selector
、serviceAccountSelector
或namespaceSelector
来选定网络策略的生效范围,默认为all(),即集群上的所有端点。下面的配置清单示例(globalnetworkpolicy-demo.yaml)为非系统类名称空间(本示例假设有kube-system、kubernetes-dashboard、logs和monitoring这4个)定义了一个通用的网络策略。
示例 定义资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 root@k8s-master01:~/yaml/chapter10 apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: namespace-default spec: order: 0.0 namespaceSelector: name not in {"kube-system" ,"kubernetes-dashboard" ,"logs" ,"monitoring" } types: ["Ingress" ,"Egress" ] ingress: - action: Allow source : namespaceSelector: name in {"kube-system" ,"kubernetes-dashboard" ,"logs" ,"monitoring" } egress: - action: Allow
应用资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 root@k8s-master01:~/yaml/chapter10 Successfully applied 1 'GlobalNetworkPolicy' resource(s) root@k8s-master01:~/yaml/chapter10 apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: creationTimestamp: "2021-08-10T03:16:58Z" name: namespace-default resourceVersion: "510265" uid: b38164a9-5d6f-441d-970a-a493d03fb868 spec: egress: - action: Allow destination: {} source : {} ingress: - action: Allow destination: {} source : namespaceSelector: name in {"kube-system" ,"kubernetes-dashboard" ,"logs" ,"monitoring" } namespaceSelector: name not in {"kube-system" ,"kubernetes-dashboard" ,"logs" ,"monitoring" } order: 0 types: - Ingress - Egress