开源无处不在。它存在于您家中的电脑里,存在于您工作场所的电脑里,存在于互联网上,并且其中很多都是用 Git 管理的。 由于 Git 是去中心化的,许多人也认为它是一种众包备份解决方案。 理论是,每次有人将 Git 仓库克隆到他们的本地计算机时,他们都在创建项目源代码的备份。 如果 100 个人这样做,那么就会有 100 个仓库的备份副本。
从理论上讲,这可以缓解“灾难”,例如项目维护者 突然决定删除仓库 或者 莫名其妙地阻止所有流量,导致开发人员争先恐后地弄清楚谁拥有 master 分支的最新版本。 同样,整个代码托管站点过去也消失过。 当 Google Code、Microsoft CodePlex 或 Gitorious 处于鼎盛时期时,没有人预料到它们会关闭。
简而言之,如果说过去几十年互联网教会了我们什么,那就是依靠互联网神奇地创建备份并不是实现冗余的最可靠途径。
此外,对很多人来说,许多开源项目都托管在 GitHub 上,而 GitHub 并不是一个开放的平台,这是一个问题。 许多开发人员和用户更喜欢支持和交互像 GitLab 这样的堆栈,GitLab 有一个开源社区版。
使用 Ansible 进行 Git 操作
Git 的去中心化对于解决这个问题很有用。 使用纯 Git,您可以使用单个 push 命令轻松地推送到两个或多个仓库。 但是,为了在发生意外故障时发挥作用,您必须经常与 Git 仓库进行交互(特别是推送)。 此外,可能存在您想要备份的仓库,即使您可能永远不会自己推送或拉取代码。
但是使用 Ansible,您可以自动执行 Git 拉取项目 master 分支(或任何其他分支,就此而言)的操作,然后自动执行 Git 推送仓库到“异地”镜像的操作。 换句话说,您可以让您的计算机定期从 GitHub 拉取并推送到 GitLab 或 Gitolite 或 Gitea(或您喜欢的任何 Git 主机)。
Ansible 模块
如果没有其优秀的模块集合,Ansible 就不会有太多意义。 就像 Python 的第三方库或 Linux 的应用程序一样,Ansible 以其有用且出人意料的简单技巧而闻名的技术驱动程序是其他人已经为您解决的部分。 因为本文探讨的是如何有效且可靠地备份 Git 仓库,所以此处使用的模块是 Git 模块 和 ini_file 模块。
首先,创建一个名为 mirror.yaml 的文件作为 playbook。 您可以像通常使用 Ansible 一样开始,使用 name 和 task 条目。 此示例将 localhost 添加到 hosts 列表中,以便该 play 在控制器机器(您现在使用的计算机)上运行,但在现实生活中,您可能会在网络上的特定主机或主机组上运行它。
---
- 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 功能,因此该过程的一部分是手动的。 但是,在将 repo 推送到备用镜像之前,您必须拥有一个镜像,并且必须将该镜像配置为备用远程。
首先,您必须将备用远程添加到您的 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 条评论