您当前的位置:首页 > 电脑百科 > 程序开发 > 容器

如何使用 Kaniko在 Kubernetes 集群中构建容器镜像

时间:2023-09-15 13:47:39  来源:微信公众号  作者:云原生运维圈

前言

如何构建 Kube.NETes 所需的容器镜像?我想你答案肯定是 Docker,没错,Docker 确实是首选。我们在使用 Jenkins 进行 CI/CD构建容器镜像的时候,做法通常是将 Jenkins 服务部署在物理机上,然后使用物理机的 docker build 命令来构建镜像。但是在 Jenkins on K8s 环境下,Jenkins Master 和 Jenkins Slave 都以 Pod 形式运行在 Kubernetes 集群的 Node 上,我们的构建环境都是 Pod ,没有 docker 命令。

众所周知 Kubernetes 在 V1.24.x 版本之后默认采用 contAInerd 作为容器运行时,不再支持 Docker,我们想用宿主机上的 /var/run/docker.sock 也用不了了。我们就需要另一种方式在 Kubernetes 集群中构建容器镜像,本文将介绍 Kaniko工具。

如何使用 Kaniko在 Kubernetes 集群中构建容器镜像

什么是Kaniko

如何使用 Kaniko在 Kubernetes 集群中构建容器镜像

Github地址:https://github.com/googleContainerTools/kaniko

Kaniko 是Google开源的一款在 Kubernetes 用来构建容器镜像的工具,它是一个从 Dockerfile 构建容器镜像的工具,就像 Docker 一样,但主要区别在于 Kaniko 可以在容器内运行,这意味着它可以在 Kubernetes 集群内运行。不需要特权模式,也不需要公开任何套接字。不需要在我们集群的节点上运行 Docker,因此我们使用哪个容器引擎来运行容器并不重要。重要的是 Kaniko 可以在容器内构建容器镜像,并在 Kubernetes 集群内自动构建,这就和宿主机上的 Docker 解绑了,更加安全可靠。特点如下:

  • docker in docker
  • 不依赖 Docker守护进程
  • 不需要 privilege 权限,安全构建
  • 仅需一条命令
  • 支持 Dockerfile 构建

现在,让我们一步一步来探索 Kaniko。

在Kubernetes中使用Kaniko

Kaniko 以容器的方式来运行的,同时需要三个参数: Dockerfile,上下文,以及远端镜像仓库的地址。

如何使用 Kaniko在 Kubernetes 集群中构建容器镜像

工作原理:

  • 读取并解析指定的Dockerfile
  • 提取基础镜像的文件系统(Dockerfile 中的 FROM 镜像)
  • 在独立的Dockerfile中分别运行每个命令
  • 每次运行后都会对用户空间文件系统的做快照
  • 每次运行时,将快照层附加到基础层并更新镜像元数据
  • 最后推送镜像

前提条件:

  • 需要一个运行的 kubernetes 集群
  • 需要创建一个 Kubernetes secret,其中包含推送到镜像仓库所需的身份验证信息
  • 需要准备好Dockerfile

创建Dockerfile

编写一个Dockerfile 文件,并创建configmap 在k8s中:

[root@localhost ~]# cat Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
 
[root@localhost ~]# kubectl create configmap kaniko-dockerfile --from-file=./Dockerfile
configmap/kaniko-dockerfile created

创建镜像仓库凭证的Secret

创建一个配置kaniko推送到 阿里云镜像仓库的凭证,找一台有安装docker的机子,登录仓库:

[root@localhost ~]# docker login --username=xxx registry.cn-shanghai.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
Login Succeeded

登入成功之后,会生成一个config.json的文件,使用该文件创建一个secret供kaniko容器使用。

  • centos环境中文件位置:/root/.docker/config.json
  • ubuntu环境中文件位置:/home/ubuntu/.docker/config.json
[root@localhost ~]# kubectl create secret generic kaniko-secret --from-file=/root/.docker/config.json
secret/kaniko-secret created

启动kaniko容器用来构建镜像

kaniko_build_image.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    args: ["--dockerfile=/workspace/Dockerfile",
            "--context=dir://workspace",
            "--destination=registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko-demo:1.0"] # 替换成自己的仓库地址
    volumeMounts:
      - name: kaniko-secret
        mountPath: /kaniko/.docker
      - name: dockerfile
        mountPath: /workspace
  volumes:
    - name: kaniko-secret
      secret:
        secretName: kaniko-secret
        items:
          - key: config.json
            path: config.json
    - name: dockerfile
      configMap:
        name: kaniko-dockerfile
  • args 部分:这部分就是上面所讲的,kaniko运行时需要三个参数: Dockerfile(--dockerfile),上下文(--context),远端镜像仓库(--destination)
  • secret 部分:推送至指定远端镜像仓库需要认证,所以以secret的方式挂载到/kaniko/.docker/这个目录下,文件名称为config.json

