k8s进阶之路一

155 阅读8分钟

image.png 与pod相关的设计

image.png

pod----微服务(某一个服务)

deployment-----部署资源是声明式部署,抽象封装了一组容器的升级和回滚过程,并使其执行成为可重复和自动化的活动

statefulset----有状态的应用部署资源

replicaset-----pod的多副本和弹性的部署

daemonset----微服务(pod)的守护线程

service-----pod所构建的服务,用于服务发现和负载均衡

image.png 初始化容器类似于对象构造函数;守护进程(daemonset)集类似于在后台运行的守护线程(例如Java垃圾收集器)。Pod类似于控制反转(Inversion of Control, IoC)上下文(例如,Spring Framework),其中多个运行的对象共享一个托管生命周期,并且可以直接访问彼此。

为了解释所说的新的抽象和原语是什么意思,这里将它们与众所周知的面向对象编程(OOP),特别是Java进行比较。在OOP领域中,有类、对象、包、继承、封装和多态性等概念。然后,Java运行时提供了特定的特性,并保证了它如何将对象和应用程序的生命周期作为一个整体来管理。 Java语言和Java虚拟机(JVM)为创建应用程序提供了本地的进程内构建块。Kubernetes通过提供一组新的分布式原语和运行时来构建跨多个节点和进程的分布式系统,为这种众所周知的思维方式增加了一个全新的维度。有了Kubernetes,不再仅仅依靠本地原语来实现整个应用程序行为。

Container

容器是基于kubernetes的云本地应用程序的构建块。如果我们比较一下OOP和Java,容器image就像class,容器就像object。container image就是解决单个问题的功能单元,并包含运行时依赖和资源需求。容器通常作为单个进程运行。 container image与微服务的原则严格匹配,一个微服务对应一个container image。

Pod

云原生平台都提供了另一种用于管理一组容器生命周期的原语——在Kubernetes中,它被称为Pod。Pod是一组容器的调度、部署和运行时隔离的原子单元。Pod中的所有容器总是被调度到同一个主机上,为了伸缩或主机迁移的目的而部署在一起,还可以共享文件系统、网络和进程名称空间。在开发和构建阶段,微服务对应于一个团队开发和发布的container image。在运行时,微服务由Pod表示,它是deploy、placement和scaling的单元。

Pod是调度的原子单位。 这意味着调度程序试图找到一个满足所有属于Pod的容器要求的主机。如果创建了一个包含许多容器的Pod,则调度程序需要找到一个具有足够资源来满足所有容器需求的主机。Pod确保容器的放置。多亏了这种搭配,同一个Pod中的容器之间有了额外的交互方式。最常见的通信方式包括使用共享的本地文件系统来交换数据,或使用本地主机网络接口,或使用一些主机进程间通信(IPC)机制来进行高性能交互。 Pod有一个IP地址、名称和端口范围,由属于它的所有容器共享。这意味着必须小心地配置同一个Pod中的容器,以避免端口冲突,就像并行运行的Unix进程在主机上共享网络空间时必须小心一样。

Service

Service是另一个简单但功能强大的Kubernetes抽象,它将Service名称永久绑定到IP地址和端口号。因此,Service代表了访问应用程序的命名入口点。在最常见的场景中,Service作为一组Pods的入口点。服务是一个通用的原语,它也可以指向Kubernetes集群之外提供的功能。因此,Service原语可以用于服务发现和负载平衡, 并允许在不影响服务使用者的情况下改变实现和扩展。

Labels and Namespace

微服务在构建时是一个容器,在运行时由Pod表示。如何表示由多个微服务组成的应用程序呢? 标签和名称空间。 在微服务出现之前,应用程序对应于具有单一版本控制方案和发布周期的单一部署单元。应用程序只有一个。应用程序被分成了微服务,这些微服务可以独立开发、发布、运行、重启或扩展。有了微服务,应用程序的概念减少了。但是,如果需要一种方法来表明一些独立的服务属于某个应用程序,那么可以使用标签。设想一下,将一个整体应用程序拆分为三个微服务,将另一个应用程序拆分为两个微服务。

