Jenkins kubernetes agent checkout scm не использует настроенный ключ

Я получаю ошибки при использовании checkout scm в конвейере из-за двух проблем.

Настройка:

  • Частный кластер Kubernetes - 1 контроллер, 2 рабочих на виртуальных машинах Ubuntu 20.04
  • Дженкинс работает в модулях Kubernetes
  • Плагин Kubernetes для создания экземпляров агентов сборки Jenkins
  • Частный сервер GIT на контроллере ВМ вне кластера, доступ по ssh
  • закрытый ключ ssh для GIT, настроенный в учетных данных Jenkins
  • Проект Jenkins 'hello' настроен на использование этого закрытого GIT и связанного с ним ключа ssh
  • Jenkinsfile (конвейер) для сборки

Я хочу использовать простой checkout scm шаг в файле Jenkins.

Проблема 1 Сборка завершается неудачно с Host key verification failed., потому что модуль агента Kubernetes не имеет сервера GIT в своем known_hosts.

Проблема 2. Если я принудительно ввожу сертификат контроллера в known_hosts (например, жестко закодирую эхо в Jenkinsfile, а затем добавлю шаг git ls-remote), он завершится неудачно с Permission denied, потому что настроенный закрытый ключ ssh отсутствует. в модуле агента.

Я нашел обходной путь для обоих:

podTemplate(
...
{
  node(POD_LABEL) {
    stage('Checkout') {
      withCredentials([sshUserPrivateKey(
          credentialsId: 'private_git', 
          keyFileVariable: 'PRIVATE_GIT_KEY',
          passphraseVariable: '',
          usernameVariable: ''
      )]) {
        sh 'mkdir -p ~/.ssh'
        sh 'cp $PRIVATE_GIT_KEY ~/.ssh/id_rsa'
        sh '/usr/bin/ssh-keyscan -t rsa kube-master.cluster.dev >> ~/.ssh/known_hosts'
        sh 'chown -R $USER:$USER ~/.ssh'
        sh '/usr/bin/git ls-remote ssh://[email protected]:/git/hello.git'
      }
      checkout scm
    }
  ...
  }
}

Что мне нужно, чтобы избежать этого обходного пути и просто использовать checkout scm так, как задумано?

Пример журнала отказов:

Running on build-pod-xdh86-53wh7 in /home/jenkins/agent/workspace/hello
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Checkout)
[Pipeline] checkout
Selected Git installation does not exist. Using Default
The recommended git tool is: NONE
using credential private_git
Cloning the remote Git repository
ERROR: Error cloning remote repo 'origin'
hudson.plugins.git.GitException: Command "git fetch --tags --force --progress -- ssh://[email protected]/git/hello.git +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout: 
stderr: Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

person jws    schedule 03.05.2021    source источник


Ответы (1)


Разумное решение - поместить ключи в секреты Kubernetes и смонтировать секреты в модуле Jenkins.

На вашем контроллере:

  1. Сделайте пустую учетную запись пользователя и вставьте в нее оболочку

  2. Сделайте секрет (типичный ssh-keygen)

  3. Добавить id_rsa.pub на сервер git authorized_users

  4. Один раз подключитесь к git ssh для создания known_hosts, например

    git ls-remote ssh://[email protected]:/git/hello.git

  5. Скопируйте ~/.ssh/id_rsa закрытый ключ пользователя и ~/.ssh/known_hosts файлы в место, где kubectl может их прочитать, например /tmp/scratchuser

  6. Выйдите из временной учетной записи пользователя и удалите ее.

  7. sudo chown -R $USER:$USER /tmp/scratchuser/

  8. Добавьте id_rsa и known_hosts в Kubernetes с помощью такой команды, как

    kubectl create secret -n jenkins generic private-git --from-file=id_rsa=/tmp/scratchuser/.ssh/id_rsa --from-file=known_hosts=/tmp/scratchuser/.ssh/known_hosts

  9. Разверните Jenkins с yaml, содержащим некоторые конкретные вещи:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: jenkins
      namespace: jenkins
    spec:
      ... your other options such as replicas, selector, etc ...
      template:
        metadata: ... your metadata section ...
        spec:
          securityContext:
            fsGroup: 1000
          containers:
          - name: jenkins
            image: jenkins/jenkins:lts
            ports:
              ... standard jenkins ports ...
            volumeMounts:
              - name: jenkins-vol
                mountPath: /var/jenkins_home
              - name: private-git-vol
                mountPath: "/var/jenkins_home/.ssh"
                readOnly: true
          volumes:
            - name: jenkins-vol
              ... your persistent volume details ...
            - name: private-git-vol
              secret:
                secretName: private-git
                defaultMode: 0600
          ... your other options such as dnsPolicy, etc. ...
    

Ключевыми моментами в приведенном выше yaml являются fsGroup, чтобы пользователь pod jenkins мог получить доступ к смонтированному секретному тому, private-git-vol монтирование для размещения секретных файлов по пути .ssh и определение private-git-vol, которое относится к секрету, созданному с помощью kubectl выше.

Еще одна подсказка. Для Jenkinsfile, который создает экземпляры модулей агентов сборки, см. Декларативный конвейер. Возможно, вам придется отказаться от podTemplate() и полностью указать модуль агента:

pipeline {
  agent {
    kubernetes {
      yamlFile 'KubernetesPod.yaml'
    }
  ... your build steps ...
}

а в KubernetesPod.yaml включите контейнер jnlp (jenkins/inbound-agent изображение) с вашим собственным yaml вместо подключаемого модуля Kubernetes. Это позволит вам использовать fsGroup в агенте сборки, как описано выше для мастера Jenkins.

person jws    schedule 05.05.2021