云原生技术系列 ---- Kubernetes 核心概念

182 阅读15分钟

(想趁着孕期🤰系统地回顾一下之前的项目和技术,今天迈出了第二步~~~,💪💪💪🩷🩷🩷) Kubernetes 是一个开源的容器编排平台,旨在自动化应用程序的部署、扩展和管理。Kubernetes 名字来源于希腊语,意为“舵手”或“飞行员”,缩写为“K8s”。

一、Kubernetes 的核心的功能:

1. 服务的发现与负载均衡

服务发现

服务发现(Service Discovery)是指在动态环境中找到运行服务的实例,并以一种可访问的方式提供该服务的过程。在 Kubernetes 中,服务发现机制确保用户和应用可以找到所需的服务,并使用简单和固定的访问点。

Kubernetes 中的服务发现

Kubernetes 提供了两种主要的服务发现方式:

  1. 环境变量:当 Pod 被分配到某个节点上时,Kubernetes 会在该 Pod 的环境中插入一些关于集群中其他服务的环境变量,这样一来,Pod 可以通过这些环境变量找到其他服务。
  2. DNS 名称解析:Kubernetes 内部的 DNS 服务会将服务名称解析为服务的 IP 地址,这是一种更灵活和常用的方式。每个服务都会在集群的 DNS 系统中得到一个域名,例如 my-service.my-namespace.svc.cluster.local

负载均衡

负载均衡(Load Balancing)是指在多个服务实例之间分配请求流量,以确保每个实例都得到均衡的负载,并避免某个实例因为负载过重而发生故障。

Kubernetes 中的负载均衡

Kubernetes 提供了内置的负载均衡机制来管理服务间的流量分配:

  1. Service 对象:在 Kubernetes 中,“服务”(Service)是指一种抽象,它定义了一组逻辑上的 Pod 及其访问策略。通常,一个服务会封装一组提供相同功能的 Pod。这些 Pod 可以动态创建和销毁,因此直接与 Pod 进行交互是不稳定的。为了稳定并且可靠地访问这些 Pod,Kubernetes 使用服务来管理 Pod 集合的访问和负载均衡。每个 Service 对象会创建一个唯一的 IP 和 DNS 名称,用于访问一组 Pod。Kubernetes 内部会自动将这些请求按一定策略分配给后端的 Pod。
  2. ClusterIP:默认的 Service 类型,提供集群内部的负载均衡。ClusterIP 提供了一个可以在 Kubernetes 集群内部访问的虚拟 IP 地址,通过这个 IP 地址可以访问服务关联的一组 Pod。
  3. NodePort:Kubernetes 服务的一种类型,它允许外部流量通过集群节点上的特定端口访问集群内部的服务。NodePort 会在每个节点上打开一个指定的端口(范围是 30000-32767),并将该端口上的流量转发到集群内部的服务上。
  4. LoadBalancer:它会自动为服务创建一个外部负载均衡器(通常依赖于云提供商),这样外部客户端可以通过云提供商分配的公共 IP 地址访问集群内部的服务。LoadBalancer 类型的服务建立在 ClusterIP 和 NodePort 之上,并提供了一个更高级别的负载均衡功能。
  5. Ingress:是 Kubernetes 中的一种资源对象,用于管理外部访问到集群内服务的 HTTP 和 HTTPS 路由。与 LoadBalancer 不同,Ingress 提供了更灵活和全面的路由、负载均衡和 SSL 终止功能。用于管理流量分发、路径重写、基于主机名或路径的路由等,通常需要配合一个 Ingress Controller 使用。

2.调度

Kubernetes 调度器(kube-scheduler)负责将新创建的 Pod 分配到合适的节点上。它通过评估资源需求和节点状况,确保各 Pod 在最佳节点上运行。比如说它所需要的 CPU以及它所需要的 memory,然后在集群中找一台相对比较空闲的机器来进行一次 placement,也就是一次放置的操作。在这个例子中,它可能会把红颜色的这个容器放置到第二个空闲的机器上,来完成一次调度的工作。

Clipboard_Screenshot_1739870636.png

调度流程

  1. 过滤阶段:排除不满足条件的节点(如资源不足、标签不匹配等)。
  2. 打分阶段:为剩余的节点评分并选择得分最高的节点。

3.自动修复

Kubernetes 提供自动修复功能,通过持续监测集群中所有节点和 Pod 的健康状态,确保系统的高可用性和自愈能力。

主要功能

  1. 节点健康检查

    • Kubernetes 会监测集群中所有节点的健康状态。
    • 当节点出现故障(如硬件故障、网络问题或节点崩溃)或无法正常工作时,会自动检测到。
  2. Pod 健康检查

    • 通过 Liveness ProbesReadiness Probes 检测 Pod 的健康状态和准备状态。
    • 如果 Pod 不健康(如进程挂掉、无法响应健康检查请求),Kubernetes 会自动重启这些 Pod。

