Kubernetes的设计与架构(翻译)


转载请注明出处即可

文章原文
用最后提交时间为20年04月02号 85e7b63ddbb86107b2850ac4b0bacc7aed194fd5的版本进行翻译

注意: 本文并非是直译,部分译文携带了笔者自己的理解,因为笔者水平有限,可能或曲解作者的原意。

概述

Kubernetes的源自于Google 15 年生产环境的运维经验,同时凝聚了社区的最佳创意和实践。它是一个生产级别的开源基础设施,可以做到在跨主机集群的环境下,对应用容器进行部署、扩展、管理和组合。Kubernetes存在的意义不仅仅是提供了"容器编排"。它方便运维人员和开发者专注于以容器为中心的自助操作[1],比如帮助开发者聚焦核心应用功能,帮助运维团队获取更高的资源利用率等。它通过对开发者屏蔽了物理/虚拟计算、网络和存储,因此开发者可以专注于应用实现,而不是花费时间去思考与基础设施的集成,运维人员也不用考虑在上面部署的是什么样的应用。Kubernetes还是一个稳定的,可移植的基础平台,可以自定义的工作流和其他在更高级别的自动化,或者说Kubernetes抽象了底层的基础设施,简化了应用开发、部署等过程。

[1] (译注: 做到了关注点隔离,方便两种不同的角色专注于各自不同的领域,当某个机器出现问题时,只需要调度到其他的机器,而无需运维人员在半夜加班处理问题,可以在第二天在处理出现问题的机器。)

Kubernetes主要用于由多个容器(Docker等)组成的应用程序(或系统、服务)。为了方便管理容器和发现容器,它通过使用pods和labels(标签)来形成了一种紧耦合或松耦合的结构[2]。

[2] (译注: 这里的紧耦合和松耦合可以理解为在部署pod时,对label的使用。可以强制将pod部署到某个或者某几个节点,也可以通过对节点资源的筛选(比如需要GPU资源)等去进行选择节点(调度)部署。当然紧耦合在生产环境一般是不推荐的。)

范围

Kubernetes是一个用于部署和管理容器的平台。Kubernetes提供了容器引擎,容器编排,以容器为中心的基础设施编排、运行时状态检查和重新调度等自我修复机制、并且还提供了服务发现和负载均衡。

Kubernetes期望能成为一个可扩展,插件化的工具集。因此,在架构上,我们希望将Kubernetes构建的组件都是可插拔的,并且可以自行选择调度器、控制器、存储系统和分发机制,我们根据这个愿景来发展这个项目。此外,我们希望大家能够扩展Kubernetes的能力,比如在无需修Kubernetes核心源代码的情况下,使用更高级的PaaS功能等,因此Kubernetes所提供的API不仅仅针对使用它的终端用户,而是针对工具和扩展Kubernetes能力的开发人员。它的API旨在作为工具、自动化系统和高级API层的开发生态系统的基础。因为,它没有“内部的”组件间的API。所有的API都是可见和可用的,包括调度器,节点控制器,复制控制器,Kubelet的API等。为了处理在不同生产环境下的独特需求,大家可以直接访问底层API。

目标

本项目有以下的设计理论和目标:

  • 方便: Kubernetes可以运行在公有云,私有云,裸机和笔记本电脑。并且无论在哪个环境下对它做的任何操作都是一致的。换句话说就是它可以到处运行,而无需考虑底层具体基础设施的差异。因此应用程序和工具可以在整个生态系统以及开发和生产环境之间进行移植。
  • 通用: Kubernetes应该运行所有的系统类别。无论是有状态的、无状态的、微服务、单体应用、服务、批处理、遗留系统等,这样只需要在Kubernetes单个基础设施运行以上所有类型,来应对实际的负载。
  • 满足一部分用户需求: 虽然Kubernetes不只满足于纯粹的云原生应用,但是也不会满足用户的所有需求。它主要专注于微服务和云原生应用的部署和管理,但是提供了一些机制来促进整体和遗留应用到Kubernetes的迁移。
  • 灵活: Kubernetes功能可以按需使用,并且可以通过自己的解决方案来替代内置的功能。
  • 可扩展的: Kubernetes通过内置功能所使用的相同公开接口来添加额外的功能。
  • 易自动化: Kubernetes的目标是大幅减少手工操作。它通过声明式API指定用户期望,声明后则通过它的内部机制来进行具体的命令式的控制执行。声明式API是系统自愈等相关能力的关键。当然, 它也支持定义更高级别的编排和自动化的命令式控制。
  • 推荐先进技术: 虽然Kubernetes可以支持非云原生应用,但是它也希望可以推进云原生和DevOps的技术发展,比如让应用参也参与到对自己的管理之中。但是它不会强迫程序锁死在Kubernetes API,这也是Kubernetes的API更喜欢配置而不是约定的原因。此外,Kubernetes不受它所依赖系统的限制,无论是容器引擎还是云厂商。例如,可以根据需要来选择不同的Pod的网络模型。

架构

Kubernetes在运行时,包含节点代理(kubelet)和集群控制平面(AKA Master),集群状态存储在分布式存储系统(etcd)中。

集群控制平面

Kubernetes的控制平面由多个组件组成,这些组件既可以单节点运行,或通过多节点来支持高可用的集群,或者将组件直接运行在Kubernetes上,进行自托管。

