您可以在不使用Docker的情况下使用kaniko在容器中构建Docker映像。 让我们了解如何在本地和Kubernetes集群中运行kaniko。

接下来是多本书
假设您决定在Kubernetes集群中构建Docker映像(嗯,您需要这样做)。 方便的是,让我们更清晰地看一个真实的例子。
我们还将讨论Docker-in-Docker及其替代产品kaniko,使用它们您可以在不使用Docker的情况下构建Docker映像。 最后,我们将学习如何在Kubernetes集群中配置映像组装。
Kubernetes的一般描述在“ Kubernetes in Action”(“ Kubernetes in Action”)一书中 。
真实的例子
在本机网络中,我们有许多私有Docker映像需要存储在某个地方。 因此,我们实施了私有Docker Hub 。 公共Docker Hub具有我们特别感兴趣的两个功能。
首先,我们想创建一个队列,该队列将异步收集Kubernetes中的Docker映像。 其次,实现将收集的图像发送到私有Docker注册表 。
通常,Docker CLI直接用于实现以下功能:
$ docker build ... $ docker push ...
但是在Kubernetes集群中,我们托管基于小型和基本Linux映像的容器,默认情况下不包含Docker。 如果现在我们想在容器中使用Docker(例如docker build...
),我们需要类似Docker-in-Docker的工具。
Docker-in-Docker有什么问题?
要在Docker中收集容器映像,我们需要在容器中运行一个Docker守护程序,即Docker-in-Docker。 Docker守护程序是一个虚拟化的环境,而Kubernetes中的容器是单独进行虚拟化的。 也就是说,如果要在容器中运行Docker守护程序,则需要使用嵌套虚拟化。 为此,请以特权模式运行容器-获得对主机系统的访问权限。 但这带来了安全性问题:例如,您必须使用不同的文件系统(主机和容器)或使用主机系统中的构建缓存。 这就是为什么我们不想接触Docker-in-Docker。
与kaniko相识
不仅仅是Docker-in-Docker ...还有另一个解决方案-kaniko 。 这是用Go编写的工具,它从没有Docker的Dockerfile收集容器映像。 然后将它们发送到指定的Docker注册表 。 建议配置kaniko-使用现成的执行程序映像 ,该映像可以作为Docker容器或Kubernetes中的容器运行。
请记住,kaniko仍在开发中,并不支持所有Dockerfile命令,例如COPY
--chownflag
。
iko子发射
如果要运行kaniko,则需要为kaniko容器指定几个参数。 首先将Dockerfile及其所有依赖项插入kaniko容器。 在本地(在Docker中),- -v <__>:<__>
选项用于此操作-v <__>:<__>
,并且Kubernetes具有volume。
将依赖项Dockerfile插入kaniko容器后,添加参数--context
,它将指示附加目录的路径(在容器内部)。 下一个参数是--dockerfile
。 它指示Dockerfile的路径(包括名称)。 另一个重要的参数是--destination
具有指向Docker注册表的完整URL(包括名称和图像标签)。
本地发布
香子子以几种方式开始。 例如,在使用Docker的本地计算机上(以免弄乱Kubernetes集群)。 使用以下命令运行kaniko:
$ docker run \ -v $(pwd):/workspace \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag>
如果在Docker注册表中启用了身份验证,则必须首先登录kaniko。 为此,请使用以下命令将具有Docker注册表凭据的本地Docker config.jsonfile
连接到kaniko容器:
$ docker run \ -v $(pwd):/workspace \ -v ~/.docker/config.json:/kaniko/.docker/config.json \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag>
在Kubernetes中启动
在示例中,我们想在Kubernetes集群中运行kaniko。 而且我们还需要诸如队列之类的东西来组装图像。 如果在组装映像或将映像发送到Docker注册表时发生故障,最好再次启动该过程。 为此,在Kubernetes中有一个工作 。 通过指定进程应重试的频率来配置backoffLimit
。
将具有依赖项的Dockerfile嵌入kaniko容器的最简单方法是使用PersistentVolumeClaim对象(在我们的示例中,它称为kaniko-workspace
)。 它将作为目录绑定到容器,并且所有数据应该已经在kaniko-workspace
。 假设在另一个容器中, kaniko-workspace
的/my-build
kaniko-workspace
中已经有一个依赖项的kaniko-workspace
。
不要忘记在AWS中使用PersistentVolumeClaim遇到麻烦。 如果您在AWS中创建PersistentVolumeClaim,则它将仅出现在AWS集群中的一个节点上,并且在那里仅可用。 (更新:实际上,当创建PVC时,将在集群的随机可用性区域中创建一个RDS卷。因此,该卷将对该区域中的所有计算机可用。Kubernetes本身使用该PVC控制在其下将在可用性区域中的节点上启动该卷。因此,如果您运行Job kaniko并且此任务在另一个节点上,则该任务将无法启动,因为PersistentVolumeClaim不可用。 我们希望Amazon Elastic File System不久将在Kubernetes上可用并且问题将消失。 (upd: 存储预配器支持Kubernetes中的EFS- 大约 。)
用于构建Docker映像的作业资源通常如下所示:
apiVersion: batch/v1 kind: Job metadata: name: build-image spec: template: spec: containers: - name: build-image image: gcr.io/kaniko-project/executor:latest args: - "--context=/workspace/my-build" - "--dockerfile=/workspace/my-build/Dockerfile" - "--destination=<repo-url-with-image-name>:<tag>" volumeMounts: - name: workspace mountPath: /workspace volumes: - name: workspace persistentVolumeClaim: claimName: kaniko-workspace restartPolicy: Never backoffLimit: 3
如果目标Docker注册表需要身份验证,请将带有凭据的config.json
文件传递给kaniko容器。 最简单的方法是将PersistentVolumeClaim连接到已经具有config.json
文件的容器。 在这里,PersistentVolumeClaim将不会作为目录挂载,而是作为文件/kaniko/.docker/config.json
在kaniko容器中的/kaniko/.docker/config.json路径中:
apiVersion: batch/v1 kind: Job metadata: name: build-image spec: template: spec: containers: - name: build-image image: gcr.io/kaniko-project/executor:latest args: - "--context=/workspace/my-build" - "--dockerfile=/workspace/my-build/Dockerfile" - "--destination=<repo-url-with-image-name>:<tag>" volumeMounts: - name: config-json mountPath: /kaniko/.docker/config.json subPath: config.json - name: workspace mountPath: /workspace volumes: - name: config-json persistentVolumeClaim: claimName: kaniko-credentials - name: workspace persistentVolumeClaim: claimName: kaniko-workspace restartPolicy: Never backoffLimit: 3
如果要检查kubectl
构建作业的状态,请使用kubectl
。 要通过stdout
过滤状态,请运行以下命令:
$ kubectl get job build-image -o go-template='{{(index .status.conditions 0).type}}'
总结
您从这篇文章中了解到Docker-in-Docker不适合在Kubernetes中构建Docker映像。 有了kaniko的想法-Docker-in-Docker的替代品,通过它可以组装不带Docker的Docker映像。 我们还学习了如何编写Job资源以在Kubernetes中收集Docker映像。 最后,他们看到了如何找出正在进行的任务的状态。