首页
常用运维脚本汇总
电子书阅读
Search
1
安装docker时报错container-selinux >= 2:2.74
172 阅读
2
rsync命令(可替代rm删除巨量文件)
141 阅读
3
docker 镜像加速器配置,daemon.json文件详解
133 阅读
4
使用国内镜像地址拉取k8s安装需要的images
94 阅读
5
docker search命令提示i/o timeout的解决方案
93 阅读
运维
自动化运维
数据库
容器与k8s
环境
云计算
脚本
ai
登录
Search
标签搜索
命令
nginx
zabbix
Mingrui
累计撰写
92
篇文章
累计收到
8
条评论
首页
栏目
运维
自动化运维
数据库
容器与k8s
环境
云计算
脚本
ai
页面
常用运维脚本汇总
电子书阅读
搜索到
69
篇与
的结果
2025-04-23
集群存储之持久卷介绍
Kubernetes支持的内置(in-tree)持久卷类型包括hostPath(宿主机目录)、FC(fibre Channel)、iSCSI(iSCSI存储设备)、Local(本地持久化存储)、NFS(基于NFS协议的网络文件系统)等资源。它们不作为PV资源对象被创建,而是直接在Pod的Volume字段被设置和使用。下面就常用的hostPath和NFS做简要介绍。hostPathhostPath类型的Volume用于将Node文件系统的目录或文件挂载到容器内部,并且在Pod删除后数据仍然被保留。由于hostPath直接使用宿主机的文件系统,无法被Kubernetes直接管理,因此存在很多安全风险,建议尽量不要使用。在必须要用时尽量以只读的方式将其挂载到容器内,以尽量减少对容器应用可能造成的破坏。使用场景容器应用的关键数据需要持久化保存到宿主机上;需要使用docker中的某些内部机制,可以将主机的/var/lib/docker目录挂载到容器内;监控系统,例如cAdvisor需要采集宿主机/sys/目录下的内容;Pod的启动依赖于宿主机上的某个目录或文件就绪。hostPath的主要配置参数为path,表示宿主机目录或文件路径;还可以设置一个可选的参数type,表示路径的操作类型。type的配置参数如下:type参数检校规则空默认值,系统在挂载path时不做任何检校DirectoryOrCreatepath指定的路径必须是目录,如果不存在系统将自动创建该目录,并将目录的权限设置为0755,具有与Kubelet相同的owner和groupDirectorypath指定的路径必须是目录,否则挂载失败FileOrCreatepath指定的路径必须是文件,如果不存在,系统将自动创建该文件,并将文件的权限设置为0644,具有与Kubelet相同的owner和groupFilepath指定的路径必须是文件,否则挂载失败SocketPath指定的UNIX Socket必须存在,否则挂载失败CharDevicepath指定的字符设备必须存在,否则挂载失败BlockDevicepath指定的块设备必须存在,否则挂载失败对于type为FileOrCreate模式的情况,如果挂载文件有上层目录,则系统不会自动创建上层目录,当上层目录不存在时,Pod启动失败。在这种情况下,可以将上层目录也设置为一个hostPath类型的Volume,并且设置type为DirectoryOrCreate,确保当目录不存在时,系统会自动创建出来。注意事项通过hostPath可能会将宿主机的某些具有特殊权限的文件挂载到容器内,例如Kubelet和容器运行时的Socket,使得容器的进程也能够越权对宿主机进行某些操作;对具有相同hostPath设置的多个Pod来说,可能会被master调度到多个Node上运行,但如果这些Node上的hostPath中的文件夹的内容(如配置文件这些)不同,则各个Pod的运行结果可能会出现差异;如果管理员设置了某些基于存储资源情况的调度策略,则hostPath目录下的磁盘空间将无法计入Node的可用资源范围内,可能出现与预期不同的调度结果;如果是之前不存在的路径,由Kubelet自动创建的文件或目录的owner和group将是root。这意味着如果容器内运行的用户(user)不是root,则将无法对该目录进行写操作,除非将容器设置为特权容器,或者由管理员修改hostPath的权限;hostPath设置的宿主机目录或文件不会随着Pod的销毁而被删除,而是在Pod被销毁之后,由管理员手动删除。NFSNFS类型的Volume用于将基于NFS协议的网络网络文件系统中的目录或文件挂载到容器内使用,并且在Pod被删除后数据仍然被保留。在Pod使用NFS协议的Volume之前,需要确保NFS服务正常运行。另外,也不能像PV那样使用mountOptions字段来定义挂载项。NFS卷可以在不同节点的Pod间共享数据。本地NFS客户端可以透明的读写位于远端NFS服务器上的 文件,就像访问本地文件一样。
2025年04月23日
45 阅读
0 评论
0 点赞
2025-04-23
集群存储之临时卷介绍
Volume在集群中也是一种资源,Pod通过挂载(Mount)的方式来使用一个或多个Volume。某些类型的Volume具有与Pod相同的生命周期,被称为“临时卷”。emptyDIr该类型的Volume在Pod被调度到Node时由Kubelet进行创建,在初始状态下是个空目录,被命名为“空目录”(Empty DIrectory)。它与Pod具有相同的生命周期,当Pod被销毁时,emptyDir对应的目录也会被删除。同一个Pod中的多个容器都可以挂载这种类型的Volume。使用场景基于磁盘进行合并排序操作时需要的暂存空间;长时间计算任务的中间检查点文件;为某个Web服务提供的临时网站内容文件。同一个Pod中容器共享数据使用内存提供存储服务emptyDir可以通过medium字段设置存储介质为“Memory”,表示使用基于内存的文件系统。需要注意的是,在主机重启后,内存中存储的信息会被清空。写入内存的数据将被计入容器的内存使用量,受到容器级别内存资源上限(Memory Resource Limit)的限制。示例{tabs}{tabs-pane label="示例1"}--- apiVersion: v1 kind: pod metadata: name: pod1 spec: containers: - image: busybox name: test1 volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}{/tabs-pane}{tabs-pane label="示例2"}#设置emptyDir使用内存 apiVersion: v1 kind: pod …… volumes: - name: cache-volume emptyDir: medium: "Memory"{/tabs-pane}{tabs-pane label="示例3"}#设置emptyDir使用内存,并设置可使用的内存上限 #需要开启SizeMemoryBackedVolumes apiVersion: v1 kind: pod …… volumes: - name: cache-volume emptyDir: medium: "Memory" sizeLimit: 500Mi{/tabs-pane}{/tabs}Generic EphemeralGeneric Ephemeral类型的Volume(通用临时卷)与emptyDir的功能相似,但更加灵活,有以下特性:后端的存储既可以是本地磁盘,也可以是网络存储;可以为Generic Ephemeral设置容量上限;在Generic Ephemeral内可以有一些初始数据。在驱动支持的情况下,Generic Ephemeral支持快照、克隆、调整大小、容量跟踪等标准的卷操作。示例--- apiVersion: v1 kind: pod metadata: name: my-app spec: containers: - name: my-frontend image: busybox command: [ "sleep", "1000" ] volumeMounts: - mountPath: "/scratch" name: scratch-volume volumes: - name: scratch-volume ephemeral: volumeClaimTemplate: matedata: labels: type: my-frontend-volume spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "scratch-storage-class" resources: requests: storage: 1Gi 说明: 上面的示例中,Generic Ephemeral类型的Volume的参数设置需要从storageClass"scratch-storage-class"中申请1GiB的存储空间。根据volumeClaimTemplate的配置,系统将自动创建一个对应的PVC,并确保在删除Pod时自动删除这个PVC。这个PVC会以Pod的名称和Volume的名称的组合为其命名,中间以“-”连接,本例中PVC的名称是“my-app-scratch-volume”。某些情况下,这种命名机制可能会引起冲突,在部署Pod时需要注意。在安全方面,当用户有权限创建Pod的时候,Generic Ephemeral会隐式地创建一个PVC(即使用户没有创建PVC的权限),这可能不符合安全要求。{mtitle title="其他类型临时卷"/}Kubernetes的一些内部资源对象也可以通过Volume的形式挂载为容器的目录或文件,包括configMap、Secret、Downward API等,这些类型的Volume也是临时卷,会随着Pod的销毁而被系统删除。ConfigMapConfigMap主要保存应用所需的配置文件,并且通过Valume的形式挂载到容器内的文件系统中,以供容器内的应用读取。这样就可以做到配置文件与镜像的分离,使容器具有可移植性。ConfigMap在使用之前需要先创建它,ConfigMap不能用来保存大量的数据,其中保存的数据不可以超过1MIB。ConfigMap主要用来生成容器内的环境变量,设置容器启动命令的命令行参数(需要设置为环境变量),以Volume的形式挂载为容器内的文件或目录等。由于ConfigMap受限于命名空间,所以要引用ConfigMap的Pod必须与ConfigMap处于相同的命名空间中才能被成功引用。静态Pod因为不受master管理,无法引用ConfigMap。创建ConfigMap的方式ConfigMap中不存在spec字段,它通过data或binaryData字段定义配置数据。data字段用于保存经过utf-8编码的字符串,binaryData字段用于保存经过Base64编码的二进制数据。ConfigMap中有个immutable字段,用于设置配置数据不可更改。即ConfigMap一旦创建成功后就不可修改。设置这个字段可以防止意外更新ConfigMap对应用带来的异常影响,减少API Server监控ConfigMap的变化带来的性能损耗。1.基于本地配置文件--- apiVersion: v1 kind: ConfigMap metadata: name: cm-appvare data: apploglevel: info appdatadir: /var/data#通过kubectl创建这个ConfigMap kubectl apply -f cm-appvare.yaml2.基于kubectl命令行 可以直接通过kubectl create configmap 命令创建ConfigMap,支持通过下面三种参数来指定不同类型的数据源创建ConfigMap。--from-file:基于指定的文件或目录创建ConfigMap--from-env-file:基于指定的env文件创建ConfigMap--from-literal:基于指定的键值对创建ConfigMap--from-file 如果基于指定文件创建ConfigMap,默认情况下key的值会被设置为文件名,value的值会被设置为问几点内容。也可以通过命令行参数指定key名,不将文件名作为key名。如果基于指定的目录创建ConfigMap,则目录下的每个文件都会被创建为data中的一个key:value键值对。参数--from-file可以多次出现,用于在一个kubectl create命令行中将多个文件或目录创建到一个ConfigMap中。用文件名作为key值时需要注意文件名要符合key的命名规范,否则命令将运行失败。名称中只能使用这些字符:[a-z] [A-Z] [0-9] - _ .#在当前目录下存在server.xml文件,创建一个只包含该文件内容的ConfigMap kubectl create configmap server-config --from-file=server.xml #在当前目录下有个configs子目录,里面有两个配置文件,创建一个包含这两个配置文件内容的ConfigMap kubectl create configmap app-config --from-file=./configs #创建ConfigMap时指定key的名字为mykey kubectl create configmap server-config --from-file=mykey=server.xml #多次使用--from-file参数,创建一个包含多个配置文件内容的ConfigMap kubectl create configmap app-config --from-file=server.xml --from-file=logging.properties--from-env-file--from-env-file同样支持多次使用该参数创建一个包含多个源配置文件的ConfigMap。 env文件包含一组环境变量的配置数据,其内容遵循如下语法规则:每行文本都为VAR=VALUE的格式,等号两边不能有空格忽略以“#”开头的注释行忽略空行对文本中的引号不做转义处理,即保留原始文本并将其作为value的值#环境变量文件示例 cat log.properties level=FINE directory="${catalina.base}/logs" prefix=catalina. #通过kubectl create命令进行创建 kubectl create configmap log-env-config --from-env-file=log.properties --from-literal --from-literal可以多次使用从而生成多个ConfigMap的数据内容。使用该参数时只能直接从命令行输入键值对,适用于简单的环境变量或少量键值对。该参数生成的ConfigMap无法动态更新。kubectl create configmap appenv --from-literal=loglevel=info --from-literal=appdatadir=/var/data在Pod中使用ConfigMap容器应用通过以下两种方式使用ConfigMap将ConfigMap中的内容设置为容器的环境变量通过volume将ConfigMap中的内容挂载为容器内的文件或目录{tabs}{tabs-pane label="ConfigMap文件示例"}cat cm-appvars apiVersion: v1 kind: ConfigMap metadata: name: cm-appvars data: apploglevel: info appdatadir: /var/data{/tabs-pane}{tabs-pane label="挂载示例1"}apiVersion: v1 kind: Pod metadata: name: cm-test-pod spec: containers: - name: cm-test image: busybox command: [ "/bin/sh", "-c", "env | grep APP" ] env: - name: APPLOGLEVEL #定义环境变量的名称 valueFrom: #key"APPLOGLEVEL"对应的值 configMapKeyRef: name: cm-appvars #环境变量的值取自cm-appvars key: apploglevel #key为apploglevel - name: APPDATADIR #定义环境变量的名称 valueFrom: #key"APPDATADIR"对应的值 configMapKeyRef: name: cm-appvars #环境变量的值取自cm-appvars key: appdatadir #key为appdatadir restartPolicy: Never kubectl create -f cm-test-pod.yaml kubectl logs cm-test-pod APPDATADIR=/var/data APPLOGLEVEL=info{/tabs-pane}{tabs-pane label="挂载示例2"}--- apiVersion: v1 kind: Pod metadata: name: cm-test-pod spec: containers: - name: cm-test image: busybox command: [ "/bin/sh", "-c", "env" ] envFrom: - configMapRef: name: cm-appvars restartPolicy: Never kubectl apply -f cm-test-pod2.yaml kubectl logs cm-test-pod2 apploglevel=info appdatadir=/var/data{/tabs-pane}{/tabs}示例2中通过envFrom字段,实现了在Pod环境下将ConfigMap中的所有key:value键值对都自动生成环境变量。环境变量的命名受POSIX命名规范约束(a-zA-Z_*),不能以数字开头。如果包含非法字符,则系统将挑过该环境变量的创建,并记录一个Event来提示环境变量无法生成,但并不阻止Pod的启动。通过Volume将ConfigMap中的内容挂载为容器内的文件或目录 {tabs}{tabs-pane label="configmap文件内容"}--- apiVersion: v1 kind: ConfigMap metadata: name: cm-appconfigfiles data: key-serverxml: | <?xml version='1.0' encoding='utf-8'?> <Server port="8005" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> …… …… </Service> </Server> key-loggingproperties: "handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, …… …… = 4host-manager.org.apache.juli.FileHandler\r\n\r\n"{/tabs-pane}{tabs-pane label="示例1"}--- apiVersion: v1 kind: Pod metadata: name: cm-test-app spec: containers: - name: cm-test-app image: kubeguide/tomcat-app:v1 ports: - containerPort: 8080 volumeMounts: - name: serverxml #引用Volume的名称 mountPath: /configfiles #挂载到容器内该目录下 volumes: - name: serverxml #定义Volume的名称 configMap: name: cm-appconfigfiles #指定ConfigMap的名称 items: - key: key-serverxml #ConfigMap中key的名称 path: server.xml #key对应的值(value)将以server.xml文件名挂载 - key: key-loggingproperties #ConfigMap中key的名称 path: logging.properties #key对应的值(value)将以logging.properties文件名挂载到容器内 kubectl exec -it cm-test-app --bash ls /configfiles sserver.xml logging.properties{/tabs-pane}{tabs-pane label="示例2"}#如果在引用ConfigMap时不指定items,则通过volumeMount方式在容器内的目录下为每个item都生成一个名为“key”的文件,文件的内容为key的值。 --- apiVersion: v1 kind: Pod metadata: name: cm-test-app spec: containers: - name: cm-test-app image: kubeguide/tomcat-app:v1 imagePullPolicy: Never ports: - containerPort: 8080 volumeMounts: - name: serverxml #引用Volume的名称 mountPath: /configfiles #挂载到容器的该目录下 volumes: - name: serverxml #定义Volume的名称 configMap: name: cm-appconfigfiles #使用ConfigMap“cm-appconfigfiles” kubectl exec -it cm-test-app --bash ls /configfiles key-loggingproperties key-serverxml {/tabs-pane}{/tabs}ConfigMap可选设置在Pod的定义中,可以将对ConfigMap的引用设置为是否可选(optional),若设置为可选(optional=true),则表示如果ConfigMap不存在,或者引用的数据项在ConfigMap中不存在,那么目标数据将被设置为空值。当ConfigMap被设置为Volume存储卷时,表示当ConfigMap不存在时,目标挂载的文件内容是空的。{tabs}{tabs-pane label="示例1"}--- apiVersion: v1 kind: Pod metadata: name: cm-test-pod-cm-env-optional spec: containers: - name: cm-test image: busybox command: [ "/bin/sh", "-c", "env | grep APP" ] env: - name: APPLOGLEVEL valueFrom: configMapKeyRef: name: cm-appvars key: apploglevel optional: true #设置为可选 - name: APPDATADIR valueFrom: configMapKeyRef: name: cm-appvars key: appdatadir optional: true #设置为可选 restartPolicy: Never kubec logs cm-test-pod-cm-env-optional [结果为空]{/tabs-pane}{tabs-pane label="示例2"}--- apiVersion: v1 kind: Pod metadata: name: cm-test-app-cm-volume-optional spec: containers: - name: tomcat image: busybox command: [ "/bin/sh", "-c", "tail -f /dev/null" ] volumeMounts: - name: serverxml mountPath: /configfiles volumes: - name: serverxml configMap: name: cm-appconfigfiles optional: true kubectl exec -it cm-test-app-cm-volume-optional --bash ls /configfiles [结果为空]{/tabs-pane}{/tabs}SecretSecret专门用于保存机密数据。在设置Secret.data字段时,所有键值都必须是经过base64编码的字符串。Secret主要用来为容器配置环境变量,挂载配置文件/目录到容器。此外,由Kubelet为Pod拉取镜像时,在需要登录仓库的时候使用。Downward API通过Downward API 可以将Pod或者Container的某些元数据信息(如Pod名称、Pod IP、Node Ip、Label、Annotation、容器资源限制等)以文件的形式挂载到容器内,以供容器内的应用使用。Downward API可以通过两种方式将Pod和容器的元数据信息注入到容器内。环境变量方式:将Pod或container的配置信息设置为容器内的环境变量Volume挂载方式:将Pod或container的配置信息以文件的形式挂载到容器内Downward API支持设置的Pod和Container信息可以通过fieldRef设置的字段字段名说明metadata.namePod名称metadata.namespacePod所在名称空间的名称metadata.uidPod的UIDmetadata.labels['']Pod的某个Label的值,通过引用metadata.annotations['']Pod某个Annotation的值,通过引用Pod的以下元数据信息可以被设置为容器内的环境变量,但在设置downwardAPI为存储卷类型时不能再设置filedRef字段的内容字段名说明spec.serviceAccountNamePod使用的ServiceAccount名称spec.nodeNamePod所在的Node的名称status.hostIPPod所在Node的IP地址status.hostIPsPod所在Node的IPv4和IPv5双栈地址status.podIPPod的IP地址status.podIPsPod的IPv4和IPv5双栈地址在设置downwardAPI为存储卷类型时,可以在其fieldRef字段设置以下信息,但不能通过环境变量的方式设置。mmetadata.lables:Pod的Label列表,每个Lable都以key为文件名,value为文件的内容,每个Label各占一行metadata.annotation:Pod的Annotation列表,每个Annotation都以key为文件名,value为文件的内容,每个Annotation各占一行可以通过resourceFieldRef设置的字段字段名说明limits.cpuContainer级别的CPU Limitrequests.cpuContainer级别的CPU Requestlimits.memoryContainer级别的Memory Limitrequests.memoryContainer级别的Memory Requestlimits.hugepages-*Container级别的HugePage(巨页)Limitrequests.hugepages-*Container级别的HugePage(巨页)Requestlimits.ephemeral-storageContainer级别的临时存储空间Limitrequests.ephemeral-storageContainer级别的临时存储空间RequestProjected VolumeProjected Volume是一种特殊的Volume类型,用于将一个或多个资源对象(ConfigMap、Secret、Downward API)一次性挂载到容器内的同一个目录下。常见应用场景通过Pod的标签生成不同的配置文件,需要使用配置文件及用户名和密码时,需要使用3种资源:ConfigMap、Secret、Downward API。在自动化运维应用中使用配置文件和帐号信息时,需要使用ConfigMap、Secret。在配置文件中使用Pod名称(metadata.name)记录日志时,需要使用ConfigMap、Downward API。使用某个Secret对Pod所在的命名空间(metadata.namespace)进行加密时,需要使用Secret、Downward API。Project Volume在Pod的Volume定义中类型为projected,通过sources字段来设置一个或多个的ConfigMap、Secret、Downward API、Service Account Token等资源。各种类型的资源配置内容与单独设置为Volume时基本一致,需要注意以下两个不同点:对于Secret类型的Volume,字段名“secretName”在projected.sources.secret中被改为“name”;Volume的挂载模式“defaultMode”只可以设置为projected级别。对于各子项,仍然可以设置各自的挂载模式,使用的字段名为“mode”。
2025年04月23日
46 阅读
0 评论
0 点赞
2025-04-21
对容器进行资源限额的几种方式
在一个集群内如何更合理的为大量容器分配有限的资源,是需要重点运维和管理的工作。
2025年04月21日
42 阅读
0 评论
0 点赞
2025-04-18
容器的调度策略介绍
kubernetes scheduler是负责Pod调度的进程(组件),它的作用是先对等待调度的Pod通过一些复杂的调度流程计算出其最佳的目标Node,再將Pod绑定到目标Node上。随着kubernetes功能的不断增强和完善,Pod的调度也变得越来越复杂。Scheduler内部的实现机制也在不断优化,从最初的两阶段调度机制(Predicates&Priorities)发展到现在的调度框架(Scheduling Framework),以满足越来越复杂的调度场景。Pod调度复杂的原因:kubernetes要努力满足不同类型应用的不同需求并努力让大家和平相处。kubernetes集群里的Pod可以分为三类:无状态服务类,有状态集群类,批处理类。不同类型的Pod对资源占用的需求不同,对Node故障引发的中断/恢复及Node迁移方面的容忍度不同。调度流程kube-apiserver将待调度的Pod的信息发送给kube-scheduler,scheduler通过一系列的计算把Pod要绑定的最优Node(或者暂时不存在)信息返还返还给apiserver。调度流程过滤阶段(Filtering):遍历所有的Node,筛选出符合要求的候选Node。此阶段Scheduler会将不合适的Node全部过滤掉,只留下符合条件的候选Node。具体方式是通过一系列待定的Predicates对每个Node进行筛选,在筛选完成后通常会有多个候选Node供调度,从而进入打分阶段。如果筛选的结果集为空,则表示当前没有符合条件的Node,此时Pod会一直处于Pending状态。打分阶段(Scoring):在过滤阶段的基础上,采用优选策略计算出每个候选Node的积分,积分最高者胜出。在挑选出最佳Node后,Scheduler会把目标Pod安置到该Node上,完成调度。注:当Node处于以下状态时,Scheduler不在给它调度新的Pod。NotReadyUnschedulableMemoryPressure(不再调度新的BestEffort PodPod到这个Node)DiskPressure调度策略指定Node名称的定向调度策略Kubernetes支持在Pod的配置中通过指定nodeName字段的方式指定要调度的目标Node名称。这个字段的优先级高于nodeSelector和亲和性策略。设置了nodeName字段的Pod将不再参与调度器的调度过程,相当于已经完成了调度,apiserver将直接通知目标Node上的kubelet开始创建这个Pod。使用nodeName具有以下限制:如果指定的node不存在或者失联,则Pod将无法运行;如果指定的node资源不足,则pod可能会运行失败;在某些云环境下,node名称不一定是稳定的。验证一下污点策略的优先级示例:--- apiVersion: v1 kind: pod metadata: name: nginx spec: containers: - name: nginx image: nginx nodeName: 192.168.88.61基于Node Label的调度策略Node也是kubernetes管理的一种资源对象,可以为其设置多个Label。在Pod的配置中,可以方便的使用Label Selector来声明需要调度到具有指定Label的Node上,调度器会在具有这些Label的Node中进行选择。通过基于Node Label的调度方式,可以把集群中具有不同特点的Node都贴上不同的Label(如“role=frontend”,“role=backend”,“role=database”等),在部署应用时可以根据应用的需求设置NodeSelector来进行指定Node范围的调度。需要注意的是,如果指定了nodeselector条件,但是在集群中不存在包含相应Label的Node,那么集群中即便存在可供使用的Node,这个Pod也无法被成功调度。示例:--- apiVersion: v1 kind: pod metadata: name: pod-node-selector spec: nodeSelector: disk: ssd containers: - name: busybox image: busybox command: ['sh','-c','sleep 3600']亲和性调度策略亲和性和反亲和性的机制,扩展了Pod的调度能力,实现了更加灵活和精细的策略。其具有如下优点:更强的逻辑选择能力(不仅仅是“符合全部”的简单情况)可以设置为软性限制或优选,使得调度器在无法找到全部满足要求的Node时,也会寻找其他Node来调度Pod。除了基于Node上的Label,还可以依据Node上正在运行的其他Pod的Label来进行亲和性和反亲和性设置。这样可以定义一组规则来描述Pod间的亲和或者互斥关系。亲和性调度功能包括节点亲和性(NodeAffinity)和Pod亲和性(PodAffinity)两种类型。节点亲和性调度策略节点亲和性调度策略与NodeSelector类似,但表达能力更强,并且允许设置软性匹配规则。设置方法也是通过Node上的Label来设置Pod是否可以调度到目标Node上。节点亲和性的配置类型有以下两种:requiredDuringSchedulingIgnoredDuringExecution:必须满足指定的规则才可以调度Pod到Node上,是硬性要求,它的功能与nodeSelector相似,但是使用的是更加灵活的语法。preferredDuringSchedulingIgnoredDuringExecution:强调优先满足指定规则,调度器会尝试调度Pod到Node上,但并不强求,是软性限制。可以设置多个规则,还可以给每个规则设置权重值(weight),以定义判断的优先级顺序。权重 可以为每个规则设置一个1-100的权重值(weight),用于给调度器提供一个类似于优先级的分数,调度器会为满足条件的Node加上weight设置的值,以选出最终得分最高的Node。这两种策略中的IgnoredDuringExecution的意思是:如果一个Pod所在的节点在Pod运行期间其标签发生了变化,不再符合该Pod的亲和性需求,则系统将忽略Node上的Label变化,让Pod在原Node上继续运行。也就是说Pod正常运行后,不再对Node进行亲和性验证。在Label的匹配规则中,使用逻辑操作符(operator)进行设置,可用使用的操作符及其含义如下:In:Label的值(value)在给定的集合中。NotIn: Label的值(value)不在给定的集合中。Exists:需要具有此Label Key,此时不需要设置key的值。DoseNotExist:需要不存在此Label的值,此时不需要设置key的值。Gt;Label的值(Value)的整数值需要大于给定的值。Lt:Label的值(Value)的整数值需要小于给定的值。{callout color="#f75008"}NodeAffinity规则设置的注意事项如下:如果在Pod配置中同时使用了nodeSelector和nodeAffinity,那么必须两个条件都得到满足,才能将Pod调度到指定的Node上。(既要满足标签调度策略,又要满足亲和性调度策略。)如果nodeAffinity指定了多个nodeSelectorTerms,则则只需要其中一个条件能匹配成功就能完成Pod的调度,即多个条件之间是逻辑或(or)的关系。如果matchExperssions在nodeSelectorTerms中设置了多个条件表达式,那么必须满足所有的条件才能完成Pod的调度,即多个条件之间是逻辑与(and)的关系。{/callout}{tabs}{tabs-pane label="示例一"}#要求运行在具有标签“kubernetes.io/arch=amd64”的节点上。 #要求尽量运行在具有标签“disk-type=ssd”的节点上,如果没有,也可以运行在其他节点上。 --- apiVersion: v1 kind: Pod metadata: name: pod-with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disk-type operator: In values: - ssd containers: - name: nginx image: nginx {/tabs-pane}{tabs-pane label="示例二"}对于具有zone=north标签的节点,系统会在调度算法的得分上加1(weigh=1),对于具有dis-type=ssd标签的节点,系统会在调度算法得分上加50(weight=50),然后综合其他条件计算出最终得分,并将pod调度到得分最高的Node上。apiVersion: v1 kind: Pod metadata: name: pod-with-node-affinity-weight spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: zone operator: In values: - north - weight: 50 preference: matchExpressions: - key: disk-type operator: In values: - ssd containers: - name: nginx image: nginx {/tabs-pane}{/tabs}Pod亲和性调度策略Pod亲和性:存在某些相互依赖,需要频繁互相调用的Pod,它们需要被尽可能地部署在同一个节点、机架、机房、网段或者区域(Zone)内。Pod反亲和性:处于避免竞争或者容错的需求,也可能使某些Pod尽可能地远离另外一些Pod。简单来说,某几个Pod可以在同一个拓扑域中共存,就是“Pod Affinity”,不能在同一个拓扑域中共存,就是“Pod Anti Affinity”。Pod亲和性与反亲和性调度的具体做法,就是通过在Pod的定义中增加topologyKey属性,来声明对应的目标拓扑域内几种相关联的Pod是“在一起还是不在一起”。需要注意的是,对于Pod的反亲和性策略,要求目标Node上需要存在相同的Label,实际上就是要求每个节点都具有相同的topologyKey指定的Label。如果某些Node不具有topologyKey指定的Label,则可能造成不可预估的调度结果。另外,设置Pod间的亲和性和反亲和性规则,会给调度器引入更多的计算量,在大规模集群中可能会造成性能问题,因此在配置Pod间的亲和性策略时需要谨慎。关于topoloygKey: 拓扑域:一个拓扑域由一些Node组成。这些Node通常具有相同的地理空间坐标。比如,在同一个机架、机房或地区。一般用Region表示机架、机房等的拓扑区域,用Zone表示地区这样跨度更大的拓扑区域。在某些情况下,可以认为一个Node就是一个拓扑区域。kubernetes为Node内置了一些常用的用于表示拓扑域概念的Label。kubernetes.io/hostnametopoloyg.kubernetes.io/regiontopoloyg.kubernetes.io/zone以上拓扑域是由kubernetes自己维护的。在node初始化时,Controller Manager会为Node设置许多标签。如,kubernetes.io/hostname这个标签的值会被设置为Node的hostname,云厂商会设置topoloyg.kubernetes.io/region和topoloyg.kubernetes.io/zone的值,以确定各个Node所属的拓扑域。{tabs}{tabs-pane label="参照Pod"}#带有两个Label --- apiVersion: v1 kind: Pod metadata: name: pod-flag labels: security: "S1" app: "nginx" spec: containers: - name: nginx image: nginx{/tabs-pane}{tabs-pane label="亲和性调度"}#亲和性Label是“security=S1” --- apiVersion: v1 kind: Pod metadata: name: pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: kubernetes.io/hostname containers: - name: pod-affinity image: nginx{/tabs-pane}{tabs-pane label="反亲和性调度1"}#新Pod与具有security=S1的Label的Pod在同一个zone的Node上运行 # 新Pod不能与具有app=nginx的Label的Pod在同一个Node上运行 --- apiVersion: v1 kind: Pod metadata: name: pod-anti-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: topology.kubernetes.io/zone podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: kubernetes.io/hostname containers: - name: pod-anti-affinity image: nginx{/tabs-pane}{tabs-pane label="反亲和性调度2"}#在同一个Node上不运行多个Pod副本。 --- apiVersion: apps/v1 kind: Deployment metadata: name: app-with-anti-affinity spec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: "kubernetes.io/hostname" containers: - name: nginx image: nginx {/tabs-pane}{/tabs}污点和容忍度调度策略污点(Taint)配置在Node上,可以让Node拒绝一些具有某些特征的Pod在其上运行。容忍度(Toleration)配置在Pod中,用于高速系统允许调度到具有指定污点的节点上运行。默认情况下,在Node上设置一个或多个Taint后,除非Pod声明中明确能够容忍这些污点,否则无法在这些Node上运行。污点和容忍度的配合使用,可以避免将Pod调度到不合适的Node上。例如,某个Node存在问题(磁盘空间不足,计算资源不足,存在安全隐患等),希望新的Pod不要调度过来,就可以通过设置某些污点来实现。但设置了污点的Node并非不可用,仍是有效的Node。所以对于可用在这些Node上运行的Pod,可以给Pod设置与污点匹配的容忍度来实现调度。污点策略:PreferNoSchedule 尽量不调度,一个Pod如果没有声明容忍这个Taint,则系统会尽量避免把这个Pod调度到这一个Node上,但不保证一定能够避免NoScheduler 不被调度,除非Pod设置了与Taint匹配的容忍度。NoExecute 驱逐节点,不能在改node上运行,包括以下几种情况。对于正在该Node上运行的Pod,如果不能容忍指定的污点,则会被立刻从该Node驱逐。对于正在该Node上运行的Pod,如果能够容忍指定的污点,但未设置运行时限(tolerationSeconds),则会在该Pod上持续运行。对于正在该Node上运行的Pod,如果能够容忍指定的污点,但设置了运行时限(tolerationSeconds),则会在到达运行时限后从该Node上被驱逐。添加污点标签kubectl taint node node-0001 key=v1:PreferNoSchedule kubectl taint node node-0002 key=v2:NoScheduler容忍策略{tabs}{tabs-pane label="精确匹配"}…… spec: tolerations: - operator: "Equal" # 完全匹配键值对 key: "k" # 键 value: "v2" # 值 effect: "NoSchedule" # 污点标签 ……{/tabs-pane}{tabs-pane label="模糊匹配"}…… spec: tolerations: - operator: "Exists" # 部分匹配,存在即可 key: "k" # 键 effect: "NoSchedule" # 污点标签 ……{/tabs-pane}{tabs-pane label="所有污点标签"}…… spec: tolerations: - operator: "Exists" # 模糊匹配 key: "k" # 键 effect: # 没有设置污点标签代表所有 ……{/tabs-pane}{/tabs}优先级和抢占调度策略技术背景:对于运行各种负载(如Service,Job)的中等规模或者大规模的集群来说,需要尽可能提高集群的资源利用率。常规做法是采用优先级方案,即不同类型的负载对应不同的优先级,同时允许集群中的所有负载 所需要的资源总量超过集群可提供的资源。在这种情况下,当资源不足时,系统可以选择释放一些低优先级的负载,保障高优先级的负载获得足够的资源稳定运行。调度方式:由集群管理员创建priorityClass,Priority是不受限于命名空间的资源类型{tabs}{tabs-pane label="高优先级不抢占"}--- kind: PriorityClass apiVersion: scheduling.k8s.io/v1 metadata: name: high-non globalDefault: false preemptionPolicy: Never value: 1000 description: non-preemptive {/tabs-pane}{tabs-pane label="低优先级不抢占"}--- kind: PriorityClass apiVersion: scheduling.k8s.io/v1 metadata: name: low-non globalDefault: false preemptionPolicy: Never value: 500 description: non-preemptive{/tabs-pane}{tabs-pane label="高优先级抢占"}--- kind: PriorityClass apiVersion: scheduling.k8s.io/v1 metadata: name: high globalDefault: false preemptionPolicy: PreemptLowerPriority value: 1000 description: non-preemptive{/tabs-pane}{/tabs-pane}{tabs-pane label="低优先级抢占"}--- kind: PriorityClass apiVersion: scheduling.k8s.io/v1 metadata: name: low globalDefault: false preemptionPolicy: PreemptLowerPriority value: 500 description: non-preemptive{/tabs-pane}{/tabs-pane}{tabs-pane label="使用方式"}--- kind: Pod apiVersion: v1 metadata: name: php3 spec: nodeSelector: kubernetes.io/hostname: node-0002 priorityClassName: high-non # 优先级名称 containers: ……{/tabs-pane}{/tabs}其中,优先级的值越高,优先级越高,允许的设置范围是(-2147483648到1000000000),最大值是10亿,超过10亿的数字被系统保留,用于设置给系统组件。在上面的配置中,globalDefault设置为true表示这个优先级配置是全局默认配置,即对没有配置priorityCKassName的Pod都默认使用这个优先级设置。在系统没有设置全局默认优先级的情况下,对于没有配置priorityClassName的Pod,系统默认设置这些Pod的优先级为0。description字段用于设置一个说明,通常用来描述该priorityClass的用途。preemptionPolicy字段用于设置抢占策略。可用设置的策略有下面两个:PreemptLowerPriority:默认策略,表示允许具有该priorityClass优先级的Pod抢占较低优先级Pod的资源。Never:具有该优先级的Pod会被置于调度优先级队列中优先级数值更低的Pod之前,但不抢占其他Pod的资源,这些Pod将一直在调度列队中等待,知道有足够的可用资源后,才会被调度。抢占式调度的主要流程考察每个候选Node,找出为了满足新Pod的调度要求,需要释放的最少Pod实例;以抢占导致的代价最小原则,对筛查出来的所有候选Node进行考察,挑选出最优的候选Node作为最终被占用的目标Node;把目标Node与新Pod绑定,使得新Pod在下一轮的调度过程中可以使用这个目标Node来完成最终的调度流程,同时,调用APIServer删除目标Node上需要被释放的Pod以释放Node资源。最优Node选择规则拥有最小违反PodDisruptionBudget约束的Node;把Node上被释放的拥有最高优先级的Pod都找出来并进行比较,优先级排名垫底的Pod所在的Node;被释放的Pod的优先级之和(目标Pod需要的资源可能需要释放多个Pod才能满足)排名垫底的Node;被释放的Pod数量最少的Node;把Node上被释放的拥有最高优先级的Pod找出来,最晚启动的那个Pod所在的Node如果上述步骤还是无法选出最佳Node(可供选择的Node还有多个),就随机选择一个。注意事项如果目标Pod与候选Node上的某个优先级比它低的Pod之间有亲和性,则发生资源抢占后(这个低优先级的Pod被删除),目标pod不满足节点亲和性规则,此时该Node不符合抢占要求,Scheduler会考虑其他候选Node,无法保证目标Pod调度成功。要避免此类情况,要注意Pod亲和性和优先级的关系——具有亲和性关系的Pod不应该被设置为低优先级的。
2025年04月18日
46 阅读
0 评论
0 点赞
2025-04-10
kubernetes集群各配置文件解析
kubelet service文件在kubelet的service文件中,有下面两行配置信息:After=containerd.service Requires=containerd.service其中After确保kubelet在containerd启动后再启动,Requires确保containerd必须已经在正常运行了才能启动kubelet。配置这两行信息的原因是kubelet的启动时会根据kubelet的配置信息去找容器的sock借口,如果找不到借口就无法启动,会有如下报错。{callout color="#f70808"}4月 10 09:06:51 node002 kubelet[1537]: E0410 09:06:51.541944 1537 run.go:72] "command failed" err="failed to run Kubelet: validate service connection: validate CRI v1 runtime API for endpoint \"unix:///run/containerd/containerd.sock\": rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing: dial unix /run/containerd/containerd.sock: connect: no such file or directory\""4月 10 09:06:51 node002 systemd[1]: kubelet.service: Main process exited, code=exited, status=1/FAILURE{/callout}因此,只有正确配置了上面两行内容,kubelet才能正常启动。配置的参数项是kubernetes集群所使用的容器运行时。(如docker,containerd,CRI-O等)集群中的地址分配相关集群中的地址分配主要是在kube-apiserver的配置文件中进行配置,核心配置是下面这个参数项--service-cluster-ip-range=10.245.0.0/16 \这个参数规定了集群中所有的service(服务)使用10.245地址段的ip地址。此外,service-node-port-range=30000-32767 是指创建NodePort类型的Service时,Kubernetes 会从 --service-node-port-range 指定的范围内自动分配一个端口。在kube-apiserver的配置配置文件中指定了IP地址段之后,还要在kube-controller-manger中进行对应的配置。核心参数是下面两项。--service-cluster-ip-range=10.245.0.0/16 \ --cluster-cidr=10.244.0.0/16 \其中,service-cluster-ip-range指定的是service服务所使用的IP地址段,与kube-apiserver中的配置应该相同。注意这个地址段不能与节点物理网络、Pod 网络或其他私有网络重叠cluster-cidr指定的是创建pod时,pod可以分配到的IP地址范围。注意这个地址段要与calico等网络插件的地址段配置一致,否则会造成pod间无法正常通信。calico网络插件对应的配置项- name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16"在kube-proxy中也有pod地址段相关的配置,需要确认与上面的配置相同。--cluster-cidr=10.244.0.0/16"
2025年04月10日
46 阅读
0 评论
0 点赞
1
...
3
4
5
...
14