POD控制器
Pod控制器,又称为工作负载(workload),是Kubernetes中用于实现管理Pod的中间层,它确保Pod资源符合预期的状态。当Pod资源出现故障时,Pod控制器会尝试进行重启,若根据重启策略无效,则会重新新建Pod资源。以下是Pod控制器的详细介绍:
一、Pod控制器的作用
1.1. 确保Pod副本数量:
Pod控制器代用户创建指定数量的Pod副本,并确保这些副本数量符合预期状态。
1.2. 自动恢复:
当Pod资源出现故障时,控制器会根据定义的策略重新编排Pod,确保应用的持续运行。
1.3. 扩缩容:
支持滚动式自动扩容和缩容功能,根据应用需求调整Pod数量。
1.4. 更新和回滚:
对于某些控制器(如Deployment),支持应用的滚动更新和版本回退。
二、常见的Pod控制器类型
2.1 ReplicaSet/ReplicationController
作用:用于保证Pod的副本数量维持在用户指定的数量。它支持Pod数量的扩缩Pod模板的更新,但不涉及应用状态的管理。
组件:主要由用户期望的Pod副本数量、标签选择器(用于判断哪个Pod归自理)和Pod资源模板组成。
特点:帮助用户管理无状态的Pod资源,精确反应用户定义的目标数量ReplicaSet不是直接使用的控制器,而是通常通过Deployment来间接管理。
2.1.1 ReplicationController(RC)
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-demo
spec: # rc期望
replicas: 3 # 定义当前pod副本数量
selector: # pod选择器
app: rc-demo # 选择符合选择器标签的pod
template: # 模版
metadata:
labels:
app: rc-demo
spec: # 容器期望
containers:
- name: rc-demo-container
image: wangyanglinux/myapp:v1.0
env: #环境变量
- name: GET_HOSTS_FROM
value: dns
- name: zhangsan
value: "123"
ports:
- containerPort: 80
[root@master 5]# kubectl get rc
NAME DESIRED CURRENT READY AGE
rc-demo 3 3 3 25s
[root@master 5]# kubectl get pod
NAME READY STATUS RESTARTS AGE
rc-demo-9rw48 1/1 Running 0 21s
rc-demo-hxtj8 1/1 Running 0 21s
rc-demo-v687d 1/1 Running 0 21s
[root@master 5]# kubectl label pod rc-demo-nrkvf version=v1
pod/rc-demo-nrkvf labeled
[root@master 5]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
rc-demo-9rw48 1/1 Running 0 5m38s app=rc-demo
rc-demo-hxtj8 1/1 Running 0 5m38s app=rc-demo
rc-demo-nrkvf 1/1 Running 0 4m17s app=rc-demo,version=v1
[root@master 5]# kubectl label pod rc-demo-nrkvf app=test --overwrite
pod/rc-demo-nrkvf labeled
[root@master 5]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
rc-demo-9rw48 1/1 Running 0 6m35s app=rc-demo
rc-demo-hxtj8 1/1 Running 0 6m35s app=rc-demo
rc-demo-nrkvf 1/1 Running 0 5m14s app=test,version=v1
rc-demo-sbhb2 1/1 Running 0 9s app=rc-demo
# 调整副本数量
[root@master 5]# kubectl scale rc rc-demo --replicas=10
replicationcontroller/rc-demo scaled
[root@master 5]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
rc-demo-98w2k 1/1 Running 0 10s app=rc-demo
rc-demo-9rw48 1/1 Running 0 13m app=rc-demo
rc-demo-cdvrq 1/1 Running 0 10s app=rc-demo
rc-demo-cf42f 1/1 Running 0 10s app=rc-demo
rc-demo-dgj5p 1/1 Running 0 10s app=rc-demo
rc-demo-f2g6k 1/1 Running 0 10s app=rc-demo
rc-demo-hxtj8 1/1 Running 0 13m app=rc-demo
rc-demo-n2fp8 1/1 Running 0 10s app=rc-demo
rc-demo-nrkvf 1/1 Running 0 12m app=test,version=v1
rc-demo-nw2h9 1/1 Running 0 10s app=rc-demo
rc-demo-sbhb2 1/1 Running 0 7m2s app=rc-demo
[root@master 5]# kubectl label pod rc-demo-nrkvf app=rc-demo --overwrite
pod/rc-demo-nrkvf labeled
[root@master 5]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
rc-demo-98w2k 1/1 Running 0 41s app=rc-demo
rc-demo-9rw48 1/1 Running 0 13m app=rc-demo
rc-demo-cdvrq 1/1 Running 0 41s app=rc-demo
rc-demo-cf42f 1/1 Running 0 41s app=rc-demo
rc-demo-dgj5p 1/1 Running 0 41s app=rc-demo
rc-demo-f2g6k 1/1 Running 0 41s app=rc-demo
rc-demo-hxtj8 1/1 Running 0 13m app=rc-demo
rc-demo-n2fp8 1/1 Running 0 41s app=rc-demo
rc-demo-nrkvf 1/1 Running 0 12m app=re-demo,version=v1
rc-demo-nw2h9 1/1 Running 0 41s app=rc-demo
rc-demo-sbhb2 1/1 Running 0 7m33s app=rc-demo
2.1.2 ReplicaSet(RS)
ReplicaSet的匹配运算符主要包括以下几种,这些运算符用于在Pod模板的标签选择器(selector)中指定选择Pod的规则:
2.1.2.1 matchLabels:
通过直接指定键值对来选择Pod。只有当Pod的标签与matchLabels中定义的标签完全匹配时,该Pod才会被选中。
示例:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-ml-demo
spec:
replicas: 3
selector:
matchLabels: # 匹配标签
app: rs-ml-demo #matchLabels与pod标签做子集关系匹配
domian: Noziroh
template:
metadata:
labels:
app: rs-ml-demo
domian: Noziroh
version: v1
spec:
containers:
- name: rs-ml-demo-container
image: wangyanglinux/myapp:v1.0
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
[root@master 5]# kubectl get pod
NAME READY STATUS RESTARTS AGE
rc-demo-9rw48 1/1 Running 0 23m
rc-demo-hxtj8 1/1 Running 0 23m
rc-demo-nrkvf 1/1 Running 0 22m
rs-ml-demo-fm427 1/1 Running 0 20s
rs-ml-demo-kzjph 1/1 Running 0 20s
rs-ml-demo-v6nbn 1/1 Running 0 20s
2.1.2.2 matchExpressions:
提供了一种更灵活的方式来选择Pod,支持使用更复杂的逻辑条件(如AND、OR、NOT等,尽管直接通过matchExpressions实现复杂的逻辑组合需要多个表达式)。
每个matchExpressions条目可以包含key、operator和values三个字段。
key:要匹配的标签的键。
operator:比较运算符,用于定义如何匹配标签的值。常见的运算符包括In(值在列表中)、NotIn(值不在列表中)、Exists(标签存在)、DoesNotExist(标签不存在)。
values:一个值列表,当operator为In或NotIn时使用。
matchExpressions字段是一个列表,其中每个条目都定义了一个匹配条件。每个条件都由key、operator和values三个字段组成:
key:要匹配的标签的键。
operator:一个字符串,指定了与values数组中的值进行比较的运算符。常见的运算符包括:
- In:标签的值必须存在于values数组中。
- NotIn:标签的值不能存在于values数组中。
- Exists:Pod必须拥有该标签,但不对标签的值进行验证。
- DoesNotExist:Pod不能拥有该标签。
values:一个字符串数组,当operator为In或NotIn时,用于与Pod标签的值进行比较。对于Exists和DoesNotExist运算符,该字段将被忽略。
下面是一个使用matchExpressions的ReplicaSet示例:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-replicaset
spec:
replicas: 3
selector:
matchExpressions:
- key: app
operator: In
values:
- my-app
- key: environment
operator: NotIn
values:
- prod
template:
metadata:
labels:
app: my-app
environment: staging
spec:
containers:
- name: my-container
image: my-image:latest
在这个例子中,ReplicaSet my-replicaset 将选择所有标签为app: my-app且标签environment的值不是prod的Pod。这意味着,只有那些同时拥有app: my-app标签且environment标签的值不是prod(例如,environment: staging)的Pod才会被my-replicaset管理。
exist
示例:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-me-exists-demo
spec:
selector:
matchExpressions:
- key: app
operator: Exists # 只要存在标签名为app即可
template:
metadata:
labels:
app: spring-k8s
spec:
containers:
- name: rs-me-exists-demo-container
image: wangyanglinux/myapp:v1.0
ports:
- containerPort: 80
[root@master 5]# kubectl create -f 02_rs.yaml
replicaset.apps/rs-me-exists-demo created
[root@master 5]# kubectl get rs
NAME DESIRED CURRENT READY AGE
rs-me-exists-demo 1 1 1 10s
[root@master 5]# kubectl label pod rs-me-exists-demo-nhr89 app=Noziroh --overwrite
pod/rs-me-exists-demo-nhr89 labeled
rs-me-exists-demo-nhr89 1/1 Running 0 2m15s app=Noziroh
in示例
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-me-in-demo
spec:
selector:
matchExpressions:
- key: app
operator: In
values:
- spring-k8s
- hahahah
template:
metadata:
labels:
app: sg-k8s
spec:
containers:
- name: rs-me-in-demo-container
image: wangyanglinux/myapp:v1.0
ports:
- containerPort: 80
[root@master 5]# kubectl create -f 02_rs_in.yaml
The ReplicaSet "rs-me-in-demo" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"sg-k8s"}: `selector` does not match template `labels`
#app: sg-k8s 属于matchExpressions app:[spring-k8s,hahahah] 所以无法创建
#修改yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-me-in-demo
spec:
selector:
matchExpressions:
- key: app
operator: In
values:
- spring-k8s
- hahahah
- sg-k8s
template:
metadata:
labels:
app: sg-k8s
spec:
containers:
- name: rs-me-in-demo-container
image: wangyanglinux/myapp:v1.0
ports:
- containerPort: 80
[root@master 5]# kubectl create -f 02_rs_in.yaml
replicaset.apps/rs-me-in-demo created
删除rc rs 创建的pod
[root@master 5]# kubectl delete rc --all
replicationcontroller "rc-demo" deleted
[root@master 5]# kubectl delete rs --all
replicaset.apps "rs-me-exists-demo" deleted
replicaset.apps "rs-me-in-demo" deleted
replicaset.apps "rs-ml-demo" deleted
注意:
在实际使用中,matchLabels和matchExpressions可以单独使用,也可以组合使用(但通常不建议这样做,因为这可能会增加配置的复杂性并导致意外的选择结果)。
matchLabels提供了一种简单直观的方式来选择Pod,而matchExpressions则提供了更强大的灵活性和表达能力。
在定义ReplicaSet时,选择器的目的是确保ReplicaSet能够正确地识别和管理它应该负责的Pod。因此,在配置选择器时,需要确保它能够准确地匹配到目标Pod,以避免出现Pod丢失或ReplicaSet无正确管理Pod的情况。
2.2 Deployment
声明式定义
- 作用:工作在ReplicaSet之上,用于管理无状态应用。它提供了应用的声明能力,允许用户定义应用的期望状态,并自动处理Pod的创建、更新和删除。
- 功能:支持滚动更新和版本回退,还提供了事件和状态查看、暂停和继续部能。
常用命令
1. 创建Deployment
使用kubectl create命令:可以直接通过命令行创建Deployment,指定容器镜像、副本数量等参数。
kubectl create deployment my-deployment --image=nginx:latest --replicas=3
这个命令会创建一个名为my-deployment的Deployment,使用nginx:latest镜像,并设置副本数量为3。
使用YAML文件:更常见的做法是先编写一个YAML文件定义Deployment,然后使用kubectl apply命令应用这个文件。
kubectl apply -f my-deployment.yaml
2. 查看Deployment
列出所有Deployments:
kubectl get deployments
这个命令会列出当前命名空间下的所有Deployments。
查看特定Deployment的详细信息:
kubectl describe deployment my-deployment
这个命令会显示名为my-deployment的Deployment的详细信息,包括Pod模板、副本数量、事件等。
3. 更新Deployment
更改副本数量:
kubectl scale deployment my-deployment --replicas=5
这个命令会将my-deployment的副本数量更改为5。
更新容器镜像:
kubectl set image deployment my-deployment my-container=nginx:1.19.2
这个命令会将my-deployment中名为my-container的容器的镜像更新为nginx:1.19.2。
4. 滚动更新和回滚
滚动更新:默认情况下,通过更改Deployment的Pod模板(如镜像版本)并重新应用,Kubernetes会执行滚动更新。
回滚到上一个版本:
kubectl rollout undo deployment my-deployment
这个命令会将my-deployment回滚到上一个版本。
查看更新历史:
kubectl rollout history deployment my-deployment
这个命令会显示my-deployment的更新历史。
回滚到指定版本:
kubectl rollout undo deployment my-deployment --to-revision=N
其中N是想要回滚到的版本号(从kubectl rollout history命令中获取)。
暂停和恢复滚动更新
# 暂停滚动更新
kubectl rollout pause deployment/<deployment-name>
# 恢复滚动更新
kubectl rollout resume deployment/<deployment-name>
更新策略
在Kubernetes(k8s)中,Deployment的更新策略是管理Pod版本升级和回滚的重要机制。主要的更新策略包括滚动更新(RollingUpdate)和重建(Recreate),每种策略都有其适用场景和配置方式。
1. 滚动更新(RollingUpdate)
滚动更新是Kubernetes Deployment的默认更新策略。在滚动更新过程中,Deployment控制器会逐步地将新版本的Pod逐个替换旧版本的Pod,从而确保在升级过程中始终有一定数量的可用Pod服务于客户端请求,实现平滑的服务过渡。
关键参数:
- maxSurge:表示在滚动更新过程中,可以超出期望副本数的最大Pod数或百分比。这有助于在更新过程中保持冗余度,以应对可能的故障。
- maxUnavailable:表示在滚动更新过程中,允许的最大不可用Pod数或百分比。这有助于控制更新过程中服务的可用性。
配置示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 或者设置为一个整数,如 maxSurge: 1
maxUnavailable: 25% # 或者设置为一个整数,如 maxUnavailable: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2
适用场景:
滚动更新特别适用于需要确保服务持续可用的场景,如生产环境中的应用程序升级。
2. 重建(Recreate)
重建策略会在创建新Pod之前删除所有现有的Pod。这种策略会导致应用程序的短暂中断,因为在删除旧Pod和创建新Pod之间存在时间差。
配置示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2
适用场景:
重建策略适用于无状态应用程序或可以容忍短暂中断的应用程序,如开发环境或测试环境中的应用程序升级。
总结
在选择Deployment的更新策略时,需要根据应用程序的特性和业务需求进行权衡。滚动更新提供了更好的服务可用性和平滑的升级体验,但可能会增加系统的复杂性和资源消耗。重建策略则更简单直接,但可能会导致服务中断。在实际应用中,可以根据具体情况选择合适的更新策略,并通过调整maxSurge和maxUnavailable等参数来优化升级过程。
金丝雀部署
- 定义:金丝雀发布是在新旧版本之间平滑过渡的一种发布方式,通过让一部分用户先使用新版本,另一部分用户继续使用旧版本,从而逐步验证新版本的稳定性和性能。
- 目的:降低新软件版本部署的风险,确保新版本在生产环境中能够稳定运行,同时避免对整个系统造成过大影响。
vi deployment-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: deployment-demo
name: deployment-demo
spec:
replicas: 10
selector:
matchLabels:
app: deployment-demo
template:
metadata:
labels:
app: deployment-demo
spec:
containers:
- image: wangyanglinux/myapp:v1.0
name: deployment-demo-container
[root@master 6]# kubectl apply -f deployment-demo.yaml
deployment.apps/deployment-demo created
[root@master 6]# kubectl create svc clusterip deployment-demo --tcp=80:80
service/deployment-demo created
[root@master 6]# kubectl get deploy deployment-demo -o yaml
spec:
progressDeadlineSeconds: 600
replicas: 10
revisionHistoryLimit: 10
selector:
matchLabels:
app: deployment-demo
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
# 修改滚动更新pod滚动时的数量
# json模式更新 允许pod超过最大值1个,允许不可用pod为0
# '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":2}}}}'
[root@master 6]# kubectl patch deploy deployment-demo -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":2}}}}'
deployment.apps/deployment-demo patched
# 进行滚动更新
# '{"spec":{"template":{"spec":{"containers":[{"image":"wangyanglinux/myapp:v2.0","name":"deployment-demo-container"}]}}}}'
[root@master 6]# kubectl patch deploy deployment-demo --patch '{"spec":{"template":{"spec":{"containers":[{"image":"wangyanglinux/myapp:v2.0","name":"deployment-demo-container"}]}}}}' && kubectl rollout pause deploy deployment-demo
deployment.apps/deployment-demo patched
deployment.apps/deployment-demo paused
[root@master 6]# kubectl get pod | grep deployment |wc -l
11
[root@master 6]# kubectl describe pod deployment-demo-7dd46c6f55-l5mdl
Image: wangyanglinux/myapp:v2.0
[root@master 6]# kubectl rollout resume deploy deployment-demo
deployment.apps/deployment-demo resumed
# 回滚
[root@master 6]# kubectl rollout undo deployment/deployment-demo
deployment.apps/deployment-demo rolled back
[root@master 6]# kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-demo-6465d4c5c9 0 0 0 2m34s
deployment-demo-6995c75668 10 10 10 8m3s
2.2.1. 应用(Apply)
kubectl apply 命令用于根据提供的配置文件(通常是YAML或JSON格式)来创建或更新资源。如果资源不存在,apply 会创建它;如果已存在,apply 会更新资源以匹配配置文件中的定义。
kubectl apply -f deployment.yaml
这个命令会根据deployment.yaml文件中的定义来创建或更新一个Deployment。
2.1.2. 替换(Replace)
在Kubernetes中,并没有直接的replace命令来替换整个Deployment。但是,你可以使用kubectl replace命令来替换资源的定义,但这通常用于特定的场景,比如你需要替换整个资源对象而不是简单地更新它。
kubectl replace -f deployment.yaml --force
注意:–force选项在较新版本的kubectl中可能不是必需的,具体取决于你的Kubernetes集群版本和kubectl版本。使用replace时要小心,因为它会替换整个资源对象,而不仅仅是更新它。
对比
kubectl apply | kubectl replace | |
---|---|---|
功能 | 创建或更新资源,使其与配置文件匹配 | 替换资源的当前配置,使其与配置文件完全匹配 |
特点 | 增量更新,幂等性,易于使用 | 全面替换,可能导致资源状态丢失,需要谨慎使用 |
适用场景 | 大多数资源更新场景 | 需要替换整个资源对象或资源状态复杂难以通过apply 更新的场景 |
测试
apiVersion: apps/v1
kind: Deployment # 类别为Deployment
metadata:
labels:
app: myapp-deploy # Deployment 标签
name: myapp-deploy # Deployment 名字
spec:
replicas: 1
selector:
matchLabels:
app: myapp-deploy # 容器标签app=myapp-deploy
template:
metadata:
labels:
app: myapp-deploy # 容器名字
spec:
containers:
- image: wangyanglinux/myapp:v1.0
name: myapp
[root@master 5]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-deploy-7977896984-gsd6m 1/1 Running 0 36s
[root@master 5]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
myapp-deploy 1/1 1 1 59s myapp wangyanglinux/myapp:v1.0 app=myapp-deploy
[root@master 5]# kubectl get deploy -o yaml
availableReplicas: 1
[root@master 5]# kubectl scale deploy myapp-deploy --replicas=10
deployment.apps/myapp-deploy scaled
[root@master 5]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
myapp-deploy 10/10 10 10 3m26s myapp wangyanglinux/myapp:v1.0 app=myapp-deploy
[root@master 5]# kubectl get deploy -o yaml
availableReplicas: 10
[root@master 5]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-7977896984-6gwzj 1/1 Running 0 101s 10.244.166.167 node1 <none> <none>
myapp-deploy-7977896984-9mmn4 1/1 Running 0 101s 10.244.104.35 node2 <none> <none>
myapp-deploy-7977896984-b47vm 1/1 Running 0 101s 10.244.166.170 node1 <none> <none>
myapp-deploy-7977896984-b6t5j 1/1 Running 0 101s 10.244.166.168 node1 <none> <none>
myapp-deploy-7977896984-gsd6m 1/1 Running 0 4m42s 10.244.104.34 node2 <none> <none>
myapp-deploy-7977896984-jbg62 1/1 Running 0 101s 10.244.166.171 node1 <none> <none>
myapp-deploy-7977896984-m2kh6 1/1 Running 0 101s 10.244.104.36 node2 <none> <none>
myapp-deploy-7977896984-r8shx 1/1 Running 0 101s 10.244.104.38 node2 <none> <none>
myapp-deploy-7977896984-rp6rz 1/1 Running 0 101s 10.244.104.37 node2 <none> <none>
myapp-deploy-7977896984-th76j 1/1 Running 0 101s 10.244.166.169 node1 <none> <none>
[root@master 5]# curl 10.244.166.167
www.xinxianghf.com | hello MyAPP | version v1.0
[root@master 5]# vim 01_deploy.yaml
- image: wangyanglinux/myapp:v2.0
[root@master 5]# kubectl apply -f 01_deploy.yaml
deployment.apps/myapp-deploy configured
[root@master 5]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
myapp-deploy 1/1 1 1 6m38s myapp wangyanglinux/myapp:v2.0 app=myapp-deploy
[root@master 5]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-58b4dc6f5-dggz9 1/1 Running 0 95s 10.244.104.39 node2 <none> <none>
[root@master 5]# curl 10.244.104.39
www.xinxianghf.com | hello MyAPP | version v2.0
[root@master 5]# vim 01_deploy.yaml
replicas: 10
- image: wangyanglinux/myapp:v3.0
[root@master 5]# kubectl replace -f 01_deploy.yaml
deployment.apps/myapp-deploy replaced
[root@master 5]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
myapp-deploy 10/10 10 10 17m myapp wangyanglinux/myapp:v3.0 app=myapp-deploy
[root@master 5]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-6fd574ffd6-287zl 1/1 Running 0 97s 10.244.104.44 node2 <none> <none>
myapp-deploy-6fd574ffd6-2rqpt 1/1 Running 0 60s 10.244.166.180 node1 <none> <none>
myapp-deploy-6fd574ffd6-987n5 1/1 Running 0 97s 10.244.104.41 node2 <none> <none>
myapp-deploy-6fd574ffd6-cmw6z 1/1 Running 0 61s 10.244.104.47 node2 <none> <none>
myapp-deploy-6fd574ffd6-g2pkf 1/1 Running 0 97s 10.244.104.42 node2 <none> <none>
myapp-deploy-6fd574ffd6-g9prr 1/1 Running 0 79s 10.244.166.178 node1 <none> <none>
myapp-deploy-6fd574ffd6-jqjbz 1/1 Running 0 72s 10.244.166.179 node1 <none> <none>
myapp-deploy-6fd574ffd6-vnzg4 1/1 Running 0 97s 10.244.166.174 node1 <none> <none>
myapp-deploy-6fd574ffd6-zlfnz 1/1 Running 0 97s 10.244.166.175 node1 <none> <none>
myapp-deploy-6fd574ffd6-zscjl 1/1 Running 0 63s 10.244.104.46 node2 <none> <none>
[root@master 5]# kubectl diff -f 01_deploy.yaml
diff -u -N /tmp/LIVE-1713354067/apps.v1.Deployment.default.myapp-deploy /tmp/MERGED-2968072580/apps.v1.Deployment.default.myapp-deploy
--- /tmp/LIVE-1713354067/apps.v1.Deployment.default.myapp-deploy 2024-08-22 23:48:21.313569984 +0800
+++ /tmp/MERGED-2968072580/apps.v1.Deployment.default.myapp-deploy 2024-08-22 23:48:21.314569996 +0800
@@ -4,7 +4,7 @@
annotations:
deployment.kubernetes.io/revision: "3"
creationTimestamp: "2024-08-22T15:29:32Z"
- generation: 4
+ generation: 5
labels:
app: myapp-deploy
name: myapp-deploy
@@ -13,7 +13,7 @@
uid: 383e54ba-ce53-4320-85d9-d72fd6abb35b
spec:
progressDeadlineSeconds: 600
- replicas: 10
+ replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
@@ -30,7 +30,7 @@
app: myapp-deploy
spec:
containers:
- - image: wangyanglinux/myapp:v3.0
+ - image: wangyanglinux/myapp:v2.0
imagePullPolicy: IfNotPresent
name: myapp
resources: {}
# deployment与rs关联升级 滚动更新
[root@master 5]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
myapp-deploy-58b4dc6f5 0 0 0 20m myapp wangyanglinux/myapp:v2.0 app=myapp-deploy,pod-template-hash=58b4dc6f5
myapp-deploy-6fd574ffd6 10 10 10 10m myapp wangyanglinux/myapp:v3.0 app=myapp-deploy,pod-template-hash=6fd574ffd6
myapp-deploy-7977896984 0 0 0 26m myapp wangyanglinux/myapp:v1.0 app=myapp-deploy,pod-template-hash=7977896984
2.1.3. 删除(Delete)
kubectl delete 命令用于删除一个或多个资源。要删除一个Deployment,你可以使用以下命令:
kubectl delete deployment <deployment-name>
将替换为你的Deployment的名称。
2.1.4. 注意事项
在使用apply或replace时,请确保你的配置文件是最新的,以避免不必要的配置错误或资源状态不一致。
在删除Deployment之前,请确保你了解这将会删除该Deployment管理的所有Pods,并且你有适当的备份或恢划。
kubectl apply是更新资源的推荐方式,因为它可以处理资源配置的增量更新,而replace则更适合于替换整个对象。
对于复杂的应用场景,可能需要结合使用kubectl的多个命令,以及编写适当的Kubernetes配置文件,来精确你的应用部署和更新过程。
2.3 StatefulSet
- 作用:用于管理有状态的应用。它为Pod提供了稳定的网络标识、顺序部署、及扩展和滚动更新的能力。
- 特点:Pod的名称是有序的,且每个Pod都有独立的存储卷。它通常与HeadleService(无头服务)和PVC(持久化卷声明)一起使用,以实现稳定的持久和网络标识。
主要特点
-
- 稳定的唯一网络标识符:
- 每个StatefulSet的Pod都有一个稳定的网络标识符(如DNS名称),这个标识符由控制器自动生成,并与Pod的生命周期保持关联。这使得有状态应用更容易被其他应用或服务访问和发现。
-
- 有序部署和扩展:
- StatefulSet能够按照定义的顺序逐个创建和更新Pod实例,确保它们按照固定的命名规则有序启动。在扩展时,新的Pod也会按照相同的顺序创建,从而保证有状态应用的数据一致性和可用性。
-
- 稳定的存储:
- 每个StatefulSet的Pod都可以使用持久卷(PersistentVolume)来存储数据,这些存储卷在Pod重新启动或迁移时保持不变,从而确保数据的持久性和可靠性。
-
- 域名解析:
- 每个StatefulSet的Pod都有一个稳定的域名,格式通常为...svc.cluster.local。这使得有状态应用可以通过域名进行服务发现和通信。
-
- 有序删除:
在删除StatefulSet时,控制器会按照指定的顺序逐个删除Pod,确保有状态应用在删除过程中不会丢失数据。
- 有序删除:
应用场景
StatefulSet适用于需要持久化存储和唯一标识的有状态应用场景,包括但不限于:
- 数据库(如MySQL、PostgreSQL、MongoDB)
- 消息队列(如RabbitMQ、Kafka)
- 分布式存储(如Elasticsearch、Cassandra)
在这些场景中,StatefulSet提供的稳定网络标识、有序部署和扩展、持久化存储等特性对于保证应用的数据一致性和高可用性至关重要。
组成部分
StatefulSet主要由以下几个部分组成:
- Headless Service:用于定义Pod的网络标识(DNS域名),没有Cluster IP,解析其名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
- volumeClaimTemplates:存储卷申请模板,用于为StatefulSet中的每个Pod生成独立的持久卷声明(PersistentVolumeClaim),从而实现数据的持久化存储。
- StatefulSet定义:定义具体应用,包括Pod副本数、Pod模板(容器配置、存储卷挂载等)、关联的Headless Service等。
示例
以下是一个简单的StatefulSet示例,用于部署一个具有3个副本的MySQL数据库服务:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-statefulset
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql-container
image: mysql:latest
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-storage
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "standard"
resources:
requests:
storage: 1Gi
在这个示例中,StatefulSet mysql-statefulset 定义了3个MySQL Pod副本,每个Pod都挂载了一个名为mysql-storage的持久卷,用于存储数据库数据。这个持久卷通过volumeClaimTemplates自动生成,并请求了1GiB的存储空间。同时,StatefulSet还关联了一个名为mysql的Headless Service,用于提供Pod的网络标识和域名解析。
2.4 DaemonSet
作用:确保在集群中的每个Node上都运行一个Pod的副本。它通常用于运行集群存储、日志收集等守护进程类任务。
特点:无论Node何时加入集群,DaemonSet都会确保在该Node上运行一个Pod副本(除非Node被标记为不可调度)。
一、概述
DaemonSet 控制器能够确保 Kubernetes 集群中的每个节点(或选定的节点)都运行一个 Pod 的副本。当集群中增加新的节点时,DaemonSet 会自动在该节点上创建一个 Pod 副本;当节点从集群中移除时,DaemonSet 也会自动删除该节点上的 Pod。
二、工作原理
- 定义对象:用户定义一个 DaemonSet 对象,指定 Pod 模板和其他配置选项。Pod 模板定义了 Pod 的规格,包括容器、存储和网络配置。
- 调度 Pod:当 DaemonSet 控制器接收到创建请求时,它会在每个匹配的节点上创建一个 Pod 实例。
- 监控 Pod:DaemonSet 控制器监视 Pod 的状态,并确保每个节点上都有 Pod 实例。如果节点失败或重启,DaemonSet 控制器会自动在该节点上重新创建 Pod 实例。
- 更新 Pod:如果用户更新了 Pod 模板,DaemonSet 控制器将负责在所有节点上滚动更新 Pod 实例,以应用新的配置。
- 节点选择:DaemonSet 允许用户通过节点标签选择器来指定应在哪些节点上运行 Pod。如果没有指定选择器,Pod 将在所有节点上运行。
三、相关特性
- 节点覆盖:DaemonSet 确保在集群中的所有节点或选定节点上运行一个 Pod 实例,或者在满足特定条件的节点上运行。
- 自动恢复:如果节点失败或重启,DaemonSet 会自动在该节点上重新创建 Pod,确保服务的连续性。
- 滚动更新:当 Pod 模板更新时,DaemonSet 支持滚动更新,逐步替换旧的 Pod 实例。但通常建议避免在 DaemonSet 中使用 RollingUpdate 更新策略,因为这可能不适用于需要高度稳定性的守护进程应用程序。
- 灵活性:用户可以指定节点标签选择器来控制 Pod 在哪些节点上运行,提供灵活性。
- 资源和调度:DaemonSet 支持资源请求和限制,允许用户为 Pod 指定所需的 CPU 和内存资源。
- 集成:DaemonSet 与 Kubernetes 的其他资源和功能(如服务发现、存储卷和网络策略)紧密集成。
四、应用场景
- 日志收集:在每个节点上运行日志收集器,如 Fluentd、Logstash 或 Filebeat,以收集并转发节点上的日志数据。
- 监控代理:在每个节点上运行监控代理,如 Prometheus Node Exporter、collectd 等,以收集节点的性能指标并发送到监控中心。
- 存储守护进程:在每个节点上运行存储守护进程,如 Glusterd 或 Ceph,以提供分布式存储服务。
五、示例
以下是一个简单的 DaemonSet YAML 配置文件示例,用于在 Kubernetes 集群的每个节点上部署一个 Nginx Pod:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
namespace: default
spec:
selector:
matchLabels:
app: nginx-daemonset
template:
metadata:
labels:
app: nginx-daemonset
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
在创建了这个 DaemonSet 后,Kubernetes 将在每个节点上部署一个 Nginx Pod 副本。如果集群中有新的节点加入,DaemonSet 将自动在该节点上创建一个新的 Nginx Pod 副本。
2.5 Job
作用:用于运行批处理任务,即执行一次性任务。当Pod完成其工作后,Job控制器会负责清理这些Pod。
K8s Job是Kubernetes中的一个核心概念,用于执行一次性任务或批处理作业。以下是关于K8s Job的详细解释:
一、基本概念
- 定义:Job是Kubernetes中的一种资源对象,专门用于处理那些需要运行至完成且不需要持续运行的任务。
- 用途:Job主要用于执行数据处理、备份恢复、日志打包压缩等一次性或批处理任务。
二、主要特性
- 任务执行:Job会创建一个或多个Pod来执行定义的任务,并确保这些Pod成功完成任务。
- 自动清理:当所有Pod都成功完成任务后,Job会停止这些Pod(默认情况下,已完成的Pod会被自动清理)。
- 失败重试:如果Pod执行失败,Job会根据定义的策略进行重试,直到任务成功或达到最大重试次数。
- 并行与串行:Job支持并行执行任务,也支持串行执行任务,具体取决于配置。
三、关键字段
- apiVersion:指定Job资源对象的API版本,通常为batch/v1。
- kind:指定资源对象的类型为Job。
- metadata:包含Job的元数据,如名称(name)、命名空间(namespace)等。
- spec:定义Job的规格,包括任务模板(template)、完成次数(completions)、并行度(parallelism)、重启策略(restartPolicy)等。
- template:定义了Pod的模板,包括使用的镜像、命令、参数等。
- completions:指定需要成功完成的任务数量。
- parallelism:指定同时运行的Pod数量。
- backoffLimit:指定任务失败后的重试次数。
四、使用场景
- 数据处理:如从数据库中导出数据到CSV文件。
- 日志打包压缩:如按时间段打包日志文件。
- 备份恢复:如备份数据库到云存储服务。
- 批处理任务:如根据输入参数计算机器学习模型的特征向量。
五、操作示例
以下是一个简单的Job配置文件示例:
apiVersion: batch/v1
kind: Job
metadata:
name: ubuntu-job
spec:
template:
spec:
containers:
- name: ubuntu-container
image: ubuntu
command: ["echo", "Hello, Kubernetes!"]
restartPolicy: Never
[root@master ~]# kubectl logs ubuntu-job-wlg8x
Hello, Kubernetes!
该配置文件定义了一个名为example-job的Job,它将启动一个Pod,该Pod包含一个运行echo "Hello, Kubernetes!"命令的容器。由于restartPolicy设置为Never,所以Pod在成功完成任务后不会重启。
六、注意事项
- Job适用于一次性任务或批处理作业,不适用于长时间运行的服务。
- 需要确保Job配置文件中定义的容器可以正常运行,并有足够的资源和权限执行指定操作。
2.6 CronJob
作用:用于周期性地创建Job对象,执行定时任务。它类似于Unix中的crontab,用于安排周期性作业。
在Kubernetes(K8s)中,CronJob是一种非常有用的资源对象,它基于Cron表达式,允许用户在指定的时间间隔内自动运行容器化的任务。以下是关于K8s CronJob的详细解释:
一、基本概念
- 定义:CronJob是Kubernetes中用于周期性执行任务的资源对象,它相当于在Job之上增加了基于时间的调度配置。
- 用途:CronJob通常用于部署定时备份、定时检查、定时同步、定时报告等周期性任务。
二、关键属性
- schedule:指定任务执行的时间表,使用标准的Cron表达式语法。例如,“0 * * * *”表示每小时执行一次任务。
- jobTemplate:定义要执行的任务的模板,通常是一个Pod模板。这个模板包含了任务所需的容器镜像、命令、环境变量等配置。
- concurrencyPolicy:指定任务并发策略,默认为Allow。Allow表示允许并发执行任务,Forbid表示禁止并发执行任务(新任务将会被跳过),Replace表示如果任务正在执行,则会终止当前任务并启动新任务。
- successfulJobsHistoryLimit和failedJobsHistoryLimit:分别指定保留成功和失败任务历史记录的数量。默认情况下,成功任务的历史记录保留数量为3,失败任务的历史记录保留数量为1。
三、工作原理
- 定义对象:用户创建一个CronJob对象,指定Pod模板和其他配置选项。
- 监控Job:Kubernetes的调度器会监控CronJob对象的状态。
- 生成Job:根据CronJob定义的时间表,调度器在预定的时间创建Job对象。
- 执行任务:Kubernetes根据Job模板创建Pod,并开始执行任务。
- 监控Pod:Kubernetes监控Pod的状态,确保任务成功完成。
- 记录历史:由CronJob创建的Job都会被记录,包括成功和失败的Job。
- 清理资源:完成的Job及对应的Pod会根据CronJob的配置进行清理。
四、Cron表达式
Cron表达式由五个或六个字段组成,分别代表分钟、小时、日、月、星期几(以及可选的年份)。每个字段的取值范围不同,可以使用通配符、逗号、连字符等方式进行配置。以下是一些常见的Cron表达式示例:
- 每分钟执行一次任务:* * * * *
- 每小时执行一次任务:0 * * * *
- 每天凌晨1点执行任务:0 1 * * *
- 每周一凌晨1点执行任务:0 1 * * 1
- 每月1号凌晨1点执行任务:0 1 1 * *
五、使用场景
- 定时备份:定期备份数据库或文件系统。
- 日志清理:定时清理过期的日志或缓存数据。
- 数据同步:定时拉取或更新数据,如镜像、代码库等。
- 发送通知:定时发送通知或警报。
六、操作示例
以下是一个简单的CronJob配置文件示例:
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello-cronjob
spec:
schedule: "*/1 * * * *" # 每一分钟执行一次任务
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: ubuntu
command: ["/bin/sh", "-c", "date; echo Hello from the Kubernetes cluster"]
restartPolicy: OnFailure
该配置文件定义了一个名为hello-cronjob的CronJob,它将每分钟执行一次任务,任务内容为打印当前日期和时间,并输出“Hello from the Kubernetes cluster”。
七、注意事项
- CronJob的时间精度为分钟级别,不支持秒级别的定时任务。
- 在设计CronJob时,应充分考虑任务执行的时间、频率和并发策略,以避免资源冲突或过度消耗。
- 对于重要的定时任务,建议设置失败重试和历史记录保留策略,以便在任务失败时能够及时发现并处理。
三、Pod与控制器之间的关系
控制器是Kubernetes中用于管理一组Pod的高级对象,而Pod是Kubernetes中运行容器的最小单元。
控制器通过定义一组标签选择器来跟踪和控制具有这些标签的Pod。当Pod因故障而终止时,控制器会根据定义的规则自动创建新的Pod来替换它,从而确保应用的持续运行和所需的副本数量。
四、Pod控制器的实现机制
Pod控制器是由Master节点的kube-controller-manager组件提供的。它通过内部和解(reconciliation loop)机制不断地监控Kubernetes集群内资源对象的状态,以保证集群中的资源对象的状限接近于用户所期望的状态。
当资源对象状态发生变动时,API Server将状态写入etcd中,并通过水平触发机制将事件主动通知给相关的客户端程序(包括kube-controller-manager)。然后,控制器通过API Server的watch实时监控目标资源对象的变动,并在必要时执行和解操作。
综上所述,Pod控制器是Kubernetes中用于管理Pod资源的重要机制,它通过确保Pod副本数量、自动恢复、扩缩容、更新和回滚等功能,为应用的持续运行和运维自动化提供了有力支持。