1 环境说明
说明: 本文主要关注微服务在k8s平台的实现过程,有些步骤不会在本文中体现,需要自行搭建。
1.1 服务器环境
实验服务器配置: 40核/64GB/2TB
补充: kubernetes集群的控制节点我打了污点不能被pod调度使用。
1.2 微服务项目说明
3 项目服务说明
1.3 应用环境准备
[root@k8s-master1 ms]# kubectl get deployment,pod,svc,sc -n default
Login Succeeded
2 微服务架构
2.1 单体应用 vs 微服务
1 单体架构
3) 新人上手难
2 微服务架构
5) 大量服务治理
3 JAVA微服务框架
(3) Dubbo: 阿里巴巴开源的微服务治理框架
2.2 在K8S平台部署微服务考虑的问题
2 对微服务项目架构理解
(7) 区分有状态应用与无状态应用
3 为什么用注册中心系统
Eureka,Nacos,Consul
4 在k8s部署项目流程
dockerfile 》》》Deployment、StatefulSet、DaemonSet 》》》Service Ingress 》》》Prometheus+Grafana、ELK Stack
3 在K8S平台部署Spring Cloud微服务项目
ms Active 23s
3.1 熟悉Spring Cloud微服务项目
注: 我这里根据 dev4 分支进行部署操作
架构图2:
3.2 源代码编译构建
# mvn clean package -Dmaven.test.skip=true
# ls -l eureka-service/target/eureka-service.jar
3.3 增加dockerfile容器编排文件
这里以order-service为例,其它服务类似
[root@k8s-master1 simple-microservice]# pwd /root/ms/simple-microservice # cat order-service/order-service-biz/Dockerfile FROM java:8-jdk-alpine LABEL maintainer lc ENV JAVA_ARGS="-Dfile.encoding=UTF8 -Duser.timezone=GMT+08" RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \ apk add -U tzdata && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY ./target/order-service-biz.jar ./ COPY skywalking /skywalking EXPOSE 8020 CMD java -javaagent:/skywalking/skywalking-agent.jar=agent.service_name=ms-order,agent.instance_name=$(echo $HOSTNAME | awk -F- '{print $1"-"$NF}'),collector.backend_service=172.16.1.60:11800 $JAVA_ARGS $JAVA_OPTS -jar /order-service-biz.jar 说明: agent.service_name=ms-order: 在skywalking中表示服务的名字,通常一个服务下有多个实例。 $(echo $HOSTNAME | awk -F- '{print $1"-"$NF}'): 表示以"-"为分割,截取pod容器主机名第一位和最后一位,然后以"-"连接,在 skywalking中表示pod实例。 示例: # echo $(echo calico-node-pmf4q | awk -F- '{print $1"-"$NF}') calico-pmf4q collector.backend_service=172.16.1.60:11800: 指定SkyWalking服务器所在的地址及端口。 $JAVA_OPTS: 该变量在k8s yaml文件中定义,在pod容器中被引用。
3.4 增加K8s服务编排文件
这里以order-service为例,其它服务类似
[root@k8s-master1 simple-microservice]# pwd /root/ms/simple-microservice # cat k8s/order.yaml apiVersion: apps/v1 kind: Deployment metadata: name: order namespace: ms spec: replicas: 1 selector: matchLabels: project: ms app: order template: metadata: labels: project: ms app: order spec: imagePullSecrets: - name: registry-pull-secret containers: - name: order image: 172.16.1.61/microservice/order:2022-01-15-22-38-07 imagePullPolicy: Always ports: - protocol: TCP containerPort: 8020 env: - name: JAVA_OPTS value: "-Xmx1g" resources: requests: cpu: 0.5 memory: 256Mi limits: cpu: 1 memory: 1Gi readinessProbe: tcpSocket: port: 8020 initialDelaySeconds: 60 periodSeconds: 10 livenessProbe: tcpSocket: port: 8020 initialDelaySeconds: 60 periodSeconds: 10
3.5 在K8s中部署MySQL
# kubectl get pvc,pv -n ms
MySQL [tb_stock]> exit
3.6 微服务部署脚本
[root@k8s-master1 k8s]# pwd /root/ms/simple-microservice/k8s 1 创建 secret 用于 pod 从 harbor 仓库拉取镜像时进行账号密码验证 # docker_registry="172.16.1.61" # 存储登录Harbor认证信息 # kubectl create secret docker-registry registry-pull-secret \ --docker-server=$docker_registry --docker-username=admin \ --docker-password=Harbor12345 --docker-email=admin@lc.com \ -n ms # kubectl get secret -n ms | grep registry-pull-secret registry-pull-secret kubernetes.io/dockerconfigjson 1 31s 2 登录habor仓库,方便脚本推送镜像到harbor仓库 # docker login 172.16.1.61 Username: admin Password: Harbor12345 WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded 3 脚本 [root@k8s-master1 k8s]# cat docker_build.sh #!/bin/bash # 说明: 执行脚本时所在的目录必须为 ../simple-microservice/k8s/ # Harbor仓库IP地址 docker_registry="172.16.1.61" # 微服务应用部署列表 service_list="eureka-service order-service product-service stock-service gateway-service portal-service" # 命令行指定微服务应用名时按指定的应用名部署,否则按照上面的应用列表进行部署 service_list="${1:-${service_list}}" # 获取执行脚本时所在目录的上层目录 work_dir="$(dirname $PWD)" # 获取执行脚本时所在目录 current_dir="$PWD" # 编译构建代码 cd $work_dir mvn clean package -Dmaven.test.skip=true # 循环部署微服务应用列表中的应用 for service in ${service_list}; do # 进入应用中Dockerfile所在的目录 cd ${work_dir}/$service # 业务程序需进入biz目录里构建 if ls |grep biz &>/dev/null; then cd ${service}-biz fi # 拿掉最后一个 "-" 及其右边的字符串,比如"eureka-service"变为"eureka" service="${service%-*}" # 镜像名称=Harbor仓库IP/Harbor仓库项目名/微服务应用名作为镜像仓库名:以镜像构建时间作为镜像版本 image_name="${docker_registry}/microservice/${service}:$(date +%F-%H-%M-%S)" # 构建微服务应用镜像 docker build -t ${image_name} . # 将微服务镜像上传到Harbor镜像仓库 docker push ${image_name} # 修改微服务应用k8s编排yaml文件中镜像地址为新推送的镜像地址并apply sed -i -r "s#(image: )(.*)#\1${image_name}#" ${current_dir}/${service}.yaml kubectl apply -f ${current_dir}/${service}.yaml done [root@k8s-master1 k8s]# 4 微服务应用部署顺序 (1) 注册中心 eureka-service (2) 业务应用 1) order-service 2) product-service 3) stock-service (3) 网关服务 gateway-service (4) 前端服务 portal-service
3.7 在K8s中部署Eureka集群
http://eureka.lc.cn/
3.8 部署微服务业务程序
# bash docker_build.sh portal-service
3.9 访问微服务
http://eureka.lc.cn/
http://172.16.1.61/
[root@k8s-master1 k8s]# kubectl get pod,svc,ep,ingress,pvc,pv -o wide -n ms
(2) http://portal.ctnrs.com/
主页面:
添加商品:
查询订单
3.10 微服务升级与扩容
(3) 访问portal应用页面
(2) 查看eureka注册的order应用
4 微服务生产环境踩坑案例
4.1 限制了容器资源,还经常被杀死
(1) 手动指定JVM堆内存大小
- XX:+UseCGroupMemoryLimitForHeap
4.2 滚动更新之健康检查重要性
2 解决办法
4.3 滚动更新期间造成流量丢失
配置preStop回调,在容器终止前优雅暂停5秒,给kube-proxy多预留一点时间。
5 APM监控微服务项目
5.1 APM监控系统说明
一个优秀的调用跟踪系统必须支持分布式部署,具备良好的可扩展性,能够支持的组件越多当然越好。
5.2 Skywalking说明
2 Skywalking架构
5.3 Skywalking部署
java -javaagent:/skywalking/skywalking-agent.jar=agent.service_name=<项目名称>,agent.instance_name=<实例名称>,collector.backend_service=<Skywalking服务器>:11800 -jar xxx.jar
5.4 Skywalking UI使用
1 导航栏
第三栏: 不同纬度展示,服务/实例/端点
2 全局
7 底部栏: 展示数据的时间区间,点击可以调整
3 Service
11 Service Instance Successful Rate: 服务实例成功率
4 Instance
9 CLR XX: .NET服务的指标,类似JVM虚拟机
5 Endpoint
7 Endpoint Successful Rate: 端点请求成功率
6 拓扑图