写在前面
本文一起看下Deployment API对象,该对象的作用是保证POD的高可用,即保证POD的可用数量一直维持在某个期望状态
中,比如期望状态是有3个POD,当有一个POD意外终止时,则会自动再启动一个新POD,所以Deployment和POD之间是一种松散的引用关系,另外被引用的POD也可能被负载均衡组件引用,所以并非专属于Deployment,这点不同于Job和CronJob,Job和CronJob同POD是一种强绑定的关系,POD只为Job或CronJob所用。下面我们一起来看下。
1:创建Deployment
首先生成yaml模板,如下:
dongyunqi@mongodaddy:~/k8s$ export out="--dry-run=client -o yaml" && kubectl create deploy ngx-dep --image=nginx:alpine $out
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: ngx-dep
name: ngx-dep
spec:
replicas: 2
selector:
matchLabels:
app: ngx-dep
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: ngx-dep
spec:
containers:
- image: nginx:alpine
name: nginx
resources: {}
status: {}
修改完善后如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ngx-dep
name: ngx-dep
spec:
replicas: 2
selector:
matchLabels:
app: ngx-dep
template:
metadata:
labels:
app: ngx-dep
spec:
containers:
- image: nginx:alpine
name: nginx
主要字段:
selector:用来选择要管理的POD,类似于spring的<bean ref=""/>中的ref,但是这里是通过labels.app选择
replicas:POD的副本数量,即POD的期望状态,如果是2则代表必须有2个POD
对于selector比较绕,可以参考下图:
apply应用:
dongyunqi@mongodaddy:~/k8s$ kubectl apply -f deploy.yml
deployment.apps/ngx-dep created
查看:
dongyunqi@mongodaddy:~/k8s$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
ngx-dep 2/2 2 2 20s
看下主要信息,READY表示正常POD和期望POD信息,格式是正常POD数/期望POD数
,UP-TO-DATE是部署完成的POD数(部署完成不一定健康,如内部应用不可用)
,AVAILABEL是健康的POD数(可正常对外提供服务)
,AGE是从apply完成到当前经过的时间。看下内部的POD:
dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 6s
ngx-dep-bfbb5f64b-xr6gw 1/1 Running 0 6s
主要看下POD的NAME命名规则,规则是deployment API对象的name-POD模板哈希值-5位随机字符串
,直接对号入座即可。
2:期望状态测试
前面我们提到了Deployment会维护POD数量在一个期望的状态,此时我们的期望状态是2
,为了方便对比,先看下当前的状态:
dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 6s
ngx-dep-bfbb5f64b-xr6gw 1/1 Running 0 6s
此时有2个PDO,ds78j
,ds78j
,然后我们模拟误删除ds78j
:
dongyunqi@mongodaddy:~/k8s$ kubectl delete pod ngx-dep-bfbb5f64b-ds78j && kubectl get pod ## 这里使用&& kubectl get pod是为了快速看到创建中的新POD
pod "ngx-dep-bfbb5f64b-chqhp" deleted
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 12m
ngx-dep-bfbb5f64b-lvdgz 0/1 ContainerCreating 0 1s ## 新创建的POD,此时容器创建中
dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 13m
ngx-dep-bfbb5f64b-lvdgz 1/1 Running 0 42s
可以看到很快就新建一个POD并进入状态ContainerCreating
,并很快创建完成进入RUNNING状态,到了2
这个期望状态
,不得不说真的很强。
3:扩容测试
扩容也比较简单,直接使用kubectl scale --replicas=新POD数
,如从2
变为3
,如下:
dongyunqi@mongodaddy:~/k8s$ kubectl scale --replicas=3 deploy ngx-dep
deployment.apps/ngx-dep scaled
dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 16m
ngx-dep-bfbb5f64b-lvdgz 1/1 Running 0 3m43s
ngx-dep-bfbb5f64b-vj9qk 1/1 Running 0 3s
可以看到POD的个数就变成3了。但是这种方式只是临时的,如果是重新apply的话,又会变回去,所以最好的办法是直接修改yaml文件,然后重新apply,但如果是线上应急的话,也可以临时采用这种方法,总之,具体情况具体分析,灵活应对。
写在后面
多知道一点
1:Deployment只能用于无状态服务,因为会随时老的退出,增加新的,对于有状态服务,如redis,kafka,es等不能使用Deployment,不然会造成数据丢失
2:Deployment用来处理无状态在线业务,和Job,CronJob处理离线业务相对应
3:Deployment仅仅负责维持POD在一个期望的状态,不具备负载均衡等功能,这符合单一职责的原则,其它功能k8s提供了对应的其它API对象,如负载均衡提供了Ingress
4:如果发现POD处于异常状态,如一直PENDING,则可执行kubectl describe pod <pod名> -n <namespace>定位问题
5:可以根据POD的label来过滤POD,支持使用==、!=、in、notin等表达式,如下:
dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l 'app in (ngx, nginx, ngx-dep)'
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 19m
ngx-dep-bfbb5f64b-lvdgz 1/1 Running 0 6m44s
ngx-dep-bfbb5f64b-vj9qk 1/1 Running 0 3m4s
dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l 'app=ngx-dep'
NAME READY STATUS RESTARTS AGE
ngx-dep-bfbb5f64b-ds78j 1/1 Running 0 20m
ngx-dep-bfbb5f64b-lvdgz 1/1 Running 0 7m22s
ngx-dep-bfbb5f64b-vj9qk 1/1 Running 0 3m42s
参考文章列表
k8s上pod一次pending解决过程 。