image.png

demo.gif

一、什么是kaniko

github 项目地址 : https://github.com/GoogleContainerTools/kaniko

  • kaniko 是一种在容器或 Kubernetes 集群内从 Dockerfile 构建容器镜像的工具。
  • kaniko 不依赖于 Docker 守护进程,而是完全在用户空间中执行 Dockerfile 中的每个命令。这使得在无法轻松或安全地运行 Docker 守护程序的环境中构建容器镜像成为可能,例如标准的 Kubernetes 集群。

二、为何要用 Kaniko

  • 其主要原因由于 kaniko 不依赖于 Docker 守护进程,并且完全在用户空间中执行 Dockerfile 中的每个命令,这使得能够在轻松或安全地运行在无Docker环境守护程序(如标准Kubernetes集群 V1.24.x)中构建容器映像。
  • 在 Kubernetes V1.24.x 版本之后默认采用 http://containerd.io 作为缺省的cri,不在支持 docker-shim 意味着我们不需要安装 docker 环境。

三、 Kaniko 工作流程

  • 1、读取指定的 Dockerfile。
  • 2、将基本映像(在FROM指令中指定)提取到容器文件系统中。
  • 3、在独立的Dockerfile中分别运行每个命令。
  • 4、每次运行后都会对用户空间文件系统的做快照。
  • 5、每次运行时,将快照层附加到基础层。
  • 6、最后推送镜像。

参数定义:

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

四、 Kaniko 工作原理

  • Kaniko 作为一个容器镜像运行,它接收三个参数 : 一个 Dockerfile ,一个构建上下文以及将镜像推送到的注册表,它在执行程序镜像中提取基本镜像的文件系统,然后在Dockerfile中执行任何命令,快照用户空间的文件系统,Kaniko在每个命令后都将一层更改的文件附加到基本镜像,最后,执行程序将新镜像推送到指定的注册表,由于Kaniko在执行程序镜像的用户空间中完全执行了这些操作,因此它完全避免了在用户计算机上需要特权访问。

image.png

五、kaniko 构建上下文

  • kaniko 的构建上下文与您将发送 Docker 守护程序以进行映像构建的构建上下文非常相似;它代表一个包含 Dockerfile 的目录,kaniko 将使用该目录构建您的映像。例如,COPY Dockerfile 中的命令应该引用构建上下文中的文件。
  • 您需要将构建上下文存储在 kaniko 可以访问的地方。目前,kaniko 支持以下存储解决方案:
    • GCS Bucket
    • S3 Bucket
    • Azure Blob Storage
    • Local Directory
    • Local Tar
    • Standard Input
    • Git Repository
  • 关于 Local Directory的注意事项:此选项是指 kaniko 容器内的目录。如果您希望使用此选项,则需要在构建上下文中将其作为目录挂载到容器中。
  • 关于本地 Tar 的注意事项:此选项指的是 kaniko 容器中的 tar gz文件。如果您希望使用此选项,则需要在构建上下文中将其作为文件挂载到容器中。
  • 如果使用 GCS 或 S3 存储桶,您首先需要创建构建上下文的压缩 tar 并将其上传到您的存储桶。运行后,kaniko 将在开始映像构建之前下载并解压构建上下文的压缩 tar。
  • 要创建压缩的 tar,您可以运行:
#  tar -C <path to build context> -zcvf context.tar.gz . 
$ ls cache/
Dockerfile

# 压缩上下文目录
$ tar -C cache/ -zcvf context.tar.gz .
./
./Dockerfile

# 查看压缩文件
$ tar -ztvf context.tar.gz
drwxr-xr-x root/root         0 2023-11-27 13:03 ./
-rw-r--r-- root/root        52 2023-11-27 13:04 ./Dockerfile
  • 然后,将压缩的 tar 复制到您的存储桶中。例如,我们可以使用 gsutil 将压缩的 tar 复制到 GCS 存储桶: gsutil cp context.tar.gz gs://<bucket name>
  • 例如,要使用名为 kaniko-bucket 的 GCS 存储桶,您需要传入 --context=gs://kaniko-bucket/path/to/context.tar.gz
  • 温馨提示:kaniko 允许的唯一标准输入是 .tar.gz 格式, 如果要创建压缩 tar,您可以运行 tar -C <path to build context> -zcvf context.tar.gz . 命令。
  • 运行 kaniko 时,使用 --context 带有适当前缀的标志指定构建上下文的位置, 如果您不指定前缀 kaniko 将假定一个本地目录, 该参数可用值:
SourcePrefixExample
Local Directorydir://[path to a directory in the kaniko container]dir:///workspace
Local Tar Gztar://[path to a .tar.gz in the kaniko container]tar:///path/to/context.tar.gz
Standard Inputtar://[stdin]tar://stdin
GCS Bucketgs://[bucket name]/[path to .tar.gz]gs://kaniko-bucket/path/to/context.tar.gz
S3 Buckets3://[bucket name]/[path to .tar.gz]s3://kaniko-bucket/path/to/context.tar.gz
Azure Blob Storagehttps://[account].[azureblobhostsuffix]/[container]/[path to .tar.gz]https://myaccount.blob.core.windows.net/container/path/to/context.tar.gz
Git Repositorygit://[repository url][#reference][#commit-id]git://github.com/acme/myproject.git#refs/heads/mybranch#<desired-commit-id>

