业务探针(Readiness probe)
一个新Pod创建后,Service就能立即选择到它,并会把请求转发给Pod,那问题就来了,通常一个Pod启动是需要时间的,如果Pod还没准备好(可能需要时间来加载配置或数据,或者可能需要执行 一个预热程序之类),这时把请求转给Pod的话,Pod也无法处理,造成请求失败。
Kubernetes中解决这个问题的方法就是给Pod加一个业务就绪探针Readiness Probe,当检测到Pod就绪后才允许Service请求转给Pod。
Readiness Probe同样是周期性的检测Pod,然后根据响应来判断Pod是否就绪,与存活探针(liveness probe)相同,云容器实例中也支持两种类型的Readiness Probe。
- HTTP GET:往容器的IP:Port发送HTTP GET请求,如果probe收到2xx或3xx,说明已经就绪。
需要为pod配置以下annotation使超时时间(timeoutSeconds)生效:
cci.io/httpget-probe-timeout-enable:"true"
具体请参见Liveness Probe高级配置样例。
- Exec:probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明已经就绪。
Readiness Probe的工作原理
如果调用kubectl describe命令查看Service的信息,您会看到如下信息。
$ kubectl describe svc nginx -n $namespace_name
Name: nginx
......
Endpoints: 192.168.113.81:80,192.168.165.64:80,192.168.198.10:80
......
可以看到一个Endpoints,Endpoints同样也是Kubernetes的一种资源对象,可以查询得到。
$ kubectl get endpoints -n $namespace_name
NAME ENDPOINTS AGE
nginx 192.168.113.81:80,192.168.165.64:80,192.168.198.10:80 14m
这里的192.168.113.81:80是Pod的IP:Port,通过如下命令可以查看到Pod的IP,与上面的IP一致。
# kubectl get pods -o wide -n $namespace_name NAME READY STATUS RESTARTS AGE IP nginx-55c54cc5c7-49chn 1/1 Running 0 1m 192.168.198.10 nginx-55c54cc5c7-x87lb 1/1 Running 0 1m 192.168.165.64 nginx-55c54cc5c7-xp4c5 1/1 Running 0 1m 192.168.113.81
通过Endpoints就可以实现Readiness Probe的效果,当Pod还未就绪时,将Pod的IP:Port在Endpoints中删除,Pod就绪后再加入到Endpoints中,如下图所示。
Exec
Exec方式与HTTP GET方式一致,如下所示,这个探针执行ls /ready命令,如果这个文件存在,则返回0,说明Pod就绪了,否则返回其他状态码。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:latest name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi readinessProbe: # Readiness Probe exec: # 定义 ls /ready 命令 command: - ls - /ready imagePullSecrets: - name: imagepull-secret
将上面Deployment的定义保存到deploy-read.yaml文件中,删除之前创建的Deployment,用deploy-read.yaml创建这个Deployment。
# kubectl delete deploy nginx -n $namespace_name deployment.apps "nginx" deleted # kubectl create -f deploy-read.yaml -n $namespace_name deployment.apps/nginx created
这里由于nginx镜像不包含 /ready 这个文件,所以在创建完成后容器不在Ready状态,如下所示,注意READY这一列的值为0/1,表示容器没有Ready。
# kubectl get po -n $namespace_name NAME READY STATUS RESTARTS AGE nginx-7955fd7786-686hp 0/1 Running 0 7s nginx-7955fd7786-9tgwq 0/1 Running 0 7s nginx-7955fd7786-bqsbj 0/1 Running 0 7s
再次查看Service,发现Endpoints一行的值为空,表示没有Endpoints。
$ kubectl describe svc nginx -n $namespace_name
Name: nginx
......
Endpoints:
......
如果此时给容器中创建一个 /ready 的文件,让Readiness Probe成功,则容器会处于Ready状态。再查看Pod和Endpoints,发现创建了/ready文件的容器已经Ready,Endpoints也已经添加。
# kubectl exec -n $namespace_name nginx-7955fd7786-686hp -- touch /ready # kubectl get po -o wide -n $namespace_name NAME READY STATUS RESTARTS AGE IP nginx-7955fd7786-686hp 1/1 Running 0 10m 192.168.93.169 nginx-7955fd7786-9tgwq 0/1 Running 0 10m 192.168.166.130 nginx-7955fd7786-bqsbj 0/1 Running 0 10m 192.168.252.160 # kubectl get endpoints -n $namespace_name NAME ENDPOINTS AGE nginx 192.168.93.169:80 14d
HTTP GET
Readiness Probe的配置与存活探针(livness probe)一样,都是在 Pod Template 的 containers 里面,如下所示,这个Readiness Probe向Pod发送HTTP请求,当Probe收到2xx或3xx返回时,说明Pod已经就绪。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:latest name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi readinessProbe: # readinessProbe httpGet: # HTTP GET定义 path: /read port: 80 imagePullSecrets: - name: imagepull-secret
Readiness Probe高级配置
与Liveness Probe相同,Readiness Probe也有同样的高级配置选项,上面nginx Pod的describe命令回显有中有如下行。
Readiness: exec [ls /var/ready] delay=0s timeout=1s period=10s #success=1 #failure=3
这一行表示readiness probe的具体参数配置,其含义如下:
- delay=0s 表示容器启动后立即开始探测,没有延迟时间
- timeout=1s 表示容器必须在1s内做出相应反馈给probe,否则视为探测失败
- period=10s 表示每10s探测一次
- #success=1 表示探测连续1次成功表示成功
- #failure=3 表示探测连续3次失败后会重启容器
这些是创建时默认设置的,您也可以手动配置,如下所示。
readinessProbe: # Readiness Probe exec: # 定义 ls /readiness/ready 命令 command: - ls - /readiness/ready initialDelaySeconds: 10 # 容器启动后多久开始探测 timeoutSeconds: 2 # 表示容器必须在2s内做出相应反馈给probe,否则视为探测失败 periodSeconds: 30 # 探测周期,每30s探测一次 successThreshold: 1 # 连续探测1次成功表示成功 failureThreshold: 3 # 连续探测3次失败表示失败