使用kaniko摆脱Docker在K8S中构建容器镜像
github 项目地址 :kaniko 是一种在容器或 Kubernetes 集群内从 Dockerfile 构建容器镜像的工具。kaniko 不依赖于 Docker 守护进程,而是完全在用户空间中执行 Dockerfile 中的每个命令。这使得在无法轻松或安全地运行 Docker 守护程序的环境中构建容器镜像成为可能,例如标准的 Kubernetes 集群。
·
文章目录
一、什么是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、最后推送镜像。
参数定义:
- –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)布局文件的路径,用于存储构建过程的元数据。
四、 Kaniko 工作原理
- Kaniko 作为一个容器镜像运行,它接收三个参数 : 一个 Dockerfile ,一个构建上下文以及将镜像推送到的注册表,它在执行程序镜像中提取基本镜像的文件系统,然后在Dockerfile中执行任何命令,快照用户空间的文件系统,Kaniko在每个命令后都将一层更改的文件附加到基本镜像,最后,执行程序将新镜像推送到指定的注册表,由于Kaniko在执行程序镜像的用户空间中完全执行了这些操作,因此它完全避免了在用户计算机上需要特权访问。
五、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 将假定一个本地目录, 该参数可用值:
Source | Prefix | Example |
---|---|---|
Local Directory | dir://[path to a directory in the kaniko container] | dir:///workspace |
Local Tar Gz | tar://[path to a .tar.gz in the kaniko container] | tar:///path/to/context.tar.gz |
Standard Input | tar://[stdin] | tar://stdin |
GCS Bucket | gs://[bucket name]/[path to .tar.gz] | gs://kaniko-bucket/path/to/context.tar.gz |
S3 Bucket | s3://[bucket name]/[path to .tar.gz] | s3://kaniko-bucket/path/to/context.tar.gz |
Azure Blob Storage | https://[account].[azureblobhostsuffix]/[container]/[path to .tar.gz] | https://myaccount.blob.core.windows.net/container/path/to/context.tar.gz |
Git Repository | git://[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') {
...
}
}
}
}
}
更多推荐
已为社区贡献5条内容
所有评论(0)