1-Kubernetes基本概念

k8s.jpg

K8S概述

Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。

部署演进


容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。 因此,容器比起 VM 被认为是更轻量级的。且与 VM 类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。
K8s优点:

  1. 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
  2. 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性), 提供可靠且频繁的容器镜像构建和部署。
  3. 关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。
  4. 可观察性:不仅可以显示 OS 级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
  5. 跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。
  6. 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
  7. 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
  8. 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
  9. 资源隔离:可预测的应用程序性能。
  10. 资源利用:高效率和高密度。

k8s可以提供什么

  • 服务发现和负载均衡
    Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定
  • 存储编排
    Kubernetes 允许自动挂载你选择的存储系统,例如本地存储、公共云提供商等。
  • 自动部署和回滚
    使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。
  • 自动完成装箱计算
    为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。
  • 自我修复
    Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。
  • 密钥与配置管理
    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
  • 批处理执行
    除了服务外,Kubernetes 还可以管理你的批处理和 CI(持续集成)工作负载,如有需要,可以替换失败的容器。
  • 水平扩缩
    使用简单的命令、用户界面或根据 CPU 使用率自动对你的应用进行扩缩。
  • IPv4/IPv6 双栈
    为 Pod(容器组)和 Service(服务)分配 IPv4 和 IPv6 地址。
  • 为可扩展性设计
    在不改变上游源代码的情况下为你的 Kubernetes 集群添加功能。

k8s核心组件

k8s是由控制平面和一个或者多个工作节点组成。

控制面组件

  • kube-apiserver:提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制。
  • etcd:存储系统,APIserver将请求的数据存储到etcd中
  • kube-scheduler:负责资源的调度,按照预定的调度策略将 Pod 调度到相应的节点上。
  • kube-controller-manager:运行控制器来实现k8s API的行为,例如故障检测、自动扩展和滚动更新。
  • cloud-controller-manager:通过云提供商的 API 管理云平台上的集群。

工作节点组件

  • kubelet:是工作节点上运行的代理,它确保容器在 Pod 中运行。kubelet 接收一组通过各类机制提供给它的 PodSpecs,并确保这些 PodSpecs 中描述的容器处于运行状态且健康。
  • kube-proxy:在节点上运行的网络代理,实现 Kubernetes 服务(Service) 概念的一部分。kube-proxy 维护节点上的一些网络规则,这些网络规则允许从集群内部或外部访问 Pod 中运行的服务。
  • 容器运行时:负责运行容器。

k8s对象

Kubernetes 对象就像是你在 Kubernetes 集群中写的一张“任务清单”。你通过创建这些对象来告诉 Kubernetes:

  • 你想运行什么应用(比如一个网站或数据库)。
  • 这些应用需要多少资源(比如 CPU 和内存)。
  • 这些应用应该怎么运行(比如出错时自动重启,或者如何更新)。

当创建了一个对象时,Kubernetes 会记住你写的“任务清单”(也就是你期望的状态)。然后,Kubernetes 会不断检查集群的实际状态,确保它和你写的“任务清单”一致。任务清单中包含spec(规约,希望对象所具有的期望状态)。status描述了对象的当前状态,k8s会不断检查实际情况,并更新status,使其与spec一致。
清单中的必须字段:

  • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
  • kind - 想要创建的对象的类别
  • metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
  • spec - 你所期望的该对象的状态
    对于不同的对象,spec 部分的内容会有所不同。详细查看官网Kubernetes API 参考

对象管理

特性 指令式命令 指令式对象配置 声明式对象配置
操作方式 直接运行命令操作资源。 通过 YAML 文件明确指定操作(创建、更新、删除)。 通过 YAML 文件描述期望状态,Kubernetes 自动处理。
命令示例 kubectl run/create/delete kubectl create/replace/delete -f kubectl apply -f
是否需要 YAML 文件 不需要。 需要。
适用场景 快速测试、临时操作。 简单操作、临时测试。 生产环境、持续管理。
幂等性 不是幂等的(多次运行可能导致错误)。 不是幂等的(多次运行可能导致错误)。 幂等的(多次运行结果一致)。
变更管理 需要手动处理变更。 需要手动处理变更。 Kubernetes 自动处理变更。

