简述Kubernetes Calico网络组件实现原理?

《Docker容器与微服务架构》测试题

Docker就是虚拟机,虚拟机器

Docker是重量级虚拟化技术

Docker是半虚拟化技术

Docker 是一个开源的应用容器引擎(正确答案)

2. Docker主要运行在什么操作系统上? [单选题] *

启动快,资源占用小,基于Linux容器技术(正确答案)

KVM属于轻量级虚拟化

下载文档原格式(Word原格式,共8页)

架构师普遍有这样的愿景:在系统中有ServiceA、ServiceB、ServiceC这3种服务,其中ServiceA需要部署3个实例,ServiceB与ServiceC各自需要部署5个实例,希望有一个平台(或工具)自动完成上述13个实例的分布式部署,并且持续监控它们。

师普遍有这样的愿景:在系统中有ServiceA、ServiceB、ServiceC这3种服务,其中ServiceA需要部署3个实例,ServiceB与ServiceC各自需要部署5个实例,希望有一个平台(或工具)自动完成上述13个实例的部署,并且持续监控它们。当发现某个服务器宕机或者某个服务实例发生故障时,平台能够自我修复,从而确保在任何时间点正在运行的服务实例的数量都符合预期。这样一来,团队只需关注服务开发本身,无须再为基础设施和运维监控的事情头疼了。

Kubernetes出现之前,没有一个平台公开声称实现了上面的愿景。Kubernetes是业界第一个将服务这个概念真正提升到第一位的平台。在Kubernetes的世界里,所有概念与组件都是围绕Service运转的。正是这种突破性的设计,使Kubernetes真正解决了多年来困扰我们的分布式系统里的众多难题,让团队有更多的时间去关注与业务需求和业务相关的代码本身,从而在很大程度上提高整个软件团队的工作效率与投入产出比。

Kubernetes里的Service其实就是微服务架构中微服务的概念,它有以下明显特点。

  • 每个Service都分配了一个固定不变的虚拟IP地址——Cluster IP。
  • 客户端访问一个 Service时,就好像访问一个远程的TCP/UDP服务,只要与Cluster IP建立连接即可,目标端口就是某个Service Port。

DNS Server,这样一来,微服务架构中的服务发现这个基本问题得以巧妙解决,不但不用复杂的服务发现API供客户端调用,还使所有以TCP/IP方式通信的分布式系统都能方便地迁移到Kubernetes平台上,仅从这个设计来看,Kubernetes就远胜过其他产品。

我们知道,在每个微服务的背后都有多个进程实例来提供服务,在Kubernetes平台上,这些进程实例被封装在Pod中,Pod基本上等同于Docker容器,稍有不同的是,Pod其实是一组密切捆绑在一起并且“同生共死”的 Docker 容器,这组容器共享同一个网络栈与文件系统,相互之间没有隔离,可以直接在进程间通信。最典型的例子是Kubenetes Sky DNS

那么,Kubernetes里的 Service 与 Pod 是如何对应的呢?我们怎么知道哪些Pod 为某个Service提供具体的服务?下图给出了答案——“贴标签”。

每个Pod都可以贴一个或多个不同的标签(Label),而每个Service都有一个“标签选择器”(Label Selector),标签选择器确定了要选择拥有哪些标签的对象。下面这段YAML格式的内容定义了一个被称为ku8-redis-master的Service,它的标签选择器的内容为“app: ku8-redis-master",表明拥有“app=

如果我们需要一个Service在任意时刻都有N个Pod实例来提供服务,并且在其中1个Pod实例发生故障后,及时发现并且自动产生一个新的Pod实例以弥补空缺,那么我们要怎么做呢?答案就是采用 Deployment/RC,它的作用是告诉Kubernetes,拥有某个特定标签的 Pod需要在Kubernetes集群中创建几个副本实例。Deployment/RC的定义包括如下两部分内容。

至此,上述YAML文件创建了一个一主二从的Redis集群,其中Redis Master被定义为一个微服务,可以被其他Pod或 Service访问,如下图所示。

Service进行通信,以实现Redis 主从同步功能。

