官方文档:https://kubernetes.io/docs/home/
一、概述
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,方便进行声明式配置和自动化。
Kubernetes可以提供:
- 服务发现和负载均衡:Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
- 存储编排:Kubernetes 允许自动挂载选择的存储系统,例如本地存储、公共云提供商等。
- 自动部署和回滚:可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,可以自动化 Kubernetes 来为部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。
- 自动调度:Kubernetes 的调度器会根据容器定义的 CPU 和内存资源,结合集群的当前状态,自动计算并选择最佳节点来运行容器,从而充分利用资源。
- 自我修复:Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。
- 密钥与配置管理:Kubernetes 允许存储和管理敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
- 批处理执行:除了服务外,Kubernetes 还可以管理你的批处理和 CI(持续集成)工作负载,如有需要,可以替换失败的容器。
- 水平扩缩:使用简单的命令、用户界面或根据 CPU 使用率自动对应用进行扩缩容。
- IPv4/IPv6 双栈:为 Pod(容器组)和 Service(服务)分配 IPv4 和 IPv6 地址。
- 可扩展性设计:在不改变上游源代码的情况下为Kubernetes 集群添加功能。
注:批处理(Batch Processing) 指的是处理一组任务或作业的方式,这些任务通常是一次性、短期的计算任务。Kubernetes 提供了特定的资源类型来管理这类作业,主要包括 Job 和 CronJob。
1.1 Kubernetes 的历史背景
传统部署
早期,各个组织是在物理服务器上运行应用程序。 由于无法限制在物理服务器中运行的应用程序资源使用,因此会导致资源分配问题。
例如,如果在同一台物理服务器上运行多个应用程序, 则可能会出现一个应用程序占用大部分资源的情况,而导致其他应用程序的性能下降。
一种解决方案是将每个应用程序都运行在不同的物理服务器上, 但是当某个应用程序资源利用率不高时,剩余资源无法被分配给其他应用程序, 而且维护许多物理服务器的成本很高。
因此,虚拟化技术被引入了。
虚拟化部署:
虚拟化技术允许在单个物理服务器的 CPU 上运行多台虚拟机(VM)。 虚拟化能使应用程序在不同 VM 之间被彼此隔离,且能提供一定程度的安全性, 因为一个应用程序的信息不能被另一应用程序随意访问。
虚拟化技术能够更好地利用物理服务器的资源,并且因为可轻松地添加或更新应用程序, 而因此可以具有更高的可扩缩性,以及降低硬件成本等等的好处。 通过虚拟化,可以将一组物理资源呈现为可丢弃的虚拟机集群。
每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。
容器部署:
容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。 因此,容器比起 VM 被认为是更轻量级的。且与 VM 类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等。
由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。
容器因具有许多优势而变得流行起来,例如:
- 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
- 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性), 提供可靠且频繁的容器镜像构建和部署。
- 关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。
- 可观察性:不仅可以显示 OS 级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
- 跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。
- 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
- 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
- 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理, 而不是在一台大型单机上整体运行。
- 资源隔离:可预测的应用程序性能。
- 资源利用:高效率和高密度。
1.2 核心概念
Kubernetes 是一个强大的容器编排平台,具有许多核心概念和组件。
概念 |
描述 |
功能 |
Pod |
Pod 是 Kubernetes 中的最小部署单元,表示一个或多个容器的集合,它们共享存储、网络和配置。 |
Pods 内的容器可以共享文件系统和网络,适合运行密切相关的应用程序。 |
Pods |
Pods 是 Pod 的复数形式,表示多个 Pod |
通常用于描述一组 Pod 或在命令行中指定多个 Pod |
Node |
Node 是 Kubernetes 集群中的一个工作机器,可以是物理或虚拟机。 |
每个 Node 上运行一个或多个 Pods,包含运行 Pods 所需的所有组件(如 kubelet、容器运行时等)。 |
Service |
Service 是一种抽象,定义了一组 Pods 的访问策略,提供稳定的网络接口。 |
通过 Service,用户可以使用 DNS 名称访问 Pods,而无需关心 Pods 的 IP 地址变化。它支持负载均衡和服务发现。 |
Deployment |
Deployment 是用于声明式管理 Pods 和 ReplicaSets 的资源。 |
自动化 Pods 的部署、升级和回滚,确保系统在更新时保持可用性。 |
ReplicaSet |
ReplicaSet 确保指定数量的 Pod 实例在运行,在1.2 版本引入,以替代早期的 Replication Controller。 |
用于扩展和缩减 Pods 的数量,确保 Pods 的高可用性。 |
Namespace |
Namespace 是 Kubernetes 的逻辑隔离机制,用于在同一集群中管理多个环境(如开发、测试和生产)。 |
通过 Namespace,可以在同一集群中使用相同的资源名称而不会冲突。 |
ConfigMap |
用于存储配置信息以供 Pods 使用。 |
允许将配置信息从镜像中分离,便于管理和更新。 |
Secret |
用于存储敏感信息(如密码、令牌等)。 |
提供安全的方式来传递敏感数据给 Pods。 |
Volume |
Volume 是 Kubernetes 中用于持久化存储的抽象。 |
提供跨容器共享数据的能力,支持多种存储类型,如本地存储、NFS、云存储等。 |
Cluster |
Cluster 是 Kubernetes 的核心概念,由多个 Node 组成。 |
提供一个统一的计算资源池,便于管理和调度。 |
Ingress |
Ingress 是用于管理外部访问 Kubernetes 服务的 API 对象。 |
提供 HTTP 和 HTTPS 路由到集群内服务的能力,支持负载均衡、SSL/TLS 终端等功能。 |
Controller |
Controller 是 Kubernetes 的控制循环,用于监控集群状态并执行所需的操作。 |
通过对比实际状态与期望状态,自动调整资源以确保系统稳定。 |
1.3 Kubernetes 组件
Kubernetes 的架构采用了一种主从设备模型,其中 Master Node 负责集群的管理和调度,而 Worker Node 则执行用户的应用程序。这个设计使得 Kubernetes 能够有效地进行容器编排和资源管理。
1.3.1 控制平面组件
控制平面组件会为集群做出全局决策,比如资源的调度以及检测和响应集群事件。
控制平面组件可以在集群中的任何节点上运行。 然而,一般情况下,控制平面组件都安装在Master 节点上,因为控制平面需要处理集群的管理和协调任务,集中在 Master 节点上可以提高管理效率。
组件 |
描述 |
kube-apiserver |
整个集群的入口,负责处理所有的 API 请求、管理集群状态、进行认证和授权。 |
etcd |
一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库,负责存储集群状态和配置数据。 |
kube-scheduler(调度器) |
接受来自kube-apiserver的任务,根据集群的资源情况和预定义的调度策略,将 Pods 调度到合适的 Node 上。 |
kube-controller-manager(控制器管理器) |
负责管理集群中的各类控制器,确保集群的实际状态与期望状态保持一致。通过不断监测和调整 Kubernetes 资源的状态,来实现自动化管理和自愈能力,例如创建、更新或删除资源。 |
cloud-controller-manager(云控制器管理器) |
专门用于与云提供商的 API 进行交互,将集群的云特有功能与 Kubernetes 的核心功能分离,使得 Kubernetes 可以在多种云环境中灵活运行。 |
1.3.2 节点组件
节点组件会在每个节点上(通常是Worker Node)运行,负责维护运行的 Pod 并提供 Kubernetes 运行时环境。
组件 |
描述 |
kubelet |
负责管理 Pods 和容器的生命周期。作为 Kubernetes 的主要代理,通过与 Kubernetes API 服务器和容器运行时的交互,确保集群中容器的正常运行和高效管理。 |
kube-proxy |
负责实现网络代理和负载均衡。在每个工作节点上运行,确保服务的网络流量能够正确地路由到相应的 Pods。用户也可选择其他的网络代理插件。 |
Container runtime(容器运行时) |
是 Kubernetes 集群中用于运行和管理容器的组件。它负责容器的创建、启动、停止、删除以及维护容器的生命周期。 |
1.3.3 插件(Addons)
在 Kubernetes 中,插件(Addons) 是增强集群功能的组件,它们通常提供附加的功能和服务,如监控、日志管理、网络管理和存储等。
组件 |
描述 |
DNS |
用于提供服务发现和名称解析功能。Kubernetes 内置的 DNS 功能使得 Pods 和服务可以通过 DNS 名称轻松互相访问,而不需要使用 IP 地址。 |
Dashboard |
基于 Web 的用户界面,用于管理和监控 Kubernetes 集群。提供了一种直观的方式来查看集群的状态、管理资源以及执行各种操作。 |
Flannel |
网络插件,简化容器网络的设置,提供跨主机网络,其他如Calico: 提供网络策略和网络安全功能;Weave Net: 提供容器间的网络连接,支持网络策略。 |
Prometheus |
监控插件,用于监控和报警,支持多种数据来源。 |
Persistent Volumes(PV) |
存储插件,处理持久化存储的管理和挂载。 |
1.4 应用
在 Kubernetes 中,应用可以分为有状态应用和无状态应用。
1.4.1 无状态应用
无状态应用是指不依赖于任何特定的会话数据或用户状态。每次请求都是独立的,服务器不需要存储会话信息。
特点:
- 可扩展性: 无状态应用可以轻松扩展,因为任何请求都可以被任何实例处理。
- 容错性: 如果某个实例失败,其他实例可以无缝接管请求。
- 易于部署: 更新和横向扩展简单,不需要考虑数据一致性问题。
示例:
- Web 服务器(如 Nginx、Apache)
- API 服务
- 静态文件托管
Kubernetes 资源: 通常使用 Deployment 资源来管理无状态应用。
1.4.2 有状态应用
有状态应用是指需要保持会话信息或数据状态。每个实例的状态是独立的,可能会影响应用的行为。
特点:
- 状态管理: 有状态应用需要管理和保存状态信息,通常需要持久化存储。
- 复杂性: 部署和管理较复杂,需要考虑数据一致性、故障恢复等。
- 数据迁移: 实例间的数据迁移和共享可能需要额外的配置。
示例:
- 数据库(如 MySQL、PostgreSQL、MongoDB)
- 缓存服务(如 Redis、Memcached)
- 消息队列(如 RabbitMQ、Kafka)
Kubernetes 资源: 通常使用 StatefulSet 资源(kube-controller-manager里的一个控制器)来管理有状态应用,以便提供稳定的网络身份和持久化存储。
1.5 YAML文件
在 Kubernetes 中,YAML 文件用于定义和配置各种资源,如 Pods、Services、Deployments、ReplicaSets 等。
语法规则:
-
大小写敏感,且资源类型通常使用大写(如
Pod
、Service
),而其他键如apiVersion
、kind
、metadata
等使用小写。 - 层级:使用缩进表示层级关系,相同层级的元素左侧对齐。
- 缩进:使用空格进行缩进,不能使用制表符(Tab),通常每一级缩进使用两个空格。
-
键值对:使用冒号
:
分隔键和值。值可以是字符串、数字、布尔值、列表或对象。 - 数据类型:支持字符串,数字,布尔,列表等
-
注释:使用
#
来添加注释,注释在行内或单独一行均可。 - 分隔符:- - - 为可选的分隔符 ,当需要在一个文件中定义多个结构的时候需要使用。
- 特殊字符:如果值包含特殊字符(如冒号、空格等),需要用引号括起来。
每个 YAML 文件通常由以下几个部分组成:
- apiVersion: 指定资源的 API 版本。
- kind: 定义资源的类型(如 Pod、Service、Deployment 等)。
- metadata: 描述资源的元数据,如名称、标签和注释。
- spec: 资源的具体配置,定义资源的期望状态。
1.5.1 apiVersion
在 Kubernetes 中,apiVersion
字段用于指定资源的 API 版本,帮助 Kubernetes 确定如何处理该资源,因此,选择合适的 apiVersion
是非常重要的。使用不兼容的版本可能导致资源创建失败或不按预期工作。
apiVersion
字段通常由两个部分组成:
- 组(Group): 表示资源所属的 API 组。
- 版本(Version): 表示该组的版本号。
例如,apps/v1
由组 apps
和版本 v1
组成。
常见的 API 组和版本(更多请看官方文档):
core(v1): 不属于任何组的资源,如 Pods、Services、Namespaces 等。版本为 v1
。
apiVersion: v1
kind: Pod
apps(v1): 包含与应用程序相关的资源,如 Deployments、ReplicaSets 和 StatefulSets。
apiVersion: apps/v1
kind: Deployment
batch(v1): 包含与批处理相关的资源,如 Jobs 和 CronJobs。
apiVersion: batch/v1
kind: Job
networking(v1): 包含与网络相关的资源,如 Ingress 和 NetworkPolicies。
apiVersion: networking.k8s.io/v1
kind: Ingress
rbac.authorization.k8s.io(v1): 包含与角色和权限相关的资源,如 Roles 和 RoleBindings。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
1.5.2 实例
定义一个yaml文件 my-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80
详解:
apiVersion: apps/v1 # 指定使用的 API 版本。在这里,apps/v1 表示这是一个 Deployment 类型的资源,属于 Kubernetes 的应用相关 API
kind: Deployment # 定义资源的类型,Deployment用于管理 Pods 的副本
metadata: # 此部分包含资源的元数据
name: my-deployment # 资源的名称,自定义
spec: # 定义资源的期望状态
replicas: 3 # 指定要运行的 Pods 副本数,即运行3个容器
selector: # 用于选择与 Deployment 关联的 Pods
matchLabels: # 定义选择器的标签。在这里,选择所有具有标签 app: my-app 的 Pods
app: my-app # 标签,自定义
template: # 定义 Pods 的模板,用于创建新的 Pods
metadata: # 包含 Pods 的元数据
labels: # 为模板中的 Pods 定义标签。在这里,所有由此 Deployment 创建的 Pods 都会被标记为 app: my-app
app: my-app # 标签名,自定义
spec: # 定义 Pods 的具体配置
containers: # 列出 Pods 中的容器
- name: my-container # 容器的名称,自定义
image: nginx:latest # 容器所使用的基础Docker镜像,其他有CentOS,busybox,Ubuntu等
ports: # 列出容器暴露的端口
- containerPort: 80 # 指定容器内部的端口号
运行这个文件来创建一个Deployment,运行3个nginx容器,端口开放80
kubectl apply -f my-deployment.yaml
查看
# 查看 Deployment
kubectl get deployments
# 查看 Deployment 详细信息
kubectl describe deployment my-deployment
# 查看 Pods
kubectl get pods
# 查看 Pod 详细信息
kubectl describe pod <pod-name>
# 删除
kubectl delete deployment my-deployment
1.6 kubectl
kubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群和其资源。它提供了一组命令,允许用户与 Kubernetes API 进行交互,从而执行各种操作,如创建、更新、删除和获取资源的状态。
主要功能:
-
管理集群资源:使用
kubectl
可以创建、更新和删除 Pods、Deployments、Services 等各种 Kubernetes 资源。 - 查看资源状态:可以通过命令查看集群中各个资源的状态和详细信息,例如 Pods、Nodes、Namespaces 等。
- 调试和排错:提供命令用于查看日志、执行命令、进入容器等,帮助用户调试和维护应用程序。
- 配置管理:支持管理 Kubernetes 配置文件(如 kubeconfig),以便连接到不同的集群。
-
集成 CI/CD 工具:
kubectl
可用于自动化和持续集成/持续部署(CI/CD)流程,方便与其他工具集成。
常用命令:
# 查看集群信息
kubectl cluster-info
# 查看 Pods
kubectl get pods
# 创建资源
kubectl apply -f my-resource.yaml
# 删除资源
kubectl delete pod my-pod
# 查看 Pod 日志
kubectl logs my-pod
# 进入容器
kubectl exec -it my-pod -- /bin/sh
kubectl apply -f 和kubectl create -f 和 kubectl replace -f:
在 Kubernetes 中,kubectl apply -f
、kubectl create -f
和 kubectl replace -f
是用于管理资源的三种命令,适用于不同的场景,在大多数情况下,使用 kubectl apply -f
是最佳实践。
命令 |
创建新资源 |
更新现有资源 |
适用场景 |
|
是 |
是 |
日常工作流、CI/CD、团队协作 |
|
是 |
否 |
确定资源不存在时的初始化设置 |
|
否 |
是 |
需要完全替换现有资源的情况 |
二、集群搭建
详见:
或者参考官方文档:https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/
三、各概念简述
3.1 Pod
Pod 是 Kubernetes 中的最小可部署单元,通常包含一个或多个容器,这些容器共享存储、网络和运行环境。
共享网络: Pod 内的所有容器共享同一个 IP 地址和端口空间,可以通过 localhost 互相通信。
共享存储: Pod 可以挂载存储卷,所有容器都可以访问同一数据。
3.1.1 容器
在 Kubernetes 中,每个 Pod 通常会包含一个特殊的容器,称为 Pause 容器(根容器),也被称为 基础设施容器。用户通常不需要直接管理 Pause 容器,它在 Pod 创建时自动启动,用户只需关注业务容器。
Pause 容器是一个轻量级的容器,通常是一个只包含基本工具的 Linux 镜像,用于创建 Pod 的网络命名空间和其他基础设施功能。如 gcr.io/google_containers/pause。
3.1.1.1 功能
网络命名空间
-
共享网络: Pause 容器创建并持有 Pod 的网络命名空间,所有在同一 Pod 中的业务容器共享这一网络命名空间。这意味着它们可以通过
localhost
互相通信。 - IP 地址分配: Pause 容器使得 Pod 拥有一个单独的 IP 地址,该地址被分配给整个 Pod,而不是单个容器。
资源管理
- 资源隔离: Pause 容器提供了一个基础设施层,帮助 Kubernetes 管理 Pod 中的容器资源。Pod 的生命周期与 Pause 容器相绑定。
- 容器状态管理: 当 Kubernetes 需要检查 Pod 的状态时,它可以通过 Pause 容器来管理和跟踪 Pod 的健康状态。
3.1.1.2 与业务容器的关系
- 紧密耦合: 用户业务容器是 Pod 中的主要应用容器,通常执行实际的业务逻辑。它们与 Pause 容器紧密耦合,共享网络和存储资源。
- 容器间协作: 通过共享 Pause 容器的网络命名空间,用户业务容器能够高效地进行数据交换和通信。
3.1.2 资源限制
在 Kubernetes 中,可以为 Pod 设置资源限制,以确保应用程序在运行时不会消耗过多的资源。资源限制主要包括 CPU 和内存。
资源请求(Requests): 表示容器启动时所需的最低资源量。如果节点没有足够的资源满足请求,该 Pod 将不会被调度到该节点。
资源限制(Limits): 表示容器可以使用的最大资源量。如果容器尝试使用超过这个限制的资源,会终止这个容器。
示例
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
resources:
requests:
memory: "64Mi" # 请求的内存
cpu: "250m" # 请求的 CPU
limits:
memory: "128Mi" # 限制的内存
cpu: "500m" # 限制的 CPU
内存单位:
- B: 字节
- Ki: Kibibyte(1024 字节)
- Mi: Mebibyte(1024 KiB)
- Gi: Gibibyte(1024 MiB)
- Ti: Tebibyte(1024 GiB)
cpu单位:
-
核(Core): 通常表示为
1
,代表一个完整的 CPU 核心。 -
毫核(milli-core): 使用
m
表示,表示一个 CPU 核心的千分之一。
3.1.3 镜像拉取
在yaml文件里,可以定义容器镜像拉取的策略。
- Always: 每次启动 Pod 时都拉取镜像。适用于需要确保使用最新版本的镜像。
- IfNotPresent: 只有在本地不存在镜像时才拉取,默认策略。
- Never: 不拉取镜像,假设镜像已经在节点上。适用于开发或测试环境
默认情况下,Kubernetes 从 Docker Hub 或指定的私有镜像仓库拉取镜像;如果镜像名称中包含仓库地址(如 my-registry/my-image:tag
),Kubernetes 将从该地址拉取。
如果镜像是私有的,Kubernetes 会使用相应的凭证进行身份验证;这些凭证通常存储在 Kubernetes 中的 Secret 对象中,并与 ServiceAccount 绑定。
如果拉取镜像失败,Kubernetes 将根据 Pod 的配置重试拉取。如果多次失败,Pod 将进入 ImagePullBackOff
状态;管理员可以通过检查 Pod 的事件或使用 kubectl describe pod <pod-name>
命令来查看具体错误信息。
示例
apiVersion: v1
kind: Pod
metadata:
name: my-nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest # 使用最新的 Nginx 镜像
imagePullPolicy: Always # 每次都拉取镜像
ports:
- containerPort: 80
3.1.4 重启策略
在 Kubernetes 中,Pod 的重启策略(restartPolicy
)决定了容器在失败后的处理方式。
- Always:无论容器的退出状态如何,Kubernetes 始终会重启该容器。通常用于长时间运行的服务,如 Web 应用或数据库。
- OnFailure:仅在容器以非零状态退出时(表示失败)重启容器。适合批处理任务或需要在失败后重新尝试的场景。
- Never:无论容器的退出状态如何,Kubernetes 都不会重启该容器。适用于一次性任务或批处理作业,通常与
Job
资源一起使用。
示例
apiVersion: v1
kind: Pod
metadata:
name: always-restart-pod
spec:
restartPolicy: Always # 设置重启策略
containers:
- name: my-container
image: my-image:latest
3.1.5 Pod的类型
- 单容器 Pod
- 定义: 每个 Pod 只包含一个容器。
- 场景: 适用于简单的应用程序,易于管理和监控。大多数情况下,用户会创建这种类型的 Pod。
- 多容器 Pod
- 定义: 一个 Pod 包含多个容器,这些容器紧密协作。
- 类型:
- Sidecar 模式: 通过辅助容器提供附加功能,例如日志收集、监控等。
- Init Containers: 在主容器启动之前执行初始化任务,用于设置环境或预处理。
- 代理模式: 代理容器处理主应用与外部的通信。
- DaemonSet Pods
- 定义: 这种 Pod 确保在每个节点上运行一个 Pod 副本。
- 场景: 适用于需要在每个节点上运行某些服务的情况,例如监控代理或日志收集器。
- Job Pods
- 定义: 用于执行一次性的任务或批处理作业。
- 场景: 适用于需要完成某项任务后退出的应用,例如数据处理或数据库迁移。
- CronJob Pods
- 定义: 类似于 Job,但按照预定的时间表定期创建 Pods。
- 场景: 适用于定期任务,例如备份、报告生成等。
- StatefulSet Pods
- 定义: 用于管理有状态应用的 Pods,确保每个 Pod 有一个唯一的身份和持久化存储。
- 场景: 适用于数据库和其他需要稳定网络身份和持久存储的应用。
- Replication Controller / ReplicaSet Pods
- 定义: 确保指定数量的 Pod 副本在任何时候都在运行。
- 场景: 适用于负载均衡和高可用性的需求。
- Namespace-specific Pods
- 定义: Pods 可以在不同的 Namespace 中创建,以实现逻辑隔离。
- 场景: 适合多租户环境或不同开发、测试、生产环境的隔离。
3.1.6 调度
Kubernetes 中的 Pod 调度是将 Pods 分配到适当节点的过程。调度器负责根据多种因素(如资源需求、节点可用性、亲和性规则等)来决定 Pods 的运行位置。
调度过程一般分为两个步骤:
过滤阶段:调度器会根据条件过滤出不符合要求的节点
- 资源需求: 检查节点是否有足够的 CPU、内存等资源。
- 节点亲和性: 检查 Pods 是否有特定的节点亲和性或反亲和性要求。
- 污点和容忍: 处理节点的污点和 Pods 的容忍度。
- Pod 反亲和性: 确保 Pods 不会被调度到不允许的节点上。
优先级阶段:在过滤出可用的节点后,调度器会根据优先级评分,选择最合适的节点,优先级包括
- 最少使用资源: 选择当前资源使用最少的节点。
- 节点亲和性: 优先选择符合 Pods 亲和性规则的节点。
- 均衡负载: 尽量将 Pods 均匀分布到各个节点上。
调度方式
- 自动调度:使用控制器(如RS,DaemonSet)创建的 Pods 会由 Kubernetes 自动调度到最适合的节点,后文介绍
-
手动调度:通过在 Pod 定义中直接指定
nodeName
字段或nodeSelector
字段,将 Pod 调度到特定节点 - 其他调度:如亲和性调度,污点和容忍等
3.1.6.1 标签
Kubernetes 中的标签(Labels)是用于组织和选择对象(如 Pods、节点等)的关键机制。标签是附加到对象上的键值对,用于标识和分类这些对象,以便于管理和查询。
1. 标签的基本概念
-
键值对: 标签由一个键(Key)和一个值(Value)组成,格式为
key: value
。 - 多元性: 同一个对象可以有多个标签,标签的组合可以提供更丰富的上下文信息。
2. 标签的用途
- 选择器: 可以使用标签选择器(Label Selector)来选择特定的对象。例如,可以选择所有具有某个特定标签的 Pods。
- 分组: 标签用于将相关的资源分组,以便进行管理和查询。
- 调度: 节点标签可以帮助调度器将 Pods 调度到适当的节点上。
- 服务发现: 通过标签,Kubernetes 服务可以选择一组 Pods 进行负载均衡。
3. 标签的格式
- 键: 必须小写字母、数字、下划线(_)、连字符(-)和点(.),且不能以点(.)开头或结尾,最大长度为 63 个字符。
- 值: 可以是任意字符,但最大长度为 63 个字符,且可以为空。
4. 标签选择器
标签选择器用于根据标签选择对象,主要有以下两种类型:
- 等值选择器: 选择具有特定键值对的对象。
- 集合选择器: 选择具有特定键的对象,并且值在给定的集合中。
为pod打标签:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: my-app
environment: production
spec:
containers:
- name: my-container
image: my-image:latest
使用命令行
# 查看
kubectl get pods --show-labels
# 创建
kubectl label pods my-pod app=my-app
# 覆盖已有标签
kubectl label pods my-pod environment=staging --overwrite
# 删除
kubectl label pods my-pod environment-
为node打标签
apiVersion: v1
kind: Node
metadata:
name: my-node
labels:
disktype: ssd
zone: us-west-1a
使用命令行
kubectl label nodes my-node disktype=ssd
3.1.6.2 NodeName
在 Kubernetes 中,使用 nodeName
字段可以将 Pod 直接调度到特定的节点,nodeName 是 Pod 的一个属性,允许用户在 Pod 的配置中指定要在哪个节点上运行。
注意事项:
-
跳过调度器: 使用
nodeName
时,Kubernetes 调度器会跳过调度过程,直接将 Pod 绑定到指定的节点。 - 节点状态: 确保指定的节点处于可用状态(NotReady 状态的节点无法调度 Pods)。
- 资源分配: 仍然需要确保指定节点有足够的资源来满足 Pod 的需求(如 CPU 和内存)。
适用场景:
- 硬件依赖: 当应用需要特定硬件(如特定型号的 GPU)时,可以将其调度到具备该硬件的节点。
- 网络配置: 对于需要特定网络配置的 Pods,可以指定在具有相应网络设置的节点上运行。
实例
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeName: my-node # 指定要调度的节点名称
containers:
- name: my-container
image: my-image:latest
3.1.6.3 NodeSelector
NodeSelector
是 Pod 规格中的一个字段,允许用户指定节点的标签,以便将 Pods 调度到具有特定标签的节点上。适用于需要特定资源或特征的 Pods,例如要求在 SSD 存储节点上运行的数据库 Pods。
如果没有节点满足 NodeSelector
的条件,Pod 将不会被调度,状态会保持为 Pending。除了标签匹配外,确保目标节点有足够的资源(如 CPU、内存)来满足 Pod 的需求。
先为节点打上标签
kubectl label nodes my-node disktype=ssd
yaml文件里选择这个标签
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeSelector:
disktype: ssd # 指定节点标签
containers:
- name: my-container
image: my-image:latest
删除标签
kubectl get nodes --show-labels
kubectl label nodes <node-name> <label-key>-
3.1.6.4 Taint(污点)
Taint 是节点的一种属性,用于标识节点不适合某些 Pods。通过在节点上设置污点,可以阻止 Pods 被调度到这些节点,除非它们具有相应的容忍度。
Taint 由三个部分构成:
- Key: 污点的名称,通常是一个字符串
- Value: 污点的具体值,通常是一个字符串
- Effect: 污点的效应,可以是以下三种之一:
-
NoSchedule
: 不允许没有容忍度的 Pods 调度到该节点。 -
PreferNoSchedule
: 尽量不调度没有容忍度的 Pods 到该节点,但不是强制的。 -
NoExecute
: 不允许没有容忍度的 Pods 在该节点上运行,如果已在运行,会被驱逐。
为节点添加污点
kubectl taint nodes node1 key=value:NoSchedule
删除污点
kubectl describe nodes <node-name>
kubectl taint nodes <node-name> <key>:<value>:<effect>-
污点使用 Key-Value 的组合的原因:
重要的原因:
1. 灵活性
- 多样性: 通过使用 Key 和 Value 的组合,可以为同一个 Key 定义多个不同的情况。例如,可以有多个污点,如: