一个新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,说 明已经就绪。
● 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中,如下图所示。
图7-7 Readiness Probe 的实现原理
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:
开发指南 7 使用 Service 和 Ingress 管理网络访问
labels:
# 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
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次失败后会重启容器
这些是创建时默认设置的,您也可以手动配置,如下所示。
8 使用 PersistentVolumeClaim 申请持久化存 储
云容器实例当前支持在容器中使用如下三种持久化存储。
● 云硬盘(Elastic Volume Service,EVS),EVS是一种块存储服务,提供高I/O
(sas)、超高I/O(ssd)和普通I/O(sata)三种类型云硬盘。
● 弹性文件服务(Scalable File Service,SFS),SFS提供共享的文件存储,支持标
准文件协议类型(nfs-rw)。SFS提供了SFS和SFS Turbo两种类型的文件系统。
– SFS为用户提供一个完全托管的共享文件存储,能够弹性伸缩至PB规模,具 备高可用性和持久性,为海量数据、高带宽型应用提供有力支持。适用于多 种应用场景,包括HPC、媒体处理、文件共享、内容管理和Web服务等。
– SFS Turbo为用户提供一个完全托管的共享文件存储,能够弹性伸缩至320TB 规模,具备高可用性和持久性,为海量的小文件、低延迟高IOPS型应用提供 有力支持。适用于多种应用场景,包括高性能网站、日志存储、压缩解压、
DevOps、企业办公、容器应用等。
● 对象存储服务(Object Storage Service,OBS),OBS是一个基于对象的海量存
储服务,为客户提供海量、安全、高可靠、低成本的数据存储能力。
上面三种存储中,OBS的使用方式最为直接,云容器实例当前支持直接以SDK方式使用 对象存储服务(OBS)。您可以在应用程序中使用SDK方式使用OBS,将应用程序打包 成容器镜像,在云容器实例中使用镜像创建负载。OBS的SDK的下载及使用方法请参见
https://developer.huaweicloud.com/sdk?OBS。
EVS和SFS的使用有个挂载的过程,下面将介绍如何使用EVS和SFS。
PersistentVolumeClaim(PVC)
Kubernetes提供PVC专门用于持久化存储的申请,PVC可以让您无需关心底层存储资源 如何创建、释放等动作,而只需要申明您需要何种类型的存储资源、多大的存储空 间。
在实际使用中,您可以通过Pod中的Volume来关联PVC,通过PVC使用持久化存储,
如图8-1所示。
图8-1 使用持久化存储
namespace: namespaces-test annotations: {
paas.storage.io/cryptKeyId: ee9b610c-e356-11e9-aadc-d0efc1b3bb6b }spec:
accessModes:
- ReadWriteMany resources:
requests:
storage: 100Gi storageClassName: sata
accessModes为存储访问模式,支持如下3种模式:
namespace: namespace-test annotations: {
paas.storage.io/cryptKeyId: ee9b610c-e356-11e9-aadc-d0efc1b3bb6b paas.storage.io/cryptAlias: sfs/default
paas.storage.io/cryptDomainId: d6912480-c3d6-4e9e-8c70-38afeea434c3 volume.beta.kubernetes.io/storage-provisioner: flexvolume-huawei.com/fuxinfs }spec:
accessModes:
- ReadWriteMany resources:
开发指南 8 使用 PersistentVolumeClaim 申请持久化存储
requests:
storage: 100Gi storageClassName: nfs-rw
使用 PVC
containers:
- image: nginx:latest name: container-0
- mountPath: "/tmp/volume0" # 将PVC挂载到容器的/tmp/volume0路径 name: pvc-test-example # Volume的名称
volumes: # 定义Volume,关联PVC - name: pvc-test-example
persistentVolumeClaim:
claimName: pvc-test # PVC的名称 imagePullSecrets:
- name: imagepull-secret
● 写入上面申请的文件存储(storageClassName设置为nfs-rw型)中。
containers:
- image: nginx:latest name: container-0
- mountPath: "/tmp/volume0" # 将PVC挂载到容器的/tmp/volume0路径
subPath: "abc" # 文件存储根路径下子路径,如果不存在会自动在文件存储中创建。该子路径 必须为相对路径。
name: pvc-test-example # Volume的名称 volumes: # 定义Volume,关联PVC
- name: pvc-test-example persistentVolumeClaim:
claimName: pvc-test # PVC的名称 imagePullSecrets:
- name: imagepull-secret
开发指南 8 使用 PersistentVolumeClaim 申请持久化存储