简述Kubernetes RC的机制?

svc负责监测它所匹配的pod的状态信息,根据标签把它加到svc队列里来,后面pod的信息有变化的话,变化信息回同步更新到svc中,目标主机通过反向代理svc时, svc会自动更新掉相关的变化信息,不需要去做手动的修改。

默认只提供4层负载均衡的能力,而没有7层的功能,但有时可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的。可使用increas功能实现7层负载均衡

  • 4层是TCP层,使用IP+端口的方式。类似路由器,只是修改下IP地址,然后转发给后端服务器,TCP三次握手是直接和后端连接的。只不过在后端机器上看到的都是与代理机的IP的established而已。
  • 7层代理则必须要先和代理机三次握手后,才能得到7层(HTTP层)的具体内容,然后再转发。意思就是代理机必须要与client和后端的机器都要建立连接。显然性能不行了,但胜在于七层,能写更多的转发规则



解释一下上图:kube-proxy去监控pod的相关信息,把信息写入到IP tables里面的规则里去,当客户端访问svc时,实际上访问的就是iptables里面的规则,即客户端访问节点node是通过iptables实现的,iptables规则是kube-proxy写入的,apiservice通过监控kube-proxy实现服务和端点信息的发现或者监控,kube-proxy通过pod标签判断端点信息是否写入到svc的endpoints端点信息中去


为什么不适用轮询DNS:DNS会在很多的客户端里进行缓存,很多服务进行访问域名解析的时候都不会对DNS进行清除缓存的操作,即访问几次以后还是这个地址信息,那么这里的负载均衡就没办法实现负载均衡了


访问由防护墙完成,访问速度增加,kube-proxy稳定性提高,压力减小,但是防火墙的性能可能没有那么高

  • 与iptables类似,ipvs与netfilter的hook功能,但使用hash表作为底层数据结构并在内核空间中工作,这意味着ipvs可以更快的重定向流量,并且在同步代理规则时具有更好的性能,此外ipvs为负载均衡提供了更多的额选项:
    sed:最短期望延迟;

创建svc以后,可以使用ipvsadm -Ln查看创建成功的ip地址下有么有对应的pod的IP地址。或者直接使用curl IP来看看IP能否被访问


双横杠--解释:代表着kubectl的命令的结束,横杠后的指令表示在pod内部需要执行的命令。


虽然没有CluserIP,但是可以通过地址加域名的格式进行访问


有很多版本,比如Ingress-Hubproxy等解决方案,类似于提供一个api接口或者暴露方式

访问官网,首先将需要下载的镜像下载到本地,然后通过提供的yaml文件就可以部署Ingress


  • 在yaml文件中添加就绪探针

Kubernetes内拥有许多的控制器类型,用来控制pod的状态、行为、副本数量等等,控制器通过Pod的标签来控制Pod ,从而实现对应用的运维,如伸缩、升级等。

常用的控制器类型如下:

  1. ReplicationController 、ReplicaSet、Deployment:无状态服务,保证在任意时间运行Pod指定的副本数量,能够保证Pod总是可用的,支持滚动更新、回滚。典型用法:web服务。
  2. DaemonSet:确保集群内全部(或部分)node节点上都分配一个pod,如果新加node节点,也会自动再分配对应的pod。典型用法:filebeat日志收集、prometheus资源监控。
  3. StatefulSet:有状态服务,如各种数据存储系统。StatefullSet内的服务有着稳定的持久化存储和网络标识,有序部署,有序伸缩。
  4. Job:只运行一次的作业。
  5. CronJob:周期性运行的作业。典型用法:数据库定时备份。

假如我们现在有一个Pod正在提供线上的服务,我们来想想一下我们可能会遇到的一些场景:

  • 某次运营活动非常成功,网站访问量突然暴增
  • 运行当前Pod的节点发生故障了,Pod不能正常提供服务了

针对第一种情况,可能比较好应对,一般活动之前我们会大概计算下会有多大的访问量,提前多启动几个Pod,活动结束后再把多余的Pod杀掉,虽然有点麻烦,但是应该还是能够应对这种情况的。