自动修复过程

  1. 节点故障处理

    • 当检测到节点不可用时,Kubernetes 会将该节点标记为未调度。
    • Kubernetes 会自动将运行在该节点上的 Pod 迁移到其他健康的节点上。
  2. Pod 故障处理

    • 如果某个 Pod 健康检查失败,Kubernetes 会重新启动或重新调度该 Pod。
  3. 控制器检查

    • 部署(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 会把这些命令或者状态下发给相应的节点,进行最终的执行。

企业微信截图_91fd5f83-def6-4bc6-b8c8-9ed2b43f004f.png

Kubernetes 的 Master 包含四个主要的组件:API Server、Controller、Scheduler 以及 etcd。如下图所示:

Clipboard_Screenshot_1739932669.png

  • 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 以及容器运行时之间的关系,使内容更容易理解。

企业微信截图_de957ba6-b60b-4093-b8b1-101b7c71d7fa.png

企业微信截图_ee18d77e-4ab8-4e4e-b8e1-b8693622d69b.png

用户可以通过 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 中的容器都是在这一逻辑主机上运行。

组成部分
  1. 一个或多个容器:Pod 内的容器通常是紧密耦合的,并共享同一个生命周期。容器通过 Pod 内的 localhost 进行通信。
  2. 存储资源:Pod 能够通过挂载 Volume(存储卷)来共享存储资源。这些 Volume 可用于持久化数据或在 Pod 中的容器之间共享数据。
  3. 网络资源:每个 Pod 在创建时会自动被分配一个唯一的 IP 地址,这个 IP 由 Kubernetes 支配。从外部看时,Pod 中的所有容器共享同一个网络命名空间。
  4. 配置信息:Pod 可以包含一些配置信息(例如环境变量、命令行参数等)用于启动和管理容器。
Pod 的生命周期

Pod 的生命周期分为不同的状态,主要有:

  1. Pending:Pod 已经被系统接受,但尚未被分配到具体节点运行。
  2. Running:Pod 已被调度到某个节点并且至少其中一个容器已经启动。
  3. Succeeded:Pod 中所有容器都已成功终止,并且不会再重启。
  4. Failed:Pod 中的所有容器都已经终止,并且至少有一个容器因严重错误终止。
  5. Unknown:由于某些原因,控制器无法获取 Pod 的状态信息。
Pod 的类型
  1. 单容器 Pod:最常见的 Pod 类型,包含一个应用容器。
  2. 多容器 Pod:包含多个容器,这些容器共享同一个 Pod 的资源,例如网络和存储卷。通常用于紧密协作的应用组件。
使用场景
  1. 单个进程的运行:例如运行一个 Web 服务器或数据库实例。
  2. 任务调度:例如运行批处理任务、工作队列等。
  3. 容器协作:例如包含主应用和边车容器(sidecar)的 Pod。边车容器可以提供监控、日志聚合等功能。

2. Volume

Volume(卷)在 Kubernetes 中是用于持久化和共享数据的一种方式,它是与 Pod 关联的存储单位。不同于容器生命周期有限,Volume 的数据在容器重启或删除时不会丢失,因此可以确保数据的持久性和可靠性。

Volume 的特点
  1. 数据持久性:容器中数据在容器重启或崩溃时会丢失,而 Volume 提供了一种在容器生命周期之外保存数据的方式。
  2. 数据共享:多个容器可以挂载同一个 Volume 实现数据共享。
  3. 存储抽象:Kubernetes Volume 抽象了底层存储实现,用户无需关心底层存储的具体细节。

4.Deployment

Deployment 是 Kubernetes 中的一种控制器,它为 Pod 和 ReplicaSet 提供了声明式更新。Deployment 使用户可以轻松地管理应用的部署和扩展,并能够快速进行滚动更新和回滚操作。

Deployment 的功能
  1. 声明式更新:用户可以定义所需的应用状态,Deployment 控制器会自动将集群中的实际状态更新到所需状态。
  2. 滚动更新:Deployment 支持滚动更新机制,在更新过程中不会中断应用服务。
  3. 版本回滚:如遇到问题,Deployment 可以方便地回滚到之前稳定的版本。
  4. 扩展和缩减:用户可以根据需要扩展或缩减 Pod 数量,方便地应对流量变化。
  5. 自愈能力:系统会自动检测和替换失效的 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 来适应不同的使用场景:

  1. ClusterIP:默认类型,创建一个仅在集群内部可访问的虚拟IP。

  2. NodePort:暴露端口号,使集群外部可以通过 : 访问 Service。

  3. LoadBalancer:使用云服务提供商的负载均衡器,将流量分发到后端的 Pod。

  4. 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
  1. apiVersion:指定使用的 API 版本,例如 v1
  2. kind:资源类型,例如 Pod
  3. metadata:资源的元数据,包括 namelabels 等信息。
    • name:资源的名称,例如 nginx
    • labels:一组键值对标签,用于标识和选择资源。
  4. spec:定义资源的期望状态。
    • containers:容器的详细定义,如名称、镜像、端口等。
  5. 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 的 coloryellow,不会被选择。