kubernetes零宕机部署探索
docker容器启动成功,并不代表容器中的服务就能处理外部的请求。比方说java web项目启动需要一段时间。Kubernetes提供了readiness probe来检测pod中的容器是否可以接受外部流量。可以在java项目中提供一个接口,kubernetes发请求给此接口,当此接口返回数据时,则表明服务准备就绪,可以接受外部请求了。先看一个简单例子,准备一个spring boot工程,...
《docker+k8s教程》
kuernetes支持滚动更新部署策略,即一个接一个地以滚动更新方式发布新版本,本文使用滚动更新策略部署应用,探索使用kubernetes零宕机部署。
1、新建一个java web服务app3。
添加spring-boot-starter-actuator依赖,方便创建端点作为健康检查接口。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yaml配置如下:
server:
port: 10013
servlet:
context-path: /app3
management:
endpoints:
web:
exposure:
include: '*'
base-path: /
server:
servlet:
context-path: ${server.servlet.context-path}
port: ${server.port}
endpoint:
health:
show-details: always
# 定义一个端点,用于健康检查。
# url:localhost:10013/app3/info
info: {status: ok}
创建一个controller测试类
@RequestMapping("/test")
@RestController
public class TestController {
Logger logger = LoggerFactory.getLogger(TestController.class);
@GetMapping("/get")
public String get() throws Exception{
Random random = new Random();
int i = random.nextInt(500)+100;
TimeUnit.MILLISECONDS.sleep(i);
// v1、v2版本的打印信息不同
String r = "版本V1,睡眠时间---"+i;
//String r = "版本V2222,睡眠时间---"+i;
logger.info(r);
return r;
}
}
2、将应用打成jar包,再将jar打成docker镜像。
Dockerfile如下:
FROM openjdk:8
ADD *.jar /app/app.jar
ADD entrypoint.sh /app/
# PORT="10013" 是项目端口号
ENV PORT="10013" JAVA_OPS="-Xmx256m -Xms256m -XX:+UseConcMarkSweepGC"
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
EXPOSE $PORT
STOPSIGNAL SIGTERM
entrypoint.sh如下:
#!/bin/sh
# 修改时间
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
exec java ${JAVA_OPS} -jar /app/app.jar
jar包启动命令前加上exec是让java应用的进程取代shell命令进程,确保java应用进程作为容器的root进程,即java应用的pid是1。当kubernetes要关闭容器时,发送SIGTERM信号给容器,java应用作为root进程将接收到SIGTERM信号,关闭应用。如果root进程是shell命令,shell命令无法响应SIGTERM信号。导致kubernetes最终会发送SIGKILL给容器。
jar启动命令加上exec,容器内进程如下图
不加exec,容器进程如下图
在kubernetes集群副节点打两个docker镜像。
docker build -t codingsoldier/app3:v1 .
docker build -t codingsoldier/app3:v2 .
打好codingsoldier/app3:v1镜像后,修改controller方法的打印信息,再打成codingsoldier/app3:v2
3、编写两个Deployment。
deployment-app3-v1.yaml配置如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-app3
spec:
# pod数量
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
# 超过期望的可用pod个数。
maxSurge: 1
# 在升级过程中不可用Pod的最大数量
maxUnavailable: 0
selector:
matchLabels:
app: app3
template:
metadata:
labels:
app: app3
spec:
# k8s将会给应用发送SIGTERM信号,可以用来正确、优雅地关闭应用,默认为30秒
terminationGracePeriodSeconds: 100
containers:
- name: app3
# 镜像版本
image: codingsoldier/app3:v1
ports:
- name: http
containerPort: 10013
lifecycle:
# 在容器被终止前睡眠一段时间,以便kube-proxy更新service的endpoint
preStop:
exec:
command: ["/bin/bash", "-c", "sleep 35"]
# 就绪探针。
# docker容器启动成功,并不代表容器中的服务就能处理外部的请求,例如java应用启动需要一定时间
# Kubernetes提供了readinessProbe来检测pod中的容器是否可以接受外部流量
readinessProbe:
httpGet:
# 连接使用的schema,默认HTTP。
scheme: HTTP
# 访问的容器的端口名字或者端口号。端口号必须介于1和65525之间
port: 10013
# 访问的HTTP server的path
path: /app3/info
# 探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。
failureThreshold: 3
# 容器启动后第一次执行探测是需要等待多少秒。
initialDelaySeconds: 20
# 执行探测的频率。默认是10秒,最小1秒。
periodSeconds: 10
# 探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
successThreshold: 1
# 探测超时时间。默认1秒,最小1秒。
timeoutSeconds: 1
# 存活探针,用于判断容器是否存活。配置参数跟就绪探针相同
livenessProbe:
httpGet:
scheme: HTTP
port: 10013
path: /app3/info
failureThreshold: 3
initialDelaySeconds: 20
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
再新建一个deployment-app3-v2.yam,修改镜像 image: codingsoldier/app3:v2
部署应用 : kubectl apply -f deployment-app3-v1.yaml
4、编写一个service-nodeport.yaml,service使用NodePort类型暴露端口。
apiVersion: v1
kind: Service
metadata:
name: service-app3
spec:
selector:
app: app3
# 使用NodePort方式暴露一个外部端口供调试使用
type: NodePort
ports:
- name: http
port: 10013
targetPort: 10013
# 外部端口
nodePort: 30013
部署service: kubectl apply -f service-nodeport.yaml
5、升级应用版本: kubectl apply -f deployment-app3-v2.yaml
在升级期间使用jmeter进行并发测试,一秒钟发送50个请求,请求/app3/test/get接口。有可能会出现几个失败的请求,请求返回结果是 Connection reset 。
暂时无法解决 Connection reset的问题。有高手知道如何解决此问题还望赐教。
6、项目代码地址 https://github.com/CodingSoldier/java-learn/tree/master/project/app3
更多推荐
所有评论(0)