六、标准输入

  • 如果运行 kaniko 并使用标准输入构建上下文,则需要添加 docker 或 kubernetes -i, --interactive 标志。运行后,kaniko 将从中获取数据STDIN并将构建上下文创建为压缩的 tar。然后它会在开始镜像构建之前解压构建上下文的压缩 tar。如果在交互式运行期间没有数据通过管道传输,您将需要通过按 自己发送 EOF 信号 Ctrl+D
  • 如何 .tar.gz 使用 docker 以交互方式使用标准输入数据运行 kaniko 的完整示例:
echo -e 'FROM alpine \nRUN echo "created from standard input"' > Dockerfile | tar -cf - Dockerfile | gzip -9 | docker run \
  --interactive -v $(pwd):/workspace gcr.io/kaniko-project/executor:latest \
  --context tar://stdin \
  --destination=<gcr.io/$project/$image:$tag>
  • 如何使用 .tar.gz 标准输入数据交互运行 kaniko 的完整示例,使用 Kubernetes 命令行与临时容器和完全无 docker
echo -e 'FROM alpine \nRUN echo "created from standard input"' > Dockerfile | tar -cf - Dockerfile | gzip -9 | kubectl run kaniko \
--rm --stdin=true \
--image=gcr.io/kaniko-project/executor:latest --restart=Never \
--overrides='{
  "apiVersion": "v1",
  "spec": {
    "containers": [
      {
        "name": "kaniko",
        "image": "gcr.io/kaniko-project/executor:latest",
        "stdin": true,
        "stdinOnce": true,
        "args": [
          "--dockerfile=Dockerfile",
          "--context=tar://stdin",
          "--destination=gcr.io/my-repo/my-image"
        ],
        "volumeMounts": [
          {
            "name": "cabundle",
            "mountPath": "/kaniko/ssl/certs/"
          },
          {
            "name": "docker-config",
            "mountPath": "/kaniko/.docker/"
          }
        ]
      }
    ],
    "volumes": [
      {
        "name": "cabundle",
        "configMap": {
          "name": "cabundle"
        }
      },
      {
        "name": "docker-config",
        "configMap": {
          "name": "docker-config"
        }
      }
    ]
  }
}'

七、 Docker中使用kaniko构建镜像

  • 执行如下命令生成 docker hub 认证票据(存储路径为 ~/.docker/config.json)
    • echo "Harbor666" | docker login -u "admin" --password-stdin myharbor.harbor.com
  • 使用如下示例命令进行 kaniko-executor 容器的创建运行,并进行镜像构建并上传到 仓库中
docker run --rm --name kaniko-executor \
    -v $HOME/.docker/:/kaniko/.docker \
    -v /root/python:/workspace \
     gcr.io/kaniko-project/executor:latest \
    --dockerfile=/workspace/dockerfile --context=dir://workspace --destination=myharbor.harbor.com/library/python-docker:v1.0

八、kubernetes中运行kaniko构建镜像

  • Requirements:
    • Standard Kubernetes cluster (e.g. using GKE )
    • Kubernetes Secret
    • A build context
    • Kubernetes secret

8.1、Kubernetes secret

  • 想要在 Kubernetes 集群中运行 kaniko,您需要一个标准的运行 Kubernetes 集群和一个 Kubernetes secret,其中包含推送最终映像所需的身份验证。
  • 推送至指定远端镜像仓库须要credential的支持,因此须要将credential 以 secret 的方式挂载到/kaniko/.docker/这个目录下,文件名称为kaniko_config.json,内容以下:
  • 运行创建secret
$ kubectl -n jenkins create secret docker-registry kaniko-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=<dockerhub-username> \
--docker-password=<dockerhub-password>

$ kubectl  get secret kaniko-secret
NAME            TYPE     DATA   AGE
kaniko-secret   Opaque   1      23s

8.2、准备Demo 程序

  • 程序 demo
$ cd /root/python
$ pip3 install Flask
$ pip3 freeze | grep Flask >> requirements.txt

$ vim app.py
#!/usr/bin/python3
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, Kaniko!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
  • dockerfile
$ cat Dockerfile 
FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY . .

CMD [ "python3", "app.py"]

8.3、编排kaniko pod

  • 项目目录
# tree /root/python
|____ app.py
|____ requirements.txt
|____ Dockerfile
  • kaniko pod
apiVersion: v1
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
 - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    args:
    - "--dockerfile=/python/Dockerfile"
    - "--context=gs:/python/"
    - "--destination=myharbor.harbor.com/library/python-docker:v1.0"
    volumeMounts:
    - name: kaniko-secret
      mountPath: /secret
    - name: python-docker
      mountPath: /python
      subPath: Dockerfile    
    env:
    - name: GOOGLE_APPLICATION_CREDENTIALS
      value: /secret/kaniko-secret.json
  restartPolicy: Never
  volumes:
 - name: kaniko-secret
    secret:
      secretName: kaniko-secret
 - name: python-docker
   hostPath: 
     path: /root/python

九、集成到 jenkins pipline 流水线

  • jenkins pipeline 声明式示例 :
pipeline {
    agent {
        kubernetes {
      yaml """
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    imagePullPolicy: Always
    command:
    - cat
    tty: true
"""
      }
    }
   
    stages {
        stage('拉代码') {
            steps {
                ...
            }
        }
       
        stage('构建镜像') {
            steps {
                // 使用 kaniko 来构建镜像
                container(name: 'kaniko') {
                    Dockerfile 内容...
                    sh "kaniko -f Dockerfile -c ./ -d myharbor.harbor.com/myapp/:$BUILD_NUMBER --force"
                }
            }
        }
         
        stage('部署') {
            steps {
              container(name: 'helm') {
                ...
              }
            }
        }
         
    }
}
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