kubernetes简单使用之高级调度与Helm包管理器
Kubernetes高级调度部分介绍了CronJob定时任务、InitContainer初始化容器、污点(Taint)与容忍度(Toleration)机制,以及节点/Pod亲和性调度策略。其中,污点机制通过NoSchedule、PreferNoSchedule和NoExecute三种效果控制Pod调度。Helm作为Kubernetes包管理器,通过Chart(应用模板)、Config(配置参数)和
一、高级调度
1、CronJob计划任务
编写cron-job-pd.yaml文件,创建CronJob对象,用于执行定时任务。
apiVersion: batch/v1
kind: CronJob
metadata:
name: cron-job-test
spec:
concurrencyPolicy: Allow # 并发策略:允许并发执行
failedJobsHistoryLimit: 1 # 保留失败任务数:1个
successfulJobsHistoryLimit: 3 # 保留成功任务数:3个
suspend: false # 是否挂起:否
schedule: "* * * * *" # 调度时间:每分钟执行一次
jobTemplate:
spec:
template:
spec:
containers:
- name: busybox
image: busybox:1.28 # 使用镜像:busybox:1.28
imagePullPolicy: IfNotPresent # 镜像拉取策略:如果不存在则拉取
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster # 执行命令:显示日期并打印信息
restartPolicy: OnFailure # 重启策略:任务失败时重启
2、初始化容器InitContainer
初始化容器(InitContainer)的作用是在真正的容器启动前,先启动InitContainer,执行一系列初始化操作,等到初始化操作完成之后再启动真实的容器。
InitContainer保证在EntryPoint之前执行,而postStart钩子则不能。与postStart适合执行简单命令不同,InitContainer作为一个独立的容器,能在其他基础容器环境下执行更复杂的初始化任务。
配置InitContainer的方式:在Pod的创建模板中,通过配置initContainers参数来定义InitContainer,包括镜像、拉取策略、执行命令和容器名称等,如下所示:
spec:
initContainers:
- name: init-test
image: nginx
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "echo 'inited;' >> ~/.init"]
3、污点和容忍度
节点亲和性 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点 (这可能出于一种偏好,也可能是硬性要求)。 污点(Taint) 则相反——它使节点能够排斥一类特定的 Pod。
容忍度(Toleration) 是应用于 Pod 上的。容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其他参数。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的。污点可以确保Master节点只运行系统组件,不部署业务应用。
污点(Taint)和容忍度(Toleration)是Kubernetes中用于控制Pod调度的核心机制,它们相互配合可以确保Pod不会被分配到不合适的节点上。
污点(Taint):节点级别的属性,用于标记节点排斥特定类型的Pod。每个污点包含三个部分:
- Key:污点的标识符
- Value:污点的值(可选)
- Effect:污点的效果,可以是以下三种之一:
- NoSchedule:禁止调度新的Pod到该节点(已运行的Pod不受影响)。
- PreferNoSchedule:尽量不调度新的Pod到该节点,但不强制。
- NoExecute:禁止调度新的Pod到该节点,并且会驱逐已运行但不满足容忍度的Pod。
容忍度(Toleration):Pod级别的配置,用于声明Pod可以容忍哪些污点。只有当Pod的容忍与节点的污点匹配时,Pod才能被调度到该节点上。容忍的定义包含以下字段:
- Key:需要匹配的污点Key
- Value:需要匹配的污点Value(可选)
- Operator:匹配操作符(Equal完全匹配或Exists仅匹配Key)
- Effect:需要匹配的污点Effect(可选)
- TolerationSeconds:仅对NoExecute污点有效,表示Pod在被驱逐前可以继续运行的时间。
容忍中的操作符operator有两个取值:Equal和Exists,两者的区别:
- Equal表示Pod容忍中的key和value需要与污点中的key和value都要匹配,否则Pod不能被分配到带有污点的节点上。
- Exists表示只要Pod容忍中的key与污点中的key匹配,这个Pod就可以被分配到带有污点的节点上,容忍中可以不用配置value。
配置示例:
1. 节点污点设置
# 为节点node1设置污点
kubectl taint nodes node1 key1=value1:NoSchedule
# 移除污点
kubectl taint nodes node1 key1=value1:NoSchedule-
2. Pod容忍度配置(YAML)
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerationSeconds: 3600 # 仅对NoExecute有效
或者使用Exists操作符:
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"
实际应用场景举例:
1. GPU节点专用:
# 标记GPU节点
kubectl taint nodes gpu-node01 accelerator=nvidia:NoSchedule
# AI训练Pod配置
tolerations:
- key: "accelerator"
operator: "Equal"
value: "nvidia"
effect: "NoSchedule"
2. 核心服务隔离:
# 创建核心业务专用节点池
kubectl taint nodes core-node01 tier=core:NoExecute
# 支付服务Pod配置
tolerations:
- key: "tier"
operator: "Equal"
value: "core"
effect: "NoExecute"
3. 节点维护模式:
# 进入维护模式(驱逐所有非系统Pod)
kubectl taint nodes node02 maintenance=true:NoExecute
# 关键守护进程配置容忍度
tolerations:
- key: "maintenance"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 86400 # 24小时宽限期
污点与节点亲和性的区别:
特性 |
污点与容忍度 |
节点亲和性 |
作用方向 |
节点排斥Pod |
Pod吸引到节点 |
配置位置 |
节点设置污点,Pod设置容忍 |
Pod设置亲和性规则 |
强制程度 |
可设置硬性排斥(NoSchedule)或软性排斥(PreferNoSchedule) |
可设置硬性要求(required)或软性偏好(preferred) |
典型用途 |
节点专用、节点维护、资源隔离 |
硬件偏好、性能优化、拓扑分布 |
高级注意事项:
- 多污点与多容忍:一个节点可以有多个污点,一个Pod可以有多个容忍度。只有当Pod容忍了节点的所有污点时,才能被调度到该节点。
- 优先级:当同时使用节点亲和性和污点/容忍度时,调度器会先检查污点/容忍度,再检查节点亲和性。
- 手动指定节点:如果手动为Pod指定了.spec.nodeName,那么选节点操作会绕过调度器;这个Pod将会绑定到你指定的节点上,即使该节点上有NoSchedule的污点。
- 静态Pod:通过kubelet管理的静态Pod不受污点限制,可以运行在任何节点上。
污点和容忍使用示例:
给节点k8s-node2添加污点memory=low,污点效果是NoSchedule:禁止调度新的Pod到该节点(已运行的Pod不受影响)。
修改Deployment对象,给Pod template添加容忍memory=low,操作符operator: Equal,污点效果是NoSchedule。
或者操作符operator: Exists,只需要配置key: memory和污点效果是NoSchedule即可。
4、亲和力
亲和性(Affinity)和反亲和性(Anti-affinity)是Kubernetes提供的比nodeSelector更强大的Pod调度约束机制。主要优势包括:
- 表达能力更强:支持基于集合的查询操作符(In、NotIn、Exists、DoesNotExist等),而nodeSelector只能精确匹配所有指定标签。
- 规则灵活性:可以定义"软需求"(preferred)而非强制要求(required),当无法满足条件时仍允许调度。
- 拓扑感知:不仅能基于节点标签,还能基于其他Pod的标签进行调度决策。
亲和性功能由两种类型的亲和性组成:
- 节点亲和性:节点亲和性功能类似于 nodeSelector 字段,但它的表达能力更强,并且允许你指定软规则。
- Pod间亲和性/反亲和性:Pod间亲和性/反亲和性允许你根据其他 Pod 的标签来约束 Pod。
节点亲和性是根据节点上的标签来约束Pod可以调度到哪些节点上,类似于nodeSelector。节点亲和性有两种实现方式:
requiredDuringSchedulingIgnoredDuringExecution:调度器只有在规则被满足的时候才能执行调度,这是硬性要求。此功能类似于 nodeSelector, 但其语法表达能力更强。
preferredDuringSchedulingIgnoredDuringExecution: 调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点,调度器仍然会调度该 Pod,这是软性要求。
Pod间亲和性表示:如果某个节点上已经运行了一个或多个满足规则的Pod,则满足规则的新Pod也应该运行在这个节点上。
Pod间反亲和性表示:如果某个节点上已经运行了一个或多个满足规则的Pod,则满足规则的新Pod不应该运行在这个节点上。
同样的,Pod间亲和性/反亲和性也有requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution两种实现方式。
示例1:节点亲和性使用示例
可以使用 Pod 规约中的 .spec.affinity.nodeAffinity 字段来设置节点亲和性。例如,下面的 Pod 规约:
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0
在这一示例中,所应用的规则如下:
- 节点必须包含一个键名为 topology.kubernetes.io/zone 的标签,并且该标签的取值必须为 antarctica-east1 或 antarctica-west1(需要事先给节点打标签)。
- 节点最好具有一个键名为 another-node-label-key 且取值为 another-node-label-value 的标签。
可以使用 operator 字段来为 Kubernetes 设置在解释规则时要使用的逻辑操作符。例如,可以使用 In、NotIn、Exists、DoesNotExist、Gt 和 Lt 之一作为操作符。NotIn和DoesNotExist可用来实现节点反亲和性行为,也可以使用节点污点将Pod从特定节点上驱逐。
权重(weight)用于定义软性偏好(preferredDuringSchedulingIgnoredDuringExecution)规则的优先级,权重越大,该规则的优先级越高,但最终调度决策还受其他因素影响(如资源可用性、其他调度策略等)。
示例2:Pod间亲和性/反亲和性使用示例
要使用 Pod 间亲和性,可以使用 Pod 规约中的 .affinity.podAffinity 字段。对于 Pod 间反亲和性,可以使用 Pod 规约中的 .affinity.podAntiAffinity 字段。
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:2.0
上面示例定义了一条 Pod 亲和性规则和一条 Pod 反亲和性规则。Pod 亲和性规则配置为 requiredDuringSchedulingIgnoredDuringExecution,Pod反亲和性配置为 preferredDuringSchedulingIgnoredDuringExecution。亲和性规则规定只有节点打上topologyKey属性值对应的标签,并且节点上的Pod已打上security=S1标签时,调度器才可以将示例Pod调度到此节点上,否则调度器不会将示例Pod调度到节点上。反亲和性规则规定如果节点打上topologyKey属性值对应的标签,并且节点上的Pod已打上security=S2标签,则调度器应尝试避免将新Pod调度到此节点上。
二、Helm包管理器
Helm是Kubernetes的包管理器,用于高效查找、分享和使用Kubernetes软件构件。其主要功能包括:
- 管理chart:chart是Kubernetes应用程序的模板,Helm可以创建新chart,将其打包为tgz文件,并与chart仓库交互。
- 安装与卸载:在Kubernetes集群中安装和卸载chart。
- 发布管理:管理chart的发布周期。
Helm涉及三个核心概念:
- chart:包含创建Kubernetes应用程序所需的一组信息。
Kubernetes应用的打包格式,包含预配置的Kubernetes资源模板(YAML文件)和默认配置。结构示例如下:
mychart/
├── Chart.yaml # 元数据(名称、版本等)
├── values.yaml # 默认配置值
├── templates/ # Kubernetes资源模板
│ ├── deployment.yaml
│ ├── service.yaml
│ └── _helpers.tpl # 模板辅助函数
└── charts/ # 子chart依赖
创建Chart的命令与流程:
# 1. 生成chart骨架
helm create mychart
# 2. 编辑关键文件
# - Chart.yaml: 定义元数据(apiVersion/v2, name, version等)
# - values.yaml: 设置默认参数(如replicaCount: 1)
# - templates/*.yaml: 编写Kubernetes资源模板
# 3. 验证模板渲染(不实际部署)
helm template mychart
# 4. 打包chart(生成mychart-0.1.0.tgz)
helm package mychart
- config:可合并到chart中的配置信息,用于定制应用。
通过values.yaml定义的参数,用于定制化chart部署。支持动态注入到模板中,实现环境差异化配置。
配置方式:
- 静态配置:直接修改values.yaml文件
- 动态覆盖:
# 命令行覆盖
helm install myapp ./mychart --set replicaCount=2
# 通过文件覆盖
helm install myapp ./mychart -f custom-values.yaml
- release:特定配置下的chart运行实例。Chart与release的关系就像java中的类与对象实例的关系。
Chart在集群中的运行实例。同一chart可多次安装,每次生成独立的release(如dev-mysql和prod-mysql)。
部署与升级:
# 安装chart(生成release)
helm install myrelease ./mychart
# 查看release状态
helm status myrelease
# 升级release(修改配置后)
helm upgrade myrelease ./mychart --set image.tag=v2
# 回滚到历史版本
helm rollback myrelease 1
1、Helm的安装
安装Helm的步骤:
1. 下载helm压缩包并解压,官网下载地址:https://github.com/helm/helm/releases
wget https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gz
可以通过wget命令在线下载,或者打开官网地址手动下载之后上传到Linux服务器上。
2. 将解压后目录下的helm程序复制到/usr/local/bin/目录下,并通过helm version验证是否安装成功。
2、Helm的常用命令
类别 |
命令 |
功能说明 |
使用示例 |
Chart操作 |
helm create <chart> |
创建新chart模板 |
helm create mychart |
helm package <chart> |
打包chart为.tgz文件 |
helm package ./mychart --version 1.0.0 |
|
helm lint <chart> |
检查chart语法错误 |
helm lint ./mychart --strict |
|
helm template <chart> |
渲染模板但不部署 |
helm template mychart -f prod-values.yaml |
|
Release管理 |
helm install <release> <chart> |
部署chart |
helm install nginx bitnami/nginx --set replicaCount=2 |
helm upgrade <release> <chart> |
升级release |
helm upgrade myapp ./mychart --set image.tag=v2 |
|
helm uninstall <release> |
卸载release |
helm uninstall myapp --keep-history |
|
helm rollback <release> <rev> |
回滚到指定版本 |
helm rollback myapp 2 |
|
helm list |
列出release |
helm list -a |
|
helm status <release> |
查看release状态 |
helm status myapp -o yaml |
|
helm history <release> |
查看版本历史 |
helm history myapp --max 5 |
|
仓库操作 |
helm repo add <name> <url> |
添加仓库 |
helm repo add bitnami https://charts.bitnami.com/bitnami |
helm repo update |
更新本地仓库索引 |
helm repo update --fail-on-repo-update-fail |
|
helm repo remove <name> |
移除仓库 |
helm repo remove bitnami |
|
helm repo list |
列出已配置仓库 |
helm repo list -o json |
|
实用工具 |
helm search repo <keyword> |
搜索仓库中的chart |
helm search repo mysql -l |
helm pull <chart> |
下载chart到本地 |
helm pull bitnami/nginx --untar |
|
helm lint <chart> |
检查chart语法错误 |
helm lint mychart |
|
helm get manifest <release> |
获取已部署资源清单 |
helm get manifest myapp --revision 3 |
|
helm plugin install <path> |
安装插件 |
helm plugin install https://example.com/helm-diff |
高级用法示例
1. 多环境部署:
helm install myapp ./mychart -f dev-values.yaml --set env=dev
使用文件覆盖默认配置并动态设置环境变量。
2. 依赖管理:
helm dependency update ./mychart
更新chart的子chart依赖。
3. 调试技巧:
helm install --dry-run --debug ./mychart
模拟安装并输出调试信息。
3、chart详解
Redis chart实践:
1. 修改Helm源,添加新仓库:
- 添加Bitnami仓库:helm repo add bitnami https://charts.bitnami.com/bitnami
- 添加阿里云仓库:helm repo add aliyun https://apphub.aliyuncs.com/stable
- 添加Azure仓库:helm repo add azure http://mirror.azure.cn/kubernetes/charts
添加仓库之后,使用命令helm repo list来列出当前配置的Helm仓库。
2. 搜索chart
# 搜索redis chart
helm search repo redis
# 查看安装说明
helm show readme bitnami/redis
3. 修改配置安装
将Redis Chart拉取到本地并解压:
helm pull bitnami/redis
tar -zxvf redis-xxx.tgz
解压之后得到一个redis目录,这个redis目录就是chart,进入到redis目录,可以看到里面的文件与chart结构一致,包括Chart.yaml、charts、templates和values.yaml等。
修改配置:修改values.yaml中的参数,包括设置存储类为managed-nfs-storage(managed-nfs-storage是在前面讲解“PV与PVC”时创建的StorageClass),配置Redis密码,选择架构(standalone或replication),调整实例存储大小,以及设置对外暴露端口范围在30000-32767之间。
vim values.yaml
创建命名空间与安装:执行helm install <release> <chart> -n <namespace>命令进行安装
使用kubectl create namespace redis命令创建命名空间redis,在解压后的目录中运行helm install redis ./redis -n redis命令来安装Redis,这个命令中第一个redis是安装的服务名称,第二个redis是chart的名称,第三个redis是命名空间的名称。
4. 升级与回滚release
升级redis:执行helm upgrade <release> <chart> -n <namespace>命令进行升级。
回滚redis:执行helm rollback <release> <version> -n <namespace>命令回滚到指定版本。
查看历史版本:helm history <release> -n <namespace>
回滚到上一版本:helm rollback <release> -n <namespace>
5. 删除或卸载release
通过kubectl delete(或uninstall) <release> -n <namespace> 命令卸载release,release卸载之后不会自动删除PVC,如果需要删除PVC,需要手动删除,PVC被删除之后,PV也会被自动删除。PVC是属于命名空间级别的资源,PV是属于集群级别的资源。
更多推荐
所有评论(0)