day04 交付dubbo微服务到k8s
1.前情提要
交付jenkins
- 制作jenkins的docker镜像
- 设置了容器启动时使用的用户root
- 设置容器内的时区UTC+8
- 加入了ssh私钥(拉取git代码的两种方式:基于http和ssh)
- 加入登录harbor的config文件
- 修改了ssh客户端的配置
- 安装了一个docker客户端
- 配置共享存储nfs
- 交付jenkins到k8s集群
- 配置ci流水线
jenkins的主要工作:拉代码,编译,变docker,push到私有仓库
2.判断jenkins在pod中如何启动成功
docker logs
docker ps -a | grep jenkins
可以docker exec -ti
3.检查jenkins的环境是否正确
使用docker exec instanceId进入到容器中去
- whoami 看是不是root启动的
- date 当前时区是不是东八区
- 看是不是连接到了宿主机的docker 引擎,docker ps -a 看是否展示的是宿主机上所有的docker 容器,和宿主机上的docker ps -a结果对比一下
- 看是否能连接到docker私服harbor.od.com (docker login harbor.od.com)
cat /root/.docker/config.json - 验证是否能用公钥从git拉取到代码
ssh -i /root/.ssh/id_rsa -T git@gitee.com (-T 代表是测试连接 )
4.安装maven
ant编译,maven编译,gradle编译
maven.apache.org
用3.6.1版本
下到7-200的运维主机上
cd /opt/src
wget http://xxxx/apache-maven-3.6.1-bin.tar.gz
解压缩到nfs共享目录中,且带有jdk版本的小设计目录
mkdir -p /data/nfs-volume/jenkins_home/maven-3.6.1-8u232
tar xfv -C /data/nfs-volume/jenkins_home/maven-3.6.1-8u232
cd /data/nfs-volume/jenkins_home/maven-3.6.1-8u232
mv apache-maven-3.6.1 ../
mv ../apache-maven-3.6.1/* .
ll
4.1 配置maven的国内镜像源
vim settings.xml
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexue/content/groups/public</url>
</mirror>
4.2 在jenkins的docker里
cd /var/jenkins_home/
ls -l
可以看到的基本都是7-200运维主机上的路径
5.构建dubbo的底包
如果jenkins底包构建不成功,可以使用软件站里的jenkins-v1.176.2-with-docker.tar的镜像
在运维主机上7-200
cd /data/dockerfile/jenkins/
wget jenkins-v2.176.2-with-docker.tar
里面已经有docker了
docker load < jenkins-v2.176.2-with-docker.tar
加载进docker引擎里
docker images ,找到里面none的就是刚load进去的
打个标签
docker tag a25e4f7b2896 harbor.od.com/public/jenkins:v2.176.2
jenkins如果一直装不上插件,可以通过copy百度云下插件文件,解压缩的插件的目录到共享存储的jenkins的插件目录下,重启jenkins就好
5.1 修改dockerfile
FROM harbor.od.com/public/jenkins:v2.176.2
USER root
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
echo 'Asia/Shanghai' > /etc/timezone
ADD id_rsa /root/.ssh/id_rsa
ADD config.json /root/.docker/config.json
RUN echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config
5.2 构建镜像
docker build . -t harbor.od.com/infra/jenkins:v2.176.2
6.maven环境准备maven3+jdk1.7
7-200机器上
cd /data/nfs-volume/jenkins_home
wget jdk-7u80-linux-x64.tar.gz
tar xf jdk-7u80-linux-x64.tar.gz -C ./
7.准备dubbo微服务的底包
从公网下载一个java运行时环境的底包
7-200机器上
docker pull docker.io/stanleyws/jre8:8u112
然后打个tag,反手提到harbor
docker tag fa3a085d6ef1 harbor.od.com/public/jre:8u112
docker push harbor.od.com/public/jre:8u112
cd /data/dockerfile/
mkdir -p jre8
cd jre8
vim Dockerfile
FROM arbor.od.com/public/jre:8u112
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
echo 'Asia/Shanghai' > /etc/timezone
ADD config.yml /opt/prom/config.yml
ADD jmx_javaagent-0.3.1.jar /opt/prom/
WORKDIR /opt/project_dir
ADD entrypoint.sh /entrypoint.sh
CMD ["/entrypoint.sh"]
说明entrypoint.sh脚本就是pid为1的进程,且必须前台运行,前台运行才能保证声明周期和docker容器保持一致
- config.yml(监控promus要监控java程序用到的配置文件)
---
rules:
- pattern: '.*'
-
jmx_javaagent-0.3.1.jar 收集你程序的jvm的使用情况
(wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.3.1/jmx_prometheus_javaagent-0.3.1.jar -O jmx_javaagent-0.3.1.jar) -
entrypoint.sh是docker运行的默认启动脚本
要不用entrypoint指定指定,要不用cmd 指定entrypoint.sh脚本
entrypoint.sh
#!/bin/sh
M_OPTS="-Duser.timezone=Asia/Shanghai -javaagent:/opt/prom/jmx_javaagent-0.3.1.jar=${hostname -i}:${M_PORT:-"12346"}:/opt/prom/config.yml"
# M_PORT:变量的默认值,不传就默认是12346
C_OPTS=${C_OPTS} # 取环境变量的C_OPTS
JAR_BALL=${JAR_BALL} # k8s的资源配置清单里的环境变量
exec java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL}
说明:
shell里面的exec 命令,后面的东西代替了shell脚本进程,自己变成了pid为1的进程
系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替
4.构建一个base镜像,放到base仓库里,harbor要准备一个base仓库
base是公开的,public
5.构建镜像
docker build . -t harbor.od.com/base/jre8:8u112
docker push harbor.od.com/base/jre8:8u112
8.base里就有了底包
9.配置流水线
9.1 配置参数
newItem->pipeline->名字写dubbo-demo->OK
选择 String Parameter,第一个参数
新加Parameter还是String Parameter,第二个参数
新加Parameter还是String Parameter,第三个参数
新加Parameter还是String Parameter,第四个参数
新加Parameter还是String Parameter,第五个参数
新加Parameter还是String Parameter,第六个参数
新加Parameter还是String Parameter,第七个参数
新加Parameter还是String Parameter,第八个参数
新加Parameter还是Choice Parameter,第九个参数
新加Parameter还是Choice Parameter,第十个参数
9.2 配置pipeline脚本
pipeline脚本
pipeline {
agent any
stages {
stage('pull') {
steps {
sh "git clone ${params.git_repo} ${params.app_name}/${env.BUILD_NUMBER} && cd ${params.app_name}/${env.BUILD_NUMBER} && git checkout ${params.git_ver}"
}
}
stage('build') {
steps {
sh "cd ${params.app_name}/${env.BUILD_NUMBER} && /var/jenkins_home/maven-${params.maven}/bin/${params.mvn_cmd}"
}
}
stage('package') {
steps {
sh "cd ${params.app_name}/${env.BUILD_NUMBER} && cd ${params.target_dir} && mkdir project_dir && mv *.jar ./project_dir"
}
}
stage('image') {
steps {
writeFile file: "${params.app_name}/${env.BUILD_NUMBER}/Dockerfile", text: """FROM harbor.od.com/${params.base_image}
ADD ${params.target_dir}/project_dir /opt/project_dir"""
sh "cd ${params.app_name}/${env.BUILD_NUMBER} && docker build -t harbor.od.com/${params.image_name}:${params.git_ver}_${params.add_tag} . && docker push harbor.od.com/${params.image_name}:${params.git_ver}_${params.add_tag}"
}
}
}
}
9.3 保存,如果要修改可以点击configuration
10.构建项目
harbor里 创建一个app的仓库,private属性
backup to dashboard
build with parameter
要填写 相关信息
如果构建报错,建议删除jenkis内部的本地仓库下的包,重新下包
构建成功 后最后
返回dashboard
harbor里就有镜像了
11.交付dubbo-demo-service到k8s集群里
资源配置清单
7-200机器上
cd /data/k8s-yaml/
mkdir -p dubbo-demo-service
只需要 一个dp.yaml
vim dp.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-service
namespace: app
labels:
name: dubbo-demo-service
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-service
template:
metadata:
labels:
app: dubbo-demo-service
name: dubbo-demo-service
spec:
containers:
- name: dubbo-demo-service
image: harbor.od.com/app/dubbo-demo-service:master_191201_1142
ports:
- containerPort: 20880
protocol: TCP
env:
- name: JAR_BALL
value: dubbo-server.jar
imagePullPolicy: Always
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600
里面用环境变量的方式 初始化启动参数
在7-21机器 上
kubectl create ns app // 创建一个 名为 app的 namespace
kubectl create secret docker-registry harbor --docker-server=harbor.od.com --docker-username=admin --docker-password=Harbor12345 -n app // 创建 一个secret为了 从harbor的私有仓库 拉镜像依赖 这个
在7-21机器上应用 资源配置清单dp.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-service/dp.yaml
看logs是否启动成功
如果不成功,一定要注意是否多个节点上的镜像不一致导致
在7-11的zk上节点也已经有 了dubbo的节点
12.借助BlueOcean插件回顾jenkins流水线构建原理
open blueocean
-
拉代码过程
cd /data/nfs-volume/jenkins_home/workspace/dubbo-demo-service/
里面有一个1目录 -
构建过程
-
Package
-
image
Dockerfile写到了/data/nfs-volume/jenkins_home/workspace/dubbo-demo-service/1/目录
写dockerfile然后
13.交付dubbo-monitor到k8s集群 中
交付 monitor,从 registry取数据 ,并展示 出来
2个开源软件做的比较好的,dubbo-admin,dubbo-monitor
github.com/Jeromefromcn/dubbo-monitor
dubbo-monitor的源码下来,放到 7-200机器上
cd /opt/src
wget dubbo-monitor-master.zip
unzip dubbo-monitor-master.zip
mv dubbo-monitor-master dubbo-monitor
cd dubbo-monitor
cd dubbo-monitor-simple/conf/dubbo_origin.properties
13.1. 修改dubbo-monitor源码 里 的start.sh
bin/start.sh
堆内存-Xmx和Xms改成128m,xmn改为32m,PermSize改为6m
把里面的 nohup改为exec,里面 的后台 &去掉
exec 下面的所有的内容 干掉,后面的执行不了了
上面的内容 修改可以简化为 一条sed命令
sed. -r -i. -e '/^nohup/{p;:a;N;$!ba;d}}'. ./dubbo-monitor-simple/bin/start.sh. &&. sed -r -i -e. "s%^nohup(.*)%exec. \1%" ./dubbo-monitor-simple/bin/start.sh
13.2. 移动路径
cp -a dubbo-monitor /data/dockerfile/
cd /data/dockerfile/
13.3 创建镜像
docker build . -t harbor.od.com/infra/dubbo-monitor:latest
docker push harbor.od.com/infra/dubbo-monitor:latest
13.4 准备资源配置清单,然后提交到k8s集群 中去
Deployment.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-monitor
namespace: infra
labels:
name: dubbo-monitor
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-monitor
template:
metadata:
labels:
app: dubbo-monitor
name: dubbo-monitor
spec:
containers:
- name: dubbo-monitor
image: harbor.od.com/infra/dubbo-monitor:latest
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 20880
protocol: TCP
imagePullPolicy: Always
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600
Service.yaml
kind: Service
apiVersion: v1
metadata:
name: dubbo-monitor
namespace: infra
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: dubbo-monitor
targetPort是在docker里面跑 什么端口
port是在cluster ip上 跑什么 端口
Ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: dubbo-monitor
namespace: infra
spec:
rules:
- host: dubbo-monitor.od.com
http:
paths:
- path: /
backend:
serviceName: dubbo-monitor
servicePort: 8080
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/dp.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/service.yaml
kubectl. apply -f. http://k8s-yaml.od.com/dubbo-monitor/ingress.yaml
13.5 解析 dns
7-11上
/var/named/od.com.zone
前滚一个 编号
dubbo-monitor A 10.4.7.10
systemctl restart named
dig -t A dubbo-monitor.od.com @10.4.7.11. +short
. 14.交付 dubbo服务的消费者到k8s集群里
dubbo-demo这一个流水线,也可以构建dubbo服务的消费者
git仓库的dubbo-demo-web是私有仓库的,就ssh通道,不能用https通道了
console日志(mvn -e -q 减少输出)
maven拉下来的jar包缓存到哪里了?
cd /root/.m2/
14.1准备资源配置清单
7-200机器上
dp.yaml
svc.yaml
ingress.yaml
14.2 解析域名
7-11机器上
/var/named/od.com.zone
demo A 10.4.7.10
验证
dig -t A demo.od.com @10.4.7.11 +short
14.3. 应用 资源 配置清单
kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-consumer/dp.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-consumer/service.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-consumer/ingress.yaml
14.4 看dubbo-monitor
15.提供者扩容
service找pod,是通过 标签 选择器来 看 的
traefik帮你找到了2个后端的真实的 podip
改成2
16.实战 dubbo集群的日常维护
写shell脚本可以实现,停pod的时候,触发,优雅的停止自己,从 zk节点 删了。再停 ,生产中有点常用的。后面 详细说
16.1 按照commit id去构建,生成 镜像
直接dashboard上修改资源配置清单,把镜像地址改了
然后update后,自己就滚动 更新 了
持续构建CI:就是jenkins拉代码 ,构建 ,生成镜像
持续集成CD:就是生成镜像后 ,自动生成资源配置清单,应用,pod里面的代码自动变成新 的额
17.K8S的毁灭性测试
宿主机down了怎么 办
滚动发布,销毁一个 ,起一个
蓝绿发布,原先 3份,起三份,然后流量切过去 ,再把之前的3份销毁了
7-21机器 的 物理机挂 了halt
kubectl delete node jdss7-21.host.com 把k8s集群的7-21集群节点删了。k8s集群会启动 自愈程序
如果不删就会有问题,k8s节点会任务 你 短暂不可达,还会尝试去 不断重试连接 ,可能是3分钟或者5分钟
K8S的自愈机制依赖 监控,一段时间都 不通 才会触发 。
(1)k8s集群摘节点,如果不摘 等着k8s集群 自己 摘,时间会很长的。
(2)nginx负载均衡摘节点
18.k8s机器修好了,加回集群
kubectl label node jdss7-21.host.com node-role.kubernetes.io/master=
kubectl. label. node jdss7-21.host.com node-role.kubernetes.io/node=
kubectl get. nodes
nginx上 的负载均衡调回来 ,7-11 机器上的
19.配置中心概述
- 配置独立于程序的可配置变量,同一份程序 在 不同配置下会有不同的行为,常见的配置有连接字符串,应用配置和业务配置等。
- 配置有多种形态,常用的
- 程序内部 hardcode,反模式,一般不建议
- 配置文件,比如spring应用过程序的配置 放到 application.properties
- 环境变量 ,配置可以预配置在操作系统 环境变量里,程序运行 时读取
- 启动参数,可以在程序启动时候提供一次性提供参数,例如 java程序启动时可以通过java -D 方式配启动参数
- 基于数据库,有经验的 开发 人员把易遍的配置放在数据库中,可以在 运行期灵活调整配置(config relation center配置中心 )
20.配置中心的分类
XDiamond:全局配置中心,存储 应用 的配置 项,解决配置混乱分散的问题,名字来源于淘宝开源项目diamond
Qconf:QConf是 一个分布式管理工具,替代传统配置文件,使得配置信息和 程序代码 分离。同时 配置变化 能够 实时同步到客户端。保证用户高效读取配置,
Disconf:专注各种分布式系统配置管理的 通用 组件和通用平台,提供统一的配置管理服务
SpringCloudConfig:spring cloud config为分布式系统中的外部配置 提供服务器和 客户端支持
K8S configMap:k8s的 一种 标准资源,专门用来几种管理应用的配置 。
Apollo:携程框架部门开源的分布式配置中心。
21.ConfigMap管理应用配置
拆分环境
测试环境+生产环境
7-21上的 zk停了,7-12机器上zk停了,(7-12机器上的data目录删了,logs的也 删了)
7-11机器上zk停了 ,
7-11机器上的zk里面的配置文件里 的server1,server2,server3都删了
7-12机器上的zk里面的 配置文件里的server1,server2,server3都删了
现在7-11机器 的zk和7-12机器 上的 zk环境都是单机的,没有关联
21.dubbo-monitor应用 的configMap的资源配置清单
在 运维 主机 7-200的机器 上的yml存放 路径,存放configMap.yaml
cm.yaml
dp.yaml
以卷 的形式挂载到指定 路径,将配置
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/cm.yaml
应用dp.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/dp.yaml
这样就将 configMap存的配置,以dubbo.properties配置文件的形式挂载到 了docker容器里
如果要改dubbo-monitor去 连zk2,则改 一下configMap.yaml配置文件,然后update就改动到了 配置 中心里。然后重启pod就生效了
service iptables save
可以把应用的springboot的配置文件几种管理到configMap里,springboot依赖外部的application.properties文件可以放到同级conf/目录下