Kubernetes总结笔记
2023-03-16 21:50:40 2 举报
AI智能生成
k8s学习总结
作者其他创作
大纲/内容
Pods
Pod的资源清单
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,资源类型,例如 Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #Pod所属的命名空间,默认为"default"
labels: #自定义标签列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口的名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存请求,容器启动的初始可用数量
lifecycle: #生命周期钩子
postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: [Always | Never | OnFailure] #Pod的重启策略
nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
kind: Pod #必选,资源类型,例如 Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #Pod所属的命名空间,默认为"default"
labels: #自定义标签列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口的名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存请求,容器启动的初始可用数量
lifecycle: #生命周期钩子
postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: [Always | Never | OnFailure] #Pod的重启策略
nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
Pod生命周期
Pod生命期
Pod生命周期起始于Pending状态,如果至少一个主要容器正常启动则进入Running状态,之后取决于Pod中是否有容器以失败状态结束而进入Succeeded或者Failed状态
Pod在其生命周期中只会被调度一次。一旦Pod被调度到某个节点,Pod会一直在该节点运行,直到Pod停止或者被终止
如果节点死掉,Pod会在给定超时期限结束后删除
Pod是个相对临时性的实体,会被创建、赋予一个唯一的ID(UID)
Pod可以被相同的Pod替换掉,名字可以不变,但是其UID会不同
控制器(通过apiserver监控集群的状态)管理Pod的创建及删除
Pod被删除或替换,期内的相关容器及对象也会被删除或重建
Pod阶段(Phase)
Pod的Status字段是一个PodStatus对象,其中包含一个phase字段
容器状态
三种状态:Waiting(等待)、Running(运行中)和 Terminated(已终止)
要检查 Pod 中容器的状态,你可以使用 kubectl describe pod <pod 名称>
Waiting (等待)
使用 kubectl 来查询会看到一个 Reason 字段,其中给出了容器处于等待状态的原因
Running(运行中)
表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。
Terminated(已终止)
如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行
容器重启策略
Pod 的 spec 中包含一个 restartPolicy 字段。其值为Always、OnFailure 和 Never。默认值是 Always。
restartPolicy只适用于同一节点上的容器。当容器重启,kubelet累计延时时间,最多延时5分钟。容器正常运行10分钟后重置重启延时时间。
Pod状况
PodStatus 对象,其中包含一个 PodConditions 数组
PodScheduled: Pod 已经被调度到某节点;
ContainersReady:Pod 中所有容器都已就绪;
Initialized: 所有的 Init 容器 都已成功启动;
Ready: Pod 可以为请求提供服务,并且应该被添加到对应服务的负载均衡池中。
ContainersReady:Pod 中所有容器都已就绪;
Initialized: 所有的 Init 容器 都已成功启动;
Ready: Pod 可以为请求提供服务,并且应该被添加到对应服务的负载均衡池中。
容器探针
kubelet 调用由容器实现的 Handler (处理程序)进行诊断:
ExecAction: 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
TCPSocketAction: 对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。
HTTPGetAction: 对容器的 IP 地址上指定端口和路径执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。
ExecAction: 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
TCPSocketAction: 对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。
HTTPGetAction: 对容器的 IP 地址上指定端口和路径执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
Success(成功):容器通过了诊断。
Failure(失败):容器未通过诊断。
Unknown(未知):诊断失败,因此不会采取任何行动。
Success(成功):容器通过了诊断。
Failure(失败):容器未通过诊断。
Unknown(未知):诊断失败,因此不会采取任何行动。
三种类型的探针
livenessProbe:容器是否正在运行。如果容器未运行,则kubelet杀死容器,并根据重启策略进一步操作
readinessProbe:容器是否准备好提供服务。如果失败,控制器将从端点列表中删除该Pod的IP地址。
startupProbe:容器中的应用是否已启动。如果启动该探针,只有此探针成功后,其他探针才会被使用。如果启动探测失败,kubelet杀死容器,根据重启策略进行重启。
Pod的终止
使用kubectl手动删除Pod,该Pod的终止时限为30S。超过30s仍未删除,将调用kill命令强制删除
使用 kubectl describe 来查验你正在删除的 Pod,该 Pod 会显示为 "Terminating" (正在终止)
如果定义了preStop回调,超出终止时限后,kubelet会一次性增加2秒钟终止时限
Pod 中的容器会在不同时刻收到 TERM 信号,接收顺序也是不确定的。 如果关闭的顺序很重要,可以考虑使用 preStop 回调逻辑来协调。
kubelet启动终止逻辑后,控制面会将Pod从对应的端点列表中引出,并停止所有请求及服务
kubectl delete 命令支持 --grace-period=<seconds> 选项, 设定自定义的期限值
设置 --grace-period=0 的同时额外设置 --force 参数才能发起强制删除请求。 意味着立即从 API 服务器删除 Pod
设置 --grace-period=0 的同时额外设置 --force 参数才能发起强制删除请求。 意味着立即从 API 服务器删除 Pod
Init容器
Init容器原理
Pod中可以有一个或多个先于应用容器的Init容器
它们总是运行到完成
每个都必须在下一个启动前成功完成
如果Pod的Init容器启动失败,kubelet会不断的重启Init容器直到成功为止
如果restartPolicy的值为Never,并且Init容器启动失败,则整个Pod状态设置为失败
设置Init容器需在Pod的spec中添加initContainers字段
init容器的状态在status.initContainerStatuses字段以容器状态数组的格式返回
与应用容器的不同之处
Init容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置
但是对资源请求和限制的处理稍有不同
Init容器不支持lifecycle、livenessProbe、redinessProbe、startupProbe,因为Init必须在Pod就绪之前完成
如果一个pod指定多个Init容器,会按顺序逐个运行。前一个init运行成功后下一个能运行。当所有Init容器运行完成后,Pod才会初始化应用容器
使用Init容器
Init容器具有与应用容器分离的单独镜像,启动相关代码具有以下优势
Init容器可以包含一些安装过程中应用容器中不存在的实用工具和个性化代码
例如:没必要为了安装sed、awk、python或dig等工具而去From一个镜像
Init容器可以安全的运行相关工具,避免这些工具导致应用镜像的安全性降低
应用镜像的创建和部署可以独自执行,不必联合构建为一个独立的应用镜像
Init容器可以访问应用容器不能访问的Secret权限
Init容器可以阻塞和延迟应用容器的启动,直到满足先决条件。一旦前置条件满足,Pod内的所有应用容器会并行启动
一些使用Init容器的示例
Init容器的使用例子
定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 myservice 启动, 第二个等待 mydb 启动。 一旦这两个 Init容器 都启动完成,Pod 将启动 spec 节中的应用容器。
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.default.svc.cluster.k8s; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.default.svc.cluster.k8s; do echo waiting for mydb; sleep 2; done"]
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.default.svc.cluster.k8s; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.default.svc.cluster.k8s; do echo waiting for mydb; sleep 2; done"]
启动Pod:kubectl apply -f myapp.yaml
输出:pod/myapp-pod created
检查其状态:kubectl get -f myapp.yaml
输出:
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
初始化中
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
初始化中
查看更多详细信息:kubectl describe -f myapp.yaml
输出类似于:
Name: myapp-pod
Namespace: default
[...]
Labels: app=myapp
Status: Pending
[...]
Init Containers:
init-myservice:
[...]
State: Running
[...]
init-mydb:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Containers:
myapp-container:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
Name: myapp-pod
Namespace: default
[...]
Labels: app=myapp
Status: Pending
[...]
Init Containers:
init-myservice:
[...]
State: Running
[...]
init-mydb:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Containers:
myapp-container:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
查看Pod内Init容器的日志:
kubectl logs myapp-pod -c init-myservice # 查看第一个 Init 容器
kubectl logs myapp-pod -c init-mydb # 查看第二个 Init 容器
kubectl logs myapp-pod -c init-myservice # 查看第一个 Init 容器
kubectl logs myapp-pod -c init-mydb # 查看第二个 Init 容器
发现Init容器正在等待名称为myservice和mydb的Service
创建相关的Service的配置文件
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
创建Service的命令:kubectl create -f services.yaml
输出:
service "myservice" created
service "mydb" created
service "myservice" created
service "mydb" created
再查看Pod状态:kubectl get -f myapp.yaml
输出:
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
运行状态
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
运行状态
Init的在Pod中的具体启动过程
Init容器会在网络和数据卷初始化之后按顺序启动。
kubelet按照Init容器在Pod规约中出现的顺序依次执行
每个Init容器成功并退出后才会启动下一个Init容器
如果某容器无法启动或以错误状态退出,kubelet会根据Pod的restartPolicy策略重试
如果Pod的restartPolicy设置为“Always”,Init容器失败时会使用“OnFailure”策略
所有Init容器没有成功前,Pod不会变为Ready状态、Init容器的端口不会在Service中进行聚集。正在初始化的Pod处于Pending状态,但会将Initializing设置为false
如果Pod重启,所有的Init容器必须重新执行
Init容器只能修改容器的image字段,修改后等同于重启Pod
因为Init容器会被重启、重试或者重新执行,所以Init容器的业务处理是要幂等的。特别是基于emptyDirs写文件操作,要做好文件已存在的处理。
Init容器具有应用容器的所有字段,但是禁止使用readlinessProbe。
在 Pod 上使用 activeDeadlineSeconds 和在容器上使用 livenessProbe 可以避免 Init 容器一直重复失败。activeDeadlineSeconds 时间包含了 Init 容器启动的时间。
在 Pod 中的每个应用容器和 Init 容器的名称必须唯一
所有Init容器定义的任何特定资源的limit或request的最大值,作为Pod的有效初始limit/request
Pod 对资源的 有效 limit/request 是如下两者的较大者:
1.所有应用容器对某个资源的 limit/request 之和
2.对某个资源的有效初始 limit/request
1.所有应用容器对某个资源的 limit/request 之和
2.对某个资源的有效初始 limit/request
Kubernetes v1.20 及更新版本:当 Init 容器的镜像发生改变或者 Init 容器的完成记录因为垃圾收集等原因被丢失时, Pod 不会被重启
Pod拓扑分布约束
使用 拓扑分布约束(Topology Spread Constraints) 来控制 Pods 在集群内故障域 之间的分布,例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 这样做有助于实现高可用并提升资源利用率。
可以定义一个或多个 topologySpreadConstraint 来约束每个传入的 Pod 部署到集群中。
maxSkew: 必须是大于零的整数,表示能容忍不同拓扑域中 Pod 数量差异的最大值。 1 意味着只允许相差 1 个 Pod。
topologyKey:节点的某个 label 的 key,能代表节点所处拓扑域,可以用 Well-Known Labels,常用的是 kubernetes.io/hostname (节点维度)、topology.kubernetes.io/zone (可用区/机房 维度)。也可以自行手动为节点打上自定义的 label 来定义拓扑域,比如 rack (机架维度)、machine (物理机维度)、switch (交换机维度)。
whenUnsatisfiable: 指 Pod 不满足分布约束条件时如何处理:
DoNotSchedule(默认)告诉调度器不要调度(保持 Pending),类似强反亲和;
ScheduleAnyway 告诉调度器继续调度,类似弱反亲和;
labelSelector 用于查找匹配的 pod。匹配此标签的 Pod 将被统计,以确定相应 拓扑域中 Pod 的数量。
你可以执行 kubectl explain Pod.spec.topologySpreadConstraints 命令以 了解关于 topologySpreadConstraints 的更多信息。
maxSkew: 必须是大于零的整数,表示能容忍不同拓扑域中 Pod 数量差异的最大值。 1 意味着只允许相差 1 个 Pod。
topologyKey:节点的某个 label 的 key,能代表节点所处拓扑域,可以用 Well-Known Labels,常用的是 kubernetes.io/hostname (节点维度)、topology.kubernetes.io/zone (可用区/机房 维度)。也可以自行手动为节点打上自定义的 label 来定义拓扑域,比如 rack (机架维度)、machine (物理机维度)、switch (交换机维度)。
whenUnsatisfiable: 指 Pod 不满足分布约束条件时如何处理:
DoNotSchedule(默认)告诉调度器不要调度(保持 Pending),类似强反亲和;
ScheduleAnyway 告诉调度器继续调度,类似弱反亲和;
labelSelector 用于查找匹配的 pod。匹配此标签的 Pod 将被统计,以确定相应 拓扑域中 Pod 的数量。
你可以执行 kubectl explain Pod.spec.topologySpreadConstraints 命令以 了解关于 topologySpreadConstraints 的更多信息。
需要部署label为app=foo的pod到可用区,Zone1中有两个相同标签的Pod,Zone2中没有,根据maxSkew=1的条件,两个可用区相同标签的Pod数量相差最大为1,因此新Pod将被部署到Zone2上
高级用法
多重拓扑扩展约束
Pod 打散调度
将 Pod 打散调度到不同地方,可避免因软硬件故障、光纤故障、断电或自然灾害等因素导致服务不可用,以实现服务的高可用部署。
https://imroc.cc/k8s/ha/pod-split-up-scheduling/
https://imroc.cc/k8s/ha/pod-split-up-scheduling/
Kubernetes 支持两种方式将 Pod 打散调度:
Pod 反亲和 (Pod Anti-Affinity)
Pod 拓扑分布约束 (Pod Topology Spread Constraints)
Pod 反亲和 (Pod Anti-Affinity)
Pod 拓扑分布约束 (Pod Topology Spread Constraints)
使用 podAntiAffinity
使用 topologySpreadConstraints
干扰(Disruptions)
自愿干扰和非自愿干扰
非自愿干扰(Involuntary Disruptions)
节点下层物理机的硬件故障
集群管理员错误地删除虚拟机(实例)
云提供商或虚拟机管理程序中的故障导致的虚拟机消失
内核错误
节点由于集群网络隔离从集群中消失
由于节点资源不足导致 pod 被驱逐。
集群管理员错误地删除虚拟机(实例)
云提供商或虚拟机管理程序中的故障导致的虚拟机消失
内核错误
节点由于集群网络隔离从集群中消失
由于节点资源不足导致 pod 被驱逐。
自愿干扰(Voluntary Disruptions)
应用程序所有者的操 作包括:
删除 Deployment 或其他管理 Pod 的控制器
更新了 Deployment 的 Pod 模板导致 Pod 重启
直接删除 Pod(例如,因为误操作)
集群管理员操作包括:
排空(drain)节点进行修复或升级。
从集群中排空节点以缩小集群(了解集群自动扩缩)。
从节点中移除一个 Pod,以允许其他 Pod 使用该节点。
删除 Deployment 或其他管理 Pod 的控制器
更新了 Deployment 的 Pod 模板导致 Pod 重启
直接删除 Pod(例如,因为误操作)
集群管理员操作包括:
排空(drain)节点进行修复或升级。
从集群中排空节点以缩小集群(了解集群自动扩缩)。
从节点中移除一个 Pod,以允许其他 Pod 使用该节点。
处理干扰
干扰预算(Kubernetes v1.21 [stable])
应用程序所有者可以为每个应用程序创建 PodDisruptionBudget 对象(PDB)。 PDB 将限制在同一时间因自愿干扰导致的复制应用程序中宕机的 pod 数量。 例如,基于票选机制的应用程序希望确保运行的副本数永远不会低于仲裁所需的数量。 Web 前端可能希望确保提供负载的副本数量永远不会低于总数的某个百分比。
https://kubernetes.io/zh/docs/concepts/workloads/pods/disruptions/
工作负载资源
Deployments
定义 Deployment 以创建新的 ReplicaSet、删除现有 Deployment, 并通过新的 Deployment 接收其资源。
Deployment 非常适合使用在多个副本上挂载的 ReadOnlyMany 或 ReadWriteMany 卷的无状态应用,但不适合使用 ReadWriteOnce 卷的工作负载。如果是使用 ReadWriteOnce 卷的有状态应用,请使用 StatefulSet。StatefulSet 旨在用于部署有状态应用和将数据保存到永久性存储空间(例如 Compute Engine 永久性磁盘)的聚簇应用。StatefulSet 适合部署 Kafka、MySQL、Redis、ZooKeeper 以及其他需要唯一持久身份和稳定主机名的应用。
创建Deployment
创建名为 nginx-deployment的 Deployment。(由 .metadata.name 字段标明)
该 Deployment 创建三个Pod 副本。(由 replicas 字段标明)
selector 字段定义 如何查找要管理的 Pods。
template 字段包含以下子字段:
Pod 使用 labels 字段打上 app: nginx 标签。
Pod 模板规约(即 .template.spec 字段)指示 Pods 运行一个 nginx 容器, 该容器运行版本为 1.14.2 的 nginx Docker Hub镜像。
创建一个容器并使用 name 字段将其命名为 nginx。
该 Deployment 创建三个Pod 副本。(由 replicas 字段标明)
selector 字段定义 如何查找要管理的 Pods。
template 字段包含以下子字段:
Pod 使用 labels 字段打上 app: nginx 标签。
Pod 模板规约(即 .template.spec 字段)指示 Pods 运行一个 nginx 容器, 该容器运行版本为 1.14.2 的 nginx Docker Hub镜像。
创建一个容器并使用 name 字段将其命名为 nginx。
说明:
spec.selector.matchLabels 字段是 {key,value} 键值对映射。 在 matchLabels 映射中的每个 {key,value} 映射等效于 matchExpressions 中的一个元素, 即其 key 字段是 “key”,operator 为 “In”,values 数组仅包含 “value”。 在 matchLabels 和 matchExpressions 中给出的所有条件都必须满足才能匹配。
spec.selector.matchLabels 字段是 {key,value} 键值对映射。 在 matchLabels 映射中的每个 {key,value} 映射等效于 matchExpressions 中的一个元素, 即其 key 字段是 “key”,operator 为 “In”,values 数组仅包含 “value”。 在 matchLabels 和 matchExpressions 中给出的所有条件都必须满足才能匹配。
创建命令:kubectl apply -f nginx-deployment.yaml
查看命令:kubectl get deployments
输出
查看上线状态:kubectl rollout status deployment/nginx-deployment
查看创建的ReplicaSet:kubectl get rs
输出
查看Pod自动生成的Label:kubectl get pods --show-labels
Pod-template-hash 标签
说明: 不要更改此标签。
Deployment 控制器将 pod-template-hash 标签添加到 Deployment 所创建或接收的 每个 ReplicaSet 。
此标签可确保 Deployment 的子 ReplicaSets 不重叠。 标签是通过对 ReplicaSet 的 PodTemplate 进行哈希处理。 所生成的哈希值被添加到 ReplicaSet 选择算符、Pod 模板标签,并存在于在 ReplicaSet 可能拥有的任何现有 Pod 中。
说明: 不要更改此标签。
Deployment 控制器将 pod-template-hash 标签添加到 Deployment 所创建或接收的 每个 ReplicaSet 。
此标签可确保 Deployment 的子 ReplicaSets 不重叠。 标签是通过对 ReplicaSet 的 PodTemplate 进行哈希处理。 所生成的哈希值被添加到 ReplicaSet 选择算符、Pod 模板标签,并存在于在 ReplicaSet 可能拥有的任何现有 Pod 中。
更新Deployment
仅当 .spec.template发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 更新。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发更新动作。
修改nginx-deployments.yaml中的.spec.template.spec.containers.image 从 nginx:1.14.2 更改至 nginx:1.16.1
执行:kubectl apply -f nginx-deployments.yaml
执行:kubectl apply -f nginx-deployments.yaml
查看Deployment的信息:kubectl describe deployments
更新中
更新 Deployment 时,它创建了一个新的 ReplicaSet ,并将其扩容为 1,然后将旧 ReplicaSet 缩容到 2, 最多时 4 个 Pod在线。 然后继续对新的 ReplicaSet 扩容并对旧的 ReplicaSet 缩容。 最后, 3 个可用的副本在新的 ReplicaSet 中,旧 ReplicaSet 将缩容到 0。
动态更新
在创建一个 Deployment 以生成 nginx:1.14.2 的 5 个副本,但接下来 更新 Deployment 以创建 5 个 nginx:1.16.1 的副本,而此时有 3 个nginx:1.14.2 副本已创建。在这种情况下,Deployment 会立即开始杀死 3 个 nginx:1.14.2 Pods, 并开始创建 nginx:1.16.1 Pods。它不会等待 nginx:1.14.2 的 5 个副本都创建完成 后才开始执行变更动作。
回滚Deployment
修改nginx-deployments.yaml中的.spec.template.spec.containers.image 更改至 nginx:1.161(版本好写错了)
执行:kubectl apply -f nginx-deployments.yaml
执行:kubectl apply -f nginx-deployments.yaml
检查上线状态:kubectl rollout status deployment/nginx-deployment
卡住了
检查Deployment修订历史:kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
3 <none>
4 <none>
REVISION CHANGE-CAUSE
1 <none>
3 <none>
4 <none>
查看历史详细信息:kubectl rollout history deployment/nginx-deployment --revision=4
deployment.apps/nginx-deployment with revision #4
Pod Template:
Labels: app=nginx
pod-template-hash=559d658b74
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Pod Template:
Labels: app=nginx
pod-template-hash=559d658b74
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
回滚之前的版本:kubectl rollout undo deployment/nginx-deployment --to-revision=4
输出
deployment.apps/nginx-deployment rolled back
deployment.apps/nginx-deployment rolled back
查看结果
扩缩容Deployment
扩缩指令:
kubectl scale deployment/nginx-deployment --replicas=10
kubectl scale deployment/nginx-deployment --replicas=10
输出:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
自动缩放:
kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80
kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80
查看自动缩放策略:kubectl get hpa
删除自动缩放策略:kubectl delete hpa NAME-OF-HPA
根据业务场景调节HPA扩缩容灵敏度
暂停、恢复Deployment
在暂停和恢复执行之间应用多个修补程序,而不会触发不必要的发布操作
更新限定资源:kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
暂停指令:kubectl rollout pause deployment.v1.apps/nginx-deployment
暂停状态的deployment,不会触发更新
恢复指令:kubectl rollout resume deployment.v1.apps/nginx-deployment
不可以回滚处于暂停状态的 Deployment,需要先恢复其执行状态。
Deployment状态
三种状态:Progressing(进行中)、Complete(完成)、Failed(失败)
kubectl get deployment nginx-deployment -o yaml
查看Deploy的状态输出
Progressing状态
Deployment 创建新的 ReplicaSet
Deployment 正在为其最新的 ReplicaSet 扩容
Deployment 正在为其旧有的 ReplicaSet(s) 缩容
新的 Pods 已经就绪或者可用(就绪至少持续了 MinReadySeconds 秒)。
Deployment 正在为其最新的 ReplicaSet 扩容
Deployment 正在为其旧有的 ReplicaSet(s) 缩容
新的 Pods 已经就绪或者可用(就绪至少持续了 MinReadySeconds 秒)。
Complete状态
与 Deployment 关联的所有副本都已更新到指定的最新版本,这意味着之前请求的所有更新都已完成。
与 Deployment 关联的所有副本都可用。
未运行 Deployment 的旧副本。
与 Deployment 关联的所有副本都可用。
未运行 Deployment 的旧副本。
Failed状态
配额(Quota)不足
就绪探测(Readiness Probe)失败
镜像拉取错误
权限不足
限制范围(Limit Ranges)问题
应用程序运行时的配置错误
就绪探测(Readiness Probe)失败
镜像拉取错误
权限不足
限制范围(Limit Ranges)问题
应用程序运行时的配置错误
设置规约中的 progressDeadlineSeconds,从而告知控制器 在 10 分钟后报告 Deployment 没有进展
kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
可以对其执行扩缩容、回滚到以前的修订版本等操作,或者在需要对 Deployment 的 Pod 模板应用多项调整时,将 Deployment 暂停
清理策略
.spec.revisionHistoryLimit字段保留多少旧的ReplicaSet,默认为10
显式将此字段设置为 0 将导致 Deployment 的所有历史记录被清空,因此 Deployment 将无法回滚。
Deployment规约
apiVersion,kind 和 metadata 字段必须有
.spec 中只有 .spec.template 和 .spec.selector 是必需的字段。
.spec.selector 必须匹配 .spec.template.metadata.labels
.spec.selector 是不可变的
.spec.replicas 是指定要部署的Pod 的数量,可选字段。它的默认值是1。
.spec.strategy 可选字段,策略指定用于用新 Pods 替换旧 Pods 的策略
.spec.strategy.type 值 “Recreate” 、“RollingUpdate”(默认值)
.spec.strategy.type==Recreate,在创建新 Pods 之前,所有现有的 Pods 会被杀死
.spec.strategy.type==RollingUpdate,采取 滚动更新的方式更新 Pods。你可以指定 maxUnavailable 和 maxSurge 来控制滚动更新 过程
最大不可用
.spec.strategy.rollingUpdate.maxUnavailable 是一个可选字段,用来指定 更新过程中不可用的 Pod 的个数上限。该值可以是绝对数字(例如,5),也可以是 所需 Pods 的百分比(例如,10%)。百分比值会转换成绝对数并去除小数部分。 如果 .spec.strategy.rollingUpdate.maxSurge 为 0,则此值不能为 0。 默认值为 25%。
例如,当此值设置为 30% 时,滚动更新开始时会立即将旧 ReplicaSet 缩容到期望 Pod 个数的70%。 新 Pod 准备就绪后,可以继续缩容旧有的 ReplicaSet,然后对新的 ReplicaSet 扩容,确保在更新期间 可用的 Pods 总数在任何时候都至少为所需的 Pod 个数的 70%。
.spec.strategy.rollingUpdate.maxUnavailable 是一个可选字段,用来指定 更新过程中不可用的 Pod 的个数上限。该值可以是绝对数字(例如,5),也可以是 所需 Pods 的百分比(例如,10%)。百分比值会转换成绝对数并去除小数部分。 如果 .spec.strategy.rollingUpdate.maxSurge 为 0,则此值不能为 0。 默认值为 25%。
例如,当此值设置为 30% 时,滚动更新开始时会立即将旧 ReplicaSet 缩容到期望 Pod 个数的70%。 新 Pod 准备就绪后,可以继续缩容旧有的 ReplicaSet,然后对新的 ReplicaSet 扩容,确保在更新期间 可用的 Pods 总数在任何时候都至少为所需的 Pod 个数的 70%。
最大峰值
.spec.strategy.rollingUpdate.maxSurge 是一个可选字段,用来指定可以创建的超出 期望 Pod 个数的 Pod 数量。此值可以是绝对数(例如,5)或所需 Pods 的百分比(例如,10%)。 如果 MaxUnavailable 为 0,则此值不能为 0。百分比值会通过向上取整转换为绝对数。 此字段的默认值为 25%。
例如,当此值为 30% 时,启动滚动更新后,会立即对新的 ReplicaSet 扩容,同时保证新旧 Pod 的总数不超过所需 Pod 总数的 130%。一旦旧 Pods 被杀死,新的 ReplicaSet 可以进一步扩容, 同时确保更新期间的任何时候运行中的 Pods 总数最多为所需 Pods 总数的 130%。
.spec.strategy.rollingUpdate.maxSurge 是一个可选字段,用来指定可以创建的超出 期望 Pod 个数的 Pod 数量。此值可以是绝对数(例如,5)或所需 Pods 的百分比(例如,10%)。 如果 MaxUnavailable 为 0,则此值不能为 0。百分比值会通过向上取整转换为绝对数。 此字段的默认值为 25%。
例如,当此值为 30% 时,启动滚动更新后,会立即对新的 ReplicaSet 扩容,同时保证新旧 Pod 的总数不超过所需 Pod 总数的 130%。一旦旧 Pods 被杀死,新的 ReplicaSet 可以进一步扩容, 同时确保更新期间的任何时候运行中的 Pods 总数最多为所需 Pods 总数的 130%。
.spec.progressDeadlineSeconds 可选字段,延时报告Deployment状态的时间
值需要大于 .spec.minReadySeconds 取值
.spec.minReadySeconds 可选字段,最短就绪时间。
指定新创建的 Pod 在没有任意容器崩溃情况下的最小就绪时间,只有超出这个时间 Pod 才被视为可用
默认值为 0(Pod 在准备就绪后立即将被视为可用)
.spec.revisionHistoryLimit 可选字段,设定要保留的旧ReplicaSet的数量
旧 ReplicaSet 会消耗 etcd 中的资源,并占用 kubectl get rs 的输出
默认情况下,系统保留 10 个旧 ReplicaSet
设置为 0 意味着将清理所有副本,将无法回滚
.spec.paused 可选字段,用于暂停和恢复 Deployment
Deployment 处于暂停状态时, PodTemplateSpec 的任何修改都不会触发新的上线。
默认:不处于暂停状态
ReplicaSet
确保给定数量的、完全相同的pod副本集合
建议使用 Deployment 而不是直接使用 ReplicaSet
ReplicaSet 是 ReplicationController 的后继者。二者目的相同且行为类似。优先考虑 ReplicaSet
StatefulSets
有状态的工作负载副本集,为每个pod维护一个永久不变的ID,拥有一个唯一的顺序索引和稳定的网络身份标识
StatefulSet 适合部署 Kafka、MySQL、Redis、ZooKeeper 以及其他需要唯一持久身份和稳定主机名的应用
StatefulSet 适合部署 Kafka、MySQL、Redis、ZooKeeper 以及其他需要唯一持久身份和稳定主机名的应用
创建StatefulSet
kubectl apply -f web.yaml
for i in 0 1; do kubectl exec "web-$i" -- sh -c 'echo "$(hostname)" > /usr/share/nginx/html/index.html'; done
给pod中的nginx的index.html赋值 各自的hostname web-0,web-1...
给pod中的nginx的index.html赋值 各自的hostname web-0,web-1...
映射的pv,要去所在的node上去查看,因为是local本地映射
查看Pods的创建情况:kubectl get pods -w -l app=nginx
顺序创建Pod
Pod 被部署时是按照 {0 …… N-1} 的序号顺序创建的
请注意在 web-0 Pod 处于 Running和Ready 状态后 web-1 Pod 才会被启动。
Pod 被部署时是按照 {0 …… N-1} 的序号顺序创建的
请注意在 web-0 Pod 处于 Running和Ready 状态后 web-1 Pod 才会被启动。
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 19s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 19s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
kubectl get service nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 12s
nginx ClusterIP None <none> 80/TCP 12s
kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 1 20s
web 2 1 20s
扩缩容StatefulSet
扩容
kubectl scale sts web --replicas=5
输出:statefulset.apps/web scaled
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2h
web-1 1/1 Running 0 2h
NAME READY STATUS RESTARTS AGE
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 1/1 Running 0 18s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 19s
StatefulSet 按序号索引顺序的创建每个 Pod,并且会等待前一个 Pod 变为 Running 和 Ready 才会启动下一个 Pod
web-0 1/1 Running 0 2h
web-1 1/1 Running 0 2h
NAME READY STATUS RESTARTS AGE
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 1/1 Running 0 18s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 19s
StatefulSet 按序号索引顺序的创建每个 Pod,并且会等待前一个 Pod 变为 Running 和 Ready 才会启动下一个 Pod
缩容
kubectl patch sts web -p '{"spec":{"replicas":3}}'
输出:statefulset.apps/web scaled
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3h
web-1 1/1 Running 0 3h
web-2 1/1 Running 0 55s
web-3 1/1 Running 0 36s
web-4 0/1 ContainerCreating 0 18s
NAME READY STATUS RESTARTS AGE
web-4 1/1 Running 0 19s
web-4 1/1 Terminating 0 24s
web-4 1/1 Terminating 0 24s
web-3 1/1 Terminating 0 42s
web-3 1/1 Terminating 0 42s
缩容按索引倒序的顺序关闭
web-0 1/1 Running 0 3h
web-1 1/1 Running 0 3h
web-2 1/1 Running 0 55s
web-3 1/1 Running 0 36s
web-4 0/1 ContainerCreating 0 18s
NAME READY STATUS RESTARTS AGE
web-4 1/1 Running 0 19s
web-4 1/1 Terminating 0 24s
web-4 1/1 Terminating 0 24s
web-3 1/1 Terminating 0 42s
web-3 1/1 Terminating 0 42s
缩容按索引倒序的顺序关闭
顺序终止Pod
Pod 序号索引相反的顺序每次删除一个 Pod。在删除下一个 Pod 前会等待上一个被完全关闭
Pod删除,但是PVC不会被删除
需要手动删除
需要手动删除
kubectl get pvc -l app=nginx
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-2 Bound pvc-e1125b27-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-3 Bound pvc-e1176df6-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-4 Bound pvc-e11bb5f8-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-2 Bound pvc-e1125b27-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-3 Bound pvc-e1176df6-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-4 Bound pvc-e11bb5f8-b508-11e6-932f-42010a800002 1Gi RWO 13h
更新StatefulSet
spec.updateStrategy
更新一个 StatefulSet 中的 Pod 的 container images,resource requests,
以及 limits,labels 和 annotations。 RollingUpdate滚动更新是 StatefulSets 默认策略
更新一个 StatefulSet 中的 Pod 的 container images,resource requests,
以及 limits,labels 和 annotations。 RollingUpdate滚动更新是 StatefulSets 默认策略
命令方式添加更新策略:kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
更新镜像:kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]'
采用倒序更新
前一个更新成功后,才会开始更新下一个pod
On Delete 策略
选择这个更新策略并修改 StatefulSet 的 .spec.template 字段时,StatefulSet 控制器将不会自动的更新 Pod
分区更新
添加分区
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'
设置分区后进行更新,只会更新比分区号>=的pod,比如partition=2,web-0、web-1不会更新,web-2会更新
partition":0 ,全部pod都更新
删除StatefulSet
非级联删除
kubectl delete statefulset web --cascade=false
只删除 StatefulSet 而不要删除它的任何 Pod。
非级联删除后,在删除Pod,不会重新创建
级联删除
kubectl delete statefulset web
级联删除会按照倒序删除 StatefulSet 和它的 Pod,但它并不会删除和 StatefulSet 关联的 Headless Service。必须手动删除nginx Service。
PersistentVolumes不会被删除,只能手动操作
kubectl delete pvc XXX
kubectl delete pv XXX
StatefulSet的管理策略
.spec.podManagementPolicy。 仅影响扩缩操作的行为。更新不受影响。
OrderedReady pod 管理策略是 StatefulSets 的默认选项。StatefulSet 控制器遵循顺序性
Parallel Pod 并行进行扩缩容
并行处理,不必等待上一个pod处理完成
PersistentVolume持久卷
定义
持久卷(PersistentVolume,PV)是集群中的一块存储,和普通的 Volume 一样,
独立于任何使用 PV 的 Pod 的生命周期
独立于任何使用 PV 的 Pod 的生命周期
静态供应
集群管理员创建若干 PV 卷,供用户使用
动态供应
PVC 申领必须请求某个 存储类,集群管理员必须 已经创建并配置了该类
PVC 申领指定存储类为 "",则相当于为自身禁止使用动态供应的卷
管理员需要在 API 服务器上启用 DefaultStorageClass
通过保证 DefaultStorageClass 出现在 API 服务器组件的 --enable-admission-plugins 标志值中实现这点;该标志的值可以是逗号 分隔的有序列表。
持久卷申领(PersistentVolumeClaim,PVC)申领特定的大小的PV和访问模式
(要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)
(要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)
绑定
PVC 申领与 PV 卷之间的绑定是一种一对一的映射,实现上使用 ClaimRef 来记述 PV 卷 与 PVC 申领间的双向绑定关系
如果找不到匹配的 PV 卷,PVC 申领会无限期地处于未绑定状态。 当与之匹配的 PV 卷可用时,PVC 申领会被绑定。
例如,即使某集群上供应了很多 50 Gi 大小的 PV 卷,也无法与请求 100 Gi 大小的存储的 PVC 匹配。当新的 100 Gi PV 卷被加入到集群时,该 PVC 才有可能被绑定。
例如,即使某集群上供应了很多 50 Gi 大小的 PV 卷,也无法与请求 100 Gi 大小的存储的 PVC 匹配。当新的 100 Gi PV 卷被加入到集群时,该 PVC 才有可能被绑定。
存储保护
确保仍被 Pod 使用的 PersistentVolumeClaim(PVC)对象及其所绑定的 PersistentVolume(PV)对象在系统中不会被删除,防止数据丢失
如果用户删除被某 Pod 使用的 PVC 对象,该 PVC 申领不会被立即移除。 PVC 对象的移除会被推迟,直至其不再被任何 Pod 使用。
此外,如果管理员删除已绑定到某 PVC 申领的 PV 卷,该 PV 卷也不会被立即移除。 PV 对象的移除也要推迟到该 PV 不再绑定到 PVC。
此外,如果管理员删除已绑定到某 PVC 申领的 PV 卷,该 PV 卷也不会被立即移除。 PV 对象的移除也要推迟到该 PV 不再绑定到 PVC。
在引用的情况下删除pvc:kubectl describe pvc hostpath
在引用的情况下删除pv:kubectl describe pv task-pv-volume
使用
创建一个目录:mkdir /mnt/data
创建文件:sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
创建 PersistentVolume
生产集群中,你不会使用 hostPath,可以使用 StorageClasses 来设置动态提供存储,或者网路存储
创建:kubectl apply -f task-pv-volume.yaml
查看:kubectl get pv task-pv-volume
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 4s
状态(STATUS) 为 Available。 这意味着它还没有被绑定给 PersistentVolumeClaim
task-pv-volume 10Gi RWO Retain Available manual 4s
状态(STATUS) 为 Available。 这意味着它还没有被绑定给 PersistentVolumeClaim
创建 PersistentVolumeClaim
访问模式有:
ReadWriteOnce -- 卷可以被一个节点以读写方式挂载;
ReadOnlyMany -- 卷可以被多个节点以只读方式挂载;
ReadWriteMany -- 卷可以被多个节点以读写方式挂载。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
RWO - ReadWriteOnce
ROX - ReadOnlyMany
RWX - ReadWriteMany
ReadWriteOnce -- 卷可以被一个节点以读写方式挂载;
ReadOnlyMany -- 卷可以被多个节点以只读方式挂载;
ReadWriteMany -- 卷可以被多个节点以读写方式挂载。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
RWO - ReadWriteOnce
ROX - ReadOnlyMany
RWX - ReadWriteMany
创建:kubectl apply -f task-pv-claim.yaml
查看PV:kubectl get pv task-pv-volume
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
status为Bound绑定状态
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
status为Bound绑定状态
查看PVC:kubectl get pvc task-pv-claim
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
创建Pod
使用PersistentVolumeClaim 作为存储卷
创建:kubectl apply -f task-pv-pod.yaml
访问容器:kubectl exec -it task-pv-pod -- bash
清理
kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume
访问控制
对 PersistentVolume 添加 GID 注解,Pod具有相同的GID才可写入
PVC绑定PV
使用sc来创建pvc
DaemonSet
建议为无状态的服务使用 Deployments,比如前端服务。 对这些服务而言,对副本的数量进行扩缩容、平滑升级,比精确控制 Pod 运行在某个主机上要重要得多。 当需要 Pod 副本总是运行在全部或特定主机上,并需要它们先于其他 Pod 启动时, 应该使用 DaemonSet
DaemonSet 会尝试遵循一个节点一个 Pod 的模型
每個 Node 上都被部署了該 DaemonSet 定义的 Pod,包括master
kubectl get pods -l name=fluentd-elasticsearch -A -o wide
Jobs
Job会创建一个或多个Pods,直到指定数量的Pods成功终止。删除job会清除所创建的全部Pods。
Job示例
π的小数点后2000位
kubectl apply -f job.yaml
kubectl describe jobs/pi
查看job的详情
kubectl get pods
查看已完成的pods
kubectl logs pod-name
查看一个pod的标准输出
Job规约
job中pod的restartPolicy只能设置Never或OnFailure
.spec.selector是可选的,一般情况下不设置
job并行
非并行job
只启动一个pod
Pod成功终止,立即视job为完成状态
设置完成计数的并行job
.spec.completions字段为非0值,默认值为1
当成功的pod个数达到completions设定的数值时,job被视为完成
当设置.spec.completionMode="Indexed"时,每个Pod都会获取一个不同的索引值,介于0~completions-1
带工作队列的并行job
不设置spec.completions,设置spec.parallelism,默认值为1
多个Pod间相互协调,或借助外部服务确定每个Pod要处理队列内容。一个pod会处理多个队列内容
pod可以确定其他pod是否已完成,进而确定job是否完成
Pod成功完成后,不会在创建新的pod
Pod完成队列内容处理成功退出,其他Pod不会再对其处理的队列内容进行操作。
控制并行度
spec.parallelism 默认值为1。如果设置为0,job启动后便被暂停,直到此值被增加
实际并行数可能比设置的并行度数值略大或略小
设置完成计数的job,并行执行的pods个数不会超过剩余的完成数。比如:完成数设置为5,并行度为3,有3个pod成功完成,剩余完成数为2,这是的并行的pod个数只能是2个
工作队列job,任何pod成功结束后,不再创建新的pod,剩余的pod会继续执行,直到成功结束
job控制器因为任何原因无法创建Pods
Pod正在终止过程中,需要一定时间才会停止
处理Pod和容器失效
Pod中的容器因不同原因失效
设置.spec.template.spec.restartPolicy = "OnFailure"
Pod保留在当前节点,容器会被重新运行
整个Pod失败
Job控制器会启动一个新的pod
即使你将 .spec.parallelism 设置为 1,且将 .spec.completions 设置为 1,并且 .spec.template.spec.restartPolicy 设置为 "Never",同一程序仍然有可能被启动两次。
将 .spec.parallelism 和 .spec.completions 都设置为比 1 大的值, 那就有可能同时出现多个 Pod 运行的情况。 为此,Pod 必须能够处理并发性问题
Pod回退失效策略
spec.backoffLimit 默认值为6 (分钟)
重试次数,重试时间将会按指数增长 (从 10 秒、20 秒到 40 秒)最多至 6 分钟
也就是10s重试一次,20秒重试一次,40s重试一次,80s重试一次。。。
重试次数,重试时间将会按指数增长 (从 10 秒、20 秒到 40 秒)最多至 6 分钟
也就是10s重试一次,20秒重试一次,40s重试一次,80s重试一次。。。
Pod被删除或者成功时,回退时间还会被重置
如果Job 的 restartPolicy 被设置为 "OnFailure",就要注意在 Job 到达失效回退次数上限时自动被终止
建议在调试 Job 时将 restartPolicy 设置为 "Never", 或者使用日志系统来确保失效 Jobs 的输出不会意外遗失。
Job终止与清理
Job完成后不再创建新的pod,老的pod和job都不会被删除,可以手动删除
终止job的另一个方式
设置.spec.activeDeadlineSeconds
优先度高于.spec.backoffLimit
一旦 Job 运行时间达到 activeDeadlineSeconds 秒,其所有运行中的 Pod 都会被终止,并且 Job 的状态更新为 type: Failed 及 reason: DeadlineExceeded。
注意:restartPolicy 对应的是 Pod,而不是 Job 本身: 一旦 Job 状态变为 type: Failed,就不会再发生 Job 重启的动作。 换言之,由 .spec.activeDeadlineSeconds 和 .spec.backoffLimit 所触发的 Job 终结机制 都会导致 Job 永久性的失败,而这类状态都需要手工干预才能解决。
自动清理完成的job
完成的job会留在系统里,占用资源
设置 Job 的 .spec.ttlSecondsAfterFinished 字段,可以让该控制器清理掉 已结束的资源。
Job pi-with-ttl 在结束 100 秒之后,可以成为被自动删除的对象。
如果该字段设置为 0,Job 在结束之后立即成为可被自动删除的对象。
如果该字段没有设置,Job 不会在结束之后被 TTL 控制器自动清除。
如果该字段设置为 0,Job 在结束之后立即成为可被自动删除的对象。
如果该字段没有设置,Job 不会在结束之后被 TTL 控制器自动清除。
垃圾回收
kubectl get pods --output=yaml
子主题
kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace
查看没有归属的事件
kubectl delete replicaset my-repset --cascade=orphan
令附属成为孤立对象
kubectl delete replicaset my-repset --cascade=foreground
在前台删除附属对象
kubectl delete replicaset my-repset --cascade=background
在后台删除附属对象
TTL控制器
CronJob
Kubernetes v1.21 [stable]
定时调度job
每分钟打印出当前时间和问候消息
Job 应该是 幂等的
在某些情况下,可能会创建两个 Job,或者不会创建任何 Job
startingDeadlineSeconds 设置为很大的数值或未设置(默认),并且 concurrencyPolicy 设置为 Allow,则作业将始终至少运行一次。
如果 startingDeadlineSeconds 的设置值低于 10 秒钟,CronJob 可能无法被调度。 这是因为 CronJob 控制器每 10 秒钟执行一次检查。
CronJob控制器会检查失败的调度次数
调度次数超过100次,将不会再启动job
ReplicationController
推荐使用配置 ReplicaSet 的 Deployment 来建立副本管理机制
服务、负载均衡和联网
Service
基于四层的负载
Kubernetes 使用标签来将多个相关的 Pod 组合成一个逻辑单元(称为 Service)。
Service 具有稳定的 IP 地址和端口,并会在一组 Pod 之间提供负载平衡
Service 具有稳定的 IP 地址和端口,并会在一组 Pod 之间提供负载平衡
定义Service
Service 在 Kubernetes 中是一个 REST 对象,和 Pod 类似
Service 能够将一个接收 port 映射到任意的 targetPort。 默认情况下,targetPort 将被设置为与 port 字段相同的值
没有选择器的Service
没有选择算符的 Service
手动添加 Endpoint 对象
服务类型
Service 类型,默认是 ClusterIP
ClusterIP(默认):内部客户端向稳定的内部 IP 地址发送请求。
NodePort:客户端向使用 Service 指定的一个或多个 nodePort 值的节点的 IP 地址发送请求。
LoadBalancer:客户端向网络负载平衡器的 IP 地址发送请求。
ExternalName:内部客户端使用 Service 的 DNS 名称作为外部 DNS 名称的别名。
Headless:如果您需要 Pod 分组,但不需要稳定的 IP 地址,则可以使用 Headless 服务。
NodePort:客户端向使用 Service 指定的一个或多个 nodePort 值的节点的 IP 地址发送请求。
LoadBalancer:客户端向网络负载平衡器的 IP 地址发送请求。
ExternalName:内部客户端使用 Service 的 DNS 名称作为外部 DNS 名称的别名。
Headless:如果您需要 Pod 分组,但不需要稳定的 IP 地址,则可以使用 Headless 服务。
NodePort 类型是 ClusterIP 类型的扩展。因此,NodePort 类型的 Service 具有集群 IP 地址。
LoadBalancer 类型是 NodePort 类型的扩展。因此,LoadBalancer 类型的 Service 具有集群 IP 地址以及一个或多个 nodePort 值。
LoadBalancer 类型是 NodePort 类型的扩展。因此,LoadBalancer 类型的 Service 具有集群 IP 地址以及一个或多个 nodePort 值。
ClusterIP
Kubernetes 会创建一个稳定的 IP 地址,该 IP 地址可从集群中的节点访问
集群中的客户端在 TCP 端口 80 上调用地址为 10.11.247.213 的 Service。请求将转发到 TCP 端口 8080 上的其中一个成员 Pod。成员 Pod 必须有一个侦听 TCP 端口 8080 的容器。
NodePort
标志指定的范围内分配端口(默认值:30000-32767)
标志指定的范围内分配端口(默认值:30000-32767)
Kubernetes 会为您提供 nodePort 值。然后,您可以使用任何节点的 IP 地址及 nodePort 值来访问 Service。
nodePort是对外使用的端口,可以使用各个节点的ip+3100访问
注意:您可以自行指定 nodePort 值(范围介于 30000-32767 之间)。
但是,最好省略该字段,让 Kubernetes 为您分配 nodePort。这样做有助于避免 Service 之间出现冲突。
但是,最好省略该字段,让 Kubernetes 为您分配 nodePort。这样做有助于避免 Service 之间出现冲突。
LoadBalancer
https://kubernetes.io/zh/docs/concepts/services-networking/service/
ExternalName
集群内部引用外部服务,集群内部访问service就可以访问到外部的服务
定义将 pod 名称空间中的 service 服务映射到 www.baidu.com
ingress
基于七层的负载
Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务
子主题
访问Ingress需要先配置一个网关
NodePort类型
通过域名加上网关的端口号,才可访问后台服务。
http
https
kubectl get ing
查看ingress
收藏
0 条评论
下一页