在Kubernetes中,资源作为控制平面的枢纽,Kubernetes提供的Rest API,主要是支持在这些资源(持久化)上进行CRUD操作。Kubernetes提供的API,比如Pods,Services和Ingress,以及生命周期的API等,都是以容器为中心的操作。通过这些API来支持业务流程(自愈、扩展、更新、终止)和常见的工作负载。比如ReplicaSet(简单的、无状态(可替换)的应用程序管理器),Deployment(部署与更新无状态应用),Job(批处理), CronJob(cron), DaemonSet(集群服务)和StateFullSet(有状态应用管理)。并且我们特意将服务注册于服务发现和负载均衡的实现分离,因为负载均衡是开放的,并且种类繁多。

用户客户端(kubectl或直接使用的k8s client)和包含异步处理的控制器(conttollers)都使用了相同的API资源、这些资源会协调中间数据状态,以及共享状态。大多数资源都包含元数据,元数据中又包含labels和annotations,资源所需的详细状态(spec),默认值和可观测到的状态。

控制器会不断检查观测状态,当期望(配置)状态与观测状态不一致时,则驱动Kubernetes达到期望的状态(自愈),同时也会为用户和其他控制器报告观测到的状态。

虽然控制器是基于声明式API已最大程序的提高容错性,但它们为了最大限度的减少延迟和冗余工作,通常会watch(监视)相关的资源更改。这样就可以在没有消息总线的情况下实现服务编排的解耦。

API Server

API Server提供Kubernetes API,它是一个相对简单的服务器,其他的组件或插件会实现大部分业务逻辑。它主要处理REST操作,并进行验证,然后更新Etcd中相应的对象(可能最终会更新其他存储)。这里请注意,Kubernetes不支持跨多个资源的原子事务。

这个基本的API机制,是Kubernetes可以运行的根本,其中包括

  • REST语义,watch(监听),持久性和保证一致性, API版本控制、默认值和校验
  • 内置控制语义,同步控制hooks和异步资源初始化
  • API的注册和发现

此外,API服务器充当集群的网关。根据定义,Kubernetes Client能够从集群外部访问API服务器,而节点和容器则不能直接在集群外部访问。API服务器会对客户端进行验证,并且用于连接节点和Pods(Services等)的代理和通道。

Cluster state store 集群状态存储

所有持久化的集群状态都存储在Etcd中。通过对wahch的支持,可以非常迅速的通知和协调组件进行更改。

Controller-Manager Server 控制器管理服务

大多数集群级别的功能都是通过Controller-Manager来执行的。他处理生命周期的功能(例如,命名空间创建和生命周期、事件垃圾收集、终止pod垃圾收集、级联删除垃圾收集、节点垃圾收集)和API的业务逻辑(例如,由复制集控制的pod扩展)。

应用程序管理和组合层,提供自修复、伸缩、应用程序生命周期管理、服务发现、路由以及服务绑定和供应。这些功能最终可能会被分解成单独的组件,以便更容易地扩展或替换。

Scheduler 调度器

Kubernetes允许用户请求集群运行一组容器。调度器会为容器自动选择要运行的主机。

调度器监视未调度的Pods,并根据所请求资源的可用性、服务质量(QoS)要求、亲和性和反亲和性以及其他的约束选择节点,然后通过Binding Pod子资源API将它们绑定到节点上。

The Kubernetes Node 节点

Kubernetes节点有运行应用容器所需的组件。

Kubelet

Kubernetes中最重要的就是Kubelet组件,它是容器执行层的Pod和Node API的主要实现者。如果没有这些API, Kubernetes就只是一个CRUD的REST应用程序框架(这些API机制可能最终会发展成为一个独立的项目)。

Kubernetes将隔离的应用容器作为默认的执行模式。应用容器不仅仅彼此隔离,而且还与它们执行的主机隔离,这对于各个应用程序管理与基础设施的管理(底层物理集群或虚拟集群)分离来说至关重要。

Kubernetes通过Pods来承载多容器和存储卷,方便每个容器只打包单个应用程序(译注: 在k8s中,一个Pod可以运行多个容器,但在实践中尽量不要在一个容器中跑多个应用)。通过Pod可以将部署和构建分离开,以及方便从物理机和虚拟机迁移。Pod的设计是现代云平台(如Kubernetes)上部署的关键。

API管理控制可能拒绝Pods或向它们添加额外的调度约束。但是Kubelet是决定Pods在指定节点(node)上是否可以运行的最终角色这,而不是调度器或其他组件。

Kubelet还链接在cAdvisor(译注: Google开源的容器资源监控项目)资源代理的监控中。

容器引擎

每个节点运行一个容器时,容器引擎负责下载镜像(images)和运行容器。

Kubelet没有关联任何的基础容器引擎。相反,我们定义了一个容器引擎的接口来控制底层引擎在该层的可插拔性。为了组件边界、方便测试和可插拔性,需要这种与某个具体容器引擎的解耦。目前至少支持了Docker、rkt、crio和frakti这些容器引擎。

Kube Proxy

Kubernetes中service提供了公共访问策略,可以为Pods进行分组(译注: 可以通过label来实现)后提供负载均衡。它实现了一个虚拟IP,客户端可以通过访问这个虚拟IP,来透明的代理到服务后的Pods中。每个节点都运行了一个kube-proxy进程,该进程通过改写iptables规则来捕获IP的访问,并将其重定向到具体的后端。这是一个高可用的负载均衡解决方案,通过平衡单个节点客户端流量,到相同的节点上,降低了单个节点的性能开销。

服务endpoints还可以通过DNS(内置的core-dns)来找到。

其他组件和其他依赖项

Kubernetes除了以上组件外,还依赖其他组件,通常运行在Kubernetes内部:

联合

一个Kubernetes可以跨多个可用区(Zone)部署。
但为了更高的可用性,我们建议使用集群联合。
(译注: 集群联合或者叫做集群联邦,是新版本提供的功能,可以跨集群资源同步和跨集群发现)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值