go-zero源码阅读-服务部署

服务部署 生产环境搭建
docker & k8s搭建 详细请看我的下一篇文章
git私有仓库 & 容器私有仓库 & CI、DI
详细请看我的下一篇文章
配置文件编写 & 生成
dockerfile 我们先用网关部分代码来演示

  • 执行代码
./cmd.sh gen dockerfile gateway

  • 生成文件 code/service/gateway/api/Dockerfile
### 加载基础镜像 FROM golang:alpine AS builderLABEL stage=gobuilderENV CGO_ENABLED 0 ENV GOOS linux ### 设置 go module 代理 ENV GOPROXY https://goproxy.cn,directWORKDIR /build/zero### 下载依赖文件 ADD go.mod . ADD go.sum . RUN go mod download COPY . . COPY service/gateway/api/etc /app/etc ### 编译源代码 RUN go build -ldflags="-s -w" -o /app/gateway service/gateway/api/gateway.go### 生成docker镜像 FROM alpineRUN apk update --no-cache && apk add --no-cache ca-certificates tzdata ENV TZ Asia/ShanghaiWORKDIR /app COPY --from=builder /app/gateway /app/gateway COPY --from=builder /app/etc /app/etcCMD ["./gateway", "-f", "etc/gateway.prod.yaml"]

从生成的Dockerfile可以看到主要有两个部分
  1. 加载golang基础镜像,将代码编译为二进制文件
  2. 加载运行环境基础镜像并生成gateway运行环境的docker镜像
为啥分为两个部分呢,我们不能直接把编译代码和打包镜像放一起吗,这当然是可以的,但是这样会导致docker镜像包会很大,而把编译和打包分开后可以大大减少docker镜像包的大小,方便我们快速分发和部署。
编译代码&镜像打包
?go-zero-mall git:(master) ? ./cmd.sh docker build gateway -------- docker build gateway-------- time: 2022-05-02 00:19:58 msg: ------------ docker build gateway ------------ Untagged: gateway:latest Deleted: sha256:0eedc326b97f06a3c5d19665309369c4c163e430b6c3d17de8ba9a1ebaf37ca8 [+] Building 31.9s (19/19) FINISHED => [internal] load build definition from Dockerfile0.0s => => transferring dockerfile: 733B0.0s => [internal] load .dockerignore0.0s => => transferring context: 2B0.0s => [internal] load metadata for docker.io/library/alpine:latest3.7s => [internal] load metadata for docker.io/library/golang:alpine3.4s => [builder 1/8] FROM docker.io/library/golang:alpine@sha256:42d35674864fbb570.0s => [internal] load build context1.2s => => transferring context: 35.78MB1.1s => [stage-1 1/5] FROM docker.io/library/alpine@sha256:4edbd2beb5f78b1014028f40.0s => CACHED [builder 2/8] WORKDIR /build/zero0.0s => CACHED [builder 3/8] ADD go.mod .0.0s => CACHED [builder 4/8] ADD go.sum .0.0s => CACHED [builder 5/8] RUN go mod download0.0s => [builder 6/8] COPY . .0.6s => [builder 7/8] COPY service/gateway/api/etc /app/etc0.0s => [builder 8/8] RUN go build -ldflags="-s -w" -o /app/gateway service/gatew26.1s => CACHED [stage-1 2/5] RUN apk update --no-cache && apk add --no-cache ca-ce0.0s => CACHED [stage-1 3/5] WORKDIR /app0.0s => CACHED [stage-1 4/5] COPY --from=builder /app/gateway /app/gateway0.0s => CACHED [stage-1 5/5] COPY --from=builder /app/etc /app/etc0.0s => exporting to image0.0s => => exporting layers0.0s => => writing image sha256:0eedc326b97f06a3c5d19665309369c4c163e430b6c3d17de80.0s => => naming to docker.io/library/gateway:latest0.0sUse 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

docker images查看docker镜像信息
?go-zero-mall git:(master) ? docker images REPOSITORYTAGIMAGE IDCREATEDSIZE gatewaylatest0eedc326b97f7 days ago41.6MB

