咱们用一个系列来解说从需要到上线、从代码到k8s部署、从日志到监控等各个方面的微服务残缺实际。
整个我的项目应用了go-zero开发的微服务,根本蕴含了go-zero以及相干go-zero作者开发的一些中间件,所用到的技术栈根本是go-zero项目组的自研组件,根本是go-zero全家桶了。
实战我的项目地址:https://github.com/Mikaelemmm...
1、概述
上一节,咱们曾经把gitlab、jenkins、harbor、k8s都曾经搭建好了,这一节咱们来编写jenkins的pipline将咱们的服务通过jenkins残缺的公布到k8s中。
2、部署中间件
将mysql、redis、es等部署到k8s之外 , 模仿用作线上独立环境(至于线上你想把某些中间件部署到k8s外部这个自行处理,本次重点是如何将go-zero开发的微服务部署到k8s集群外部),这里我就间接应用我的项目下的docker-compose-env.yaml了,把所有依赖的第三方中间件环境间接装置在srv-data.com(192.168.1.181)这台服务器,前提是这台服务器曾经装置好docker、docker-compose。
登陆到 192.168.1.181
$ mkdir data && cd data && vim docker-compose.yml$ docker-compose up -d$ docker-compose ps #查看确认
3、独立配置
将每个服务的配置都独立进去,对立放在一个git仓库,这样只给一个人线上仓库的权限,如果线上配置有变间接批改这个仓库的文件,在jenkins做cd的时候,会先拉取代码再拉取对应服务的配置主动构建,具体能够看前面的pipline。
【问】为什么不必配置核心?
1)批改db、redis等须要重启服务,然而有一些配置又不须要重启服务,运维又要去记,记混了比拟容易造成线上事变
2)不便回滚。咱们发新版本到线上,并且又改了新版本配置。这时候线上用户反馈有问题,线上须要疾速回滚的话,如果咱们应用将文件构建到镜像中,间接应用k8s一行命令就能够将上一个版本代码加配置间接回滚回来。如果应用了配置核心,回滚了代码,还要将上个版本的配置去配置核心改回来,很麻烦。
独立线上仓库目录构造如下(这个构造是跟pipline中写法相干的)
仓库地址 : https://github.com/Mikaelemmm... , 间接下载就好
1、批改配置中的中间件,数据库、redis等都要改成192.168.1.181这台机器,咱们把这台机器当成线上环境的中间件。
2、另外一个就是咱们的服务发现,线上咱们部署在k8s中,go-zero间接反对k8s服务发现,所以不须要etcd等,咱们在配置zrpc client的时候,要改成target,k8s的配置形式。
4、编写 jenkins 的 pipline
4.1 配置参数
拜访 http://192.168.1.180:8989/ 关上jenkins,进入jenkins首页,点击左侧菜单新建Item
咱们先创立 identity
受权服务的流水线
而后点击“General” , 抉择“This project is parameterized” , "增加参数",“Choice Parameter”,如下图
而后编写内容如下
间接保留。
4.2 编写pipline
向下滑动找到Pipeline script
,填写脚本内容
pipeline { agent any parameters { gitParameter name: 'branch', type: 'PT_BRANCH', branchFilter: 'origin/(.*)', defaultValue: 'master', selectedValue: 'DEFAULT', sortMode: 'ASCENDING_SMART', description: '抉择须要构建的分支' } stages { stage('服务信息') { steps { sh 'echo 分支:$branch' sh 'echo 构建服务类型:${JOB_NAME}-$type' } } stage('拉取代码') { steps { checkout([$class: 'GitSCM', branches: [[name: '$branch']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-cert', url: 'ssh://git@192.168.1.180:2222/root/go-zero-looklook.git']]]) } } stage('获取commit_id') { steps { echo '获取commit_id' git credentialsId: 'gitlab-cert', url: 'ssh://git@192.168.1.180:2222/root/go-zero-looklook.git' script { env.commit_id = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } } } stage('拉取配置文件') { steps { checkout([$class: 'GitSCM', branches: [[name: '$branch']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'conf']], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-cert', url: 'ssh://git@192.168.1.180:2222/root/go-zero-looklook-pro-conf.git']]]) } } stage('goctl版本检测') { steps{ sh '/usr/local/bin/goctl -v' } } stage('Dockerfile Build') { steps{ sh 'yes | cp -rf conf/${JOB_NAME}/${type}/${JOB_NAME}.yaml app/${JOB_NAME}/cmd/${type}/etc' //线上配置文件 sh 'cd app/${JOB_NAME}/cmd/${type} && /usr/local/bin/goctl docker -go ${JOB_NAME}.go && ls -l' script{ env.image = sh(returnStdout: true, script: 'echo ${JOB_NAME}-${type}:${commit_id}').trim() } sh 'echo 镜像名称:${image} && cp app/${JOB_NAME}/cmd/${type}/Dockerfile ./ && ls -l && docker build -t ${image} .' } } stage('上传到镜像仓库') { steps{ //docker login 这里要留神,会把账号密码输入到jenkins页面,能够通过port.sh相似形式解决,官网文档有这里我就不具体写了 sh 'docker login --username=${docker_username} --password=${docker_pwd} http://${docker_repo}' sh 'docker tag ${image} ${docker_repo}/go-zero-looklook/${image}' sh 'docker push ${docker_repo}/go-zero-looklook/${image}' } } stage('部署到k8s') { steps{ script{ env.deployYaml = sh(returnStdout: true, script: 'echo ${JOB_NAME}-${type}-deploy.yaml').trim() env.port=sh(returnStdout: true, script: '/root/port.sh ${JOB_NAME}-${type}').trim() } sh 'echo ${port}' sh 'rm -f ${deployYaml}' sh '/usr/local/bin/goctl kube deploy -secret docker-login -replicas 2 -nodePort 3${port} -requestCpu 200 -requestMem 50 -limitCpu 300 -limitMem 100 -name ${JOB_NAME}-${type} -namespace go-zero-looklook -image ${docker_repo}/${image} -o ${deployYaml} -port ${port} --home /root/template' sh '/usr/local/bin/kubectl apply -f ${deployYaml}' } } stage('Clean') { steps{ sh 'docker rmi -f ${image}' sh 'docker rmi -f ${docker_repo}/${image}' cleanWs notFailBuild: true } } }}
十分重要!!!
- 构建优化:pipline中生成dockerfile的时候,咱们是应用k8s形式部署不须要etcd,然而这种形式部署须要指定账号(有去k8s的endpoints中get的权限,应用默认default就好了,每次创立一个新的命名空间k8s会主动帮咱们创立好一个default),然而应用goctl 生成的 k8s yml没有增加指定账号选项,这个曾经反馈了,可能后续版本会加上,这里咱们也用模版做了,同样模版是在我的项目目录下https://github.com/Mikaelemmm...,pipline中构建指定这个模版即可
- ${credentialsId}要替换为你的具体凭据值,即【增加凭据】模块中的一串字符串,咱们之前配置的是gitlab-cert所以这里就填写gitlab-cert,如果你不是这个本人要更换,${gitUrl}须要替换为你代码的git仓库地址,其余的${xxx}模式的变量无需批改,放弃原样即可。
- 这里跟官网文档有一点点不一样,因为我我的项目文件夹目录不同,goctl生成的dockerfile文件我手动做了点调整,在一个我不是在构建时候生成的dockerfile,是在创立我的项目时候就把dockerfile一起放在目录下,这样构建镜像时候不须要goctl了
5、配置k8s拉取公有仓库镜像
k8s在默认状况下,只能拉取harbor镜像仓库的私有镜像,如果拉取公有仓库镜像,则是会报 ErrImagePull
和 ImagePullBackOff
的谬误
1、先在jenkins公布机器登陆harbor
$ docker login 192.168.1.180:8077$ Username: admin$ Password:Login Succeeded
2、在k8s中生成登陆harbor配置文件
#查看上一步登陆harbor生成的凭证$ cat /root/.docker/config.json { "auths": { "192.168.1.180:8077": { "auth": "YWRtaW46SGFyYm9yMTIzNDU=" }}
3、对秘钥文件进行base64加密
$ cat /root/.docker/config.json | base64 -w 0ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEuMTgwOjgwNzciOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9Cn0=
4、创立docker-secret.yaml
apiVersion: v1kind: Secretmetadata: name: docker-logintype: kubernetes.io/dockerconfigjsondata: .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEuMTgwOjgwNzciOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9Cn0=
$ kubectl create -f docker-secret.yaml -n go-zero-looklooksecret "docker-login" created
6、构建
咱们进入首页,点击idenity进入详情页
而后能够看到,下面咱们配置好的identity服务,如下图 ,点击“Build with Parameters”, 而后抉择rpc,点击“开始构建”
第一次构建在拉代码时候都会失败,应该是初始化啥货色,再点一次就好了。
部署胜利
同样情理,去构建identity-api,再去配置usercenter服务 构建usercenter-rpc、构建usercenter-api,接着配置其余服务、构建即可,本次咱们先只构建identity-api、identity-rpc、usercenter-rpc、usercenter-api给大家演示。
6、增加网关
因为咱们的api服务通过goctl公布在k8s中都会裸露nodeport端口,索引咱们看下k8s中go-zero-looklook命名空间下的service的nodeport端口服务,而后将nodeport配置在nignx即可。
本次咱们独立一台虚拟机在k8s之外,装置nginx,将k8s后端api服务通过nodeport形式把端口裸露给nginx,而后nginx在配置中配置此api服务,这样nginx就充当网关应用。
nginx的装置就不再这里多说了,记得肯定要有auth_request模块,没有的话本人去装置。
nginx的配置
server{ listen 8081; access_log /var/log/nginx/looklook.com_access.log; error_log /var/log/nginx//looklook.com_error.log; location /auth { internal; proxy_set_header X-Original-URI $request_uri; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_pass http://192.168.1.182:31001/identity/v1/verify/token; } location ~ /usercenter/ { auth_request /auth; auth_request_set $user $upstream_http_x_user; proxy_set_header x-user $user; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.1.182:31002; } location ~ /travel/ { auth_request /auth; auth_request_set $user $upstream_http_x_user; proxy_set_header x-user $user; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.1.182:31003; } location ~ /order/ { auth_request /auth; auth_request_set $user $upstream_http_x_user; proxy_set_header x-user $user; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.1.182:31004; } location ~ /payment/ { auth_request /auth; auth_request_set $user $upstream_http_x_user; proxy_set_header x-user $user; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.1.182:31005; }}
如果是线上的话,应该配置多台nignx放弃高可用,在nignx后面还会有一个slb,你的域名包含https配置都应该解析到slb,在slb后面在有防火墙等这些。
8、结束语
至此,整个系列就完结了,整体架构图应该如第一篇所展现,本系列心愿能给你带来帮忙。
我的项目地址
https://github.com/zeromicro/go-zero
欢送应用 go-zero
并 star 反对咱们!
微信交换群
关注『微服务实际』公众号并点击 交换群 获取社区群二维码。