如何为 Gitlab 运行器启用通过 SSH 克隆?

Posted

技术标签:

【中文标题】如何为 Gitlab 运行器启用通过 SSH 克隆?【英文标题】:How do I enable cloning over SSH for a Gitlab runner? 【发布时间】:2017-01-05 14:42:30 【问题描述】:

我在我的 Windows Gitlab 运行器上通过 HTTP 克隆大型存储库时遇到了一些问题。我尝试了几种方法来进行浅克隆或禁用克隆压缩。还是没有运气。

通过 SSH 克隆相同的存储库作为一种临时解决方案非常有效,我想让它在我们的 Gitlab CI 流程中运行。

现在的问题是我不知道如何使用 SSH 作为 gitlab-multi-runner 的克隆方法。它似乎只是默认使用 HTTP,而我关于克隆的唯一选择是它是否会进行完整克隆或获取。

谁能解释我如何让克隆/获取通过 SSH 而不是 HTTP 在运行器上工作?

Gitlab 版本:GitLab 社区版 8.10.7

谢谢!

【问题讨论】:

此功能似乎确实存在一个问题 (233),但它似乎已在未实施的情况下关闭... 【参考方案1】:

作为 gitlab 的新手,我已经设法解决了这个问题,因为我还没有找到改变默认克隆过程的内置方法(尽管here is a recent comment about how it can be done)。

通过disabling the automatic cloning process,您可以通过在before_script 中简单地编写自己的克隆过程来有效地完全覆盖其行为。仅出于示例目的,以下显示了如何为 HTTP 克隆完成此操作,但可以适用于 ssh 克隆 (if you're trying to use HTTP cloning you should use the built-in cloning process and the config.toml):

    创建一个名为“gitlab-runner”的新用户并生成他们的用户身份验证令牌以供以后使用(或者在您的情况下,您将生成 ssh 密钥)。

    通过在您的项目或组设置中添加以下变量来禁用运行器的克隆过程:.../settings/ci_cd

    键:GIT_STRATEGY

    值:无

    before_script 中克隆您的存储库,例如:

before_script: ##清理工作目录 - BUILD_DIR=/home/gitlab-runner/builds/$RUNNER_TOKEN/0 - CLONE_DIR="$BUILD_DIR/$CI_PROJECT_PATH" - cd $BUILD_DIR -rm -rf $CLONE_DIR - mkdir -p $CLONE_DIR ## 每次都克隆项目(效率低下,如果已经存在,请考虑执行 fetch 代替) - git clone http://gitlab-runner:$GITLABRUNNER_USER_AUTH_TOKEN@server:8888/$CI_PROJECT_PATH.git $CLONE_DIR - cd $CLONE_DIR

注意:这里是我在第 2 步中也配置的相关变量,而不是在脚本中硬编码它们:

RUNNER_TOKEN:管理员“跑步者”菜单中列出了您尝试跑步的特定跑步者的“跑步者令牌”值。 GITLABRUNNER_USER_AUTH_TOKEN:这是您在步骤 1 中生成的身份验证令牌。

进一步阅读:

您可以通过发出Deploy Keys 来避免上述假帐户 方法。或者,如果访问任何项目的安全隐患是一个问题,Deploy Tokens 是具有更多安全控制的替代方案。作为比较,see the docs:

部署密钥可在不相关或不属于同一组的项目之间共享。部署令牌属于项目或组。

部署密钥是您需要在自己的计算机上生成的 SSH 密钥。部署令牌由您的 GitLab 实例生成,并且仅提供给用户一次(在创建时)。

只要注册并启用部署密钥,它就有效。部署令牌可能具有时间敏感性,因为您可以通过为其设置过期日期来控制其有效性。

您无法使用部署密钥登录注册表,或对其执行读/写操作,但使用部署令牌可以做到这一点。 您需要一个 SSH 密钥对才能使用部署密钥,但不需要部署令牌。

【讨论】:

【参考方案2】:

根据:

https://docs.gitlab.com/ee/ci/ssh_keys/README.html

你需要:

    使用 ssh-keygen 创建新的 SSH 密钥对 将私钥作为秘密变量添加到项目中 在作业期间运行 ssh-agent 以加载私钥。

示例 gitlab_ci.yml:

before_script:
  # Install ssh-agent if not already installed, it is required by Docker.
  # (change apt-get to yum if you use a CentOS-based image)
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

  # Run ssh-agent (inside the build environment)
  - eval $(ssh-agent -s)

  # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
  - ssh-add <(echo "$SSH_PRIVATE_KEY")

  # For Docker builds disable host key checking. Be aware that by adding that
  # you are suspectible to man-in-the-middle attacks.
  # WARNING: Use this only with the Docker executor, if you use it with shell
  # you will overwrite your user's SSH config.
  - mkdir -p ~/.ssh
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
  # In order to properly check the server's host key, assuming you created the
  # SSH_SERVER_HOSTKEYS variable previously, uncomment the following two lines
  # instead.
  # - mkdir -p ~/.ssh
  # - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'

【讨论】:

这并不能解决gitlab-runner 仍然试图通过 https 克隆 repo 的问题,即使配置了密钥也是如此。请参阅@ecoe answer 了解如何做到这一点。【参考方案3】:

我有一个类似的问题,需要通过 ssh 使用克隆:在非常旧的客户 linux 操作系统中使用 virtualbox 执行程序。我可以通过一些小的配置更改来解决它:

    创建一个deploy key 以访问该项目。

    强制执行克隆的用户帐户使用部署密钥。在我的virtualbox 案例中,我修改了在/etc/gitlab-runnner/config.toml 中为virtualbox 配置的用户的ssh 配置。

~/.ssh/config

Host gitlab.example.com
  Preferredauthentications publickey
  IdentityFile ~/.ssh/deploy-key
    将运行器配置为通过/etc/config.toml 中的ssh 执行克隆。

/etc/config.toml

[[runners]]

  # [...]

  environment = ["GIT_STRATEGY=none"]
  pre_build_script = '''
    # Fetching using ssh (via pre_build_script in config.toml)
    if [ -d "$CI_PROJECT_DIR" ]; then rm -rf "$CI_PROJECT_DIR"; fi
    mkdir -p "$CI_PROJECT_DIR"
    cd "$CI_PROJECT_DIR"
    git init
    git remote add origin "ssh://git@$CI_SERVER_HOST/$CI_PROJECT_PATH.git"
    git fetch origin "$CI_COMMIT_SHA"
    git reset --hard FETCH_HEAD
  '''

  # [...]

以下是对 config.toml 的新增内容的细分:

GIT_STRATEGY=none 环境变量禁用运行器的内部 git 克隆机制。 (参见 CI/CD 参考的Git Strategy 部分) pre_build_script 使用predefined CI/CD environment variables 执行实际克隆。就我而言,这是一个 bash 脚本,用于执行类似于 GIT_STRATEGY=fetch 可能执行的操作。 如果pre_build_script 是多行,则运行器的输出将只显示第一行。将注释作为第一行有助于增加运行器输出的清晰度。 pre_clone_script 此处未使用。它已被禁用,因为环境设置了 GIT_STRATEGY=none

【讨论】:

这很酷,几个月前我实际上一直在寻找这个解决方案,在你真正写之前:) 谢谢,@aledpardo!希望它对那里的一些人有用。 :)【参考方案4】:

