【问题标题】:Best way to clone a git repository when authenticating via ssh key forwarding通过 ssh 密钥转发进行身份验证时克隆 git 存储库的最佳方法
【发布时间】:2016-04-16 20:49:50
【问题描述】:

先决条件:

  • 主机和 git 身份验证通过 ssh 密钥进行
  • ssh 密钥转发已启用
  • 我们团队的每个用户都使用一个专用的用户帐户 - 无法通过无头用户帐户登录

现在我们要从 git 存储库部署应用程序。这应该很简单,但事实并非如此。

- name: Clone app repo
  git:
    repo: githost:org/repo.git
    dest: /some/location
    version: HEAD
    force: yes
    ssh_opts: -o StrictHostKeyChecking=no
  notify:
    - Restart app

githost 是我们的 .ssh/config 中的一个条目

上述任务有效。但是存储库(当然)被克隆为执行剧本的用户。我们需要的是:

  • 所有文件都应该归无头用户所有,我们称他为zaphod
  • 只允许zaphod 读取文件。我们说的是 0600/0700 权限。

以下任务将无法执行,因为使用become 我们将丢失转发的 ssh 密钥,因此 git 身份验证将失败:

- name: Clone app repo
  git:
    repo: githost:org/repo.git
    dest: /some/location
    version: HEAD
    force: yes
    ssh_opts: -o StrictHostKeyChecking=no
  notify:
    - Restart app
  become: yes
  become_user: zaphod

以下变体将首先调用一个处理程序,该处理程序在(重新)启动应用程序之前更改结帐的所有权:

- name: Clone app repo
  git:
    repo: githost:org/repo.git
    dest: /some/location
    version: HEAD
    force: yes
    ssh_opts: -o StrictHostKeyChecking=no
  notify:
    - Fix ownership
    - Restart app

这工作一次。但是如果你第二次运行 playbook,git 任务会失败,因为运行 play 的用户没有修改克隆的权限。

我们有一个非常丑陋的解决方案:

  • 克隆到 /tmp/foo
  • 修复 /tmp/foo 的所有权
  • rm -rf /some/location
  • mv /tmp/foo /some/location
  • 终于(重新)启动应用程序

这样做的问题是:

  • 每次执行 playbook 时都会触发重启
  • Ansible 摘要显示了 5 个已更改的任务,即使没有发生任何事情 - 除了一开始不需要的重新启动

我在这里有点挑剔,但我只想在某些事情真的改变时改变状态,所以在一个完美的世界中,即使 git 任务也不会改变状态。为此,我没有看到解决方案。因为我们要求克隆的文件只能由 zaphod 访问 - 但 zaphod 本人无法克隆 repo。所以必须有一些操纵是某种形式导致变化。

有什么建议可以以干净的方式改进吗?我不想再添加 20 个任务,包括临时副本、临时更改权限、手动比较文件等等......

当然,自定义编写的模块可以处理所有这些 - 但我更感兴趣的是不需要 2 天的开发和实战测试的东西。 ;-)

【问题讨论】:

  • 你不能创建一个group 并将所有需要操作同一个 repo 的人添加到同一个组中。您也不需要“另外 20 项任务”,您可能还可以再完成一项(chmod repo) - 请参阅此处了解更多详细信息serverfault.com/questions/26954/…

标签: git ansible ansible-playbook git-clone


【解决方案1】:

您似乎正在尝试通过简单地克隆包含您需要的东西的存储库来部署应用程序/网页,而不是需要能够将任何更改从该服务器推回存储库。

如果是这种情况,那么您可以通过本地任务将git archive 回购到压缩包或其他东西中,然后使用unarchive 将生成的存档复制到目标计算机并解压缩。 unarchive 将允许您设置权限和所有权。

所以你的剧本可能看起来像:

- name: locally clone repo
  git:
    repo: githost:org/repo.git
    dest: /some/tmp/location
    version: HEAD
    force: yes
  delegate_to: localhost
  changed_when: false #

- name: archive app repo
  command: git archive --format zip --output /path/to/archive master
    chdir: /some/tmp/location
  delegate_to: localhost
  changed_when: false

- name: unarchive app repo
  unarchive:
    src: /path/to/archive
    dest: /some/location
    owner: zaphod
    mode: 0700
    creates: /some/location
  notify:
    - Restart app

【讨论】:

  • 虽然这在紧要关头可以很好地工作,但即使 git repo 没有更改,它也会强制下载和上传,对吧?
【解决方案2】:

基于@ydaetskcoR 的回答,以下版本也可以使用:

- name: locally clone repo
  git:
    repo: githost:org/repo.git
    dest: /some/tmp/location
    version: HEAD
    force: yes
  delegate_to: localhost

- name: archive app repo
  archive: 
    path: /some/tmp/location
    dest: /some/tmp/archive.tgz
  delegate_to: localhost

- name: unarchive app repo
  unarchive:
    src: /some/tmp/archive.tgz
    dest: /some/remote/location
    owner: zaphod
    mode: 0700
  notify:
    - Restart app

【讨论】:

  • Git 比archive 更了解自己。 git archive 可以使用/不使用忽略的文件,并使用显式引用进行导出。
猜你喜欢
  • 1970-01-01
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-19
  • 2017-02-21
  • 1970-01-01
  • 2022-10-17
相关资源
最近更新 更多