针对第二种情况,可能某天夜里收到大量报警说服务挂了,然后起来打开电脑在另外的节点上重新启动一个新的Pod,问题也很好的解决了。

如果我们都人工的去解决遇到的这些问题,似乎又回到了以前刀耕火种的时代了,是吧。要是有一种工具能够来帮助我们管理Pod就好了,Pod不够了自动帮我们新增一个,Pod挂了自动帮我们在合适的节点上重新启动一个Pod,如果这样的话,是不是遇到上面的问题,我们都不需要手动去解决了。

Pod分为自主式Pod和控制器管理的Pod这两类。

  • 自主式 Pod:Pod 退出后不会被自动创建,如图中的Pod A
  • 控制器管理的 Pod:在控制器的生命周期里,始终要维持 Pod 的副本数目,如图中的Pod B

简单来说,RC可以保证在任意时间运行Pod的副本数量,能够保证Pod总是可用的。如果实际Pod数量比指定的多,那就结束掉多余的,如果实际数量比指定的少,就新启动一些Pod。当Pod失败、被删除或者挂掉后,RC都会去自动创建新的Pod来保证副本数量,所以即使只有一个Pod,我们也应该使用RC来管理我们的Pod。

简而言之,RC用于确保其管控的Pod对象副本数满足期望的数值,它能实现以下功能:

  • 确保Pod的资源数量精确反应期望值

大部分情况下,我们可以通过定义一个RC实现的Pod的创建和副本数量的控制
RC中包含一个完整的Pod定义模块(不包含apiversion和kind),RC是通过label selector机制来实现对Pod副本的控制的。通过改变RC里面的Pod副本数量,可以实现Pod的扩缩容功能。通过改变RC里面的Pod模板中镜像版本,可以实现Pod的滚动升级功能(但是不支持一键回滚,需要用相同的方法去修改镜像地址)

使用ReplicaSet进行更富表达力的标签选择器有四个有效的运算符:

  • Exists : pod 必须包含 一个指定名称的标签(值不重要)。使用此运算符时,不应指定 values字段。

如果你指定了多个表达式,则所有这些表达式都必须为true才能使选择器与pod匹配。如果同时指定matchLabels和matchExpressions, 则所有标签都必须匹配,并且所有表达式必须计算为true以使该pod与选择器匹配。

不过我们也很少会去单独使用RS,它主要被Deployment这个更加高层的资源对象使用,除非用户需要自定义升级功能或根本不需要升级Pod,

用来创建Pod和ReplicaSet、滚动更新和回滚、扩容和缩容、暂停与恢复。

  • 事件和状态查看:可以查看Deployment对象升级的详细进度和状态
  • 回滚:当升级操作完成后发现问题时,支持将应用返回到指定的历史版本中
  • 版本记录:对Deployment 对象的每一次操作都予以保存
  • 暂停和启动:每一次升级,都可以随时暂停和启动
  • RollingUpdate 策略:旧控制器的Pod数量不断减少,同时新控制器的Pod不断增加,以下两个属性:maxSurge:升级期间存在的总Pod数量最多可超过期望值的个数,可以是数值或百分比。maxUnavailabe:升级期间正常可用的Pod数(新旧版本)最多不能低于期望的个数,可以是数值或百分比。
  • Recreate 策略:在删除旧的 pod 之后才开始创建新的 pod。 如果你的应用程序不支持多个版本同时对外提供服务, 需要在启动新版本之前完全停用旧版本, 那么需要使用这种策略。 但是使用这种策略的话, 会导致应用程序出现短暂的不可用。

