Kubernetes 学习19基于canel的网络策略

Posted presley-lpc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes 学习19基于canel的网络策略相关的知识,希望对你有一定的参考价值。

一、概述

  1、我们说过,k8s的可用插件有很多,除了flannel之外,还有一个流行的叫做calico的组件,不过calico在很多项目中都会有这个名字被应用,所以他们把自己称为project calico,但是很多时候我们在kubernets的语境中通常会单独称呼他为calico。其本身支持bgp的方式来构建pod网络。通过bgp协议的路由学习能使得去每一节点上生成到达另一节点上pod之间的路由表信息。会在变动时自动执行改变和修改,另外其也支持IP-IP,就是基于IP报文来承载一个IP报文,不像我们VXLAN是通过一个所谓的以太网帧来承载另外一个以太网帧的报文的方式来实现的。因此从这个角度来讲他是一个三层隧道,也就意外着说如果我们期望在calico的网络中实现隧道的方式进行应用,来实现更为强大的控制逻辑,他也支持隧道,不过他是IP-IP隧道,和LVS中所谓的IP-IP的方式很相像。不过calico的配置依赖于我们对bgp等协议的理解工作起来才能更好的去了解他。我们这儿就不再讲calico怎么去作为网络插件去提供网络功能的,而是把他重点集中在calico如何去提供网络策略。因为flannel本身提供不了网络策略。而flannel和calico二者本身已经合二为一了,即canel。事实上,就算我们此前不了解canel的时候类似于使用kubectl的提示根据很多文章的提示直接安装并部署了flannel这样的网络插件都想把flannel换掉。但在这基础之上我们又想去使用网络策略。其实也是有解决方案的,我们可以在flannel提供网络功能的基础之上在额外去给他提供calico去提供网络策略。

  2、在实现部署之前要先知道,calico默认使用的网段不是10.244.0.0,如果要拿calico作为网络插件使用的话它工作于192.168.0.0网络。而且是16位掩码。每一个节点网络分配是按照192.168.0.0/24,192.168.1.0/24来分配的。但此处我们不把其当做网络插件提供者而是当做网络策略提供者,我们仍然使用10.244.0.0网段。

二、安装calico

  1、可以在官方文档中看到calico有多种安装方式(目前为止calico还不支持ipvs模式)

  技术图片

  2、安装教程链接https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/flannel

  3、calico新版本中部署比较复杂,calico对集群节点的所有的地址分配都没有自己介入,而是需要依赖于etcd来介入,这就比较麻烦了,首先,大家知道我们k8s自己有etcd database,而calico也需要etcd database,它是两套集群,各自是各自的etcd,这样子分裂起来进行管理来讲对我们k8s工程师都不是一个轻松的事情,那我们应该怎么做呢?后来的calico也支持不把数据放在自己专用的etcd集群中,而是掉apiserver的功能,直接把所有的设置都发给apiserver,由apiserver再存储在etcd中,因为整个k8s集群任何节点的功能,任何组件都不能直接写k8s的etcd,必须apiserver写,主要是确保数据一致性。这样一来也就意外着说我们calico部署有两种方式。第一就是和k8s的etcd分开;第二,直接使用k8s的etcd,不过是要通过apiserver去调用。这儿我们直接使用第二种方式部署。官网对部署方式描述如下

Installing with the Kubernetes API datastore (recommended)
Ensure that the Kubernetes controller manager has the following flags set:
--cluster-cidr=10.244.0.0/16 and --allocate-node-cidrs=true.

Tip: If you’re using kubeadm, you can pass --pod-network-cidr=10.244.0.0/16 to kubeadm to set the Kubernetes controller flags.

If your cluster has RBAC enabled, issue the following command to configure the roles and bindings that Calico requires.

kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
Note: You can also view the manifest in your browser.

Issue the following command to install Calico.

kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml
Note: You can also view the manifest in your browser.

  4、现在我们来部署

    a、首先我们部署一个rbac.yaml配置文件

[root@k8smaster flannel]# kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
clusterrole.rbac.authorization.k8s.io/calico created
clusterrole.rbac.authorization.k8s.io/flannel configured
clusterrolebinding.rbac.authorization.k8s.io/canal-flannel created
clusterrolebinding.rbac.authorization.k8s.io/canal-calico created

    b、第二步我们部署canal.yaml

