服务容器化改造和生产迁移实践

背景:

现在K8s容器化是技术趋势,很多部署在虚拟机上的服务都要迁移到容器化。而迁移到容器化的步骤是要先对服务代码进行容器化改造,之后发布再将生产环境流量从虚拟机切到容器化。 这里以Java服务为例,说下容器化改造需要的准备和流程

配置改动

Java服务接入容器化,需要准备Dockerfile文件,启动脚本,配置文件迁移到Nacos

  • Dockerfile文件:

使用Maven作为项目构建工具

js 复制代码
FROM xxxx/maven:3.8.5-openjdk-17 AS builder
# 设置工作目录
COPY . /app
WORKDIR /app
# 构建项目编译命令
RUN mvn -B -U -f pom.xml -s ./settings.xml clean install -e -Dmaven.test.skip=true -P trait-boot-jar
# 使用  JDK 17 作为运行时镜像
FROM xxxx/openjdk:17
# 设置工作目录
WORKDIR /java
# 从 Maven 镜像中拷贝构建好的 JAR 文件
COPY --from=builder /app/scripts/*.sh ./scripts/
# 这里根据实际生成的制品名称来进行修改拷贝
COPY --from=builder /app/application/target/application-*.jar ./application.jar
COPY --from=builder /app/application/src/main/resources/log4j2.xml ./config/
# 服务端口
EXPOSE 8080
# 监控指标端口
EXPOSE 8082
# 设置容器启动命令
CMD ["/bin/sh", "./scripts/start.sh"]

使用Gradle作为项目构建工具

js 复制代码
FROM gradle:8.4.0-jdk17 as builder  
WORKDIR /app  
COPY . .  
RUN gradle clean bootJar  
FROM xxx/openjdk:17  
WORKDIR /java  
RUN mkdir config \  
&& mkdir scripts \  
&& groupadd -g 5000 java \  
&& useradd -d /java -m -u 5000 -g 5000 -s /bin/sh java \  
&& chown -R java:java /java   

COPY --from=builder /app/application/build/libs/application-*.jar ./application.jar  
COPY --from=builder /app/application/src/main/resources/log4j2.xml ./config/  
COPY --from=builder /app/scripts/start.sh ./scripts/  
  
CMD ["/bin/sh", "./scripts/start.sh"]  
EXPOSE 8080
js 复制代码
#!/bin/sh
java    ${APP_OPTS} \
        -Dspring.cloud.nacos.config.enabled=true \
        -Dspring.cloud.nacos.config.server-addr=${NACOS_HOST}:${NACOS_PORT} \
        -Dspring.cloud.nacos.config.namespace=${NACOS_TENANT} \
        -Dspring.config.import[0]=nacos:${NACOS_DATA_ID} \
        -Dspring.cloud.nacos.config.file-extension=yaml \
        -Dspring.cloud.nacos.config.username=${NACOS_USERNAME} \
        -Dspring.cloud.nacos.config.password=${NACOS_PASSWORD} \
        -Dfile.encoding=UTF-8\
        -server \
        ${JAVA_OPTS} -jar application.jar
  • 容器内环境变量配置
js 复制代码
- name: ENV_NAME
  value: "prod"
- name: JAVA_OPTS
  value: "-XX:InitialRAMPercentage=70.0 
          -XX:MaxRAMPercentage=70.0 
          -XX:+UseZGC 
          -XX:+HeapDumpOnOutOfMemoryError 
          -XX:HeapDumpPath=/java"
- name: APP_OPTS
  value: "-Dreactor.netty.ioWorkerCount=50
          -Dreactor.netty.pool.leasingStrategy=lifo 
          -Dreactor.netty.pool.maxIdleTime=1000"
js 复制代码
NACOS_DATA_ID: xxx
NACOS_HOST: xxx
NACOS_PORT: xxx
NACOS_USERNAME: xxx
NACOS_PASSWORD: xxx 
NACOS_TENANT: xxx
  • 配置文件从本地的application-{env}.yaml迁移到Nacos,定义好NameSpace,Group和Data Id。

预估资源配置

容器化改造需要先预估所需要的生产资源,比如多少核的CPU还有多少G内存,还有副本多少,这涉及到容器的HPA策略,生产一般是横向扩容,比如给定2C4G的资源,副本pod最小2个,最大5个。副本数量会根据生产负载进行扩容

生产迁移

当服务在生产容器化启动成功时,还需要做最后的流量切换,让API网关把流量转发从虚拟机服务转发到容器化服务,因为容器化服务提供出来的域名地址与虚拟机服务的IP地址是不一样。如图所示:

相比于前面配置改造,这个迁移过程更应该注重流程的重要性。这是比较大的变更动作,作为开发,需要提前同步API网关同事,测试同事,运维同事要做这个变更,协调好各位职能的时间来完成这个变更动作。

  • 在服务日志方面,需要配置好日志采集监控,做好接口日志打印,有请求日志后就可以知道已经有流量进来了

  • 在监控方面,需要事先在Grafana上配置服务接口监控,还要对虚拟机的接口监控和容器化的接口监控进行对比,在网关流量切换时可以看到虚拟机的接口监控请求逐渐减少,容器化的接口监控请求逐渐增加,这才是符合预期的变化。常见的接口监控配置有以下两种:

    1. Top5接口QPS监控:展示QPS最高的前5个接口
    js 复制代码
    topk(5, sum(rate(http_server_requests_seconds_count[1m])) by (method, uri))
    1. P95接口监控:展示所有接口的P95响应时间,是个统计值
    js 复制代码
    histogram_quantile(0.95, sum by(method, uri, le) (rate(http_server_requests_seconds_bucket{status="200"}[5m])))
  • 在网关流量切换方面,不能全部切换,可以先切20%的流量到容器化服务,然后观察一段时间,没问题的话就可以切50%,最后100%全部切换。

  • 在测试方面,需要让测试同事回归,确保切换后的服务功能没问题,但可能需要在流量全部切换过去后才能测试,因为不确定测试的账户是否已经切换到新服务。

  • FailOver,在网关流量切换过程中如果有问题,需要把流量重新切换到虚拟机服务。就算切换成功后,原有的虚拟机服务也不能直接下掉,需要保持一段时间,方便后续发现问题可以切换回去,相当于是一个备份副本,这是一种FailOver机制。

相关推荐
程序员清风24 分钟前
什么时候会考虑用联合索引?如果只有一个条件查就没有建联合索引的必要了么?
java·后端·面试
Seven9726 分钟前
【设计模式】掌握建造者模式:如何优雅地解决复杂对象创建难题?
java·后端·设计模式
子洋43 分钟前
AnythingLLM + SearXNG 实现私有搜索引擎代理
前端·人工智能·后端
heart000_11 小时前
基于SpringBoot的智能问诊系统设计与隐私保护策略
java·spring boot·后端
汐泽学园1 小时前
基于ASP.NET校园二手交易网站设计与实现
后端·asp.net
MZWeiei2 小时前
Scala:case class(通俗易懂版)
开发语言·后端·scala
小杨4042 小时前
springboot框架项目实践应用三(监控运维组件admin)
spring boot·后端·监控
sevevty-seven4 小时前
Spring Boot 自动装配原理详解
java·spring boot·后端
lamdaxu4 小时前
分布式调用(02)
后端