Deployment不足以覆盖所有的应用编排问题,因为在它看来,一个应用的所有Pod,是完全一样的,所以它们之间就没有顺序,也无所谓运行在哪台宿主机上。需要时,Deployment就通过Pod模板创建新的Pod。不需要时,就“杀掉”任意一个Pod。但是在实际场景中,并不是所有应用都满足这样的要求。比如:主从关系,主备关系,还有就是数据存储类应用,多个实例通常会在本地磁盘上保存一份数据,而这些实例一旦被杀掉,即使重建出来,实例与数据之间的对应关系也已经丢失,从而导致应用失败。这种实例之间有不对等关系,或者有依赖关系的应用,被称为“有状态应用”。

StatefulSet将真实世界里的应用状态,抽象为了两种情况:

  • 拓扑状态:这种情况是说,应用的多个实例之间不是完全对等的关系。这些应用实例,必须按照某些顺序启动,比如某个应用的主节点A要先于B启动,那么当我把A和B两个节点删除之后,重新创建出来时,也要是这个顺序才行。并且,新创建出来的A和B,必须和原来的A和B网络标识一样,这样原先的访问者才能使用同样的方法,访问到这个新Pod。
  • 存储状态:这种情况是说,应用的多个实例分别绑定了不同的存储数据。对于这些应用实例来说,Pod A第一次读取到的数据,和隔了十分钟之后再次读取到的数据,应该是同一份,哪怕在此期间Pod A被重新创建过。

所以,StatefulSet的核心功能就是通过某种方式,记录这些状态,然后在Pod被重新创建时,能够为新Pod恢复这些状态。

我们知道,Service是Kubernetes项目中用来将一组Pod暴露给外界访问的一种机制。比如,一个Deployment有3个Pod,那么我就可以定义一个Service,然后用户只要能访问到这个Service,就能访问到某个具体的Pod。但是,这个Service是怎么被访问到的呢?

  • 第二种方式,就是以Service的DNS方式。在这里又分为两种处理方法:第一种是Normal Service。这种情况下,当访问DNS记录时,解析到的是Service的VIP。第二种是Headless Service。这种情况下,访问DNS记录时,解析到的就是某一个Pod的IP地址。

这样设计可以使Kubernetes为Pod分配唯一“可解析身份”。而有了这个身份之后,只要知道了一个Pod的名字以及它对应的Service的名字,就可以非常确定地通过这条DNS记录访问到Pod的IP地址。

StatefulSet使用标识完全一致的新的Pod替换, ReplicaSet则是使用一个不相干的新的Pod替换。

Service来保证Pod的“可解析身份”。这样,在创建Pod过程中,StatefulSet给它所管理的所有Pod名字,进行编号,使得每个Pod实例不重复。而更重要的是,这些Pod的创建,也是严格按照编号顺序来进行的。

DaemonSet控制器确保集群中的每一个Node只运行一个特定的Pod副本,实现系统级的后台任务,也具有标签选择器。

也可以指定部分满足条件的Node运行一个Pod副本,比如监控具有ssd存储的Node节点。

常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:

到目前为止, 我们只谈论了需要持续运行的 pod。 你会遇到只想运行完成工作后就终止任务的清况。 ReplicationController 、 ReplicaSet和 DaemonSet 会持续运行任务, 永远达不到完成态。 这些 pod 中的进程在退出时会重新启动。 但是在一个可完成的任务中, 其进程终止后, 不应该再重新启动。

Job控制器用于配置Pod对象运行一次性任务,容器中的进程在正常运行结束后不会进行重启,而是将Pod对象置于“Completed”状态。若容器中的进程因为错误而终止,则需要配置确定是否要重启。

Job控制器对象主要有两种:

  • 单工作队列地串行式Job:多个一次性的作业方式串行执行多次作业,直到满足期望的次数
  • 多工作队列的并行式Job:多个工作队列并行运行多个一次性作业
  • activeDeadlineSeconds:最大活动时间长度,超出此时长的作业将被终止
  • backoffLimit:将作业标记为失败状态之前的重试次数,默认为6
  • ttlSecondsAfterFinished:Completed的job默认不会清理。此配置项设置当job完成后的保留xx秒就自动清理这个job。当ttl controller清理job的时候是级联删除的,会把这个job下的pod一并删除。如果设置为0,job会被立即删除。如果不指定,job则不会被删除。