[root@k8smaster flannel]# kubectl apply -f > https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml
configmap/canal-config created
daemonset.extensions/canal created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created

    c、接下来我们来看一下对应的组件是否已经启动起来了

三、canel的使用

  1、部署完canel后我们怎么去控制我们对应的pod间通信呢?现在我们在我们的cluster上创建两个namespaces,一个叫dev,一个叫pro,然后在两个名称空间中创建两个pod,我们看看两个名称空间中跨名称空间通信能不能直接进行,如果能进行的话我们如何让他不能进行。并且我们还可以这样来设计,我们可以为一个名称空间设置一个默认通信策略,任何到达此名称空间的通信流量都不被允许。简单来讲我们所用的网络控制策略是通过这种方式来定义的。如图,我们网络控制策略(Network Policy)他通过Egress或Ingress规则分别来控制不同的通信需求,什么意思呢?Egress即出栈的意思,Ingress即入栈的意思(此处Ingress和我们k8sIngress是两回事)。Egress表示我们pod作为客户端去访问别人的。即自己作为源地址对方作为目标地址来进行通信,Ingress表示自己是目标,远程是源。所以我们要控制这两个方向的不同的通信,而控制Egress的时候客户端端口是随机的而服务端端口是固定的,因此作为出栈的时候去请求别人很显然对方是服务端,对方的端口可预测,对方的地址也可预测,但自己的地址能预测端口却不能预测。同样的逻辑,如果别人访问自己,自己的地址能预测,自己的端口也能预测,但对方的端口是不能预测的。因为对方是客户端。

    技术图片

  2、因此去定义规则时如果定义的是Egress规则(出栈的),那么我们可以定义目标地址和目标端口。如果我们定义的是Ingress规则(入栈的),我们能限制对方的地址,能限制自己的端口,那我们这种限制是针对于哪一个Pod来说的呢?这个网络策略规则是控制哪个pod和别人通信或接受别人通信的呢?我们使用podSelector(pod选择器)去选择pod,意思是这个规则生效在哪个pod上,我们一般使用单个pod进行控制,也可以控制一组pod,所以我们使用podSelector就相当于说我这一组pod都受控于这个Egress和Ingress规则,而且更重要的是我们将来定义规则时还可以指定单方向。意思是入栈我们做控制出栈都允许或出栈做控制入栈都允许。因此定义时可以很灵活的去定义,可以发现他和iptables没有太大的区别。那种方式最安全呢?肯定是拒绝所有放行已知。甚至于如果说你是托管了每一个名称空间托管了不同项目的,甚至不同客户的项目。我们名称空间直接设置默认策略。我们在名称空间内所有pod可以无障碍的通信,但是跨名称空间都不被允许。这种都可以叫一个名称空间的默认策略。

  3、接下来我们看这些策略怎么工作起来

    a、我们可以看到我们加载的canal pod已经启动起来了

[root@k8smaster ~]# kubectl get pods -n kube-system |grep canal
canal-hmc47                            3/3       Running   0          45m
canal-sw5q6                            3/3       Running   0          45m
canal-xxvzk                            3/3       Running   0          45m

    b、我们看我们网络策略怎么定义

[root@k8smaster ~]# kubectl explain networkpolicy
KIND:     NetworkPolicy
VERSION:  extensions/v1beta1

DESCRIPTION:
     DEPRECATED 1.9 - This group version of NetworkPolicy is deprecated by
     networking/v1/NetworkPolicy. NetworkPolicy describes what network traffic
     is allowed for a set of Pods

FIELDS:
   apiVersion    <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

   kind    <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

   metadata    <Object>
     Standard objects metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

   spec    <Object>
     Specification of the desired behavior for this NetworkPolicy.
[root@k8smaster ~]# kubectl explain networkpolicy.spec
KIND:     NetworkPolicy
VERSION:  extensions/v1beta1

RESOURCE: spec <Object>

DESCRIPTION:
     Specification of the desired behavior for this NetworkPolicy.

     DEPRECATED 1.9 - This group version of NetworkPolicySpec is deprecated by
     networking/v1/NetworkPolicySpec.

