记一个适用于初创中小型团队/服务器资源紧张的轻量级GitOps解决方案

由于个别原因,接手了一个很古老且服务器资源很吃紧的项目,早期没有DevOps的意识,发版的流程也很乱,每次发版都需要上服务器上传代码等操作,在经历过几次发版的折磨下,开始考虑上CI/CD。

代码托管工具选项

代码托管工具,GithubGitee 这些代码托管平台是大家平时接触最多的平台,但是这些都是开源托管平台,如果需要私有化部署的话,一般会选择GitLab,甚至GitLab大而全的整合了CI/CD,但是GitLab十分的占用资源,日常的内存占用是14GB,GitLab CPU 占用率(在一个核心的情况下)日常待机在 35% 上下,很明显在我们项目中不适用。在一通Google下,搜到了一个官方宣称最低的系统硬件要求为一个廉价的树莓派的代码托管服务Gitea,官网中也有写到如果用于团队项目,建议使用 2 核 CPU 及 1GB 内存,在实际的生产中实测,日常的内存占用只有几百MB,CPU占用率(在一个核心的情况下)也只在02%上下。相较于GitLab,占用资源可以说是很小了。

CI 工具选型

CI工具,大家一般接触的最多的就是JenkinsTeamCityGitLab CI等,我们原本是准备在Jenkins和TeamCity中去做选型的,然后相较于Jenkins来说,我们更倾向与TeamCity,实属是JenKins的UI界面做的确实很丑,所以我们在其他项目(不是同一个业主,所以不是在用一个内网环境下)中使用的一般都是TeamCity偏多。但是由于我们在代码托管工具中选型是Gitea,发现Gitea并没有支持TeamCity需要的webhook鉴权,所以我们又开始Google,最后发现了Drone。这是一款开源产品,在我们发现它的时候,它在GitHub 上的 Stars 数超过了 2 万,镜像较小。它使用 Go 语言编写,支持云、本地和 Kubernetes 部署,尤其适合运行在 Kubernetes 上,并能与 Kubernetes 进行很好的集成,这对于后续如果要迁移到Kubernetes上也不用做很大的改动。Drone 没有明显缺点,如果硬要说一个的话,它的示例 / 官方文档还不是很完善。

Docker 镜像仓库选型

(ps:如果项目部署不涉及到打包docker镜像,可以忽略这块内容)

由于我们项目是用Docker run起来的,所以这里又涉及到了一个docker 镜像仓库的选型,其实Gitea会自带一个软件包管理,可以直接使用gitea自带的软件包管理,具体可参考软件包注册表 | Gitea。如果用不惯自带的包管理,也可以选择registry或者harbor,如果每次打的镜像会比较大,且磁盘空间相对紧张,可能需要定期清理,那建议使用harbor,2.x的版本是自带可以编写清理策略的。

部署

上面所述的三种工具的部署,我们这里都是用的docker-compose,启动时可能会存在遇到服务起来了之后,ssh连不上去了之类的奇奇怪怪的问题,可以翻一下上一篇记一次使用docker-compose部署应用的时候踩得坑,看看能不能解决自己的问题。

Gitea

  1. 创建gitea目录

    mkdir /data/gitea
    mkdir /data/gitea/data /data/gitea/config
    
  2. 给docker用户授权 gitea启动时用的是这个用户

    chown 1000:1000 /data/gitea
    
  3. 编写docker-compose.yml

    vim /data/gitea/docker-compose.yml
    
    version: "3"
    
    services:
      server:
        image: gitea/gitea:latest
        container_name: gitea
        restart: always
        volumes:
          - ./data:/data
          - ./config:/etc/gitea
          - /etc/timezone:/etc/timezone:ro
          - /etc/localtime:/etc/localtime:ro
        ports:
          - "3000:3000"
    
  4. 启动gitea

    cd /data/gitea
    docker-compose up -d
    