Job的示例如下所示:

定义了一个Job类型的资源,它将运行luksa/batch-job镜像,该镜像调用 一个运行120秒的进程,然后退出。

上面没有指定pod选择器,它将根据pod模板中的标签进行创建。

在一个pod的定义中,可以指定在容器中运行的进程结束时,Kubernetes应该做什么?

这是通过pod配置的属性restartPolicy完成的,默认为Always。Job类型的资源pod不能使用默认策略,因为它们不是要无限期地运行。因此,需要明确地将重启策略设置为OnFailure或Never。此设置防止容器在完成任务时重新启动。

CronJob控制器执行周期性任务作业,控制其运行的时间点及重复运行的方式,类似于Linux操作系统的周期性任务作业计划的方式控制其运行的时间点和重复运行的方式。

  • schedule:Cron格式的作业调度运行的时间点。
  • concurrencyPolicy:并发执行策略,用于定义前一次作业尚未完成时如何执行下一此任务。默认是Allow,即允许前后Job,甚至是属于同一个CrontJob的更多Job同时运行。如果设置为Forbid则禁止前后两个Job同时运行,如果前一个尚未结束,后一个不会启动(跳过),如果设置为Replace,则后一个Job会替代前一个Job,即终止前一个,启动后一个。
  • startingDeadlineSeconds:因各种原因缺乏执行作业的时间点所导致的启动作业错误的超时时长,会被记入错误历史记录
  • suspend:是否挂起后续的任务执行,默认是false。

CronJob的示例如下所示:

定义了一个CronJob类型的资源每15分钟运行一次批处理任务。

配置时间表如下图所示:

时间表从左到右包含以下五个条目:

了解调度Job如何运行

你可能发生 Job或Pod创建并运行得相对较晚的情况。你可能对这项作业有很高的要求,任务开始不能落后于预定的时间过多。

Pod 最迟必须在预定时间15秒后开始运行, 假如作业运行的时间应该是10:30:00。如果因为任何原因10:30:15不启动,任务将不会运行,并将显示为Failed。

在正常情况下,CronJob总是为schedule中配置的每个执行创建一个 Job, 但可能会同时创建两个Job, 或者根本没有建。
为了解决第一个问题,你的任务应该是幕等的(多次(而不是一次)运行不会得到不希望的结果)。
对于第二个问题,请确保下一个任务运行完成本应该由上一次(错过的) 运行完成的任何工作。

应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让Service中的Pod 个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放(按照期望的pod的cpu或内存来自动伸缩pod数量)。

# cpu 阈值 CPU大于80会自动创建pod来分担服务压力,小于80则减少pod数量

基于多个Pod度量的自动伸缩(例如: CPU使用率和每秒查询率[QPS])的计算也并不复杂。 Autoscaler单独计算每个度量的副本数, 然后取最大值(例如:如果需要4个pod达到目标CPU使用率, 以及需要3个pod来达到目标QPS, 那么Autoscaler 将扩展到4个pod) 。

我们通常将应用分为无状态应用、有状态应用、守护型应用、批处理应用这四种。Kubernetes针对各种类型的应用设计了相应的控制器。本文简单介绍了这几种控制器的不同用途。

