前言

在 1.20 版本之后, Kubernetes 社区放弃了对 Docker 的支持, 但并不是说未来 Docker 将无法使用。本文主要是针对非 Docker 驱动的 Kubernetes 集群下,给出一个可行的 CICD 方案。如果你对非 Docker 环境下进行 CICD 也有需求,请留言,欢迎一起讨论方案。

阅读本文需要一些基础,这些包括:

  • 熟悉 KubeSphere Devops,能独立阅读文档进行自定义配置
  • 熟练使用流水线功能

不建议刚接触 DevOps 的人阅读本文。由于这种变更对用户影响较大,后面的版本中,希望能达成统一的实践,再集成到产品中,预期会支持 Containerd、cri-o、Kind 等。

测试环境描述

安装非 Docker 集群可以参考文档, https://kubesphere.com.cn/forum/d/3054-dockerkubernetes

执行如下命令, 查看 Kubernetes 版本:

kubectl version

Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:18:16Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:10:45Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

执行如下命令, 查看 containerd 版本:

containerd --version

containerd github.com/containerd/containerd v1.4.3 269548fa27e0089a8b8278fc4

去除 KubeSphere DevOps 对 Docker 的依赖

主要有两点:

  • Docker Volumes
  • docker.sock

下面主要针对这两个依赖进行配置。请参考文档 https://kubesphere.com.cn/docs/devops-user-guide/how-to-use/jenkins-setting/#%E4%BF%AE%E6%94%B9-configmap 对 CasC 进行修改。

如上图,以 Maven 为例,主要有三点需要修改:

  • 添加特权模式启动
  • 将 docker.sock 挂载,改为 /var/lib/containers
  • 将缓存路径改为主机绝对路径

最后别忘了重启 jenkins 或重新加载配置。

流水线改造

这里主要用于测试,因此没有将 Podman 安装到基础镜像中,而是在流水线中实时安装。生产环境,应该提前安装,以加快执行速度。

https://github.com/kubesphere/devops-java-sample 为例,流水线中主要需要增加如下部分

        stage ('install podman') {
            steps {
                container ('maven') {
                    sh '''
                    curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_7/devel:kubic:libcontainers:stable.repo
                    yum -y install podman
                    mv  /usr/bin/docker /usr/bin/docker_ce
                    ln -s /usr/bin/podman /usr/bin/docker
                    '''
                }
            }
        }

相关脚本,已经更新到 https://github.com/kubesphere/devops-java-sample/tree/podman 分支中。

测试 devops-java-sample 项目

使用 https://github.com/kubesphere/devops-java-sample 创建 SCM 流水线,Jenkinsfile 路径设置为 Jenkinsfile-online,并配置好相关的秘钥值。

最后执行时,在 podman 分支上可以看到如下日志:

在 DockerHub 上可以查看到推送的镜像:

在 KubeSphere 中可以看到项目部署成功:

总结

本文主要提供了一种在非 Docker 驱动的 Kubernetes 集群中,进行 CICD 镜像构建的思路,使用 Podman 替换 Docker 。选择 Podman 的原因是, 其使用方式更贴近 Docker,而 Buildah 需要用户修改镜像编译指令,因为 Buildah 使用的是 buildah bud。

扩展阅读 https://www.chenshaowen.com/blog/using-podman-to-build-images-under-kubernetes-and-jenkins.html


    不是用 Podman 来打包编译镜像么,为啥还需要 containerd ?

      Feynman

      这里只是描述基础环境是 containerd,以它为例进行的测试,还应该测试一下cri-o、isula等。

      shaowenchen 这块作用类似于docker image 本地缓存吧。可以说明一下,或提供个使用pvc的例子

      1 个月 后

      为什么要用特权模式呢?是有什么地方有限制吗?

      您好,我按照上述去构建流水线,其中Dockerfile中包含RUN语句,镜像就会构建失败,并提示:

      + docker build -f Dockerfile.future_k_line -t demo .
      STEP 1: FROM python:3.9.0
      STEP 2: ENV SOURCEDIR /opt
      --> Using cache 8b24536d469dc34fc80ce772af054dd5bc41c3cdb3114e62cfe3254b8bf49bcc
      --> 8b24536d469
      STEP 3: COPY . $SOURCEDIR/aa
      --> 4f6ed9e5258
      STEP 4: WORKDIR $SOURCEDIR/aa
      --> c1b5512bc5a
      STEP 5: RUN rm -rf /var/lib/apt/lists/*
      error running container: error creating container for [/bin/sh -c rm -rf /var/lib/apt/lists/*]: time="2021-04-01T14:11:36Z" level=error msg="systemd cgroup flag passed, but systemd support for managing cgroups is not available"
      : exit status 1
      time="2021-04-01T14:11:36Z" level=error msg="unable to write build event: \"write unixgram @77635->/run/systemd/journal/socket: sendmsg: no such file or directory\""
      Error: error building at STEP "RUN rm -rf /var/lib/apt/lists/*": error while running runtime: exit status 1
      script returned exit code 125

      目前在github上podman的issue中有类似问题,但并未提供解决方法,在google上也未能找到。

      参考报错信息,是由于镜像默认是systemd,无法去cgroup而导致,但没有什么头绪。

      • Wmm 回复了此帖

        您好,参照上面的文档,使用podman去构建镜像和推送后,最后一个步骤需要部署到k8s集群中,需要给crictl配置私有镜像仓库,请问您这边有具体的配置详情吗?
        我参照官方文档 https://github.com/containerd/containerd/blob/master/docs/cri/registry.md ,配置后重启containerd,通过crictl info能看到配置的镜像仓库和认证的账号密码,但去拉取镜像,就提示401 未认证,debug显示Auth为nil。
        若使用crictl –creds 指定账号密码,则可以拉取成功,是否是我漏配置了什么呢?

          leksas

          可能是需要挂载配置文件,运行环境和主机环境不是一个环境。直接用 Podman 不好使么?

          用podman构建镜像和推送镜像是ok的,但是k8s集群里面是用的crictl,它没有凭据去私有仓库中拉取镜像,目前已通过配置config.toml解决了。

          1 年 后

          [未知用户] 要在devops-jenkins对应的节点服务器上安装podman. 不用流水线实时命令就好了

          22 天 后

          有几个疑问:

          1. ln -s /usr/bin/podman /usr/bin/docker,这样在 sh ’docker ….'这样的命令中是会报docker: command not found 的错误的
          2. 安装podman是不是就不再像docker那样使用K8s node上的docker了?而是直接使用这个容器里的podman来工作。因为我看到没有像docker那样把K8s node上的contaierd的socket挂载进去

          [未知用户] 这里不是挂载类似docker的socket来使用K8s node上的containerd么?只是做存储用么?

          1 年 后
          2 个月 后

          leksas 您好,我自己打包的镜像也报这个错,有什么解决办法吗?