开源无处不在。它在您家中的电脑里,在您工作场所的电脑里,在互联网上,并且其中很多都是通过 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 一样开始,使用 name 和 task 条目。此示例将 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'
5 条评论