docker容器启动成功,并不代表容器中的服务就能处理外部的请求。比方说java web项目启动需要一段时间。
Kubernetes提供了readiness probe来检测pod中的容器是否可以接受外部流量。
可以在java项目中提供一个接口,kubernetes发请求给此接口,当此接口返回数据时,则表明服务准备就绪,可以接受外部请求了。

先看一个简单例子,准备一个spring boot工程,提供一个外部接口。以下服务用的端口号是10012

    @GetMapping("/test02/version")
    public String version(){
        return "app02/version/v1";
    }
在node节点上,编写Docker配置文件,并打成镜像

Dockerfile

FROM openjdk:8
ADD *.jar /app/app.jar
ADD entrypoint.sh /app/
# PORT="10012" 是项目端口号
ENV PORT="10012" TIME="Asia/Shanghai" JAVA_OPS="-Xmx256m -Xms256m -XX:+UseConcMarkSweepGC"
RUN set -e \
    && chmod +x /app/entrypoint.sh \
    && ln -snf /usr/share/zoneinfo/$TIME /etc/localtime \
    && echo $TIME > /etc/timezone
ENTRYPOINT  ["/app/entrypoint.sh"]
EXPOSE $PORT
STOPSIGNAL SIGTERM
entrypoint.sh

#!/bin/sh
exec java ${JAVA_OPS} -jar /app/app.jar
打成镜像codingsoldier/app02:v1

docker build -t codingsoldier/app02:v1 .

 

在master节点上编写部署文件

k8s-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: service-app02
spec:
  selector:
    app: app02
  ports:
  - name: http
    port: 10012
    targetPort: 10012
k8s-app02.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-app02
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app02
  template:
    metadata:
      labels:
        app: app02
    spec:
      containers:
      - name: app02
        image: codingsoldier/app02:v1
        ports:
        - name: http
          containerPort: 10012
部署服务

kubectl apply -f k8s-service

kubectl apply -f k8s-app02

获取k8s-service的ip

kubectl get svc 

重新开一个终端,循环调用接口,不要关闭这个终端,要一直开着。

while true; \
curl http://10.101.75.203:10012/test02/version; \
echo " "; \
do sleep 1; \
done;

现在就来升级版本吧

1、把/test02/version接口返回值改成v2

    @GetMapping("/test02/version")
    public String version(){
        return "app02/version/v2";
    }
2、打成jar包,上传到所有node节点

3、生成docker镜像

docker build -t codingsoldier/app02:v2 .

4、修改k8s-app02.yaml镜像为v2

image: codingsoldier/app02:v2

5、重新开一个终端,执行  kubectl get pod -w   动态查看pod状态

6、重新部署下k8s-app02.yaml

kubectl apply -f k8s-app02.yaml 

在循环调用的监控中可以看到,服务有短暂的时间无法提供服务。

原因是:docker容器启动成功了,k8s就认为此容器可以提供服务了。但事实上docker容器启动成功的时候,java服务还没启动完成,暂时无法给外部提供服务。

解决办法,使用readiness probe来检测pod中的容器是否可以接受外部流量。

1、java工程新增一个服务就绪接口

    //服务就绪接口,提供给k8s检测
    @GetMapping("/readiness")
    public String readiness(){
        return "yes";
    }
2、k8s-app02.yaml加上就绪探针

readinessProbe:
  httpGet:
    port: http
    path: /readiness
  initialDelaySeconds: 20
  periodSeconds: 10


readinessProbe详细的配置:
    initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
    periodSeconds:执行探测的频率。默认是10秒,最小1秒。
    timeoutSeconds:探测超时时间。默认1秒,最小1秒。
    successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
    failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。

httpGet配置项:
    host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置”Host”而不是使用IP。
    scheme:连接使用的schema,默认HTTP。
    path: 访问的HTTP server的path。
    httpHeaders:自定义请求的header。HTTP运行重复的header。
    port:访问的容器的端口名字或者端口号。端口号必须介于1和65525之间。    

3、改下 /test02/version ,的返回值 app02/version/v3

4、修改 k8s-app02.yaml中镜像的版本image: codingsoldier/app02:v3

5、打成jar,上传

6、打成镜像

docker build -t codingsoldier/app02:v3 .

7、重新部署服务

kubectl apply -f k8s-app02.yaml 

 

查看循环调用接口的终端,服务一直可用

 

查看运行了kubectl get pod -w 的终端

1、新pod处于Running状态,但READY是0/1。pod已经运行,但未就绪,此时不接收外部请求

2、25秒后,新pod处于Running状态,READY是1/1。pod可以接收外部请求了

3、新pod能够接收外部请求后,一个旧pod开始终止

4、由于pod服务数设置为2,所以此时另一个新pod开始创建,过程跟上面的一样,新pod能就收请求后,旧pod终止。
--------------------- 
 

转载于:https://my.oschina.net/xiaominmin/blog/3069658

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