image.png 现在有5个Pod定义(可能还有更多的Pod实例),它们独立于开发和运行时的观点。前三个pod表示一个应用程序,另外两个pod表示另一个应用程序。即使是pod也可能是独立的,以提供业务价值,但它们可能相互依赖。例如,一个Pod可能包含负责前端的容器,其他两个Pod负责提供后端功能。如果这两个pod中的任何一个坏了,那么从业务的角度来看,应用程序是无用的。使用标签选择器使我们能够查询和识别一组Pods,并将其作为一个逻辑单元进行管理。

Deployment

将一个服务升级到下一个版本涉及的活动包括:启动Pod的新版本,优雅地停止Pod的旧版本,等待并验证它已经成功启动,有时在失败的情况下将它全部回滚到上一个版本。这些活动的执行方式是:允许一些停机时间,但不运行并发服务版本;或者不允许停机时间,但由于在更新过程中运行两个版本的服务而增加了资源使用。手动执行这些步骤可能会导致人为错误,而正确地编写脚本可能需要大量的工作,这两者都会迅速地将发布过程变成瓶颈。

image.png 1-声明三个副本。滚动更新需要多个副本才有意义。 2-除了更新期间指定的副本之外,可以临时运行的Pods的数量。在本例中,最多可以有四个副本。 3-更新过程中不可用Pods的数量。在这里,在更新过程中,一次只能使用两个pod。

image.png rolling update的策略对于确保更新过程中的零停机。该策略的作用是将maxUnavailable设置为已声明的副本的数量。这意味着它首先杀死当前版本的所有容器,然后在旧容器被驱逐时同时启动所有新容器。

image.png Recreate strategyRollingUpdate策略对于确保更新过程中的零停机时间非常有用。但是,这种方法的副作用是,在更新过程中,容器的两个版本同时运行。这可能会给服务消费者带来问题,特别是当更新过程在服务api中引入了向后不兼容的更改,而客户端没有能力处理这些更改时。对于这种场景,有一个重建策略。

image.png Blue-Green部署是一种发布策略,通过减少停机时间和降低风险,在生产环境中部署软件。Kubernetes的部署抽象是一个基本概念,它允许你定义Kubernetes如何将不可变容器从一个版本转换到另一个版本。 但是,如果没有使用Service Mesh或Knative这样的扩展,Blue-Green部署需要手动完成。从技术上讲,它是通过使用容器的最新版本(让我们称它为绿色)创建第二个Deployment来工作的,它还没有服务于任何请求。在这个阶段,来自原始部署的旧Pod副本(称为blue)仍然在运行,并为活动请求提供服务。 一旦我们确信新版本的Pod是健康的,并且可以处理实时请求,我们就将流量从旧的Pod副本切换到新的副本。Kubernetes中的这个活动可以通过更新Service选择器来匹配新的容器(标记为绿色)来完成。如图所示,一旦绿色容器处理了所有的流量,就可以删除蓝色容器,并释放资源供未来的blue - green部署使用。

image.png Canary release是一种将应用程序的新版本软部署到生产环境中的方法,只需用新实例替换旧实例的一小部分。这种技术通过只让部分使用者使用更新的版本,降低了将新版本引入生产环境的风险。当对服务的新版本以及它在一小部分用户样本中的表现感到满意时,就用新版本替换所有的旧实例。图显示了运行中的金丝雀释放。 在Kubernetes中,这种技术可以通过为新容器版本(最好使用Deployment)创建一个新的ReplicaSet来实现,该副本数量小,可以用作Canary实例。在这个阶段,服务应该将一些消费者指向更新后的Pod实例。一旦我们确信新ReplicaSet的所有内容都能按照预期工作,我们就会将一个新的ReplicaSet放大,并将旧的ReplicaSet缩小到零。在某种程度上,我们执行的是受控的、经过用户测试的增量展示。