如何使用 Ansible 共同托管 GitHub 和 GitLab

通过使用 Ansible 镜像 Git 仓库来保护您对重要项目的访问。
143 位读者喜欢这篇文章。
hands programming

WOCinTech Chat。由 Opensource.com 修改。CC BY-SA 4.0

开源无处不在。它在您家里的电脑中,它在您工作场所的电脑中,它在互联网上,并且其中很多内容都是使用 Git 进行管理的。由于 Git 是去中心化的,许多人也将其视为一种众包备份解决方案。其理论是,每次有人将 Git 仓库克隆到他们的本地计算机时,他们都在创建项目源代码的备份。如果 100 个人这样做,那么就有了 100 个仓库的备份副本。

理论上,这可以缓解“灾难”,例如项目维护者 突然决定删除仓库莫名其妙地阻止所有流量,导致开发人员争先恐后地找出谁拥有 master 分支的最新版本。同样,整个代码托管站点过去也消失了。当 Google Code、Microsoft CodePlex 或 Gitorious 处于鼎盛时期时,没有人预料到它们的关闭。

简而言之,如果互联网在过去几十年里教会了我们什么,那就是依赖互联网来神奇地创建备份并不是实现冗余最可靠的途径。

此外,对于很多人来说,许多开源项目都托管在 GitHub 上,这不是一个开放平台,这是一个问题。许多开发人员和用户更愿意支持和使用像 GitLab 这样的堆栈,它有一个开源社区版。

使用 Ansible 进行 Git 操作

Git 的去中心化对于解决这个问题非常有用。使用纯 Git,您可以使用单个 push 命令轻松推送到两个或多个仓库。但是,为了使其对意外故障有用,您必须经常与 Git 仓库进行交互(特别是推送)。此外,可能存在您想要备份的仓库,即使您自己可能永远不会推送或拉取代码。

但是使用 Ansible,您可以自动化 Git 拉取项目 master 分支(或任何其他分支)的操作,然后自动化将仓库推送到“异地”镜像的操作。换句话说,您可以让您的计算机定期从 GitHub 拉取并推送到 GitLab 或 Gitolite 或 Gitea(或您喜欢的任何 Git 主机)。

Ansible 模块

如果没有其出色的模块集合,Ansible 就不会有太多内容。就像 Python 的第三方库或 Linux 的应用程序一样,Ansible 以其有用且出奇简单的技巧而闻名的技术驱动是其他人已经为您解决的部分。因为本文正在探讨如何有效且可靠地备份 Git 仓库,所以这里使用的模块是 Git 模块ini_file 模块。

首先,创建一个名为 mirror.yaml 的文件作为 playbook。您可以像通常使用 Ansible 一样开始,使用 nametask 条目。此示例将 localhost 添加到 hosts 列表,以便 playbook 在控制器机器(您现在坐着的计算机)上运行,但在现实生活中,您可能会在网络上的特定主机或主机组上运行它。

---
- name: "Mirror a Git repo with Ansible"
  hosts: localhost
  tasks:

Git pull 和 clone

如果您要进行备份,那么您需要最新代码的副本。使用 Git 仓库实现此目的的显而易见的方法是执行 git pull。但是,pull 假设克隆已经存在,而编写良好的 Ansible play(Ansible 脚本)假设尽可能少。最好先告诉 Ansible clone 一个仓库。

将您的第一个任务添加到 playbook

---
- name: "Mirror a Git repo with Ansible"
  hosts: localhost 
  vars:
    git_dir: /tmp/soso.git
  tasks:

  - name: "Clone the git repo"
    git:
       repo: 'https://github.com/ozkl/soso.git'
       dest: '{{ git_dir }}'
       clone: yes
       update: yes

此示例使用开源的类 Unix 操作系统 soso 作为我要镜像的仓库。这是一个完全任意的选择,绝不意味着对该仓库的未来缺乏信心。它还使用一个变量来引用目标文件夹 /tmp/soso.git,这现在很方便,如果您想将其扩展为通用镜像脚本,以后也会很有用。在现实生活中,您可能会在您的工作机器上使用比 /tmp 更永久的位置,例如 /home/gitmirrors/soso.git/opt/gitmirrors/soso.git

