Kubernetes (K8s) 选择 etcd 作为其默认的分布式键值存储(Key-Value Store)核心组件,主要基于以下关键设计特性和实际需求:
1. 强一致性与高可靠性
- Raft 共识算法:etcd 使用 Raft 实现强一致性(CP 系统),确保集群中所有节点的数据一致,这对 K8s 的 控制平面(如调度、配置、状态管理)至关重要。
- 数据持久化:etcd 支持持久化存储,即使节点重启也能恢复数据,保障 K8s 集群状态的可靠性。
2. 高性能与低延迟
- 读写优化:etcd 针对读多写少的场景(如 K8s 频繁查询 Pod 状态)优化,支持每秒数万次读写操作。
- 低延迟响应:通过 Raft 的 Leader 节点处理写请求,减少分布式协商开销,满足 K8s 对实时性的要求(如快速响应
kubectl
命令)。
3. Watch 机制(事件监听)
- 核心功能:etcd 提供高效的
Watch
API,K8s 利用它监听资源变更(如 Pod 创建/删除),触发控制器(Controller)的协调逻辑(Reconcile)。 - 事件驱动架构:这是 K8s 实现声明式 API 和自动化运维的基础。
4. 简单清晰的 API 设计
- 键值存储模型:etcd 的简单 KV 接口(如
Put
/Get
/Delete
)与 K8s 的资源存储需求高度匹配。 - 事务支持:支持原子事务操作,适合 K8s 需要同时更新多个资源的场景(如 Deployment 和 ReplicaSet 联动)。
5. 社区与生态集成
- CNCF 项目:etcd 和 K8s 同属 CNCF 项目,协同开发和维护,确保兼容性。
- 广泛验证:etcd 在大型生产环境中久经考验(如 Google、AWS 等),稳定性有保障。
6. 安全性
- TLS 加密:支持客户端与集群间的加密通信,符合 K8s 对安全通信的要求。
- RBAC 集成:与 K8s 的 RBAC 系统无缝对接,精细化控制访问权限。
对比其他数据库为何不选?
- ZooKeeper:虽然类似,但 ZooKeeper 的 ZAB 协议和复杂 API 不如 etcd 轻量。
- Consul:更侧重服务发现,KV 存储性能不如 etcd 专注。
- MySQL/PostgreSQL:关系型数据库的强一致性代价高,且缺乏原生 Watch 机制。
潜在挑战
- 运维复杂度:etcd 需要单独维护(备份、扩缩容等),高可用部署需谨慎。
- 存储限制:默认适合存储元数据,不适合大规模非结构化数据(需配合其他存储方案)。
总结
etcd 凭借 强一致性、高性能、事件监听 等特性,成为 K8s 存储集群状态的理想选择,两者共同构建了云原生基础设施的基石。
Kubernetes 调度器
在 Kubernetes 中,调度是指将 Pod 放置到合适的节点上,以便对应节点上的 Kubelet 能够运行这些 Pod。
调度概览
调度器通过 Kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod。 调度器会将所发现的每一个未调度的 Pod 调度到一个合适的节点上来运行。 调度器会依据下文的调度原则来做出调度选择。
简介
Calico是一个基于BGP的纯三层的网络方案,与OpenStack,Kubernetes,AWS,GCE等云平台都能够良好地集成.
Calico在每个计算节点利用Linux kernel实现了一个高效的vrouter来负责转发.每个vrouter通过BGP1协议把在本节点上运行的容器的路由信息向整个calico网络广播,并自动设置到达其它节点的路由转发规则.
CustomResourceDefinition简介
在 Kubernetes 中一切都可视为资源,Kubernetes 1.7 之后增加了对 CRD 自定义资源二次开发能力来扩展 Kubernetes API,通过 CRD 我们可以向 Kubernetes API 中增加新资源类型,而不需要修改 Kubernetes 源码来创建自定义的 API server,该功能大大提高了 Kubernetes 的扩展能力。 当你创建一个新的CustomResourceDefinition (CRD)时,Kubernetes API服务器将为你指定的每个版本创建一个新的RESTful资源路径,我们可以根据该api路径来创建一些我们自己定义的类型资源。CRD可以是命名空间的,也可以是集群范围的,由CRD的作用域(scpoe)字段中所指定的,与现有的内置对象一样,删除名称空间将删除该名称空间中的所有自定义对象。customresourcedefinition本身没有名称空间,所有名称空间都可以使用。
kubectl explain pod.spec.volumes
去查看该对象下面的属性非常多,前面我们只是简单的使用了hostpath和empryDir{}这两种模式,其中还有一种叫做downwardAPI这个模式和其他模式不一样的地方在于它不是为了存放容器的数据也不是用来进行容器和宿主机的数据交换的,而是让pod里的容器能够直接获取到这个pod对象本身的一些信息。了解pause
Kubernetes 中所谓的 pause 容器有时候也称为 infra 容器,它与用户容器”捆绑“运行在同一个 Pod 中,最大的作用是维护 Pod 网络协议栈(当然,也包括其他工作,下文会介绍)。
都说 Pod 是 Kubernetes 设计的精髓,而 pause 容器则是 Pod 网络模型的精髓,理解 pause 容器能够更好地帮助我们理解 Kubernetes Pod 的设计初衷。为什么这么说呢?还得从 Pod 沙箱(Pod Sandbox)说起。
|
|
|
|
使用场景 当我们需要进行服务端认证,甚至双向认证时,我们需要生成密钥对和服务信息,并使用ca对公钥和服务信息进行批准签发,生成一个证书。
我们简单描述下单向认证和双向认证的场景流程
基础原则
- 每个Pod都拥有一个独立的IP地址,而且假定所有Pod都在一个可以直接连通的、扁平的网络空间中,不管是否运行在同一Node上都可以通过Pod的IP来访问。
- 对于支持主机网络的平台,其Pod若采用主机网络方式,则Pod仍然可以不通过NAT的方式访问其余的Pod
- k8s中Pod的IP是最小粒度IP。同一个Pod内所有的容器共享一个网络堆栈,该模型称为IP-per-Pod模型。
- Pod由docker0实际分配的IP,Pod内部看到的IP地址和端口与外部保持一致。同一个Pod内的不同容器共享网络,可以通过localhost来访问对方的端口,类似同一个VM内的不同进程。
- IP-per-Pod模型从端口分配、域名解析、服务发现、负载均衡、应用配置等角度看,Pod可以看作是一台独立的VM或物理机。
Kubernetes网络地址4大关注点
- Pod内的容器可以通过loopback口通信
- 集群网络为Pods间的通信提供条件
- Service API暴露集群中的Pod的应用给外部,以便外部使用
- 也可只使用Services在集群内部使用
从外面看Pod IP地址之Kubernetes API
kubectl get pod
或者kubectl describe pod
就可以- 如果运行在容器内的进程希望获取该容器的IP,可以通过环境变量的方式来获取IP
|
|
从外面看Pod IP之docker命令
假设容器的ID是6e8147cd2f3d, 一般情况下可以通过以下命令查询容器的IP地址:
k8s网络模型设计的一个基础原则是:每个Pod都拥有一个独立的IP地址,而且假定所有Pod都在一个可以直接连通的、扁平的网络空间中。
所以不管他们是否运行在同一个Node(宿主机中),都要求他们可以直接通过对方的IP进行访问。 设计这个原则的原因是,用户不需要额外考虑如何建立Pod之间的连接,也不需要考虑将容器端口映射到主机端口等问题。
ConfigMap
使用ConfigMap 的限制条件如下。
-
ConfigMap 必须在Pod 之前创建。
-
ConfigMap 受Namespace 限制,只有处于相同Namespaces 中的Pod 可以引用它。
-
ConfigMap 中的配额管理还未能实现。
Pod 生命周期
Pod 在整个生命周期过程中被系统定义为各种状态 Pod 的状态如表2.14 所示。 表2.14 Pod 的状态
状态值 | 描述 |
---|---|
Pending | API Server已经创建该Pod,但Pod内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程 |
Running | Pod 内所有容器均己创建,且至少有一个容器处于运行状态、正在启动状态或正在重启状态 |
Succeeded | Pod 内所有容器均成功执行退出, 且不会再重启 |
Failed | Pod 内所有容器均已退出,但至少有一个容器退出为失败状态 |
Unknown | 由于某种原因无法获取该Pod 的状态, 可能由于网络通信不畅导致 |
Pod重启策略
Pod 的重启策略( RestartPolicy )应用于Pod 内的所有容器,井且仅在Pod 所处的Node上由kubelet 进行判断和重启操作。当某个容器异常退出或者健康检查(详见下节)失败时, kubelet将根据RestartPolicy 的设置来进行相应的操作。 Pod 的重启策略包括Always、OnFailure和Never, 默认值为Always:
Service
|
|
K8s Pod创建流程-从kubelet到cni插件
参考大牛博客 https://blog.csdn.net/qq_40378034/article/details/135181476
Kubernetes集群核心组件全解析:从控制平面到应用生态
Kubernetes作为容器编排领域的核心平台,其架构由多个解耦的组件协同工作。本文将深度剖析集群的三大层级组件,并扩展关键生态工具,帮助读者构建全面的知识体系。
K8s通信问题
- 容器间通信:即同一个Pod内多个容器间通信,通常使用loopback来实现。
- Pod间通信:K8s要求,Pod和Pod之间通信必须使用Pod-IP 直接访问另一个Pod-IP
- Pod与Service通信:即PodIP去访问ClusterIP,当然,clusterIP实际上是IPVS或iptables规则的虚拟IP,是没有TCP/IP协议栈支持的。但不影响Pod访问它.
- Service与集群外部Client的通信,即K8s中Pod提供的服务必须能被互联网上的用户所访问到。
需要注意的是,k8s集群初始化时的service网段,pod网段,网络插件的网段,以及真实服务器的网段,都不能相同,如果相同就会出各种各样奇怪的问题,而且这些问题在集群做好之后是不方便改的,改会导致更多的问题,所以,就在搭建前将其规划好。
参考文章:https://zhuanlan.zhihu.com/p/102897620
CRI是什么
CRI: Container Runtime Interface,容器运行时接口;
CRI包括Protocol Buffers、gRPC API、运行库支持及开发中的标准规范和工具,是以容器为中心设计的API,设计CRI的初衷是不希望向容器(比如docker)暴露pod信息或pod的api。
Service
在k8s中,Service(服务)是分布式集群架构的核心,一个Service对象拥有如下关键特征:
- 拥有一个唯一指定的名字(比如mysql-server)
- 拥有一个虚拟IP(Cluster IP、service IP或VIP)和端口号。
- 能够提供某种远程服务能力。
- 被映射到了提供这种服务能力的一组容器应用上。
为了建立Service和Pod之间的关联关系,k8s给每个Pod贴上标签(Label),如运行MySQL的Pod贴上name=mysql标签。然后给相应的Service定义标签选择器(Label Selector)