过去的大多数软件都是大型的单体应用,以但进程或多进程的方式运行在几个服务器上,但是随着架构的逐渐演化,现在的大型单体应用正在逐渐被分解为小的,可独立运行的组件,我们称之为微服务。微服务彼此之间解耦,所以他们之间可以被独立开发、部署、升级、伸缩。但是随着组件的增多,如何保持系统正常运行变得更加困难,手动做这些并不现实,需要一些自动化措施,例如自动调度,配置,监管和故障处理,这正是Kubernetes的用武之地。
Kubemetes 使开发者可以自主部署应用,并且控制部署的频率,完全脱离运维团队的帮助。 Kubemetes 同时能让运维团队监控整个系统,并且在硬件故障时重新调度应用 。 系统管理员的工作重心 ,从监管应用转移到了监管 Kubemetes ,以及剩 余的系统资源,因为 Kubemetes 会帮助监管所有的应用 。
在最近几年中,我们看到了应用在开发流程和生产运维流程中的变化。在过去 ,开发团队的任务是创建应用并交付给运维团队,然后运维团队部署应用并使它运行 。 但是现在,公司都意识到,让同一个团队参与应用的开发、部署、运维的整个生命周期更好。 这意味着开发者 、QA和运维团队彼此之间的合作需要贯穿整个流程 。这种实践被称为 DevOps。
下图展示了最简单的Kubernetes系统图。整个系统由一个主节点和若干个工作节点组成 。 开发者把一个应用列表提交到主节点, Kubemetes 会将它们部署到集群的工作节点。组件被部署在哪个节点对于开发者和系统管理员来说都不用关心 。
开发者能指定一些应用必须一起运行, Kubemetes 将会在一个工作节点上部署它们 。其他的将被分散部署到集群中,但是不管部署在哪儿,它们都能以相同的方式互相通信。
在硬件级别,一个Kubernetes集群由很多节点组成,这些节点被分成以下两种类型 :
- 主节点 ,它承载着Kubernetes控制和管理整个集群系统的控制面板
- 工作节点, 它们运行用户实际部署的应用
控制面板用于控制集群并使它工作。它包含多个组件,组件可以运行在单个主节点上或者通过副本分别部署在多个主节点以确保高可用性。 这些组件是 :
- Kubernetes API 服务器, 你和其他控制面板组件都要和它通信
- Scheculer, 它调度你的应用(为应用的每个可部署组件分配一个工作节点〕
- Controller Manager, 它执行集群级别的功能, 如复制组件、持续跟踪工作节点 、 处理节点失败等
- etcd,一个可靠的分布式数据存储, 它能持久化存储集群配置
控制面板的组件持有井控制集群状态, 但是它们不运行你的应用程序。这是由工作节点完成的。
工作节点是运行容器化应用的机器。 运行、监控和 管理应用服务的任务是由以下组件完成的 :
- Docker、rtk或其他的容器类型
- Kubelet, 它与 API 服务器通信, 并管理它所在节点的容器
- Kubernetes Service Proxy (kube-proxy) ,它负责组件之间的负载均衡网络流量
为了在Kubernetes中运行应用, 首先需要将应用打包进一个或多个容器镜像, 再将那些镜像推送到镜像仓库, 然后将应用的描述发布到 Kubemetes API 服务器。
该描述包括诸如容器镜像或者包含应用程序组件的容器镜像、这些组件如何相互关联,以及哪些组件需要同时运行在同一个节点上和哪些组件不需要同时运行等信息。此外,该描述还包括哪些组件为内部或外部客户提供服务且应该通过单个 IP 地址暴露 ,并使其他组件可以发现。
当 API 服务器处理应用的描述时,调度器调度指定组的容器到可用的工作节点上,调度是基于每组所需的计算资源,以及调度时每个节点未分配的资源。然后,那些节点上的Kubelet指示容器运行时(例如Docker)拉取所需的镜像并运行容器。
仔细看下图可以更好地理解如何在Kubernetes中部署应用程序。应用描述符列出了四个容器,并将它们分为三组(这些集合被称为 pod)。前两个 pod 只包含 一个容器, 而最后一个包含两个。 这意味着两个容器都需要协作运行 ,不应该相互隔离。 在每个pod旁边 ,还可以看到一个数字 , 表示需要并行运行的每个 pod的副本数量。 在向Kubernetes 提交描述符之后, 它将把每个pod的指定副本数量调度到可用的工作节点上 。节点上的 Kubelets 将告知 Docker 从镜像仓库中拉取容器镜像井运行容器。
一旦应用程序运行起来,Kubernetes就会不断地确认应用程序的部署状态始终与你提供的描述相匹配 。 例如, 如果你指出你需要运行五个 web 服务器实例, 那么 Kubernetes 总是保持正好运行五个实例。 如果实例之一停止了正常工作, 比如当进程崩溃或停止响应时,Kubernetes将自动重启它。
同理, 如果整个工作节点死亡或无法访问,Kubernetes将为在故障节点上运行的所有容器选择新节点, 并在新选择的节点上运行它们。
当应用程序运行时,可以决定要增加或减少副本量 ,而 Kubemetes 将分别增加附加的或停止多余的副本。 甚至可以把决定最佳副本数目的工作交给Kubemetes。 它可以根据实时指标(如CPU负载、内存消耗、每秒查询或应用程序公开的任何其他指标)自动调整副本数。
我们己经说过, Kubemetes 可能需要在集群中迁移你的容器。 当它们运行的节点失败时, 或者为了给其他容器腾出地方而从节点移除时,就会发生这种情况。如果容器向运行在集群中的其他容器或者外部客户端提供服务,那么当容器在集群内频繁调度时,它们该如何正确使用这个容器?当这些容器被复制并分布 在整个集群中时, 客户端如何连接到提供服务的容器呢?
为了让客户能够轻松地找到提供特定服务的容器,可以告诉 Kubemetes 哪些容器提供相同的服务, 而 Kubemetes 将通过一个静态 IP 地址暴露所有容器, 并将该地址暴露给集群中运行的所有应用程序。 这是通过环境变量完成的, 但是客户端也可以通过良好的 DNS 查找服务 IP。kube-proxy将确保到服务的连接可跨提供服务的容器实现负载均衡。 服务的 IP 地址保持不变, 因此客户端始终可以连接到它的容器, 即使它们在集群中移动。
{% embed url="https://kubernetes.feisky.xyz/" %}
{% embed url="https://mp.weixin.qq.com/s/aC6NDfQm6Gm4sWsr1izURg" %}