运行您的 playbook

$ ansible-playbook mirror.yaml

首次运行 playbook 时,Ansible 会正确检测到 Git 仓库在本地尚不存在,因此它会克隆它。

PLAY [Ansible Git mirror] ********

TASK [Gathering Facts] ***********
ok: [localhost]

TASK [Clone git repo] ************
changed: [localhost]

PLAY RECAP ***********************
localhost: ok=2 changed=1 failed=0 [...]

如果您再次运行 playbook,Ansible 会正确检测到自上次运行以来没有任何更改,并报告未执行任何操作

localhost: ok=2 changed=0 failed=0 [...]

接下来,必须指示 Ansible 将仓库推送到另一个 Git 服务器。

Git push

Ansible 中的 Git 模块不提供 push 功能,因此该过程的这一部分是手动的。但是,在您可以将仓库推送到备用镜像之前,您必须拥有一个镜像,并且必须将该镜像配置为备用远程仓库。

首先,您必须将备用远程仓库添加到您的 Git 配置中。由于 Git 配置文件是 INI 样式的配置,因此您可以使用 ini_file Ansible 模块轻松附加所需的信息。将其添加到您的 playbook

  - name: "Add alternate remote"
    ini_file: dest={{ git_dir }}/.git/config section='remote \"mirrored\"' option=url value='git@gitlab.com:example/soso-mirror.git' 
    tags: configuration

为了使其工作,您必须在您的目标服务器上有一个空仓库(在本例中为 GitLab.com)。如果您需要在您的 playbook 中创建目标仓库,您可以通过遵循 Steve Ovens 的优秀文章“如何使用 Ansible 通过 SSH 设置 Git 服务器”来做到这一点。

最后,直接使用 Git 将 HEAD 推送到您的备用远程仓库

  - name: "Push the repo to alternate remote"
    shell: 'git --verbose --git-dir={{ git_dir }}/.git push mirrored HEAD'

像往常一样运行 playbook,然后自动化该过程,这样您就永远不必再次直接运行它。您可以使用变量和特定的 Git 命令来调整脚本以满足您的需求,但是通过定期拉取和推送,您可以确保在一个服务器上运行的重要项目安全地镜像到另一个服务器上。

这是完整的 playbook 以供参考

---
- name: "Mirror a Git repository with Ansible"
  hosts: localhost
  vars:
    git_dir: /tmp/soso.git

  tasks:

  - name: "Clone the Git repo"
    git:
       repo: 'https://github.com/ozkl/soso.git'
       dest: '{{ git_dir }}'
       clone: yes
       update: yes

  - name: "Add alternate remote"
    ini_file: dest={{ git_dir }}/.git/config section='remote \"mirrored\"' option=url value='git@gitlab.com:example/soso-mirror.git' 
    tags: configuration
  
  - name: "Push the repo to alternate remote"
    shell: 'git --verbose --git-dir={{ git_dir }}/.git push mirrored HEAD'
接下来阅读什么
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,而且经常同时进行。

5 条评论

Gitlab 允许用户通过设置推送在用户级别自动镜像您的仓库。Ansible 在这里有点过度。

但这是否适用于允许我保留托管在 GitHub 上且我不拥有的仓库的镜像副本?这确实是我认为这对我的工作流程有帮助的用例。

回复 ,作者:ritzk (未验证)

Gitlab 只是一个托管选项。正如我在文章中解释的那样,这适用于任何 Git 源和目标(正如 Jason Baker 指出的那样,它也适用于您不拥有的仓库)。

再说一遍,所有这些都可以使用 Git hooks 或任何数量的工具来完成,所以这实际上是使用 Ansible 的练习,而不是为了突出 Ansible 的某些特殊功能。

回复 ,作者:ritzk (未验证)

Creative Commons 许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.