本文由博客一文多发平台 发布!

  • 每个Node 节点上都运行着以下一组关键进程

      1. kubelet:负责pod对应的容器创建、启停等任务,同时与master 节点密切协作,实现集群管理的基本功能。
    • equality-based :可以使用=、==、!=操作符,可以使用逗号分隔多个表达式

    定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包含如下几个场景:

    1. 当pod的副本数量小于预期的时候,用于创建新的Pod的pod模板(Template)
    • 扩容Deployment以满足更高的负载。

    • 一个简单的nginx 应用可以定义为:

    应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service中的Pod个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放。这个Object(跟Pod、Deployment一样都是API resource)也是最能体现kubernetes之于传统运维价值的地方,不再需要手动扩容了,终于实现自动化了,还可以自定义指标,没准未来还可以通过人工智能自动进化呢!

    在不同版本的API中,HPA autoscale时可以根据以下指标来判断:

    • HPA会根据每个metric的值计算出scale的值,并将最大的那个指作为扩容的最终结果

    • 一个简单的HPA示例:

    • Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector(查看下面了解,为什么可能需要没有 selector 的 Service)实现的。

    Kubernetes 支持2种基本的服务发现模式 —— 环境变量和 DNS。

    kubernets 通过Add-On增值包的方式引入了DNS 系统,把服务名称作为DNS域名,这样一来,程序就可以直接使用服务名来建立通信连接。目前kubernetes上的大部分应用都已经采用了DNS这一种发现机制,在后面的章节中我们会讲述如何部署与使用这套DNS系统。

    • 外部系统访问service的问题

    为了更加深刻的理解和掌握Kubernetes,我们需要弄明白kubernetes里面的“三种IP”这个关键问题,这三种IP 分别如下:

    对一些应用(如 Frontend)的某些部分,可能希望通过外部(Kubernetes 集群外部)IP 地址暴露 Service。

    Type 的取值以及行为如下:

    • ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType

    • LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。

    我们知道默认情况下容器的数据都是非持久化的,在容器消亡以后数据也跟着丢失,所以Docker提供了Volume机制以便将数据持久化存储。类似的,Kubernetes提供了更强大的Volume机制和丰富的插件,解决了容器数据持久化和容器间共享数据的问题

    (PVC)提供了更方便的管理卷的方法:PV提供网络存储资源,而PVC请求存储资源。这样,设置持久化的工作流包括配置底层文件系统或者云数据卷、创建持久性数据卷、最后创建claim来将pod跟数据卷关联起来。PV和PVC可以将pod和数据卷解耦,pod不需要知道确切的文件系统或者支持它的持久化引擎。

      PersistentVolume(PV)是集群之中的一块网络存储。跟 Node 一样,也是集群的资源。PV 跟 Volume (卷) 类似,不过会有独立于 Pod 的生命周期。比如一个本地的PV可以定义为
    • 第一种,ReadWriteOnce:是最基本的方式,可读可写,但只支持被单个Pod挂载。
    • 第二种,ReadOnlyMany:可以以只读的方式被多个Pod挂载。
    • 第三种,ReadWriteMany:这种存储可以以读写的方式被多个Pod共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是NFS。在PVC绑定PV时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式

上面通过手动的方式创建了一个NFS Volume,这在管理很多Volume的时候不太方便。Kubernetes还提供了StorageClass来动态创建PV,不仅节省了管理员的时间,还可以封装不同类型的存储供PVC选用。

PVC可以直接挂载到Pod中:

    NFS 是Network File System的缩写,即网络文件系统。Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。

如果Pod配置了emptyDir类型Volume, Pod 被分配到Node上时候,会创建emptyDir,只要Pod运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod发生迁移),emptyDir也会被删除,并且永久丢失。

  • 哪些情况下适合使用多个namesapce

因为namespace可以提供独立的命名空间,因此可以实现部分的环境隔离。当你的项目和人员众多的时候可以考虑根据项目属性,例如生产、测试、开发划分不同的namespace。

应用构建和发布流程说明。

  1. 用户在发布应用时需要填写git仓库地址和分支、服务类型、服务名称、资源数量、实例个数,确定后触发Jenkins自动构建
  2. Jenkins的CI流水线自动编译代码并打包成docker镜像推送到Harbor镜像仓库
  3. Jenkins的CI流水线中包括了自定义脚本,根据我们已准备好的kubernetes的YAML模板,将其中的变量替换成用户输入的选项
  4. 更新Ingress的配置,根据新部署的应用的名称,在ingress的配置文件中增加一条路由信息
  5. 更新PowerDNS,向其中插入一条DNS记录,IP地址是边缘节点的IP地址。关于边缘节点,请查看边缘节点配置

我要回帖

更多关于 简述干部交流机制创新的内容 的文章

 

随机推荐