FIELDS:
   egress    <[]Object> #出栈规则
     List of egress rules to be applied to the selected pods. Outgoing traffic
     is allowed if there are no NetworkPolicies selecting the pod (and cluster
     policy otherwise allows the traffic), OR if the traffic matches at least
     one egress rule across all of the NetworkPolicy objects whose podSelector
     matches the pod. If this field is empty then this NetworkPolicy limits all
     outgoing traffic (and serves solely to ensure that the pods it selects are
     isolated by default). This field is beta-level in 1.8

   ingress    <[]Object> #入栈规则
     List of ingress rules to be applied to the selected pods. Traffic is
     allowed to a pod if there are no NetworkPolicies selecting the pod OR if
     the traffic source is the pods local node, OR if the traffic matches at
     least one ingress rule across all of the NetworkPolicy objects whose
     podSelector matches the pod. If this field is empty then this NetworkPolicy
     does not allow any traffic (and serves solely to ensure that the pods it
     selects are isolated by default).

   podSelector    <Object> -required-   #规则应用在哪个pod上
     Selects the pods to which this NetworkPolicy object applies. The array of
     ingress rules is applied to any pods selected by this field. Multiple
     network policies can select the same set of pods. In this case, the ingress
     rules for each are combined additively. This field is NOT optional and
     follows standard label selector semantics. An empty podSelector matches all
     pods in this namespace.

   policyTypes    <[]string>  #策略类型,指的是假如我在当前这个策略中即定义了Egress又定义了Ingress,那么谁生效呢?虽然他们并不冲突,但是你可以定义在某个时候某一方向的规则生效。
     List of rule types that the NetworkPolicy relates to. Valid options are
     Ingress, Egress, or Ingress,Egress. If this field is not specified, it will
     default based on the existence of Ingress or Egress rules; policies that
     contain an Egress section are assumed to affect Egress, and all policies
     (whether or not they contain an Ingress section) are assumed to affect
     Ingress. If you want to write an egress-only policy, you must explicitly
     specify policyTypes [ "Egress" ]. Likewise, if you want to write a policy
     that specifies that no egress is allowed, you must specify a policyTypes
     value that include "Egress" (since such a policy would not include an
     Egress section and would otherwise default to just [ "Ingress" ]). This
     field is beta-level in 1.8

      我们来看egress定义

[root@k8smaster ~]# kubectl explain networkpolicy.spec.egress
KIND:     NetworkPolicy
VERSION:  extensions/v1beta1

RESOURCE: egress <[]Object>

DESCRIPTION:
     List of egress rules to be applied to the selected pods. Outgoing traffic
     is allowed if there are no NetworkPolicies selecting the pod (and cluster
     policy otherwise allows the traffic), OR if the traffic matches at least
     one egress rule across all of the NetworkPolicy objects whose podSelector
     matches the pod. If this field is empty then this NetworkPolicy limits all
     outgoing traffic (and serves solely to ensure that the pods it selects are
     isolated by default). This field is beta-level in 1.8

     DEPRECATED 1.9 - This group version of NetworkPolicyEgressRule is
     deprecated by networking/v1/NetworkPolicyEgressRule.
     NetworkPolicyEgressRule describes a particular set of traffic that is
     allowed out of pods matched by a NetworkPolicySpecs podSelector. The
     traffic must match both ports and to. This type is beta-level in 1.8

FIELDS:
   ports    <[]Object>
     List of destination ports for outgoing traffic. Each item in this list is
     combined using a logical OR. If this field is empty or missing, this rule
     matches all ports (traffic not restricted by port). If this field is
     present and contains at least one item, then this rule allows traffic only
     if the traffic matches at least one port in the list.

   to    <[]Object>
     List of destinations for outgoing traffic of pods selected for this rule.
     Items in this list are combined using a logical OR operation. If this field
     is empty or missing, this rule matches all destinations (traffic not
     restricted by destination). If this field is present and contains at least
     one item, this rule allows traffic only if the traffic matches at least one
     item in the to list.

 

以上是关于Kubernetes 学习19基于canel的网络策略的主要内容,如果未能解决你的问题,请参考以下文章

k8s基于canel的网络策略

Kubernetes 学习总结(19)—— Kubernetes 集群管理平台如何选择?Rancher vs KubeSphere

Kubernetes 学习总结(19)—— Kubernetes 集群管理平台如何选择?Rancher vs KubeSphere

化繁为简,京东云发布地域级高可用Kubernetes集群服务

在 vCenter 上运行 Kubernetes

基于OVN的Kubernetes网络架构解析