在Jenkins代理节点旁边运行Docker-in-Docker容器

74次阅读
没有评论

问题描述

想要在使用Jenkins Kubernetes插件配置的Jenkins代理节点旁边运行一个Docker-in-Docker(dind)容器。他目前正在运行一个普通的代理节点,已经安装了所有的工具,包括Docker客户端,但没有运行Docker服务器/守护进程。他的想法是添加另一个容器,该容器运行Docker守护进程。这两个容器共享相同的工作目录,因此它们可以操作相同的数据。他之所以选择使用两个容器,是因为Docker守护进程需要特权访问,并且他希望尽可能限制它的权限。

他遇到的第一个问题是,当代理节点构建完成后,Jenkins并没有”杀死pod”,而只是结束了代理进程。现在有另一个容器在运行,pod仍然保持活动状态。他通过在代理pod停止时向另一个共享卷写入一个文件来解决了这个问题,然后dind pod读取该文件,并在文件存在时退出。

以下是他当前Pod配置的摘录:

apiVersion: "v1"
kind: "Pod"
spec:
  serviceAccountName: jenkins-agent
  containers:
  - image: "jenkins-jnlp-image"
    command: [ "/bin/sh", "-c" ]
    args:
    - |
      trap 'touch /usr/share/pod/done' EXIT
      /entrypoint.sh
    name: "jnlp"
    env:
    - name: DOCKER_HOST
      value: tcp://localhost:2375
    securityContext:
      privileged: false
    tty: true
    volumeMounts:
    - mountPath: "/home/jenkins/agent"
      name: "workspace-volume"
      readOnly: false
    - mountPath: /usr/share/pod
      name: tmp-pod
    workingDir: "/home/jenkins/agent"
  - image: "dind-image"
    name: "dind"
    command: [ "/bin/sh", "-c" ]
    args:
      - |
        dockerd-entrypoint.sh &
        while ! test -f /usr/share/pod/done; do
        echo 'Waiting for the jnlp to finish...'
        sleep 5
        done
        echo "Agent pod finished, exiting"
        exit 0
    securityContext:
      privileged: true
    tty: false
    volumeMounts:
    - mountPath: "/home/jenkins/agent"
      name: "workspace-volume"
      readOnly: false
    - mountPath: /usr/share/pod
      name: tmp-pod
    workingDir: "/home/jenkins/agent"
  volumes:
    - emptyDir:
        medium: ""
      name: "workspace-volume"
    - emptyDir: {}
      name: tmp-pod

用户想知道这种做法是否正确,是否有更好的方法来实现这个目标。另外,他使用的是官方Helm chart进行安装,他想知道是否有一种好的方法来添加另一个容器,而不需要覆盖整个pod模板。如果没有,他可能会创建一个PR来添加这个功能。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

你可以使用Docker-in-Docker代理来实现在Jenkins代理节点旁边运行Docker-in-Docker容器。这种方法使用两个容器,一个是带有Docker客户端的代理容器,另一个是带有Docker守护进程的容器。

以下是实现这种方法的步骤:
1. 在Jenkins Kubernetes插件的配置文件(JCasC)中,将Docker-in-Docker代理添加为额外的代理。
2. 在Jenkins的Helm chart中,添加一个容器来运行Docker守护进程。

下面是一个示例的Jenkins Kubernetes插件配置文件(JCasC)的部分内容:

jenkins:
  agents:
    kubernetes:
      containers:
        - name: jnlp
          image: jenkins/jnlp-agent-docker
          args: ["$(JENKINS_SECRET)", "$(JENKINS_NAME)"]
        - name: dind
          image: docker:dind
          securityContext:
            privileged: true

在上面的示例中,我们在Jenkins Kubernetes插件的配置文件中添加了一个名为dind的容器,使用docker:dind镜像运行Docker守护进程。同时,我们还保留了原来的jnlp容器,它是带有Docker客户端的代理容器。

请注意,这只是一个示例配置,你需要根据你的实际需求进行相应的修改。

方案2

如果你使用的是官方Helm chart进行安装,你可以通过修改Helm chart的values.yaml文件来添加另一个容器,而不需要覆盖整个pod模板。

以下是一个示例的values.yaml文件的部分内容:

agent:
  additionalAgents:
    - name: dind
      image: docker:dind
      securityContext:
        privileged: true

在上面的示例中,我们在additionalAgents中添加了一个名为dind的容器,使用docker:dind镜像运行Docker守护进程。这样就可以在Jenkins的Helm chart中添加另一个容器,而不需要覆盖整个pod模板。

请注意,这只是一个示例配置,你需要根据你的实际需求进行相应的修改。

总结

在Jenkins代理节点旁边运行Docker-in-Docker容器可以通过使用两个容器来实现,一个是带有Docker客户端的代理容器,另一个是带有Docker守护进程的容器。你可以根据你的实际需求选择适合你的方法,并根据需要进行相应的配置。

希望这些解决方案对你有帮助!如果你有任何其他问题,请随时提问。

正文完