- Đăng vào
Jenkins trên Kubernetes: Build docker image bằng Kaniko
Giới thiệu
Ở các bài viết trước, mình đã giới thiệu cách Deploy Jenkins trên Kubernetes. Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu cách build docker image trên con Jenkins này bằng công cụ Kaniko.
Run Docker in a Docker Container
Như chúng ta đã biết, thì bản chất của việc deploy Jenkins trên cụm Kubernetes là chúng ta chạy Jenkins master ở dang 1 docker container (pod) và các Agent sẽ được tạo khi các pipeline chay. Agent chính là docker container được đóng gói trong pod.
Như vậy nếu Pipeline của chúng ta chạy task build docker image chẳng hạn, thì sẽ phát sinh ra vấn đề docker container có thể chạy được các lệnh docker để làm nhiệm vụ build docker image khác.
lấy mỡ nó rán nó
Khái niệm này có thể search với từ khóa Run Docker in a Docker Container
. Về cơ bản sẽ có 2 giải pháp chính để chúng ta làm được nhiệm vụ đó:
- DooD (Docker outside of Docker): là một phương pháp triển khai Docker container trong một Docker container khác. Nó được xây dựng dựa trên khái niệm Docker socket (
docker.sock
), một cơ chế cho phép các container truy cập vào Docker daemon của host. Với DooD, Docker daemon được chạy trên host và các container được triển khai trong một môi trường Docker độc lập.
- DinD (Docker in Docker): là giải pháp khác cho việc triển khai Docker container trong một Docker container khác. Nó bao gồm việc chạy một Docker daemon trong một container và sử dụng nó để tạo ra các container con. Tuy nhiên, DinD không được khuyến khích sử dụng do các vấn đề về bảo mật, quản lý và hiệu suất.
Cả hai giải pháp trên có nhiều hạn chế và cần được cân nhắc kỹ trước khi triển khai sử dụng.
Kaniko
Kaniko là một công cụ mã nguồn mở dùng để xây dựng các image Docker từ một Dockerfile mà không cần sử dụng daemon Docker. Kaniko có thể chạy trên bất kỳ nền tảng nào hỗ trợ container, như Kubernetes, Google Cloud Build, Tekton, Jenkins, GitLab và nhiều hơn nữa. Kaniko giải quyết vấn đề về bảo mật và hiệu suất khi xây dựng các image Docker trên môi trường của container.
Một số tính năng chính của Kaniko là:
- Hỗ trợ xây dựng các image Docker từ các nguồn khác nhau, như local directory, Git repository, Google Cloud Storage, Amazon S3, v.v. Hỗ trợ đẩy các image Docker lên các kho lưu trữ khác nhau, như Docker Hub, Google Container Registry, Amazon Elastic Container Registry, v.v.
- Hỗ trợ sử dụng các biến môi trường, các tham số build-time và các file cấu hình để tùy biến quá trình xây dựng image
- Hỗ trợ sử dụng cache để tăng tốc độ xây dựng image và giảm dung lượng image
- Hỗ trợ xây dựng các image đa tầng (multi-stage) và kế thừa từ các image khác
- Hỗ trợ kiểm tra tính hợp lệ của Dockerfile và thông báo lỗi nếu có
Build docker image
Để build docker image bằng kaniko, bạn cần có một Dockerfile, một build context và một registry để đẩy image sau khi xây dựng. Bạn cũng cần có một container hoặc Kubernetes cluster để chạy kaniko.
Kaniko hỗ trợ build và push image lên một remote docker registry, trong ví dụ này docker image sẽ được đẩy lên Docker Hub. Thường sau khi bạn dùng command docker login
nếu thành công sẽ có 1 file $HOME/.docker/config.json
trên Linux hoặc %USERPROFILE%/.docker/config.json
trên Windows. Kaniko cần sử dụng file này để sau khi build có thể đẩy docker image của bạn lên Docker Hub.
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "xxxxxxxxxxxxxxx"
}
}
}
Nếu bạn sử dụng Container Registry khác thì vui lòng xem thêm trên Google.
Tiếp theo, chúng ta chỉ cần chạy command dưới đây:
docker run -ti --rm -v `pwd`:/workspace -v `pwd`/config.json:/kaniko/.docker/config.json:ro gcr.io/kaniko-project/executor:latest --dockerfile=Dockerfile --destination=yourimagename
Cần chú ý rằng, bạn cần chạy command tại folder chứa file config.json
và Dockerfile
muốn build.
Tích hợp vào Jenkins
Trong bài viết này, mình sử dụng Jenkins chạy trên Kubernetes. Vui lòng xem thêm bài viết Deploy Jenkins trên Kubernetes để có thêm thông tin.
Kubernetes secret
Tương tự như các bước ở trên, đầu tiên chúng ta phải lưu file config.json
vào kubernetes secret
kubectl -n jenkins create secret generic kaniko-secret --from-file=config.json
Tạo pod Agent
Mục đích bước này cho phép chúng khởi tạo Kaniko khi cần sử dụng bằng cú pháp:
agent {
label 'docker-build'
}
Vào phần Clouds và chọn Cluster mà đã đã có trước đó rồi chọn Add Pod Template
- Name: kaniko
- Namespace: jenkins
- Labels: docker-build
- Usage: Only build jobs with label expressions matching this node
- Containers: (Chúng ta sẽ tạo 2 container)
- Container 1:
- Name: jnlp
- Docker image:
jenkins/inbound-agent:alpine
- Working directory:
/home/jenkins/agent
- Command to run: Để trống
- Arguments to pass to the command: để trống
- Allocate pseudo-TTY: không chọn
- Container 2:
- Name: kaniko
- Docker image:
gcr.io/kaniko-project/executor:debug
- Working directory:
/home/jenkins/agent
- Command to run:
/busybox/cat
- Allocate pseudo-TTY: Tích chọn
- Container 1:
- Volumnes:
- Secret name:
kaniko-secret
- Mount path:
/kaniko/.docker
- Secret name:
Sau đó lưu lại. Nhưng config mình không đề cập thì để mặc định hoặc để trống. Tiếp theo, chúng ta sẽ thử làm một pipeline đơn giản để build docker image bằng Kaniko
Tích hợp vào Jenkin pipeline
Chúng ta cần tạo 1 project , với các thông số cấu hình như dưới đây
Dưới đây mình sẽ giới thiệu ví dụ đơn giản:
- Checkout source code từ git
- Chạy pipeline với cấu hình được thiết lập trong
Jenkinsfile
pipeline {
agent any
options {
skipDefaultCheckout()
}
parameters {
string(name:'GIT_URL', defaultValue:'https://github.com/nvtienanh/jenkins-agent-docker-kubectl.git', description:'The URL of the source Git repository to use.')
string(name:'GIT_BRANCH', defaultValue:'main', description:'The branch in the source Git repository to use.')
}
stages {
stage("Checkout") {
steps {
checkout(changelog: false, poll: false, scm: [
$class: 'GitSCM',
branches: [
[name: params.GIT_BRANCH],
],
doGenerateSubmoduleConfigurations: false,
submoduleCfg: [],
userRemoteConfigs: [
[
url: params.GIT_URL,
],
],
])
stash name: 'sources', includes: '**', excludes: '**/.git,**/.git/**'
}
}
stage("Build docker") {
agent {
label 'docker-build'
}
steps {
unstash 'sources'
container(name: 'kaniko') {
sh '/kaniko/executor --context=`pwd` --dockerfile=`pwd`/Dockerfile --destination=nvtienanh/jnlp-from-kaniko:latest'
}
}
}
}
}
Đây là file dockerimage sẽ build
FROM jenkins/inbound-agent:alpine
USER root
ENV KUBECTLVERSION=1.28.3
RUN curl -fsSL https://dl.k8s.io/release/v$KUBECTLVERSION/bin/linux/amd64/kubectl > /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl
USER jenkins
Chi tiết có thể xem trên repository: Kubectl in Docker Jenkins
Hy vọng bài viết này sẽ có ích.