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

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

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

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

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

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

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

使用 Ansible 进行 Git 操作

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

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

Ansible 模块

如果没有 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 拉取和克隆

如果您要进行备份,那么您需要最新代码的副本。使用 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 推送

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 在这里有点 overkill 了。

但这是否适用于让我保留我在 GitHub 上托管的我不拥有的仓库的镜像副本?这真的是我看到这种方法在我的工作流程中有所帮助的用例。

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

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

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

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

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.