• Kubernetes平台上更安全的构建容器镜像工具Kaniko


    背景

    在云原生趋势下,用容器的方式来进行软件产品交付越来越普通,对于云原生的DevOps,它的CICD环境完全运行在容器中,镜像的构建也是在容器中完成的。而我们不仅要考虑如何在容器中成功构建镜像,也需要考虑如何以更安全的方式来构建容器镜像。

    容器内构建镜像的方式

    容器中构建镜像一般分为两种:

    • 在Docker容器中运行Docker,依赖Docker Daemon
    • Kaniko -K8s中构建镜像,不依赖Docker Daemon

    下面分开来讨论两种方式

    在Docker容器中运行Docker

    在Docker中实现Docker的二种方法:

    1. 通过挂载docker.sock运行docker:需要root权限
    2. dind(docker in docker):需要privileged特权

    通过挂载docker.sock运行docker

    要在docker内部运行docker,要做的只是在默认Unix套接字docker.sock作为卷的情况下运行docker 。

    docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker
    

    缺点:只有root权限才能访问docker daemon进程,在docker daemon无法暴露或者用户没有权限获取docker daemon进程的前提下,用 docker build 来构建镜像就不可行了。

    dind(docker in docker)

    docker build镜像就是需要docker命令可以成功运行,只要在容器里面安装一个docker就可以。这种方式不需要挂载宿主机的socket文件,但是需要以 --privileged 权限来以dind镜像创建一个容器

    docker run --rm -it --privileged docker:dind
    

    缺点:该方式需要提供特权,可能会看到宿主机上的一些设备,并且可以执行mount命令。

    比较

    这两种方式,一种需要root权限,一种需要privileged特权,从安全角度来看是有风险的。特别是在K8S多租户的场景下,这种方式不能被接受。同时当一台机器上同时运行多个docker build流水线时,因为这批流水线用的是宿主机上同一个docker进程,会出现阻塞的情况。因此Google提供了一个工具Kaniko用来解决这个问题

    Kaniko

    Kaniko是一个Google开源的方便我们在k8s中使用dockfile构建镜像的工具。它不依赖docker daemon进程,并完全在用户空间执行dockfile文件的每一条命令。这样我们就可以在一些没法获取docker daemon进程的环境下也可以构建镜像。比如在K8S上。

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

    下面给出一个利用kaniko来构建镜像的示例

    前提条件

    1. 一个Kubernetes集群
    2. 一个dockerhub账户,用于push镜像

    为kaniko准备配置文件

    kaniko以容器镜像的方式运行,同时需要三个参数:Dockerfile,context 以及远端镜像仓库的地址。需要准备几个配置文件来在k8s中创建资源,他们是:

    • kaniko_build_image.yaml 用于启动kaniko容器用来构建镜像
    • configmap 存放Dockerfile文件
    • secret 存放dockerhub授权信息

    创建一个Dockerfile文件

    编写一个Dockerfile文件:

    FROM ubuntu
    ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
    

    并创建一个configmap:
    kubectl create configmap kanikodockerfile --from-file=./Dockerfile

    创建一个保存远端镜像仓库凭证的Secret

    k8s集群使用docker-registry类型的Secret去授权docker仓库去推送镜像。创建这个Secret:

    kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

    <your-registry-server>: 你的私有Docker仓库地址,DockerHub是https://index.docker.io/v1/
    <your-name>: 你的仓库用户名
    <your-pword>: 你的仓库密码
    <your-email>: 你的仓库邮箱 可选

    这个Secret会在pod.yaml,也就是用kaniko创建镜像的容器中使用。

    或者编辑名为config.json的文件,并生成Secret,后需要以secret的方式挂载到/kaniko/.docker/这个目录下。文件内容为:

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

    其中auth的值为: echo"docker_registry_username:docker_registry_password"|base64

    准备kaniko_build_image.yaml 用于启动kaniko容器用来构建镜像

    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=<user-name>/<repo>"] # replace with your dockerhub account
        volumeMounts:
          - name: kaniko-secret
            mountPath: /kaniko/.docker
          - name: dockerfile
            mountPath: /workspace
      restartPolicy: Never
      volumes:
        - name: kaniko-secret
          secret:
            secretName: regcred
            items:
              - key: .dockerconfigjson
                path: config.json
        - name: dockerfile
           configMap:
             name: kanikodockerfile
    

    构建

    现在就是创建pod,查看状态,并看log是否正常完成。
    创建构建podkubectl apply -f kaniko_build_image.yaml

    测试

    用kaniko生成的镜像来测试下是否可用:sudo docker run -it <user-name>/<repo-name>

    参考链接

    https://cloud.tencent.com/developer/article/1697053
    https://www.shangmayuan.com/a/38d1cc5f039540899ceb0d43.html
    https://www.yinyubo.com/2021/06/25/自定义一个kaniko镜像/

  • 相关阅读:
    视频输入 范例
    视频输出 范例
    开启VI视频输入设备 范例
    初始化MMP系统 范例
    Git 的使用
    DVS/DVR/NVR/XVR
    shell命令中 && 和 || 的区别
    码流 / 码率 / 比特率 / 帧速率 / 分辨率 / 高清
    DNS与DSN
    ob_start()失效与phpunit的非正常结束
  • 原文地址:https://www.cnblogs.com/brilliantl/p/16211583.html
Copyright © 2020-2023  润新知