存活探针
● HTTP GET:向容器发送HTTP GET请求,如果probe收到2xx或3xx,说明容器是 健康的。
● Exec:probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明 健康。
HTTP GET
HTTP GET方式是最常见的探测方法,其具体机制是向容器发送HTTP GET请求,如果 probe收到2xx或3xx,说明容器是健康的,定义方法如下所示。
apiVersion: v1 kind: Pod metadata:
name: liveness-http spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness args:
$ kubectl create -f liveness-http.yaml -n $namespace_name pod/liveness-http created
如上,这个probe往容器的8080端口发送HTTP GET请求,上面的程序会在第五次请求 会返回500状态码,这时Kubernetes会去重启容器。
查看Pod详情。
$ kubectl describe po liveness-http -n $namespace_name Name: liveness-http
...
Containers:
container-0:
...
Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3 ... failed liveness probe.. Container will be killed and recreated.
可以看到Pod当前状态是Running,Last State是Terminated,Restart Count为1,说 明已经重启1次,另外从事件中也可以看到 Killing container with id docker://
container-0:Container failed liveness probe.. Container will be killed and recreated.
另外,容器Kill后会重新创建一个新容器,不只是之前的容器重启。
开发指南 4 Pod
Exec
name: liveness-exec spec:containers:
- name: liveness image: busybox args:
- /bin/sh - -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 livenessProbe: # liveness probe
Liveness Probe 高级配置
上面liveness-http的describe命令回显中有如下行。
Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
这一行表示liveness probe的具体参数配置,其含义如下:
● delay=0s 表示容器启动后立即开始探测,没有延迟时间
● timeout=1s 表示容器必须在1s内做出相应反馈给probe,否则视为探测失败
● period=10s 表示每10s探测一次
● #success=1 表示探测连续1次成功表示成功
● #failure=3 表示探测连续3次失败后会重启容器
这些是创建时默认设置的,您也可以手动配置,如下所示。
apiVersion: v1 kind: Pod metadata:
name: liveness-http spec:
containers:
- image: k8s.gcr.io/liveness livenessProbe:
另外failureThreshold可以设置多次循环探测,这样在实际应用中健康检查的程序就不 需要多次循环,这一点在开发应用时需要注意。
配置有效的 Liveness Probe
● liveness probe应该检查什么
一个好的liveness probe应该检查应用内部所有关键部分是否健康,并使用一个专 有的URL访问,例如 /health,当访问 /health 时执行这个功能,然后返回对应结 果。这里要注意不能做鉴权,不然 probe 就会一直失败导致陷入重启的死循环。
另外检查只能限制在应用内部,不能检查依赖外部的部分,例如当前端web server不能连接数据库时,这个就不能看成web server不健康。
● liveness probe必须轻量
liveness probe不能占用过多的资源,且不能占用过长的时间,否则所有资源都在 做健康检查,这就没有意义了。例如Java应用,就最好用HTTP GET方式,如果用 Exec 方式,JVM启动就占用了非常多的资源。
开发指南 4 Pod
5 Label
为什么需要 Label
当资源变得非常多的时候,如何分类管理就非常重要要了,Kubernetes提供了一种机 制来为资源分类,那就是Label(标签)。Label非常简单,但是却很强大,
Kubernetes中几乎所有资源都可以用Label来组织。
Label的具体形式是key-value的标记对,可以在创建资源的时候设置,也可以在后期添 加和修改。
以Pod为例,当Pod变得多起来后,就显得杂乱且难以管理,如下图所示。
图5-1 没有分类组织的 Pod
如果我们为Pod打上不同标签,那情况就完全不同了,如下图所示。
图5-2 使用 Label 组织的 Pod
添加 Label
Label的形式为key-value形式,使用非常简单,如下,为Pod设置了app=nginx和 env=prod两个Label。
apiVersion: v1 kind: Pod metadata:
name: nginx
labels: # 为Pod设置两个Label app: nginx
env: prod spec:
containers:
- image: nginx:latest name: container-0 resources:
limits:
cpu: 500m memory: 1024Mi requests:
cpu: 500m memory: 1024Mi imagePullSecrets:
- name: imagepull-secret
Pod有了Label后,在查询Pod的时候带上 --show-labels 就可以看到Pod的Label。
$ kubectl get pod --show-labels -n $namespace_name NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 50s app=nginx,env=prod
还可以使用 -L 只查询某些固定的Label。
$ kubectl get pod -L app,env -n $namespace_name
NAME READY STATUS RESTARTS AGE APP ENV nginx 1/1 Running 0 1m nginx prod
对已存在的Pod,可以直接使用 kubectl label 命令直接添加Label。
$ kubectl label po nginx creation_method=manual -n $namespace_name pod "nginx" labeled
$ kubectl get pod --show-labels -n $namespace_name NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 50s app=nginx,env=prod,creation_method=manual
开发指南 5 Label
修改 Label
对于已存在的Label,如果要修改的话,需要在命令中带上--overwrite,如下所示。
$ kubectl label po nginx env=debug --overwrite -n $namespace_name pod "nginx" labeled
$ kubectl get pod --show-labels -n $namespace_name NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 50s app=nginx,env=debug,creation_method=manual
6 Deployment
Pod,每个Pod占用500m core CPU、1G内存。apiVersion: apps/v1 # 注意这里与Pod的区别,Deployment是apps/v1而不是v1 kind: Deployment # 资源类型为Deployment
开发指南 6 Deployment
memory: 1024Mi
$ kubectl create -f deployment.yaml -n $namespace_name
$ kubectl get deployment -n $namespace_name
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 2 2 2 2 8s
Deployment 如何控制 Pod
继续查询Pod,如下所示。
$ kubectl get pods -n $namespace_name
NAME READY STATUS RESTARTS AGE
$ kubectl delete pod nginx-7f98958cdf-txckx -n $namespace_name
$ kubectl get pods -n $namespace_name
NAME READY STATUS RESTARTS AGE
$ kubectl get rs -n $namespace_name
NAME DESIRED CURRENT READY AGE nginx-7f98958cdf 3 3 3 1m
这个ReplicaSet的名称为nginx-7f98958cdf,后缀-7f98958cdf也是随机生成的。
Deployment控制Pod的方式如图6-1所示,Deployment控制ReplicaSet,ReplicaSet控 制Pod。
图6-1 Deployment 通过 ReplicaSet 控制 Pod
如果使用kubectl describe命令查看Deployment的详情,您就可以看到ReplicaSet,如 下所示,可以看到有一行 NewReplicaSet: nginx-7f98958cdf (2/2 replicas created),
而且 Events 里面事件确是把ReplicaSet的实例扩容到2个。在实际使用中您也许不会直 接操作ReplicaSet,但了解Deployment通过控制ReplicaSet来控制Pod会有助于您定位 问题。
$ kubectl describe deploy nginx -n $namespace_name Name: nginx
Namespace: default
CreationTimestamp: Sun, 16 Dec 2018 19:21:58 +0800 Labels: app=nginx
...
NewReplicaSet: nginx-7f98958cdf (2/2 replicas created) Events:
Type Reason Age From Message ---- --- ---- ----
Normal ScalingReplicaSet 5m deployment-controller Scaled up replica set nginx-7f98958cdf to 2
升级
$ kubectl edit deploy nginx -n $namespace_name
$ kubectl get rs -n $namespace_name
NAME DESIRED CURRENT READY AGE nginx-6f9f58dffd 2 2 2 1m
nginx-7f98958cdf 0 0 0 48m
$ kubectl get pods -n $namespace_name
NAME READY STATUS RESTARTS AGE nginx-6f9f58dffd-tdmqk 1/1 Running 0 21s nginx-6f9f58dffd-tesqr 1/1 Running 0 21s
Deployment可以通过maxSurge 和 maxUnavailable两个参数控制升级过程中同时重 新创建Pod的比例,这在很多时候是非常有用,配置如下所示。 是25%,比如spec.replicas为 4,那升级过程中就不能超过5个 Pod存在,即按1个
开发指南 6 Deployment
的步伐升级,实际升级过程中会换算成数字,且换算会向上取整。这个值也可以 直接设置成数字。
● maxUnavailable:与Deployment中spec.replicas相比,可以有多少个Pod失效,
也就是删除的比例,默认值是25%,比如spec.replicas为 4,那升级过程中就至少 有3个Pod存在,即删除Pod 的步伐是 1。同样这个值也可以设置成数字。
在前面的例子中,由于spec.replicas是2,如果maxSurge和maxUnavailable都为默认 值25%,那实际升级过程中,maxSurge允许最多3个 Pod 存在(向上取整,
2*1.25=2.5,取整为3),而 maxUnavailable 则不允许有 Pod Unavailable(向上取 整,2*0.75=1.5,取整为2),也就是说在升级过程中,一直会有2个Pod处于运行状 态,每次新建一个Pod,等这个Pod创建成功后再删掉一个旧Pod,直至Pod全部为新 Pod。
回滚
回滚也称为回退,即当发现升级出现问题时,让应用回到老的版本。Deployment可以 非常方便的回滚到老版本。
例如上面升级的新版镜像有问题,可以执行kubectl rollout undo命令进行回滚。
$ kubectl rollout undo deployment nginx -n $namespace_name deployment "nginx" rolled back
Deployment之所以能如此容易的做到回滚,是因为Deployment是通过ReplicaSet控制 Pod的,升级后之前ReplicaSet都一直存在,Deployment回滚做的就是使用之前的 ReplicaSet再次把Pod创建出来。Deployment中保存ReplicaSet的数量可以使用 revisionHistoryLimit参数限制,默认值为10。