问题描述
在Kubernetes集群上使用官方Helm Chart安装了Jenkins,并且该集群使用containerd
作为容器运行时。用户希望配置容器化的代理(agent),这些代理需要能够运行docker client命令,例如用于构建Docker镜像。但是在Kubernetes节点上并没有docker守护进程。用户想知道是否有一种选项,可以使用containerd客户端与节点上的containerd服务器进行交互,就像容器内的docker client与节点上运行的docker守护进程交互一样。此外,用户还在考虑以下两种选项来配置Jenkins代理:
- 在容器中运行docker守护进程(docker daemon in docker)。
- 使用sysbox容器,其中包含docker守护进程。
用户想了解最佳实践是什么。
解决方案
请注意以下操作可能涉及版本差异,请确保备份数据,并了解所使用的工具及其适用性。
使用Kaniko构建Docker镜像
一种绕过问题的方式是使用Kaniko,它可以在不需要docker守护进程或套接字的情况下处理容器的构建(以及推送)部分。
以下是在K8s的Jenkins Helm Chart的values.yaml
中定义代理(agent)的一部分示例:
agent:
namespace: jenkins
podTemplates:
builder: |
- name: 'builder'
label: 'builder'
serviceAccount: jenkins
nodeUsageMode: EXCLUSIVE
yamlMergeStrategy: "merge"
yaml: |-
apiVersion: v1
kind: Pod
metadata:
name: builder
namespace: jenkins
spec:
serviceAccountName: jenkins
containers:
- name: builder
image: builder:latest
imagePullPolicy: IfNotPresent
command: ["sleep"]
args: ["99d"]
tty: true
resources:
requests:
cpu: 1
memory: 1Gi
limits:
cpu: 2
memory: 2Gi
workingDir: /home/jenkins/agent
- name: kaniko
image: gcr.io/kaniko-project/executor:debug
imagePullPolicy: IfNotPresent
command: ["sleep"]
args: ["99d"]
tty: true
volumeMounts:
- name: docker-config
mountPath: /kaniko/.docker
workingDir: /home/jenkins/agent
env:
- name: DOCKER_REPOSITORY
value: "private_docker_repository"
volumes:
- name: docker-config
configMap:
name: docker-config
在上面的示例中,我们定义了两个容器:builder
和kaniko
。builder
容器负责执行一些基本操作,而kaniko
容器负责构建Docker镜像。我们通过将docker-config
挂载到kaniko
容器来处理Docker的授权,确保Kaniko能够访问所需的Docker仓库。
要在Jenkinsfile中使用这些代理,可以按以下方式操作:
pipeline {
agent {
label 'builder' // 指的是在Jenkins Helm Chart的values.yaml中定义的自定义K8s Pod Template
}
environment {
RELEASE_TAG = "1.0.0"
}
stages {
stage('Build') {
steps {
container('builder') {
echo "执行Maven构建或其他所需步骤"
}
container('kaniko') {
sh "/kaniko/executor --dockerfile `pwd`/dockerfile --context `pwd` --destination=${DOCKER_REPOSITORY}:${RELEASE_TAG}"
}
}
}
}
}
使用Docker守护进程(Docker Daemon in Docker)
另一种方法是在一个长时间运行的Pod中运行Docker守护进程,并在需要时启动具有docker client的Jenkins代理。这些代理可以与容器化的Docker守护进程进行交互。
用户可以使用类似以下脚本的方式来实现:
#!/bin/bash
# 启动Docker守护进程的容器
docker run -d --name docker_daemon_container docker:latest
# 启动具有docker client的Jenkins代理
docker run -d --name jenkins_agent --link docker_daemon_container -e DOCKER_HOST=tcp://docker_daemon_container:2375 jenkins/agent
上面的脚本中,我们首先启动了一个包含Docker守护进程的容器,并将其命名为docker_daemon_container
。然后,我们启动了一个Jenkins代理容器,并使用环境变量DOCKER_HOST
指定了与docker_daemon_container
容器的连接。
使用sysbox容器
用户还提到了使用sysbox容器,这是另一种在容器中运行Docker守护进程的方法。这是一个可行的解决方案,但具体的实现细节可能与Kubernetes版本、sysbox的版本以及其他因素有关。用户应该查看sysbox的文档以了解如何在Kubernetes中使用它来运行Jenkins代理。
无论选择哪种方式,都需要根据具体情况进行适当的配置和测试。并且请确保理解所使用的工具及其适用性,并对您的环境和需求进行适当的调整。
最佳实践选择
根据用户提供的信息以及回复,使用Kaniko构建Docker镜像是一种可靠的方法,无需在Kubernetes节点上运行docker守护进程,同时具有良好的控制和安全性。这在许多Kubernetes环境中是常见的做法,特别是在没有docker守护进程的情况下。这种方法可以避免直接在Kubernetes集群