Drone

  1. 创建drone目录

    mkdir /data/drone
    mkdir /data/drone/lib /data/drone/data
    
  2. 编写docker-compose.yml

    version: '3'
    services:
      drone-server:
        restart: always
        image: drone/drone:2
        ports:
          - "3001:80"
        volumes:
          - /data/drone/lib:/var/lib/drone/
          - /data/drone/data:/data/
        environment:
          - DRONE_GITEA_SERVER=http://10.36.199.249:3000 # gitea的网址
          - DRONE_GITEA_CLIENT_ID=9110d930-xxxx-xxxx-xxxx-0b80205839ab	# gitea oauth的id  (在gitea右上角 设置->应用->创建新的 OAuth2 应用程序, 重定向地址填 drone的网址+/login)
          - DRONE_GITEA_CLIENT_SECRET=gto_tdrjjxxxxxxxxiiq7xxxxxxxxxxass4g3lbxe3xixmladna  # gitea oauth的密钥
          - DRONE_SERVER_HOST=10.36.199.249:3001
          - DRONE_SERVER_PROTO=http # 支持http, https
          - DRONE_RPC_SECRET=4b229b87xxxxxxxx24c9f79ab49a214f			# 通过 openssl rand -hex 16 生成
          - DRONE_GIT_ALWAYS_AUTH=true
          - DRONE_GIT_USERNAME=drone 	# gitea 的 Access Token 名称(在gitea右上角 设置->应用->管理 Access Token,注意给一下read仓库的权限)
          - DRONE_GIT_PASSWORD=cc2d09d9fbbxxxxxxxxxx3462612fe1fd26			# gitea 的 Access Token  
          - DRONE_USER_CREATE=username:root,admin:true # 开启管理员账户 只有管理员账号可以修改setting中的Trusted选项
      drone-runner-docker:
        restart: always
        image: drone/drone-runner-docker:1
        ports:
          - "3005:3000"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
        environment:
          - DRONE_RPC_PROTO=http # 支持http, https
          - DRONE_RPC_HOST=10.36.199.249:3001
          - DRONE_RPC_SECRET=4b229b87xxxxxxxx24c9f79ab49a214f		# 这个要和上面的一致
          - DRONE_RUNNER_NAME=drone-runner-docker
          - DRONE_RUNNER_CAPACITY=2  # 这个参数用于限制runner的并行数
    
  3. 启动drone

    cd /data/drone
    docker-compose up -d
    
  4. 如果是没有互联网的环境 记得提前在本地save好需要的镜像,并load到runner所在的机器上

    # 这个插件是必须要的 如果没有互联网,请一定要在本地save好,然后load进去
    docker pull drone/git:latest
    docker save -o drone-git.tar.gz drone/git:latest
    
    # 这个插件是必须要的 如果没有互联网,请一定要在本地save好,然后load进去
    docker pull appleboy/drone-ssh:latest
    docker save -o drone-ssh.tar.gz appleboy/drone-ssh
    
    # 如果需要发布前端代码 那基本上这个也是必须要的 
    docker pull appleboy/drone-scp:latest
    docker save -o drone-scp.tar.gz appleboy/drone-scp:latest
    
    # 这个一般部署后端服务的时候使用
    docker pull plugins/docker:latest
    docker save -o plugins-docker.tar.gz plugins/docker:latest
    
    # 在drone-runner在的那台机器上上传需要的镜像tar包,并load
    
    docker load -i drone-git.tar.gz
    docker load -i drone-ssh.tar.gz
    docker load -i drone-scp.tar.gz
    docker load -i plugins-docker.tar.gz
    

registry

  1. 创建保存registry账号密码的文件

    mkdir /data/registry
    mkdir /data/registry/auth /data/registry/lib
    
    docker run --entrypoint htpasswd httpd:2 -Bbn username userpasswd > /data/registry/auth/htpasswd
    
  2. 创建registry容器

    docker run  -d -p 3002:5000 --restart=always --name registry-auth \
      -v  /data/registry/auth:/auth \
      -v /data/registry/lib:/var/lib/registry \
      -e "REGISTRY_AUTH=htpasswd" \
      -e  "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
      -e  REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
      registry
    

harbor

  1. 离线下载Harbor安装包

    wget https://github.com/goharbor/harbor/releases/download/v2.6.2/harbor-offline-installer-v2.6.2.tgz
    
  2. 解压安装包

    tar xf  harbor-offline-installer-v2.6.2.tgz
    
  3. 复制harbor.yml文件,并修改配置

    cp harbor.yml.tmpl harbor.yml
    vim harbor.yml  #更改hostname和/data目录 注释掉https 要不然安装报错
    配置端口80为3002,修改密码Harbor#0602
    
  4. 开始安装

    ./install.sh
    
  5. 安装完成,用浏览器输入ip访问(默认账号是admin 密码是Harbor#0602)(配置文件里的密码二次修改不生效,登陆系统后修改才生效)

  6. 重启应用

    docker-compose up -d