zoukankan      html  css  js  c++  java
  • Golang交付至Kubernetes

    0、前言

    如果还不知道kubernetes下如何实现jenkins slave可以参考我的另一个博文Kubernetes Jenkins动态创建Slave

    1、Go服务构建

    我们需要通过自定义镜像底包,能够让该底包拥有启动go程序的基本功能和日志重定向输出到指定目录下,方便日志收集,编辑完相关文件后,我们需要通过docker命令去构建镜像,构建完毕后将其推送到harbor base仓库,该名为base的仓库需要手动去harbor上创建。

    1.1、制作Go服务镜像底包

    1.编写Dockerfile以及相关的启动脚本

    • Dcokerfile
    FROM alpine
    USER root
    RUN apk add tzdata && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&
        echo 'Asia/Shanghai' >/etc/timezone &&
        mkdir /opt/logs 
    WORKDIR /opt/project_dir/
    ADD entrypoint.sh /entrypoint.sh
    CMD ["/entrypoint.sh"]
    
    • entrypoint.sh
    #!/bin/sh
    APP_NAME=${APP_NAME:-"app"}
    exec ${APP_NAME} >> /opt/logs/stdout.log 2>&1
    

    APP_NAME:启动的二进制文件名,这个可以手动传入或者默认为名为app

    2.构建镜像并上传到harbor仓库

    $ docker build ./ -t harbor.od.com/base/go-run:1.14.2-1
    Sending build context to Docker daemon  3.072kB
    Step 1/6 : FROM alpine
     ---> a187dde48cd2
    Step 2/6 : USER root
     ---> Using cache
     ---> f0673624a0e0
    Step 3/6 : RUN apk add tzdata && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&    echo 'Asia/Shanghai' >/etc/timezone &&    mkdir /opt/logs
     ---> Using cache
     ---> e91f2e8a4919
    Step 4/6 : WORKDIR /opt/project_dir/
     ---> Using cache
     ---> 6afa8e9ddd43
    Step 5/6 : ADD entrypoint.sh /entrypoint.sh
     ---> Using cache
     ---> 7a7efe533a5f
    Step 6/6 : CMD ["/entrypoint.sh"]
     ---> Using cache
     ---> 17d85fd60af3
    Successfully built 17d85fd60af3
    Successfully tagged harbor.od.com/base/go-run:1.14.2-1
    
    $ docker push harbor.od.com/base/go-run:1.14.2-1
    The push refers to repository [harbor.od.com/base/go-run]
    20c042b1ca31: Mounted from base/go-test 
    98e20bd596b3: Mounted from base/go-test 
    f4ee0579d5d8: Mounted from base/go-test 
    beee9f30bc1f: Mounted from base/go-test 
    1.14.2-1: digest: sha256:49dda47c11a3148fdfd60fe4850ada128e6550fb33c1a6284caadf0e6ea8016d size: 1153
    

    1.2、制作slave基础镜像底包

    我们是基于jenkins slave方式去构建项目,并且使用pipeline来实现流程化,我们都知道slave运行的是一个pod,那么pod里可以有多个容器,而这些一个一个的容器就是执行我们对应操作的环境,所以我们需要通过制作一些镜像来满足我们的需求。

    镜像需求:
    1、编译golang应用:golang:v1.14.2
    2、打包镜像并推送到harbor:

    1.2.1、Golang镜像

    该镜像主要用于构建golang应用,我们是在基于golang v1.14.2环境下开发的golang程序,所以这里镜像版本就选择:golang:v1.14.2

    $ docker pull golang:v1.14.2
    $ docker tag a1c86c0786 harbor.od.com/public/golang:v1.14.2
    $ docker push harbor.od.com/public/golang:v1.14.2
    

    1.2.2、Docker镜像

    该镜像主要用于将编译好的golang项目打包成镜像并推送到harbor,但需要定制化一下镜像,需要将一台已经实现docker login 登录到harbor仓库所生成的配置文件,路径为:/root/.docker/config.json,与原始Docker镜像一起打包生成新的Docker镜像并推送到本地仓库。
    1.准备镜像文件

    $ docker pull docker:19.03
    $ docker tag e036013d6d10 harbor.od.com/public/docker:v19.03
    $ docker push harbor.od.com/public/docker:v19.03
    

    2.准备Dockerfile和config.json

    • Dockerfile
    FROM harbor.od.com/public/docker:v19.03
    USER root
    ADD config.json /root/.docker/config.json
    

    3.将/root/.docker/config.json文件拷贝到Dockerfile目录下

    {
    	"auths": {
    		"harbor.od.com": {
    			"auth": "YWRtaW46SGFyYm9yMTIzNDU="
    		}
    	},
    	"HttpHeaders": {
    		"User-Agent": "Docker-Client/19.03.6 (linux)"
    	}
    }
    

    4.制作并推送镜像

    $ docker build ./ -t harbor.od.com/public/docker:v19.03
    $ docker push  harbor.od.com/public/docker:v19.0
    

    2、Jenkins流水线

    2.1、创建流水线

    1.添加参数化构建

    - Choice Parameterr:app_project
      Value:zj-skyquery
      Describe:项目名必须和git仓库名一致
    
    - Choice Parameterr:image_name
      Value:app/skyquery
      Describe:镜像名称:仓库名/镜像名
    
    - String Parameterr:git_ver
      Value:zmaster
      Describe:Git仓库分支或Commit ID
    
    - String Parameterr:add_tag
      Value:
      Describe:打包镜像tag,一般为日期时间
    
    - Choice Parameterr:git_repo
      Value:https://gitee.com/jasonminghao/zj-skyquery.git
      Describe:代码仓库地址
    
    - Choice Parameterr:base_image
      Value:base/go-run:1.14.2-1
      Describe:基础镜像底包
    

    2.pipeline代码

    podTemplate(cloud:'kubernetes',containers: [
        containerTemplate(
           name: 'go-build', 
           envVars: [
             envVar(key: 'GO111MODULE', value: 'on'), 
             envVar(key: 'GOPROXY', value: 'https://goproxy.io'),
             envVar(key: 'CGO_ENABLED', value: '0'),
             envVar(key: 'GOOS', value: 'linux')
           ],
           image: 'harbor.od.com/infra/golang:v1.14.2', 
           ttyEnabled: true,
           command: 'cat'),
        containerTemplate(
           name: 'docker',
          ttyEnabled: true,
          image: 'harbor.od.com/public/docker:v19.03'),
        ],
        volumes: [
           nfsVolume(mountPath: '/go/pkg/mod', readOnly: false, serverAddress: 'hdss7-200.host.com', serverPath: '/data/nfs-volume/go-pkg/'),
           hostPathVolume(hostPath: '/run/docker.sock', mountPath: '/run/docker.sock')
                ]
     ){
        node(POD_LABEL) {
            stage('Get a Go project') {
            // 从git仓库拉取代码
            checkout([$class: 'GitSCM', branches: [[name: "${params.git_ver}"]], browser: [$class: 'GitLab', repoUrl: ''], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'git', name: 'git', refspec: 'refs/changes/*:refs/changes/*', url: "${params.git_repo}"]]])
    
                container('go-build') {
                    stage('Build a go project') {
                      // 将go应用构建名为app的可执行二进制文件
                      sh "go build -o app"
                    }
                }
            }
            stage('Docker build') {
                container('docker') {
                    stage('create dir'){
                      sh "mkdir -p /tmp/${params.app_project}/project_dir && mv ./app /tmp/${params.app_project}/project_dir"
                    stage('build docker iamge'){
                     sh """
                       echo "FROM harbor.od.com/${params.base_image}" >/tmp/${params.app_project}/Dockerfile
                       echo "ADD ./project_dir /opt/project_dir" >>/tmp/${params.app_project}/Dockerfile
                      """
                      sh "cd /tmp/${params.app_project}/ && pwd && 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} "                              
    
                     }
                  }
                }
            }
        }
    }
    

    我们在podTemplate里需要导入以下几个变量(pipeline已通过env实现)

    // 如果运行的golang镜像没有以下变量会导致无法执行go build以及可执行文件无法在linux上运行
    GO111MODULE =  on
    GOPROXY = "https://goproxy.io"
    CGO_ENABLED = 0 
    GOOS = linux 
    

    之前我们遇到过一个问题,golang应用构建成功,也有二进制文件,但是我们将其通过deployment交付到k8s的时候容器会启动失败,并且报错是 not found,但是把编译的文件拿到linux上可正常运行,就是在docker里运行失败,最后我们去网上查了一些资料,通过增加CGO_ENABLED=0 参数重新编译即可解决该问题。

    2.2、流水线构建

    1.填写参数构建

    2.构建后的结果

    3、golang资源配置清单

    3.1、准备资源配置清单

    1.deployment

    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: sky-query
      namespace: app
      labels: 
        name: sky-query
    spec:
      replicas: 1
      selector:
        matchLabels: 
          name: sky-query
      template:
        metadata:
          labels: 
            app: sky-query
            name: sky-query
        spec:
          containers:
          - name: sky-query
            image: harbor.od.com/app/skyquery:master_20200424_1725
            ports:
            - containerPort: 80
              protocol: TCP
            imagePullPolicy: IfNotPresent
          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
    

    2.svc

    kind: Service
    apiVersion: v1
    metadata: 
      name: sky-query
      namespace: app
    spec:
      ports:
      - protocol: TCP
        port: 80
        targetPort: 80
      selector: 
        name: sky-query
    

    3.ingress

    kind: Ingress
    apiVersion: extensions/v1beta1
    metadata: 
      name: sky-query
      namespace: app
    spec:
      rules:
      - host: sk-query.od.com
        http:
          paths:
          - path: /
            backend: 
              serviceName: sky-query
              servicePort: 80
    

    3.2、应用资源配置清单

    $ kubectl  apply -f ./
    deployment.extensions/sky-query created
    ingress.extensions/sky-query created
    service/sky-query created
    

    查看pod运行状态

    $ kubectl get pods -n app
    NAME                         READY   STATUS    RESTARTS   AGE
    sky-query-55474c768d-x8qj5   1/1     Running   0          2m10s
    

    3.3、浏览器访问golang业务

    我们是通过ingress实现域名访问golang业务,以为是实验环境,我部署了内部自建dns,那我就直接将A记录添加到dns中,那么各位如果没有自建dns,直接将解析添加到hosts文件中。

    1.域名解析

    $ vim /var/named/od.com.zone 
    sk-query           A    10.4.7.10
    
    $ systemctl restart named
    

    2.浏览器访问

  • 相关阅读:
    swoole 安装方法 使用即时聊天
    git的介绍以及简单应用
    curl的应用
    linux下监听和同步代码配置
    mac skim 修改背景色
    php 编译安装的一个 configure 配置
    mac mysql error You must reset your password using ALTER USER statement before executing this statement.
    yii2 控制器里 action 大小写组合造成的路由问题
    warning : json_decode(): option JSON_BIGINT_AS_STRING not implemented in xxx
    redis 自启动脚本
  • 原文地址:https://www.cnblogs.com/jasonminghao/p/12769072.html
Copyright © 2011-2022 走看看