目录
- Kubernetes 是什么
- 为什么要用 Kubernetes
- Kubernetes 概念
- Master
- Node
- Pod
- Label
- Replication Controller
- Deployment
- Horizontal Pod Autoscaler
- StatefulSet
- Service
- 服务发现机制
- Job
- Volume
- Persistent Volume
- Namespace
- Configmap
Kubernetes 是什么
Kubernetes是一个开放的开发平台、完备的分布式系统支撑平台,具有完备的集群管理能力。
对现有的编程语言、编程框架、中间件没有任何侵入性。它让我们不必费心于负载均衡器的选型和部署实施,不必考虑服务治理,不必头疼于服务监控和故障处理;让开发更专注于业务本身,而且其强大的自动化机制,使得后期的运维难度和成本大幅降低。
- 多层次的安全防护和准入机制
- 多租户应用支撑能力
- 透明的服务注册和服务发现机制
- 内建的智能负载均衡器
- 强大的故障发现和自我修复能力
- 服务滚动升级和在线扩容能力
- 可扩展的资源自动调度机制
- 多粒度的资源配额管理能力
Kubernetes 是一个全新的基于容器技术的分布式架构解决方案,Service 是分布式集群架构的核心,关键特征有:
- 拥有唯一 指定的名称(如 redis-server)
- 拥有一个虚拟 IP(Cluster IP、Service IP 或 VIP)和端口号
- 能够提供远程服务能力
- 被映射到提供这种服务能力的一组容器应用上、
Service 的服务进程都基于 Socket 通信方式对外提供服务,或者是实现了某个具体业务的特定 TCP Server 进程。每个服务进程都有一个独立的 Endpoint(IP + Port),但是 Kubernetes 能够通过 Service(虚拟 Cluster IP + Service Port)连接到指定的 Service。
容器提供了强大的隔离功能。k8s 设计了 Pod 对象,将每个服务进程都包装到相应的 Pod 中,使其成为在 Pod 中运行的一个容器。为了建立 Service 和 Pod 的关联关系,k8s 给每个 Pod 贴上一个标签(Label),解决了 Service 和 Pod 的关联问题。
比如给运行MySQL的Pod贴上name=mysql标签
MySQL Service的标签选择器的选择条件为name=mysql,意为该Service要作用于所有包含name=mysql Label的Pod
- Pod 运行在节点(Node)的环境中,节点可以是物理机或虚拟机,通常一个节点上可以运行几百个 Pod;
- 每个 Pod 中都运行着一个特殊的 Pause 容器,其他容器为业务容器,共享 Pause 容器的网络栈和 Volume 挂在卷,这样它们之间的通信和数据交换更为高效。在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个 Pod 中。
- 最后,并不是每个 Pod 和它里面运行的容器都能被映射到一个 Service 上,只有提供服务的那组 Pod 才会被映射为一个服务。
Node 作为集群中的工作节点,运行真正的应用程序,在 Node 上 k8s 管理的最小运行单元是 Pod。在 Node 上运行着 k8s 的 kubelet、kube-proxy 服务进程,负责 Pod 的创建、启动、监控、销毁,以及实现软件模式的负载均衡器。
在 k8s 集群中,只需为需要扩容的 Service 关联的 Pod 创建一个RC(Replication Controller,定义 Pod 模板),服务扩容以至服务升级都迎刃而解。在一个RC定义文件中包括以下3个关键信息:
- 目标Pod的定义
- 目标Pod需要运行的副本数量(Replicas)
- 要监控的目标Pod的标签
为什么要用 Kubernetes
- 微服务架构的核心是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务可能由多个实例副本支撑,副本的数量可以随着系统的负荷变化进行调整
- 在 k8s 的架构方案中完全屏蔽了底层网络的细节,基于 Service 的虚拟 IP 地址(Cluster IP)的设计思路让架构与底层的硬件拓扑无关,我们无须改变运行期的配置文件,就能将系统从现有的物理机环境无缝迁移到公有云上
- k8s 内在的服务弹性扩容机制可以让我们轻松应对突发流量
Kubernetes 概念
以下简要介绍 k8s 中重要的资源对象。
Master
Master 是集群控制节点,每个集群中都需要一个 Master 负责整个集群的管理和控制,基本上 k8s 的所有控制指令都发给它来执行。Master 很重要,通常会占据一个独立的服务器(HA: 3台),如果它宕机或不可用,对集群内容器应用的管理都将失效。
Master上的关键进程:
- Kubernetes API Server(kube-apiserver):提供了HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程。
- Kubernetes Controller Manager(kube-controller-manager):Kubernetes里所有资源对象的自动化控制中心,可以将其理解为资源对象的“大总管”。
- Kubernetes Scheduler(kube-scheduler):负责资源调度(Pod调度)的进程,相当于公交公司的“调度室”。
另外,Master 上通常还需要部署 etcd 服务,所有资源对象的数据都被保存在 etcd 中。
Node
Node 是 k8s 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载(Docker容器),当某个 Node 宕机时,其上的工作负载会被 Master 自动转移到其他节点上。
Node 上的关键进程:
- kubelet:负责 Pod 对应的容器的创建、启停等任务,同时与 Master 密切协作,实现集群管理的基本功能
- kube-proxy:实现 Kubernetes Service 的通信与负载均衡机制的重要组件
- Docker Engine(docker):Docker 引擎,负责本机的容器创建和管理工作
Node 可以在运行期间动态增加到 k8s 集群中:
- 默认情况下 kubelet 会向 Master 注册自己,这也是 k8s 推荐的Node管理方式
- 一旦 Node 被纳入集群管理范围,kubelet进程就会定时向 Master 汇报自身的情报,例如操作系统、Docker 版本、机器的 CPU 和内存情况,以及当前有哪些 Pod 在运行等,这样 Master 就可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略
- 某个 Node 在超过指定时间不上报信息时,会被Master判定为“失联”,Node 的状态被标记为不可用(Not Ready),随后Master会触发“工作负载大转移”的自动流程
kubectl get nodeskubectl desscribe node k8s-node-1
Pod
Pod 是 k8s 最重要的基本概念,每个 Pod 都有一个特殊的被称为“根容器”的 Pause 容器。Pause 容器对应的镜像属于 k8s 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器。
- 引入业务无关并且不易死亡的Pause容器作为Pod的根容器,以它的状态代表整个容器组的状态,对“整体”进行判断及有效地行动。
- Pod里的多个业务容器共享Pause容器的IP,共享Pause容器挂接的Volume,这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题
Kubernetes为每个Pod都分配了唯一的IP地址,称之为Pod IP,一个Pod里的多个容器共享Pod IP地址。Kubernetes要求底层网络支持集群内任意两个Pod之间的TCP/IP直接通信,这通常采用虚拟二层网络技术来实现,在Kubernetes里,一个Pod里的容器与另外主机上的Pod容器能够直接通信。
Label
Label(标签)是 k8s 系统中另外一个核心概念。一个 Label 是一个key=value的键值对,其中 key 与 value 由用户自己指定。Label 可以被附加到各种资源对象上,例如 Node、Pod、Service、RC 等,一个资源对象可以定义任意数量的Label,同一个 Label 也可以被添加到任意数量的资源对象上。Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。
可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。
Label Selector可以被类比为SQL语句中的where查询条件,例如,name=redis-slave这个Label Selector作用于Pod时,可以被类比为select * from pod where pod’s name =‘redis-slave’这样的语句。
Label Selector 在 k8s 中的场景:
- kube-controller 进程通过在资源对象RC上定义的Label Selector来筛选要监控的Pod副本数量,使Pod副本数量始终符合预期设定的全自动控制流程
- kube-proxy 进程通过 Service 的 Label Selector 来选择对应的 Pod,自动建立每个 Service 到对应 Pod 的请求转发路由表,从而实现Service 的智能负载均衡机制
- 通过对某些 Node 定义特定的Label,并且在 Pod 定义文件中使用 NodeSelector 这种标签调度策略,kube-scheduler 进程可以实现 Pod 定向调度的特性
Replication Controller
RC是 k8s 系统中的核心概念之一,它其实定义了一个期望的场景,即声明某种 Pod 的副本数量在任意时刻都符合某个预期值,所以 RC 的定义包括如下几个部分:
- Pod 期待的副本数量
- 用于筛选目标 Pod 的 Label Selector
- 当 Pod 的副本数量小于预期数量时,用于创建新 Pod 的 Pod 模板
Master 上的 Controller Manager 会定期巡检系统中当前存活的目标 Pod,并确保目标 Pod 实例的数量刚好等于此 RC 的期望值,如果有过多的 Pod 副本在运行,系统就会停掉一些 Pod,否则系统会再自动创建一些 Pod。可以说,通过 RC,k8s 实现了用户应用集群的高可用性,并且大大减少了系统管理员在传统IT环境中需要完成的许多手工运维工作(如主机监控脚本、应用监控脚本、故障恢复脚本等)。
k8s 1.2中,升级为另外一个新概念——Replica Set。Replica Set 与 RC当前的唯一区别是,Replica Sets 支持基于集合 的Label selector(Set-based selector),而 RC只 支持基于等式的 Label Selector(equality-based selector),这使得 Replica Set 的功能更强
Replica Set 很少单独使用,它主要被 Deployment 这个更高层的资源对象所使用,从而形成一整套Pod创建、删除、更新的编排机制。
RC (Replica Set) 特性与作用:
- 通过定义一个 RC 实现 Pod 的创建以及副本数量的自动控制
- 在 RC 里包括完整的 Pod 定义模板
- RC 通过 Label Selector 机制实现对 Pod 副本的自动控制
- 通过改变 RC 里的 Pod 副本数量,实现 Pod 的扩缩容
- 通过改变 RC 里的 Pod 模板中的镜像版本,实现 Pod 的滚动升级
Deployment
k8s 在1.2版本中引入的新概念,用于更好地解决Pod的编排问题。Deployment 在内部使用了 Replica Set 来实现目的,无论从 Deployment的作用与目的、YAML定义,还是从它的具体命令行操作来看,我们都可以把它看作 RC 的一次升级,两者的相似度超过 90%。
Deployment 相对于 RC 的一个最大升级是我们可以随时知道当前 Pod “部署”的进度。
Deployment 使用场景:
- 创建一个 Deployment 对象来生成对用的 Replica Set 并完成 Pod 副本的创建
- 检查 Deployment 的状态来看部署动作是否完成
- 更新 Deployment 来创建新的 Pod(比如镜像升级)
- 如果当前 Deployment 不稳定,可以回滚之前的版本
- 暂停 Deployment 来一次性修改多个 PodTemplate 的配置项,然后回复 Deployment 重新发布
- 扩展 Deployment 来 应对高负载
- 查看 Deployment 状态,是否发布成功
- 清理不再需要的 旧版本 Replica Set
Horizontal Pod Autoscaler
k8s 1.1中首次发布重量级新特性——Horizontal Pod Autoscaling(Pod横向自动扩容,HPA)。
HPA 与之前的 RC、Deployment 一样,也属于一种 k8s 资源对象。通过追踪分析指定 RC 控制的所有目标 Pod 的负载变化情况,来确定是否需要有针对性地调整目标 Pod 的副本数量,这是 HPA 的实现原理。当前,HPA有以下两种方式作为Pod负载的度量指标:
- CPUUtilizationPercentage
- 应用程序自定义的度量指标,比如服务在每秒内的相应请求数(TPS或QPS)
StatefulSet
在 k8s 系统中,Pod 的管理对象 RC、Deployment、DaemonSet 和 Job 都面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如 MySQL 集群、MongoDB 集群、ZooKeeper 集群等,这些应用集群有4个共同点:
- 每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并通信
- 集群的规模是比较固定的,集群规模不能随意变动
- 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中
- 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损
StatefulSet 从本质上来说,可以看作 Deployment/RC 的一个特殊变种,它有如下特性:
- StatefulSet 中的每个 Pod 都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。比如 StatefulSet 的名称为 kafka,那么第1个Pod 叫 kafka-0,第2个叫 kafka-1,以此类推
- StatefulSet 控制的 Pod 副本的启停顺序是受控的,操作第n个 Pod 时,前n-1个 Pod 已经是运行且准备好的状态
- StatefulSet 里的 Pod 采用稳定的持久化存储卷,通过 PV 或 PVC 实现,删除 Pod 时默认不会删除与 StatefulSet 相关的存储卷
Service
Service 服务也是 k8s 里的核心资源对象之一,k8s 里的每个 Service 其实就是我们经常提起的微服务架构中的一个微服务,之前讲解 Pod、RC 等资源对象其实都是为讲解 k8s Service 做铺垫。
k8s 的 Service 定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由 Pod 副本组成的集群实例,Service 与其后端 Pod 副本集群之间则是通过 Label Selector 来实现对接的。RC 的作用实际上就是保证 Service 的服务能力和服务质量符合预期。
运行在每个 Node上 的 kube-proxy 进程其实就是一个智能的软件负载均衡器,负责把对 Service 的请求转发到后端的某个 Pod 实例上,并在内部实现服务的负载均衡与会话保持机制。但 k8s 发明了一种很巧妙又影响深远的设计:Service 没有共用一个负载均衡器的IP地址,每个 Service 都被分配了一个全局唯一的虚拟 IP 地址,这个虚拟I P 被称为 Cluster IP。这样一来,每个服务就变成了具备唯一 IP 地址的通信节点,服务调用就变成了最基础的 TCP 网络通信问题。
Service 一旦被创建,k8s 就会自动为它分配一个可用的 Cluster IP,而且在 Service 的整个生命周期内,它的 Cluster IP 不会发生改变。于是,服务发现这个棘手的问题在 k8s 的架构里也得以轻松解决:只要用 Service 的 Name 与 Service 的 Cluster IP 地址做一个 DNS 域名映射即可完美解决问题。
# 创建 service
kubectl create -f tomcat-server.yaml
# 查询 endpoints
kubectl get endpoints
# 查询 service cluster ip
kubectl get svc tomcat-service -o yaml
服务发现机制
每个 k8s 中的 Service 都有唯一的 Cluster IP 及唯一的名称,而名称是由开发者自己定义的,部署时也没必要改变,所以完全可以被固定在配置中。
最早时 k8s 采用了 Linux 环境变量解决这个问题,即每个 Service 都生成一些对应的 Linux 环境变量(ENV),并在每个 Pod 的容器启动时自动注入这些环境变量。每个 Service 的 IP 地址及端口都有标准的命名规范,遵循这个命名规范,就可以通过代码访问系统环境变量来得到所需的信息,实现服务调用。
现在,k8s 上的大部分应用都已经采用了 DNS 这种新兴的服务发现机制。
k8s 中的3中 IP:
- Node IP:Node的IP地址
- Pod IP:Pod的IP地址
- Cluster IP:Service的IP地址
Node IP 是 k8s 集群中每个节点的物理网卡的 IP 地址,是一个真实存在的物理网络,所有属于这个网络的服务器都能通过这个网络直接通信,不管其中是否有部分节点不属于这个 k8s 集群。这也表明在 k8s 集群之外的节点访问 k8s 集群之内的某个节点或者 TCP/IP 服务时,都必须通过Node IP通信.
Pod IP是每个 Pod 的 IP 地址,它是 Docker Engine 根据 docker0 网桥的 IP 地址段进行分配的,通常是一个虚拟的二层网络,k8s 中要求位于不同 Node 上的 Pod 都能够彼此直接通信,所以 k8s 里一个 Pod 里的容器访问另外一个 Pod 里的容器时,就是通过 Pod IP 所在的虚拟二层网络进行通信的,而真实的 TCP/IP 流量是通过 Node IP 所在的物理网卡流出的。
Service的Cluster IP,它也是一种虚拟的IP,但更像一个“伪造”的IP网络:
- Cluster IP 仅仅作用于Kubernetes Service这个对象,并由 k8s 管理和分配IP地址(来源于Cluster IP地址池)
- Cluster IP 无法被 Ping,因为没有一个“实体网络对象”来响应
- Cluster IP 只能结合 Service Port 组成一个具体的通信端口,单独的 Cluster IP 不具备 TCP/IP 通信的基础,并且它们属于 k8s 集群这样一个封闭的空间,集群外的节点如果要访问这个通信端口,则需要做一些额外的工作
- 在 k8s 集群内,Node IP 网、Pod IP 网与 Cluster IP 网之间的通信,采用的是 k8s 自己设计的一种编程方式的特殊路由规则,与我们熟知的IP路由有很大的不同
Service 的Cluster IP 属于 k8s 集群内部的地址,无法在集群外部直接使用这个地址。 那用户怎么访问 Web 端服务呢?
采用 NodePort 是解决上述问题的最直接、有效的常见做法。如 http://:port/。NodePort 的实现方式是在 k8s 集群里的每个Node上都为需要外部访问的 Service 开启一个对应的 TCP 监听端口,外部系统只要用任意一个 Node 的 IP 地址+具体的 NodePort 端口号即可访问此服务。
但 NodePort 还没有完全解决外部访问 Service 的所有问题,比如负载均衡问题。假如在我们的集群中有10个 Node,则此时最好有一个负载均衡器,外部的请求只需访问此负载均衡器的 IP 地址,由负载均衡器负责转发流量到后面某个 Node 的 NodePort 上。
Load balancer 组件独立于 k8s 集群之外,通常是一个硬件的负载均衡器,或者是以软件方式实现的,例如 HAProxy 或者 Nginx。对于每个Service,我们通常需要配置一个对应的 Load balancer 实例来转发流量到后端的 Node 上,这的确增加了工作量及出错的概率。于是 k8s 提供了自动化的解决方案,只要把 Service 的 type=NodePort 改为 type=LoadBalancer,k8s 就会自动创建一个对应的 Load balancer 实例并返回它的 IP 地址供外部客户端使用。
Job
批处理任务通常并行(或者串行)启动多个计算进程去处理一批工作项(work item),在处理完成后,整个批处理任务结束。
k8s 1.2版本开始,支持批处理类型的应用,我们可以通过 k8s Job 这种新的资源对象定义并启动一个批处理任务 Job。与RC、Deployment、ReplicaSet、DaemonSet类似,Job 也控制一组Pod容器。
与 RC、Deployment、ReplicaSet、DaemonSet 类似,Job 也控制一组 Pod 容器。Job 也是一种特殊的 Pod 副本自动控制器,同时 Job 控制 Pod 副本与 RC 等控制器的工作机制有差别:
- Job 所控制的 Pod 副本是短暂运行的,可以将其视为一组 Docker 容器,其中的每个 Docker 容器都仅仅运行一次。当Job控制的所有Pod副本都运行结束时,对应的 Job 也就结束了。Job 在实现方式上与 RC 等副本控制器不同,Job 生成的 Pod 副本是不能自动重启的,对应Pod 副本的 RestartPoliy 都被设置为 Never
- k8s 在1.5版本之后又提供了类似 crontab 的定时任务——CronJob,解决了某些批处理任务需要定时反复执行的问题
- Job 所控制的 Pod 副本的工作模式能够多实例并行计算,以 TensorFlow 框架为例,可以将一个机器学习的计算任务分布到10台机器上,在每台机器上都运行一个 worker 执行计算任务,这很适合通过 Job 生成10个 Pod 副本同时启动运算
Volume
Volume(存储卷)是 Pod 中能够被多个容器访问的共享目录。k8s 的 Volume 概念、用途和目的与 Docker 的 Volume 比较类似,但两者不能等价。
- k8s 的 Volume 被定义在 Pod 上,被一个 Pod 里的多个容器挂载到具体 的文件目录下
- k8s 的 Volume 与 Pod 的生命周期相同,但与容器的生命周期不想关,当容器终止或重启时,Volume 的数据不会丢失
- 多种类型的 Volume:GlusterFS、Ceph等分布式文件系统
Persistent Volume
Volume 是被定义在 Pod 上的,属于计算资源的一部分,而实际上,网络存储是相对独立于计算资源而存在的一种实体资源。
在使用虚拟机的情况下,我们通常会先定义一个网络存储,然后从中划出一个“网盘”并挂接到虚拟机上。Persistent Volume(PV)和与之相关联的 Persistent Volume Claim(PVC)也起到了类似的作用。
PV 可以被理解成 k8s 集群中的某个网络存储对应的一块存储,它与 Volume 类似,但有以下区别:
- PV 只能是网络存储,不属于任何 Node,但可以在每个 Node 的访问
- PV 并不是被定义在 Pod 上,而是独立于 Pod 之外定义的
- PV 目前支持的类型有:gcePersistentDisk、AWSElasticBlockStore、AzureFile、AzureDisk、NFS、CephFS、Cinder、GlusterFS、HostPath(仅供单机测试)等等。
如果某个 Pod 想申请某种类型的 PV,则首先需要定义一个 PersistentVolumeClaim 对象,然后,在Pod的Volume定义中引用上述PVC即可。PV 是有状态的对象,它的状态有以下几种:
- Available:空闲状态
- Bound:已经绑定到某个PVC上
- Released:对应的PVC已经被删除,但资源还没有被集群收回
- Failed:PV自动回收失败。
Namespace
Namespace 是 k8s 一个非常重要的概念,它在很多情况下用于实现多租户的资源隔离。Namespace 通过将集群内部的资源对象“分配”到不同的 Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。
k8s 集群在启动后会创建一个名为 default 的 Namespace,通过 kubectl 可以查看:
kubectl get namespaces
如果不特别指明 Namespace,则用户创建的 Pod、RC、Service 都将被系统创建到这个默认的名为 default 的 Namespace 中。一旦创建了Namespace,我们在创建资源对象时就可以指定这个资源对象属于哪个 Namespace。
如果 Pod 加入了某个 Namespace,通过 kubectl get命令无法显示,这是因为如果不加参数,则 kubectl get 命令将仅显示属于 default 命名空间的资源对象。
可以在 kubectl 命令中加入–namespace参数来查看某个命名空间中的对象:
kubectl get pods --namespace=dev
当给每个租户创建一个 Namespace 来实现多租户的资源隔离时,还能结合 k8s 的资源配额管理,限定不同租户能占用的资源,例如CPU 使用量、内存使用量等。
Configmap
先从Docker说起。我们知道,Docker通过将程序、依赖库、数据及配置文件“打包固化”到一个不变的镜像文件中的做法,解决了应用的部署的难题,但这同时带来了棘手的问题,即配置文件中的参数在运行期如何修改的问题?。
我们不可能在启动 Docker 容器后再修改容器里的配置文件,然后用新的配置文件重启容器里的用户主进程。为了解决这个问题,Docker 提供了两种方式:
- 在运行时通过容器的环境变量来传递参数;
- 通过Docker Volume将容器外的配置文件映射到容器内。
这两种方式都有其优势和缺点,在大多数情况下,后一种方式更合适我们的系统,因为大多数应用通常从一个或多个配置文件中读取参数。但这种方式也有明显的缺陷:我们必须在目标主机上先创建好对应的配置文件,然后才能映射到容器里。
上述缺陷在分布式情况下变得更为严重,因为无论采用哪种方式,写入(修改)多台服务器上的某个指定文件,并确保这些文件保持一致,都是一个很难完成的目标。此外,在大多数情况下,我们都希望能集中管理系统的配置参数,而不是管理一堆配置文件。针对上述问题,k8s 给出了实现:
- 首先,把所有的配置项都当作key-value字符串,当然 value 可以来自某个文本文件,比如配置项 password=123456、user=root、host=192.168.8.4 用于表示连接 FTP 服务器的配置参数。这些配置项可以作为 Map 表中的一个项,整个 Map 的数据可以被持久化存储在k8s 的 Etcd 数据库中,然后提供 API 以方便 k8s 相关组件或客户应用 CRUD 操作这些数据,上述专门用来保存配置参数的 Map 就是k8s ConfigMap资源对象。
- 接下来,k8s 提供了一种内建机制,将存储在 etcd 中的 ConfigMap 通过 Volume 映射的方式变成目标 Pod 内的配置文件,不管目标 Pod被调度到哪台服务器上,都会完成自动映射。进一步地,如果 ConfigMap 中的 key-value 数据被修改,则映射到 Pod 中的“配置文件”也会随之自动更新。所以,k8s ConfigMap 就成了分布式系统中最为简单(使用方法简单,但背后实现比较复杂)且对应用无侵入的配置中心。