对象名称和ID

名称: 在同一个命名空间中,每一个对象都有一个名称来标识在同类资源中的唯一性,不同类型的资源可以同名。
UID: 在集群中全局唯一,用来区分同一个命名空间中的不同对象。

  • Kubernetes 资源的唯一性由 API 组、资源类型、名字空间 和 名称 决定。
  • API 版本 不会影响资源的唯一性。
  • 删除资源后,可以创建同名的新对象。
  • 在同一资源类型和名字空间中,名称必须是唯一的。

namespace

Namespace 是 Kubernetes 中用于将资源逻辑分组和隔离的机制。它可以将一个物理集群划分为多个虚拟集群,每个 Namespace 中的资源名称是唯一的,但不同 Namespace 中的资源可以重名。Kubernetes 控制面会为所有名字空间设置一个不可变更的标签 kubernetes.io/metadata.name。 标签的值是名字空间的名称。
Namespace 的作用:

  • 资源隔离:将不同的项目、团队或环境(如开发、测试、生产)的资源隔离开。
  • 权限控制:通过 RBAC(基于角色的访问控制)为不同的 Namespace 设置不同的权限。
  • 资源管理:可以为每个 Namespace 设置资源配额(Resource Quota),限制其资源使用量。
default 如果没有指定 Namespace,资源会默认创建到这里。
kube-system 存放 Kubernetes 系统组件的资源(如 kube-proxy、CoreDNS 等)。
kube-public 存放公共资源,通常对所有用户可见。
kube-node-lease 用于节点心跳机制,与节点健康检查相关。
1
2
3
4
5
6
7
8
9
10
11
12
# 列出所有命名空间
kubectl get namespaces
# 列出指定空间的指定资源
kubectl get pod --namespace=kube-system

# 修改默认的namespace
kubectl config set-context --current --namespace=<名字空间名称>
# 验证,若没有输出,则默认namespace为default
kubectl config view --minify | grep namespace:

# 查看所有资源类型和它们的缩写名称,以及它们是否在namespace中的。
kubectl api-resources

标签与注解

标签是附加到 Kubernetes 对象(如 Pod、Service、Node 等)上的键值对(key-value pairs)。用于标识和选择对象,通常用于筛选、分组或关联资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 标签示例
metadata:
labels:
key1: value1
key2: value2
key3: value3

# 标签筛选,筛选app=my-app且enc≠prod的pod
kubectl get pods -l app=my-app,env!=prod

# 标签更新
kubectl label pod my-pod env=prod #

注解也是附加到 Kubernetes 对象上的键值对,但它用于存储非标识性的元数据,注解通常用于存储额外的信息,如配置、说明、工具链信息等。

1
2
3
4
5
metadata:
annotations:
key1: value1
key2: value2
key3: value3
特性 标签(Labels) 注解(Annotations)
用途 用于标识和选择资源。 用于存储非标识性的元数据。
键值对长度 较短,通常用于快速识别。 可以较长,适合存储详细信息。
是否可用于选择器 是,可以通过选择器筛选资源。 否,不能用于筛选资源。
示例 app: my-app, env: prod description: “Production frontend”
使用场景 资源分组、服务选择、节点调度。 存储构建信息、工具链集成、说明文档。

字段选择器

字段选择器(Field Selector)是 Kubernetes 中用于根据资源的字段值筛选资源的一种机制。它允许你通过指定资源的特定字段值来过滤资源。

1
2
3
4
5
#使用字段选择器筛选资源
kubectl get pods --field-selector metadata.name=my-pod
#常用的字段选择器
metadata.name=my-pod #资源名称
status.phase= #资源状态,不同资源的状态不一样,比如pod有Pending、Running、Succeeded、Failed