这对我有用,将其添加到您的 .gitlab-ci.yml 中

script:
  - git remote set-url --push origin git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git

这将在 .git/config 文件中设置您的推送 url,并且运行程序将在将代码推送回您的 git 存储库而不是使用 ci-token 的 url 时使用它。

【讨论】:

【参考方案5】:

我在使用非常旧版本的 git 克隆 https 时遇到问题。我最终制作了一个模板,如果需要,它会克隆 repo,否则会获取最新的更改并将 repo 清理到裸露的干净状态。

您需要为所有涉及的 repos 设置部署密钥,包括同一 gitlab 服务器上的子模块。根据 Using SSH keys 文档设置 SSH 密钥,并将其添加为 Deploy Key 用于所有需要克隆的存储库。

这是可以随时扩展的模板:

.ssh_cloning:
    variables:
        GIT_STRATEGY: none
    before_script:
        # set up ssh keys for cloning
        - eval $(ssh-agent -s)
        - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
        # clean the working directory
        - |
            if [ ! -d "$CI_PROJECT_DIR/.git" ]
            then
                mkdir -p "$CI_PROJECT_DIR"
                cd "$CI_PROJECT_DIR"
                git init
                git remote add origin "ssh://git@$CI_SERVER_HOST/$CI_PROJECT_PATH.git"
            fi
        - cd "$CI_PROJECT_DIR"
        # clone the project
        - git fetch origin
        - git checkout "$CI_COMMIT_SHA"
        - git reset --hard HEAD
        - git submodule update --init --recursive
        # clean up files from the last build
        - git clean -ffdx

您可以将它包含在其他工作中,类似这样(未经测试):

include:
    - 'ssh_cloning.yml'

stages:
    - build

do_git_stuff:
    stage: build
    extends: .ssh_cloning
    script:
        - git status

【讨论】:

以上是关于如何为 Gitlab 运行器启用通过 SSH 克隆?的主要内容,如果未能解决你的问题,请参考以下文章

具有私有 IP 的 AWS Gitlab Autoscale 运行器,不想启用公共 IP

来自共享 Gitlab 运行器的 SSH 停止工作

如何为作业禁用 GitLab 构建缓存

GitLab runner 无法通过 http 克隆存储库

Docker-in-Docker 与 Gitlab 共享运行器,用于构建和推送 docker 镜像到注册表

如何为同一主机的多个 gitlab 帐户使用多个 ssh 密钥[重复]