scale命令行功能实现扩容即可。命令如下,我们发现,服务的水平扩容变得如此方便:

CPU利用率会不断变化,在这些Pod 的CPU平均利用率超过80%后,就会自动扩容,直到CPU利用率下降到80%以下或者最多达到5个副本位置,而在请求的压力减小后,Pod的副本数减少为1个,用下面的HPA命令即可实现这一目标:

除了很方便地实现微服务的水平扩容功能,Kubernetes还提供了使用简单、功能强大的微服务滚动升级功能(rolling update),只要一个简单的命令即可快速完成任务。举个例子,假如我们要将上述Redis Slave服务的镜像版本从devopsbq/redis-slave升级为leader/redis-slave,则只要执行下面这条命令即可:

滚动升级的原理如下图所示,Kubernetes在执行滚动升级的过程中,会创建一个新的RC,这个新的RC使用了新的Pod镜像,然后Kubernetes每隔一段时间就将旧RC的replicas数减少一个,导致旧版本的Pod副本数减少一个,然后将新RC的replicas数增加一个,于是多出一个新版本的Pod副本,在升级的过程中 Pod副本数基本保持不变,直到最后所有的副本都变成新的版本,升级才结束。

集群中的其他节点被称为Node节点,属于工人(Worker 节点),它们都由Master 节点领导,主要负责照顾各自节点上分配的Pod副本。下面这张图更加清晰地表明了Kubernetes各个进程之间的交互关系。

从上图可以看到,位于中心地位的进程是API Server,所有其他进程都与它直接交互,其他进程之间并不存在直接的交互关系。那么,APl Server的作用是什么呢?它其实是Kubernetes的数据网关,即所有进入Kubernetes 的数据都是通过这个网关保存到Etcd数据库中的,同时通过API Server将Eted里变化的数据实时发给其他相关的Kubernetes进程。API Server 以REST方式对外提供接口,这些接口基本上分为以下两类。

  • 所有资源对象的CRUD API:资源对象会被保存到Etcd中存储并提供Query接口,比如针对Pod、Service及RC等的操作。
  • 资源对象的 Watch API:客户端用此API来及时得到资源变化的相关通知,比如某个Service 相关的Pod实例被创建成功,或者某个Pod 状态发生变化等通知,Watch API主要用于Kubernetes 中的高效自动控制逻辑。

下面是上图中其他Kubernetes进程的主要功能。

  • controller manager:负责所有自动化控制事物,比如RC/Deployment的自动控制、HPA自动水平扩容的控制、磁盘定期清理等各种事务。
  • kubelet:负责本Node节点上Pod实例的创建、监控、重启、删除、状态更新、性能采集并定期上报 Pod 及本机 Node节点的信息给Master节点,由于Pod实例最终体现为Docker'容器,所以Kubelet还会与Docker交互。

在理解了Kubernetes各个进程的功能后,我们来看看一个RC 从YAML定义到最终被部署成多个Pod 及容器背后所发生的事情。为了很清晰地说明这个复杂的流程,这里给出一张示意图。

Manager就得到了通知,它会读取RC的定义,然后比较在RC中所控制的Pod 的实际副本数与期待值的差异,然后采取对应的行动。此刻,Controller Manager 发现在集群中还没有对应的Pod实例,就根据RC里的Pod模板(Template)定义,创建一个Pod并通过API Server保存到Etcd中。类似地,Scheduler进程监听所有 Pod,一旦发现系统产生了一个新生的Pod,就开始执行调度逻辑,为该Pod 安排一个新家(Node),如果一切顺利,该Pod就被安排到某个Node节点上,即Binding to a Node。接下来,Scheduler进程就把这个信息及 Pod状态更新到Etcd里,最后,目标Node节点上的Kubelet监听到有新的Pod被安排到自己这里来了,就按照Pod里的定义,拉取容器的镜像并且创建对应的容器。在容器成功创建后,Kubelet进程再把 Pod的状态更新为Running 并通过API Server更新到 Etcd 中。如果此 Pod还有对应的Service,每个Node上的Kube-proxy进程就会监听所有Service及这些Service对应的Pod实例的变化,一旦发现有变化,就会在所在 Node节点上的 iptables 里增加或者删除对应的NAT转发规则,最终实现了Service的智能负载均衡功能,这一切都是自动完成的,无须人工干预。