创建pod,查看状态,并看log是否正常完成。

[root@localhost ~]# kubectl Apply -f kaniko_build_image.yaml
pod/kaniko created
 
[root@localhost ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
kaniko                     1/1     Running   0          3s
 
[root@localhost ~]# kubectl logs -f kaniko
INFO[0000] Retrieving image manifest ubuntu            
INFO[0000] Retrieving image ubuntu from registry index.docker.io
INFO[0003] Built cross stage deps: map[]               
INFO[0003] Retrieving image manifest ubuntu            
INFO[0003] Returning cached image manifest             
INFO[0003] Executing 0 build triggers                  
INFO[0003] Building stage 'ubuntu' [idx: '0', base-idx: '-1']
INFO[0003] Skipping unpacking as no commands require it.
INFO[0003] ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
INFO[0003] Pushing image to registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko-demo:1.0
INFO[0004] Pushed registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko-demo@sha256:d1855cc00550f9048c88b507626e0f24acf4c22e02856e006b2b9fdb0b80e567

查看阿里云镜像仓库已经上传上去了:

如何使用 Kaniko在 Kubernetes 集群中构建容器镜像

用kaniko生成的镜像来测试下是否可用:

[root@localhost ~]# docker run -it --rm registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko-demo:1.0
Unable to find image 'registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko-demo:1.0' locally
1.0: Pulling from kubesre02/kaniko-demo
445a6a12be2b: Pull complete
Digest: sha256:49bb962115b70a15a99b87e48fda28a883758081e41aef14766833d3a1578069
Status: Downloaded newer image for registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko-demo:1.0
hello

出来hello即成功。

自定义一个Kaniko镜像

官方 kaniko 镜像是基于 scratch 构建的,里面没有 shell,想在 kaniko 原生镜像里在调用 shell 命令是很麻烦的。所以我们可以自定义我们自己私有的 Kaniko 镜像。kaniko 的关键文件其实是/kaniko目录下的二进制文件,官方推荐是用 gcr.io/kaniko-project/executor 镜像,我们就可以拷贝这个/kaniko目录下的 executor 到我们自己的私有镜像 Dockerfile:


FROM gcr.io/kaniko-project/executor:latest AS plugin
 
FROM ubuntu
 
ENV DOCKER_CONFIG /kaniko/.docker
 
COPY --from=plugin /kaniko/executor /usr/local/bin/kaniko
 
RUN mkdir -p /kaniko/.docker/
COPY config.json /kaniko/.docker/

上面 Dockerfile 构建了一个基于Ubuntu的Docker镜像:

(1) FROM gcr.io/kaniko-project/executor:latest AS plugin

  • 从名为gcr.io/kaniko-project/executor:latest的Docker镜像开始构建一个临时阶段,并将其命名为plugin。
  • 这个步骤是在一个已经包含了Kaniko工具的Docker镜像中构建一个中间容器。

(2) FROM ubuntu

接下来创建一个新的Docker镜像,基于官方的Ubuntu基础镜像。

(3) ENV DOCKER_CONFIG /kaniko/.docker

设置环境变量DOCKER_CONFIG为/kaniko/.docker,这是Kaniko工具使用的Docker配置目录。这是为了确保Kaniko可以找到必要的Docker配置信息。

(4) COPY --from=plugin /kaniko/executor /usr/local/bin/kaniko

从之前构建的plugin阶段的镜像中复制/kaniko/executor文件到新的镜像的/usr/local/bin/kaniko路径下。这将把Kaniko二进制文件复制到新的Ubuntu镜像中,以便后续在该镜像中使用。

(5) RUN mkdir -p /kaniko/.docker/

在新的镜像中创建/kaniko/.docker/目录,用于存放Docker配置文件。

(6) COPY config.json /kaniko/.docker/

将本地的config.json文件复制到新的镜像的/kaniko/.docker/目录下。这个config.json文件很可能包含了Docker仓库的认证信息和其他配置,以便Kaniko可以访问和推送Docker镜像。

最终,这个Docker镜像将包含了Ubuntu操作系统和Kaniko工具,并配置了Kaniko所需的Docker环境,使得可以在容器内使用Kaniko构建Docker镜像,并且有了 shell 环境,同时保持了一定程度的隔离性和安全性。构建并上传镜像:

[root@localhost ~]# docker build -t registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko:latest .
Sending build context to Docker daemon  212.1MB
Step 1/6 : FROM gcr.io/kaniko-project/executor:latest AS plugin
 ---> 03375da0f864
Step 2/6 : FROM ubuntu
 ---> aa786d622bb0
Step 3/6 : ENV DOCKER_CONFIG /kaniko/.docker
 ---> Using cache
 ---> f7cd726aa130
Step 4/6 : COPY --from=plugin /kaniko/executor /usr/local/bin/kaniko
 ---> Using cache
 ---> 8fcac536196f
Step 5/6 : RUN mkdir -p /kaniko/.docker/
 ---> Using cache
 ---> 1afce75446a3
Step 6/6 : COPY config.json /kaniko/.docker/
 ---> Using cache
 ---> 4a2873a75a7c
Successfully built 4a2873a75a7c
Successfully tagged registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko:latest
 
[root@localhost ~]# docker push registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko:latest
The push refers to repository [registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko]
0cb4fb37580b: Pushed
c9dbd3644e5a: Pushed
33a2214b827c: Pushed
c5077dd8160b: Pushed
948c7f86fd48: Pushed
403aab81b15b: Pushed
7bff100f35cb: Pushed
latest: digest: sha256:b5642885f1333a757625cbe36a9b1102aba27646f2572acab79861a74dba1050 size: 1783

Kaniko 更多参数

  • --context:指定构建上下文的路径。默认情况下,上下文是Dockerfile所在的目录。可简写 -c
  • --dockerfile:指定要使用的Dockerfile的路径。默认情况下,Kaniko会在上下文中查找名为Dockerfile的文件。可简写 -f
  • --destination:指定构建完成后的Docker镜像名称,可以包括标签。例如:myregistry/myimage:tag。可简写 -d
  • --cache:启用或禁用Kaniko的构建缓存功能。默认情况下,缓存是启用的。
  • --cache-ttl:设置构建缓存的生存时间。例如,--cache-ttl=10h表示缓存在构建完成后的10小时内有效。
  • --cache-repo:指定用于存储构建缓存的Docker仓库。默认情况下,缓存存储在本地。
  • --cache-dir:指定用于存储构建缓存的本地目录路径。
  • --skip-tls-verify:跳过TLS证书验证,用于不安全的Docker仓库。
  • --build-arg:传递构建参数给Dockerfile中的ARG指令。例如:--build-arg key=value。
  • --insecure:允许从不受信任的Registry拉取基础镜像。
  • --insecure-registry:允许连接到不受信任的Registry。
  • --verbosity:设置构建的详细程度,可以是panic、error、warning、info、debug或trace。
  • --digest-file:指定一个文件,用于存储构建生成的镜像的摘要(Digest)。
  • --oci-layout-path:指定OCI(Open Container Initiative)布局文件的路径,用于存储构建过程的元数据。

更多参考 官方:https://github.com/GoogleContainerTools/kaniko#additional-flags

Kaniko 构建缓存

--cache-copy-layers 此参数在执行命令之前 kaniko 会检查层的缓存,如果存在 kaniko将拉取并提取缓存层,而不是执行命令。如果没有 kaniko将执行命令,然后将新创建的层推送到缓存。用户可以通过设置 --cache=true 参数决定是否启用缓存,并且可以通过--cache-repo 标志提供用于存储缓存层的远程存储库,如果未提供此标志则将从提供的 –destination 推断缓存的repo。通常  --cache=true --cache-copy-layers=true 这两个参数同时使用。

CI/CD 中使用Kaniko

jenkins pipline 中使用:

基于 Kubernetes 的 动态生成 Jenkins Slave pod CI/CD,以下是一个简化的Pipeline示例:

// 镜像仓库地址
def registry = "registry.cn-shanghai.aliyuncs.com/kubesre02/demo"
 
pipeline {
    agent {
        kubernetes {
      yaml """
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
  - name: kaniko
    # 使用自定义的 kaniko 镜像
    image: registry.cn-shanghai.aliyuncs.com/kubesre02/kaniko:latest
    imagePullPolicy: Always
    command:
    - cat
    tty: true
"""
      }
    }
   
    stages {
        stage('拉代码') {
            steps {
                git clone ...
            }
        }
       
        stage('构建镜像') {
            steps {
                // 使用 kaniko 来构建镜像
                container(name: 'kaniko') {
                    Dockerfile 内容...
                    sh "kaniko -f Dockerfile -c ./ -d $registry:$BUILD_NUMBER --force"
                }
            }
        }
         
        stage('部署') {
            steps {
                部署...
            }
        }
         
    }
}

可以看出,Kaniko 是非常适合在Kubernetes平台上构建容器镜像的,而且易于集成到 DevOps Jenkins pipeline 里,好了,kaniko 就介绍到这里。



Tags:Kaniko   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
如何使用 Kaniko在 Kubernetes 集群中构建容器镜像
前言如何构建 Kubernetes 所需的容器镜像?我想你答案肯定是 Docker,没错,Docker 确实是首选。我们在使用 Jenkins 进行 CI/CD构建容器镜像的时候,做法通常是将 Jenkins 服务部署...【详细内容】
2023-09-15  Search: Kaniko  点击:(178)  评论:(0)  加入收藏
▌简易百科推荐
Docker 和传统虚拟机有什么区别?
我有一个程序员朋友,他每年情人节都要送女朋友一台服务器。他说:“谁不想在过节当天收到一台 4核8g 的服务器呢?”“万一对方不要,我还能留着自己用。” 给他一次过节的机会,他能...【详细内容】
2024-03-26  小白debug  微信公众号  Tags:Docker   点击:(11)  评论:(0)  加入收藏
掌握Docker网络驱动程序:优化容器通信
Docker为在容器内包装、交付和运行应用程序提供了一个强大的平台,从而彻底改变了容器化。网络是容器化的重要组成部分,Docker提供了各种网络驱动程序来支持容器之间的通信以...【详细内容】
2024-03-22    51CTO  Tags:Docker   点击:(10)  评论:(0)  加入收藏
Containerd容器管理
Nginx 指定容器名称 使用 ctr container create 命令创建容器后,容器并没有处于运行状态,其只是一个静态的容器。容器基本操作容器基本操作主要是 ctr image 命令,查看命令帮...【详细内容】
2024-03-20  云原生运维圈  微信公众号  Tags:容器   点击:(13)  评论:(0)  加入收藏
如何基于Docker镜像逆向生成Dockerfile
引言你是否曾经遇到过一个想要使用的 Docker 镜像,但却无法修改以适应你的特定需求?或者你可能发现了一个喜欢的 Docker 镜像,但想要了解它是如何构建的?在这两种情况下,将 Docke...【详细内容】
2024-03-07  云原生运维圈  微信公众号  Tags:Docker   点击:(22)  评论:(0)  加入收藏
Kubernetes是什么?主要特点是什么?
Kubernetes是什么?Kubernetes,也称为K8s,是一个开源的容器编排系统,由Google首次开发和维护。它允许容器化的应用程序在集群中自动部署、扩展和管理。Kubernetes提供了一种容器...【详细内容】
2024-02-01    简易百科  Tags:Kubernetes   点击:(153)  评论:(0)  加入收藏
我们一起聊聊容器资源自愈
在企业实际在使用容器这类资源的时候,除了技术本身,要考虑的其他问题也会很多。企业管理的容器有千千万万,出于效率考虑,对于有特殊需求的容器如何进行批量创建和管理呢,这就需要...【详细内容】
2024-01-30  匠心独运维妙维效  微信公众号  Tags:容器   点击:(47)  评论:(0)  加入收藏
Docker与Docker Compose入门:释放你应用部署的威力
今天给大家介绍一项强大而有趣的技能,那就是使用 Docker 和 Docker Compose 来释放你的应用部署的威力!无论你是一名开发人员还是系统管理员,掌握这个技能都将为你的工作带来巨...【详细内容】
2024-01-17  waynblog  微信公众号  Tags:Docker   点击:(65)  评论:(0)  加入收藏
Docker镜像与容器的交互及在容器内部执行代码的原理与实践
Docker作为一种流行的容器技术,已经成为现代应用程序开发和部署的重要工具。在Docker中,镜像是构建和运行容器的基础,而容器则是基于镜像创建的可执行实例。Docker镜像与容器的...【详细内容】
2024-01-10  编程技术汇  今日头条  Tags:Docker   点击:(76)  评论:(0)  加入收藏
如何在 Ubuntu 上安装 Docker
使用 Docker 意味着开启一个新的计算领域,但如果你刚刚开始使用 Docker,安装可能看起来是一项艰巨的任务。在 Ubuntu 上安装 Docker 有两种推荐的方法: 从 Ubuntu 的仓库安装 D...【详细内容】
2024-01-04    Linux中国  Tags:Docker   点击:(124)  评论:(0)  加入收藏
从Kubernetes的探针到DevOps
今天在群里又看有人问如何设置 Kubernetes 的探针,感觉要补充的话太多了,结合我们在一些 DevOps 项目中痛苦的体验,今天一劳永逸的全部说完,此外,也为大家展现一下为什么 DevOps...【详细内容】
2023-12-27  云云众生s  微信公众号  Tags:Kubernetes   点击:(114)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条