kaniko构建镜像的方式

木木10个月前技术文章253

docker构建镜像

用docker来构建容器镜像也是常用的方法,在具备构建容器镜像所需的两个要素(Dockerfile & 上下文)的前提下,用下述命令就能构建一个容器镜像出来

```Plain Text docker build -t yourregistry/yourrepository:tag .

然后用 `docker push` 将镜像推送到镜像仓库

Plain Text docker push yourregistry/yourrepository:tag

现在DevOps 的CI/CD环境大多数都会运行在容器内,镜像的构成也是在容器内完成的。这时候,通常用以下两种方式来完成容器内构建镜像的工作:

## 挂载宿主机的socket文件到容器内部

Plain Text docker run -it -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/kaniko:/tmp/kaniko docker

然后在容器内部用 `docker build` 构建镜像

由于docker依赖于 `docker daemon` 进程, `docker daemon` 进程是一个 `Unixsocket` 连接,且 `/var/run/docker.sock` 文件是root权限

Plain Text $ ls -ltr /var/run/docker.sock lrwxr-xr-x 1 root  daemon 69 Nov 26 15:13 /var/run/docker.sock

说明只有root权限才能访问 `docker daemon` 进程,在 `docker daemon` 无法暴露或者用户没有权限获取 `docker daemon` 进程的前提下,用 `docker build` 来构建镜像就变的非常困难了。

可能我们会想,docker build镜像无非就是需要docker命令能运行成功,只要在容器里面安装一个docker不就成功了吗?这也就是下面讲的第二种方法。

## dind(docker-in-docker)

这种方式不需要挂载宿主机的socket文件,但是需要以 **--privileged** 权限来以dind镜像创建一个容器

Plain Text $ docker run --rm -it --privileged docker:18.06-dind

然后在容器里面构建容器镜像并推送至远端仓库。

dind能够满足构建容器镜像的需求,但是从上面的命令看,有一个参数:**--privileged** 。意味这这个容器具有一些特权,他可能会看到宿主机上的一些设备,而且能够执行mount命令。

上述两种方法,都能满足在容器内构建容器镜像且推送镜像至远端仓库的需求,但是从security角度来讲,**需要root 权限(第一种方式),提供特权(第二种方式)** 都使得风险增大,在Kubernetes 多租户的场景下,这种风险是不能接受的。那是否有一种不需要特殊权限,还能快速构建容器镜像的方法呢?答案就是下面将的Kaniko。

# Kaniko

[https://github.com/GoogleContainerTools/kaniko](https://github.com/GoogleContainerTools/kaniko)

kaniko是谷歌开源的一款用来构建容器镜像的工具。与docker不同,Kaniko 并不依赖于Docker daemon进程,完全是在用户空间根据Dockerfile的内容逐行执行命令来构建镜像,这就使得在一些无法获取 `docker daemon` 进程的环境下也能够构建镜像,比如在**标准的Kubernetes Cluster**上。

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

Kaniko会先提取基础镜像(Dockerfile FROM 之后的镜像)的文件系统,然后根据Dockerfile中所描述的,一条条执行命令,每一条命令执行完以后会在用户空间下面创建一个snapshot,并与存储与内存中的上一个状态进行比对,如果有变化,就将新的修改生成一个镜像层添加在基础镜像上,并且将相关的修改信息写入镜像元数据中。等所有命令执行完,kaniko会将最终镜像推送到指定的远端镜像仓库。 

## kaniko使用

Dockerfile

Dockerfile $ cat Dockerfile FROM alpine:latest

MAINTAINER

RUN apk add busybox-extras curl

CMD ["echo","Hello DevOps"]

pod yaml

YAML apiVersion: v1 kind: Pod metadata: name: kaniko spec: containers:

  • name: kaniko image: gcr.io/kaniko-project/executor:latest args: ["--dockerfile=/workspace/Dockerfile",      "--context=/workspace/",      "--destination=dllhb/kaniko-test:v0.4"] volumeMounts:

    • secret:  name: regcred  items:    - key: .dockerconfigjson      path: config.json

    • name: kaniko-secret mountPath: /kaniko/.docker

    • name: dockerfile mountPath: /workspace/Dockerfile subPath: Dockerfile restartPolicy: Never volumes:

    • name: dockerfile configMap:  name: dockerfile

    • name: kaniko-secret projected: sources:

    需要说明几点:
    
    - args 部分
    
    这部分就是上面所讲的,kaniko运行时需要三个参数: **Dockerfile(--dockerfile),上下文(--context),远端镜像仓库(--destination)**
    
    - secret 部分
    
    推送至指定远端镜像仓库需要credential的支持,所以需要将credential以secret的方式挂载到/kaniko/.docker/这个目录下,文件名称为config.json,内容如下:

    JSON {
       "auths": {        "https://index.docker.io/v1/": {            "auth": "AbcdEdfgEdggds="       }    }

    }

    > 其中auth的值为: `echo"docker_registry_username:docker_registry_password"|base64`
    
    ## 参数
    
    #### Flag `--build-arg`
    
    此标志允许您在构建时传入 ARG 值,类似于 Docker。 您可以为多个参数多次设置它。
    
    请注意,传递包含空格的值本身不受支持 - 您需要 以确保在执行程序命令之前将 IFS 设置为 null。您可以设置 这是通过在执行人调用之前添加的。请参阅以下内容 例`export IFS=''`

    Plain Text export IFS='' /kaniko/executor --build-arg "MY_VAR='value with spaces'" … ```

    Flag --dockerfile

    dockerfile的路径. (默认值为 "Dockerfile")

    Flag --force

    在容器外强制构建

    Flag --insecure-registry

    使用http协议访问镜像仓库,不推荐生产环境使用。

    Flag --no-push

    只生成镜像,不推送到镜像仓库

    Flag --skip-tls-verify

    推送镜像时跳过tls证书验证,不推荐生产环境使用。

    Flag --skip-tls-verify-pull

    拉取镜像时跳过tls证书验证,不推荐生产环境使用。

    Flag --skip-tls-verify-registry

    访问指定镜像仓库时跳过tls验证,可多次使用来跳过多个镜像仓库,不推荐生产环境使用。


    相关文章

    Kafak顺序写入与数据读取详解

    Kafak顺序写入与数据读取详解

    生产者(producer)是负责向Kafka提交数据的,Kafka会把收到的消息都写入到硬盘中,它绝对不会丢失数据。为了优化写入速度Kafak采用了两个技术,顺序写入和MMFile。1. 顺序写入因为...

    Kubernetes 认证授权

    Kubernetes 认证授权

    1、认证所有 Kubernetes 集群都有两类用户:由 Kubernetes 管理的服务账号和普通用户。任何客户端访问之前,经由 kubernetes 时,需经过:认证(token, ssl)、授权...

    开源大数据集群部署(九)Ranger审计日志集成(solr)

    开源大数据集群部署(九)Ranger审计日志集成(solr)

    1、下载solr安装包并解压包tar -xzvf solr-8.11.2.gzcd solr-8.11.2执行安装脚本./bin/install_solr_service.sh /opt/solr-8...

    日志聚合工具loki

    1、loki是什么Loki是一个水平可扩展,高可用性,多租户的日志聚合系统,受到Prometheus的启发。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流编制一组标签。...

    kubernetes job和cronjob

    kubernetes job和cronjob

    一、JobJob 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。特殊说明:1、spec.template 格式同 Pod2、RestartPolicy 仅支持 N...

    RBAC

    RBAC

    API 对象在学习 RBAC 之前,我们还需要再去理解下 Kubernetes 集群中的对象,我们知道,在 Kubernetes 集群中,Kubernetes 对象是我们持久化的实体,就是最终存入 e...

    发表评论    

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。