那么,如果某个Node'宕机,则会发生什么事情呢?假如某个Node宕机一段时间,则因为在此节点上没有Kubelet进程定时汇报这些Pod 的状态,因此这个Node 上的所有Pod'实例都会被判定为失败状态,此时Controller Manager会将这些Pod删除并产生新的Pod实例,于是这些Pod被调度到其他 Node 上创建出来,系统自动恢复。

本节最后说说Kube-proxy的演变,如下图所示。

的流量通过NAT方式重定向到本机的Kube-proxy,在这个过程中涉及网络报文从内核态到用户态的多次复制,因此效率不高。Kube-proxy 之后的版本改变了实现方式,在生成 iptables规则时,直接NAT 到目标Pod地址,不再通过Kube-proxy进行转发,因此效率更高、速度更快,采用这种方式比采用客户端负载均衡方式效率稍差一点,但编程简单,而且与具体的通信协议无关,适用范围更广。此时,我们可以认为Kubernetes Service基于 iptables机制来实现路由和负载均衡机制,从此以后,Kube-proxy已不再是一个真正的“proxy"”,仅仅是路由规则配置的一个工具类“代理”。

基于iptables 实现的路由和负载均衡机制虽然在性能方面比普通Proxy提升了很多,但也存在自身的固有缺陷,因为每个Service都会产生一定数量的 iptables 规则。在Service数量比较多的情况下,iptables

当我们逐渐向着微服务、云原生迈进的时候,传统静态的、相对简单的网络安全策略开始显得吃力。 Kubernetes 的 Network Policy 特性正是来解决这个问题的。在刚刚出炉不久的/R97OVqc

为了简单起见,我们会直接使用 default namespace。如果你在一个现有的环境里面, 可以将以下的命令在一个独立的 namespace 里面运行。

现在我们还没有做任何的限制,所以 Kubernetes 缺省情况是所有 Pod 都是开放的。

上面的 Wget 命令是在 BusyBox 这个 Pod 里面执行的。-q 和 -O - 的组合会使这个命令在命令行输出 nginx 的缺省首页,这表明我们的验证是成功的。用 Ctl-D 退出容器。

接下来我们就要加入限制了。我们的做法是先限制对所有 Pod 的访问,然后建立白名单。 kubectl apply下面的 YAML 文件就可以限制所有访问:

我们再试着用之前的 BusyBox 的方式来访问一下:

这此我们设置了 5 秒的超时。因为访问被拒接,所以确实会超时:

好,我们的第一个 Network Policy 已经生效了。然而,限制对所有 Pod 的访问显然是没有意义的。接下来我们建立一个白名单 . apply 下面的 YAML 文件:

接下来我们试试看能否成功地访问了:

我们依然会看到熟悉的 Nginx 缺省首页。如果我们运行一个不符合上述 selector 的 Pod,就无法访问。这个留给有兴趣的同学自己回去验证。

正式的 API 和之前的 API 区别有:

这里细节很多,我们只需要关注这几点:

Calico 使用 conntrack 来优化。就是说,一旦一个连接已经建立,之后的packet都会直接被允许通过。比如:

A:两者在 iptables 层面上的实现原理是一样的。都用了-m

Q:Calico 结合 Kubernetes 怎么实现多租户,比如网络隔离之类的?

A:各有各的市场 :-)。

Q:NPC 必须用 iptables 实现吗?在某些情况下,Pod 出向流量并不会由主机协议栈,这样 iptables 就用不了,这种情况下 NPC 怎么实现呢 ?

本次培训围绕基于Docker的CI/CD实战展开,具体内容包括:持续集成与持续交付(CI/CD)概览;持续集成系统介绍;客户端与服务端的 CI/CD 实践;开发流程中引入 CI、CD;Gitlab 和 CI、CD 工具;Gitlab CI、Drone 的使用以及实践经验分享等。点击识别下方二维码加微信好友了解 。

我要回帖

更多关于 简述arp欺骗的实现原理 的文章

 

随机推荐