(想趁着孕期🤰系统地回顾一下之前的项目和技术,今天迈出了第二步~~~,💪💪💪🩷🩷🩷) Kubernetes 是一个开源的容器编排平台,旨在自动化应用程序的部署、扩展和管理。Kubernetes 名字来源于希腊语,意为“舵手”或“飞行员”,缩写为“K8s”。
一、Kubernetes 的核心的功能:
1. 服务的发现与负载均衡
服务发现
服务发现(Service Discovery)是指在动态环境中找到运行服务的实例,并以一种可访问的方式提供该服务的过程。在 Kubernetes 中,服务发现机制确保用户和应用可以找到所需的服务,并使用简单和固定的访问点。
Kubernetes 中的服务发现
Kubernetes 提供了两种主要的服务发现方式:
- 环境变量:当 Pod 被分配到某个节点上时,Kubernetes 会在该 Pod 的环境中插入一些关于集群中其他服务的环境变量,这样一来,Pod 可以通过这些环境变量找到其他服务。
- DNS 名称解析:Kubernetes 内部的 DNS 服务会将服务名称解析为服务的 IP 地址,这是一种更灵活和常用的方式。每个服务都会在集群的 DNS 系统中得到一个域名,例如
my-service.my-namespace.svc.cluster.local。
负载均衡
负载均衡(Load Balancing)是指在多个服务实例之间分配请求流量,以确保每个实例都得到均衡的负载,并避免某个实例因为负载过重而发生故障。
Kubernetes 中的负载均衡
Kubernetes 提供了内置的负载均衡机制来管理服务间的流量分配:
- Service 对象:在 Kubernetes 中,“服务”(Service)是指一种抽象,它定义了一组逻辑上的 Pod 及其访问策略。通常,一个服务会封装一组提供相同功能的 Pod。这些 Pod 可以动态创建和销毁,因此直接与 Pod 进行交互是不稳定的。为了稳定并且可靠地访问这些 Pod,Kubernetes 使用服务来管理 Pod 集合的访问和负载均衡。每个
Service对象会创建一个唯一的 IP 和 DNS 名称,用于访问一组 Pod。Kubernetes 内部会自动将这些请求按一定策略分配给后端的 Pod。 - ClusterIP:默认的
Service类型,提供集群内部的负载均衡。ClusterIP 提供了一个可以在 Kubernetes 集群内部访问的虚拟 IP 地址,通过这个 IP 地址可以访问服务关联的一组 Pod。 - NodePort:Kubernetes 服务的一种类型,它允许外部流量通过集群节点上的特定端口访问集群内部的服务。NodePort 会在每个节点上打开一个指定的端口(范围是 30000-32767),并将该端口上的流量转发到集群内部的服务上。
- LoadBalancer:它会自动为服务创建一个外部负载均衡器(通常依赖于云提供商),这样外部客户端可以通过云提供商分配的公共 IP 地址访问集群内部的服务。LoadBalancer 类型的服务建立在 ClusterIP 和 NodePort 之上,并提供了一个更高级别的负载均衡功能。
- Ingress:是 Kubernetes 中的一种资源对象,用于管理外部访问到集群内服务的 HTTP 和 HTTPS 路由。与 LoadBalancer 不同,Ingress 提供了更灵活和全面的路由、负载均衡和 SSL 终止功能。用于管理流量分发、路径重写、基于主机名或路径的路由等,通常需要配合一个 Ingress Controller 使用。
2.调度
Kubernetes 调度器(kube-scheduler)负责将新创建的 Pod 分配到合适的节点上。它通过评估资源需求和节点状况,确保各 Pod 在最佳节点上运行。比如说它所需要的 CPU以及它所需要的 memory,然后在集群中找一台相对比较空闲的机器来进行一次 placement,也就是一次放置的操作。在这个例子中,它可能会把红颜色的这个容器放置到第二个空闲的机器上,来完成一次调度的工作。
调度流程
- 过滤阶段:排除不满足条件的节点(如资源不足、标签不匹配等)。
- 打分阶段:为剩余的节点评分并选择得分最高的节点。
3.自动修复
Kubernetes 提供自动修复功能,通过持续监测集群中所有节点和 Pod 的健康状态,确保系统的高可用性和自愈能力。
主要功能
-
节点健康检查:
- Kubernetes 会监测集群中所有节点的健康状态。
- 当节点出现故障(如硬件故障、网络问题或节点崩溃)或无法正常工作时,会自动检测到。
-
Pod 健康检查:
- 通过 Liveness Probes 和 Readiness Probes 检测 Pod 的健康状态和准备状态。
- 如果 Pod 不健康(如进程挂掉、无法响应健康检查请求),Kubernetes 会自动重启这些 Pod。
自动修复过程
-
节点故障处理:
- 当检测到节点不可用时,Kubernetes 会将该节点标记为未调度。
- Kubernetes 会自动将运行在该节点上的 Pod 迁移到其他健康的节点上。
-
Pod 故障处理:
- 如果某个 Pod 健康检查失败,Kubernetes 会重新启动或重新调度该 Pod。
-
控制器检查:
- 部署(Deployment)、副本集(ReplicaSet)、状态集合(StatefulSet)等控制器会持续监控其管理的 Pod 数量和状态,并确保实际运行的 Pod 实例数与期望值一致。
4.水平伸缩
Kubernetes(k8s)的水平伸缩(Horizontal Pod Autoscaling, HPA)是一种自动化扩展方案,基于资源使用水平(如 CPU 使用率、内存使用率等)自动调节 Pod 的副本数量。HPA 能够帮助应用在负载增加时自动扩展副本数量,在负载减小时减少副本数量,从而提高应用的可伸缩性和资源利用效率。
二、K8S 的架构
Kubernetes 架构是一个比较典型的二层架构和 server-client 架构。Master 作为中央的管控节点,会去与 Node 进行一个连接。 所有 UI 的、clients、这些 user 侧的组件,只会和 Master 进行连接,把希望的状态或者想执行的命令下发给 Master,Master 会把这些命令或者状态下发给相应的节点,进行最终的执行。
Kubernetes 的 Master 包含四个主要的组件:API Server、Controller、Scheduler 以及 etcd。如下图所示:
-
API Server: 顾名思义是用来处理 API 操作的,Kubernetes 中所有的组件都会和 API Server 进行连接,组件与组件之间一般不进行独立的连接,都依赖于 API Server 进行消息的传送;
-
Controller: 是控制器,它用来完成对集群状态的一些管理。比如刚刚提到的两个例子之中,第一个自动对容器进行修复、第二个自动进行水平扩张,都是由 Kubernetes 中的 Controller 来进行完成的;
-
Scheduler: 是调度器,“调度器”顾名思义就是完成调度的操作,就是我们刚才介绍的第一个例子中,把一个用户提交的 Container,依据它对 CPU、对 memory 请求大小,找一台合适的节点,进行放置;
-
etcd: 是一个分布式的一个存储系统,API Server 中所需要的这些原信息都被放置在 etcd 中,etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。
Node
在 Kubernetes 中,Node 是实际运行业务负载的地方。业务负载以 Pod 的形式存在,而每个 Pod 内可能运行一个或多个容器。负责实际运行这些 Pod 的关键组件叫做 kubelet。
kubelet 从 API Server 获取需要运行的 Pod 的状态信息,然后将这些 Pod 提交给位于 Node 上的容器运行时(Container Runtime)进行实际执行。这个流程确保业务负载能够在各个 Node 上正常运行。
优化后的说明更清晰地解释了 Node、Pod、kubelet 以及容器运行时之间的关系,使内容更容易理解。
用户可以通过 UI 或者 CLI 提交一个 Pod 给 Kubernetes 进行部署,这个 Pod 请求首先会通过 CLI 或者 UI 提交给 Kubernetes API Server,下一步 API Server 会把这个信息写入到它的存储系统 etcd,之后 Scheduler 会通过 API Server 的 watch 或者叫做 notification 机制得到这个信息:有一个 Pod 需要被调度。
这个时候 Scheduler 会根据它的内存状态进行一次调度决策,在完成这次调度之后,它会向 API Server report 说:“OK!这个 Pod 需要被调度到某一个节点上。”
这个时候 API Server 接收到这次操作之后,会把这次的结果再次写到 etcd 中,然后 API Server 会通知相应的节点进行这次 Pod 真正的执行启动。相应节点的 kubelet 会得到这个通知,kubelet 就会去调 Container runtime 来真正去启动配置这个容器和这个容器的运行环境,去调度 Storage Plugin 来去配置存储,network Plugin 去配置网络。
三、Kubernetes 的核心概念与它的 API
核心概念
1.Pod
Pod 是 Kubernetes 中的最小可调度单位和资源管理单位。Pod 表示一个或多个需要一起调度的容器组,这些容器共享相同的网络命名空间、存储卷和其他相关资源。可以将 Pod 看作一个逻辑上的“主机”,所有在 Pod 中的容器都是在这一逻辑主机上运行。
组成部分
- 一个或多个容器:Pod 内的容器通常是紧密耦合的,并共享同一个生命周期。容器通过 Pod 内的 localhost 进行通信。
- 存储资源:Pod 能够通过挂载 Volume(存储卷)来共享存储资源。这些 Volume 可用于持久化数据或在 Pod 中的容器之间共享数据。
- 网络资源:每个 Pod 在创建时会自动被分配一个唯一的 IP 地址,这个 IP 由 Kubernetes 支配。从外部看时,Pod 中的所有容器共享同一个网络命名空间。
- 配置信息:Pod 可以包含一些配置信息(例如环境变量、命令行参数等)用于启动和管理容器。
Pod 的生命周期
Pod 的生命周期分为不同的状态,主要有:
- Pending:Pod 已经被系统接受,但尚未被分配到具体节点运行。
- Running:Pod 已被调度到某个节点并且至少其中一个容器已经启动。
- Succeeded:Pod 中所有容器都已成功终止,并且不会再重启。
- Failed:Pod 中的所有容器都已经终止,并且至少有一个容器因严重错误终止。
- Unknown:由于某些原因,控制器无法获取 Pod 的状态信息。
Pod 的类型
- 单容器 Pod:最常见的 Pod 类型,包含一个应用容器。
- 多容器 Pod:包含多个容器,这些容器共享同一个 Pod 的资源,例如网络和存储卷。通常用于紧密协作的应用组件。
使用场景
- 单个进程的运行:例如运行一个 Web 服务器或数据库实例。
- 任务调度:例如运行批处理任务、工作队列等。
- 容器协作:例如包含主应用和边车容器(sidecar)的 Pod。边车容器可以提供监控、日志聚合等功能。
2. Volume
Volume(卷)在 Kubernetes 中是用于持久化和共享数据的一种方式,它是与 Pod 关联的存储单位。不同于容器生命周期有限,Volume 的数据在容器重启或删除时不会丢失,因此可以确保数据的持久性和可靠性。
Volume 的特点
- 数据持久性:容器中数据在容器重启或崩溃时会丢失,而 Volume 提供了一种在容器生命周期之外保存数据的方式。
- 数据共享:多个容器可以挂载同一个 Volume 实现数据共享。
- 存储抽象:Kubernetes Volume 抽象了底层存储实现,用户无需关心底层存储的具体细节。
4.Deployment
Deployment 是 Kubernetes 中的一种控制器,它为 Pod 和 ReplicaSet 提供了声明式更新。Deployment 使用户可以轻松地管理应用的部署和扩展,并能够快速进行滚动更新和回滚操作。
Deployment 的功能
- 声明式更新:用户可以定义所需的应用状态,Deployment 控制器会自动将集群中的实际状态更新到所需状态。
- 滚动更新:Deployment 支持滚动更新机制,在更新过程中不会中断应用服务。
- 版本回滚:如遇到问题,Deployment 可以方便地回滚到之前稳定的版本。
- 扩展和缩减:用户可以根据需要扩展或缩减 Pod 数量,方便地应对流量变化。
- 自愈能力:系统会自动检测和替换失效的 Pod,确保应用运行正常。
3.Service
Service 是 Kubernetes 中用于定义一组 Pod 的访问策略的资源。它提供了一种抽象的方法来访问一组动态变化的 Pod。通过 Service,用户可以实现负载均衡和服务发现等功能。
比如,在 Kubernetes 中,一个 Deployment 可能包含两个或更多的相同 Pod。外部用户希望通过负载均衡均匀分配流量,并且只需访问一个固定的虚拟 IP 地址(VIP),而不需要知道每个具体 Pod 的 IP 地址。
然而,Pod 是动态的,可能会终止并被替换为新的 Pod。如果直接提供多个具体的 Pod 地址,外部用户需要频繁更新这些地址,非常繁琐。
为了简化这一过程,Kubernetes 提供了名为 Service 的抽象。Service 为一组 Pod 提供一个固定的虚拟 IP 地址,实现自动负载均衡和服务发现,使外部用户无需关心 Pod 的地址变化。
Service 的类型
Kubernetes 提供了多种类型的 Service 来适应不同的使用场景:
-
ClusterIP:默认类型,创建一个仅在集群内部可访问的虚拟IP。
-
NodePort:暴露端口号,使集群外部可以通过 : 访问 Service。
-
LoadBalancer:使用云服务提供商的负载均衡器,将流量分发到后端的 Pod。
-
ExternalName:将 Service 映射到 DNS 名称,起到服务代理的作用。
5.Namespace
在 Kubernetes 中,Namespace 是一种逻辑分区机制,主要用于在同一个 Kubernetes 集群中隔离资源和对象。Namespace 提供了一种划分集群资源的方式,使得不同的组、项目或用户可以在同一个集群中独立工作,而不互相干扰。Kubernetes 的每个资源,比如 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源需要命名的唯一性,不同的 Namespace 中的资源可以重名。
Kubernetes API
Kubernetes API 是 Kubernetes 的核心组件,用户通过 HTTP 协议访问 API,使用 JSON 格式进行数据交换。无论是通过命令行工具 kubectl、Kubernetes UI(例如 Dashboard),还是使用 curl 进行直接调用,都是基于 HTTP + JSON 的方式与 Kubernetes 进行通信。
资源访问路径示例
以 Pod 资源为例,HTTP 访问路径通常如下:
- API Server URL:
http://<kubernetes-api-server> - API Version:
v1 - Namespace:
default - Resource Type:
pods - Resource Name:
mypod
完整路径为:
http://<kubernetes-api-server>/api/v1/namespaces/default/pods/mypod
使用示例
例如,使用 curl 命令行工具获取一个 Pod 的信息:
curl -X GET http://<kubernetes-api-server>/api/v1/namespaces/default/pods/mypod
或使用 kubectl 工具:
kubectl get pod mypod -n default -o json
配置示例
操作 Kubernetes 资源时,通常使用 YAML 或 JSON 格式的文件进行定义。例如,下面是一个描述 Pod 的 YAML 文件:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: myapp
environment: production
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
- apiVersion:指定使用的 API 版本,例如
v1。 - kind:资源类型,例如
Pod。 - metadata:资源的元数据,包括
name和labels等信息。- name:资源的名称,例如
nginx。 - labels:一组键值对标签,用于标识和选择资源。
- name:资源的名称,例如
- spec:定义资源的期望状态。
- containers:容器的详细定义,如名称、镜像、端口等。
- status:描述资源的当前状态(通常由 Kubernetes 系统自动生成和管理)。
Label
Label 是 Kubernetes 中非常重要的概念,用来识别和组织资源。Label 是一组 Key-Value 对,可以用于对资源进行分类和过滤。示例:
metadata:
labels:
color: red
size: big
Label Selector
Label Selector 用于选择一组带有指定 Label 的资源。类似于 SQL 的 SELECT 查询语句,通过匹配标签来筛选资源。例如,选择标签 color=red 的 Pod:
kubectl get pods --selector=color=red
假设有以下三个 Pod 资源:
- Pod A:
labels: {color: red, size: big} - Pod B:
labels: {color: red, size: small} - Pod C:
labels: {color: yellow, size: big}
使用 selector=color=red 将只选择 Pod A 和 Pod B,因为它们的 color 标签是 red,而 Pod C 的 color 是 yellow,不会被选择。