本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2020年07月31日 统计字数: 4148字 阅读时间: 9分钟阅读 本文链接: https://soulteary.com/2020/07/31/lightweight-and-safe-deployment-solution.html ----- # 轻量安全的部署方案 智源大会结束,虽然还是很忙,但是总归有了一些时间,可以开始对之前的文章计划进行补完操作,本篇是第一篇补全,聊聊如何在容器环境下,花比较少的资源,来搞定高质量发布。 这个方案适用于小型团队、个人HomeLab,本文有别于我们当前团队使用的 GitLab Runner 相对比较重的方案,如果你面临的是更大规模的团队协作、项目管理需求和追求更全面的 CI/CD 阶段解耦,可以浏览我之前写的关于 [GitLab](https://soulteary.com/tags/gitlab.html) 的内容。 ## 写在前面 部署属于持续集成中场景的一环,而持续集成中和部署相关有几个步骤必不可少:管理代码、产物部署、产物版本管理。也正是因为有这些清晰的步骤划分,配合其他的措施,比如产物检测、安全检测、健康检查等我们才能够做到高效的秒级部署、多分支、多项目快速迭代。 我个人和团队虽然都使用 GitLab 作为 HomeLab 服务器的代码管理方案,但是这个方案如果放在公有云上,对个人/小团队而言,较多的资源消耗对于个人而言还是一个不能忽视的成本,所以这里需要使用一个轻量的解决方案。 诸如 `rsync`、`scp` 等无版本控制的方式在此忽略,因为我们还是期望有一些简单的版本回滚能力的。 下面聊两种不同的简单使用的方案。 ## 方案一:Git Over SSH 最轻量的安全方案便是使用 SSH + Git,对资源的消耗几乎可以忽略不计,Git 官方社区文档中也有对这种方案进行描述:[ Git on the Server - Setting Up the Server ](https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server)。 首先在服务器端创建一个空的仓库,这里不一定需要使用 `bare` 模式进行创建,一般模式也是可以的,比如将仓库创建在 `/repo-path/` 目录。 考虑到服务端安全问题,我们一般使用 RSA KEY 进行 SSH 交互,可以在 `~/.ssh/config` 定义服务器配置,减少在使用过程中的命令复杂度: ```bash Host pub-server Hostname 123.456.789.000 User user Port 12345 IdentityFile ~/.ssh/id_rsa_for_server ControlPath ~/.ssh/pub-%r@%h:%p ControlPersist yes TCPKeepAlive yes Compression yes ForwardAgent yes ``` 当你将你的 RSA PUBLIC KEY 在目标服务器授权之后,便可以和服务器进行数据交互了: ```bash git clone ssh://pub-server/repo-path/repo-name/ dest-name Cloning into 'dest-name'... remote: Enumerating objects: 9, done. remote: Counting objects: 100% (9/9), done. remote: Compressing objects: 100% (6/6), done. remote: Total 9 (delta 1), reused 9 (delta 1) Receiving objects: 100% (9/9), done. Resolving deltas: 100% (1/1), done. ... git pull git commit -m "your message" git push ... ``` 当然因为没有启动 Git Server 所以,这里的仓库需要提前在服务端创建好,或者将非服务端的内容先进行初始化并同步至服务端。 而触发 CI 命令也很简单,使用 Git Hook 即可。 但是这种方案也有一些小缺陷: 1. 必须使用 SSH 协议进行交互,不少场景下使用 SSH 或者公开使用 SSH 并不是一个十分稳定/安全的方案,比如会受到网络设备干扰等、或不使用密钥使用密码等。 2. 适合项目不多的场景,项目多了之后,不易管理。 ## 方案二:使用轻量 Git 服务软件 关于 Git 轻量软件的基础搭建使用,之前的文章中有提到过: [使用 Docker 和 Traefik v2 搭建轻量代码仓库(Gitea)](https://soulteary.com/2020/02/04/gitea-git-server-with-docker-and-traefik-v2.html)、[使用 Docker 和 Traefik v1 搭建轻量代码仓库(Gogs)](https://soulteary.com/2020/02/04/gogs-git-server-with-docker-and-traefik-v1.html) ,感兴趣可以进行了解,接下来我们基于第一款软件继续聊聊。 先给出一份参考配置: ```yaml version: '3.6' services: gitea: image: gitea/gitea:1.10.3 container_name: gitea.lab.com ports: - 127.0.0.1:22:22 environment: - USER_UID=1000 - USER_GID=1000 - APP_NAME=Private - RUN_MODE=prod - RUN_USER=git - SSH_DOMAIN=gitea.lab.com - OFFLINE_MODE=true - HTTP_PORT=3000 - ROOT_URL=https://gitea.lab.com - LFS_START_SERVER=false - DB_TYPE=mysql - DB_HOST=db - DB_NAME=gitea - DB_USER=gitea - DB_PASSWD=gitea - DB_CHARSET=utf8 - INSTALL_LOCK=false - DISABLE_GRAVATAR=true networks: - traefik - gitea restart: unless-stopped labels: - "traefik.enable=true" - "traefik.docker.network=traefik" - "traefik.http.routers.giteaweb.middlewares=https-redirect@file" - "traefik.http.routers.giteaweb.entrypoints=http" - "traefik.http.routers.giteaweb.rule=Host(`gitea.lab.com`)" - "traefik.http.routers.giteassl.middlewares=content-compress@file" - "traefik.http.routers.giteassl.entrypoints=https" - "traefik.http.routers.giteassl.tls=true" - "traefik.http.routers.giteassl.rule=Host(`gitea.lab.com`)" - "traefik.http.services.giteabackend.loadbalancer.server.scheme=http" - "traefik.http.services.giteabackend.loadbalancer.server.port=3000" volumes: # 标准 Linux 系统下使用 - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - ./repositories:/data/git/repositories - ./data:/data/gitea/ logging: driver: "json-file" options: max-size: "10m" extra_hosts: - "gitea.lab.com:127.0.0.1" healthcheck: test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:3000 || exit 1"] interval: 5s db: image: mysql:5.7.16 restart: always networks: - gitea expose: - 3306 command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci environment: MYSQL_ROOT_PASSWORD: gitea MYSQL_DATABASE: gitea MYSQL_USER: gitea MYSQL_PASSWORD: gitea TZ: Asia/Shanghai volumes: - ./mysql:/var/lib/mysql # 标准 Linux 系统下使用 - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro healthcheck: test: ["CMD-SHELL", "/etc/init.d/mysql status"] interval: 30s networks: gitea: internal: true traefik: external: true ``` 这里有几个小技巧: - 分离应用网络避免不同应用都暴露在相同网络,尤其是公网 - 使用 Traefik 进行服务按需暴露 - 将 SSH 等端口暴露在服务器本地,用于服务器内部其他服务调用,比如部署服务 - 对于非长时间使用的服务,也可以在使用的时候进行启动,非活跃时间进行关闭,这个小技巧后面的文章再展开聊吧 ## 最后 三年前我曾在 GitHub 上开了一个项目,想聊聊HomeLab:[soulteary/Home-Network-Note](https://github.com/soulteary/Home-Network-Note),三年过去了,HomeLab 建设的差不多了,但是过程中的不少文章却永远成为了草稿。今天大会结束了,或许是一个整理的好时机。 --EOF