自动部署文件编写deploy.yaml
apiVersion: apps/v1 kind: Deployment metadata: labels: app: go-zero-mall-gateway name: go-zero-mall-gateway namespace: zero#一定要写名称空间 spec: progressDeadlineSeconds: 600 replicas: 3 selector: matchLabels: app: go-zero-mall-gateway strategy: rollingUpdate: maxSurge: 50% maxUnavailable: 50% type: RollingUpdate template: metadata: labels: app: go-zero-mall-gateway spec: imagePullSecrets: - name: aliyun-docker-hub#提前在项目下配置访问阿里云的账号密码 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app: go-zero-mall-gateway topologyKey: kubernetes.io/hostname containers: - image: $REGISTRY/$ALIYUNHUB_NAMESPACE/gateway:latest imagePullPolicy: Always name: app ports: - containerPort: 8000 protocol: TCP resources: limits: cpu: 200m memory: 60Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always terminationGracePeriodSeconds: 30 --- apiVersion: v1 kind: Service metadata: labels: app: go-zero-mall-gateway name: go-zero-mall-gateway namespace: zero spec: ports: - name: http port: 8000 protocol: TCP targetPort: 8000 selector: app: go-zero-mall-gateway sessionAffinity: None type: ClusterIP

通过自动部署文件我们可以指定一些关键指标
  • 服务名称
  • pod数量
  • 自动扩容阀值
  • 服务权重
  • 容器端口
  • cpu&memory最大使用量
通过这些指标我们的服务基本可以稳定运行啦
Jenkins文件编写Jenkinsfile
pipeline { agent { node { label 'go' }} stages { stage('clone code') { agent none steps { git(url: 'https://gitee.com/go-open-project/go-zero-mall.git', changelog: true, poll: false) sh 'ls -al' } }stage('deploy user') { // agent none steps { container ('go') { withCredentials([ kubeconfigFile( credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG' )]) { sh 'envsubst < code/service/user/rpc/deploy.yaml | kubectl apply -f -' } } } }stage('deploy product') { // agent none steps { container ('go') { withCredentials([ kubeconfigFile( credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG' )]) { sh 'envsubst < code/service/product/rpc/deploy.yaml | kubectl apply -f -' } } } }stage('deploy order') { // agent none steps { container ('go') { withCredentials([ kubeconfigFile( credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG' )]) { sh 'envsubst < code/service/order/rpc/deploy.yaml | kubectl apply -f -' } } } }stage('deploy gateway') { // agent none steps { container ('go') { withCredentials([ kubeconfigFile( credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG' )]) { sh 'envsubst < code/service/gateway/api/deploy.yaml | kubectl apply -f -' } } } }} environment { DOCKER_CREDENTIAL_ID = 'dockerhub-id' GITHUB_CREDENTIAL_ID = 'github-id' KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig' REGISTRY = 'registry.cn-shanghai.aliyuncs.com' DOCKERHUB_NAMESPACE = 'ttsimple' ALIYUNHUB_NAMESPACE = 'ttsimple' GITHUB_ACCOUNT = 'kubesphere' APP_NAME = 'go-zero-mall-gateway' } parameters { string(name: 'TAG_NAME', defaultValue: '', description: '') } }

我们在 DevOps 中设置好环境变量、仓库地址、webhook 后便可在我们推送代码后自动部署我们的项目
说明:我们的容器是在开发环境打包的,我们当然也可以通过 Jenkins 来自动打包镜像
  • 自动部署状态
go-zero源码阅读-服务部署
文章图片

  • 服务运行状态
go-zero源码阅读-服务部署
文章图片

  • 调用线上用户登录接口
go-zero源码阅读-服务部署
文章图片

总结
  • 通过 go-zero 可以方便生成dockerfile
  • deploy.yaml 中指定服务部署指标
  • Jenkinsfile 中指定服务从哪里来,分别需要部署哪些服务,等等。
  • 【go-zero源码阅读-服务部署】私有部署
    • 镜像服务可以使用Harbor搭建,
    • 镜像制品可以使用云服务或Jenkins来打包生成,
    • 私有仓库可以使用云服务,gitee,开源仓库服务来搭建

    推荐阅读