finalizers终结器

  1. Finalizers 是 Kubernetes 中一种用于控制资源删除行为的机制。存储在资源的 metadata.finalizers 字段中。本质上就是一个 标记,用于告诉 Kubernetes:“这个资源还不能删除,需要先完成某些操作”。这个标记的添加和移除是由你自定义的逻辑控制的,通常通过编写控制器或外部系统来完成。逻辑上就是在删除这个资源时暂时不能删除,要等完成一些自定义的操作后,删除finalizers标记,然后才能删除资源。
  2. Finalizers 的主要作用是确保在删除资源之前,完成一些必要的清理操作。
  • 释放外部资源(如云存储、数据库连接等)。
  • 确保依赖资源的正确删除顺序。
  • 防止资源被意外删除。
    1
    2
    3
    metadata:
    finalizers:
    - my-finalizer

    属主与附属

  1. 什么是属主和附属?
    在 Kubernetes 中,属主(Owner) 和 附属(Dependent) 是一种资源之间的从属关系。属主资源拥有一个或多个附属资源,Kubernetes 通过这种关系来管理资源的生命周期。
  • 属主(Owner):通常是更高级别的资源,例如 Deployment、StatefulSet、ReplicaSet 等。
  • 附属(Dependent):通常是由属主创建或管理的资源,例如 Pod。
  1. 属主和附属的关系
    属主和附属之间的关系通过资源的 metadata.ownerReferences 字段来定义。每个附属资源都会在其 metadata.ownerReferences 字段中记录其属主资源的信息。
    示例:一个由 Deployment 创建的 Pod 的 metadata.ownerReferences 字段可能如下所示:
    1
    2
    3
    4
    5
    6
    7
    8
    复制
    metadata:
    ownerReferences:
    - apiVersion: apps/v1
    kind: Deployment
    name: my-deployment
    uid: 12345678-1234-1234-1234-123456789012
    controller: true
  2. 属主和附属的作用
    属主和附属的关系在 Kubernetes 中有以下作用:
  • 生命周期管理
    当属主资源被删除时,Kubernetes 会自动删除其所有附属资源。
    例如,删除一个 Deployment 时,Kubernetes 会自动删除由该 Deployment 创建的所有 Pod。
  • 垃圾回收
    Kubernetes 的垃圾回收器(Garbage Collector)会检查资源的 metadata.ownerReferences 字段。如果属主资源被删除,垃圾回收器会自动删除所有附属资源。
  • 资源关联
    通过属主和附属的关系,可以清晰地表示资源之间的依赖关系。
    例如,一个 Service 可以通过标签选择器关联到由 Deployment 创建的 Pod。\

属主关系与 Finalizer

  1. 属主关系与 Finalizer 的作用
    属主关系和 Finalizer 都是 Kubernetes 中用于管理资源生命周期的机制,但它们的作用不同:
    属主关系:用于表示资源之间的从属关系(如 Deployment 和 Pod),并控制资源的级联删除。
    Finalizer:用于在删除资源之前执行清理操作,防止资源被意外删除。

  2. 级联删除与 Finalizer
    Kubernetes 支持两种级联删除策略:前台删除(Foreground) 和 后台删除(Background)。在前台删除中,Kubernetes 会为属主资源添加 Finalizer,以确保删除顺序。

  • 前台删除(Foreground):先删除附属资源,再删除属主资源。
    Kubernetes 会为属主资源添加 foreground Finalizer。
    控制器必须删除所有 ownerReferences.blockOwnerDeletion=true 的附属资源后,才能删除属主资源。
    这种策略确保属主资源在删除之前,所有依赖它的附属资源都被清理。
    kubectl delete deployment my-deployment --cascade=foreground

  • 后台删除(Background):立即删除属主资源,然后异步删除附属资源。默认的删除方式
    Kubernetes 会立即删除属主资源,然后由垃圾回收器异步删除附属资源。
    这种策略不会为属主资源添加 Finalizer。

  • 孤立删除(Orphan)
    Kubernetes 会为属主资源添加 orphan Finalizer。
    删除属主资源后,附属资源会被保留,不再被属主资源管理。
    kubectl delete deployment my-deployment --cascade=orphan
    至于为什么属主添加了orphan Finalizer还是会被删除,是因为这个 Finalizer 的作用是告诉 Kubernetes:“在删除属主资源之前,先解除它与附属资源(如 Pod)的属主关系”。也就是执行这条命令的流程:属主添加 orphan Finalizer–>解除属主关系(将附属metadata.ownerReferences 字段中指向属主资源的条目移除)–>删除属主资源。