6부 Advanced Patterns 중 하나로, 그 동안 다른 카테고리에서 다르지 않는 복잡한 주제를 다룬다.
Image Builder 패턴은, 쿠버네티스 클러스터 외부에서 (로컬 PC나 CI 서버에서) 컨테이너 이미지를 빌드하던 것을, 클러스터 내부에서 직접 빌드하도록 한다.
쿠버네티스는 범용적인 목적의 오케스트레이션 엔진 이며, 단순히 애플리케이션을 실행하는 것 뿐 아니라 컨테이너 이미지를 빌드하기에도 적합하다. Image Builder 패턴은 클러스터 내부에서 컨테이너 이미지를 빌드하는 것이 왜 적합한지와 관련 테크닉에 대해 다룬다.
이제까지 다루었던 패턴은 쿠버네티스에서 애플리케이션 운영에 관한 것이이였다. (cloud native한 application을 위해 어떻게 개발하고 준비해야할지) 그러나, 이번 장에서 다룰 문제는 애플리케이션 빌드에 관한 것이다.
전통적인 애플리케이션 빌드 방식은 다음과 같다.
컨테이너 이미지 빌드를 클러스터 내부에서 하는 것은 다음과 같은 장점이 있다.
Image Builder pattern을 사용하면, 클러스터는 "이미지 빌드 + 배포 (deployment)" 모두 잘 파악할 수 있고, base image가 바뀌는 경우의 재배포도 자동화할 수 있다.
essential image-building techniques within a Kubernetes cluster (2023)

위 도구들은 크게 두 가지 카테고리로 분류할 수 있다.
핵심은 노드 host에 대한 privileged access 없이, 클러스터 내부에서 이미지를 빌드하는 것.
클러스터는 빌드 프로세스 전체를 완전히 제어해야하며, 여러 취약점으로부터 보호를 위한 높은 보안 기준이 필요하다. 이를 위한 대표적인 방법이, 루트 권한 없이 빌드를 실행하는 것 (rootless build)이다.
Docker 데몬은 컨테이너 실행을 위해 루트 권한이 필요하며, 컨테이너 이미지 빌드 시에도 마찬가지이다.
이와달리 아래에서 설명하는 다양한 클러스터 내 빌드 도구들은 nonpriviledged mode에서 컨테이너 이미지를 빌드하는 모드를 지원한다.
Dockerfile 형식을 기반으로 하는 builder 이다. 백그라운드 데몬과 전혀 통신하지 않고, nonpriviledged mode로 실행되는 빌드 프로세스 + REST API를 통해 원격으로 통신한다.
| 도구 | 데몬 필요 여부 | 특징 | 제약 |
|---|---|---|---|
| Buildah/Podman | 불필요 | 완전한 daemonless, OCI 호환 이미지 빌드 도구 | - |
| Kaniko | 불필요 | K8s 빌드 컨테이너 특화, Google Cloud Build 핵심 | 컨테이너 내 UID 0 필요 → OpenShift 와 같이 컨테이너 내부에서 루트 사용자로 실행을 허용하지 않는 클러스터는 사용 불가 |
| BuildKit | 필요 (Buildkit 데몬되어 빌드 작 대기) | Docker로부터 분리된 자체 빌드 엔진 프로젝트 LLB (Low-Level Build) 형식으로 복잡한 빌드 그래프 지원 분산 rootless 빌드 가능 | - |
Spring Boot 애플리케이션이나 일반적인 Python 빌드와 같은 기존 프로젝트를 감지하고, 그에 맞는 이미지 빌드 흐름을 자동으로 선택하는 builder.
CNB(Cloud Native Buildpacks)
cf push) → 2018년 CNCF 통합npm install)| 도구 | 실행 위치 | 특징 |
|---|---|---|
| pack | 로컬 | CLI 명령어, Docker/Podman 런타임 필요 |
| Tekton build task나 GitHub Actions 같은 CI 단계 | CI 파이프라인 | Builder 이미지에서 라이프사이클 직접 호출 |
| kpack | K8s 클러스터 내 | Operator 방식, CNB 개념 (Builder, Builder-packs)을 CRD로 표현 |
특정 상황에서 + 독자적인 방식으로 이미지를 생성하는 builders.
RUN 같은 명령을 실행하는 방식이 아님)| 도구 | 대상 언어/환경 | 특징 |
|---|---|---|
| Jib | Java (Maven/Gradle 같은 빌드 도구와 통합) | 아티팩트·의존성·리소스를 별도 레이어로 분리 → 재빌드 시간 최적화 |
| ko | Golang | 원격 Git에서 직접 빌드, Pod 명세 자동 업데이트 |
| Apko | Alpine 기반 이미지 | Apk 패키지를 빌딩 블록으로 사용 → 유사 이미지 재사용 용이 |
Build Orchestrator는 Tekton, Argo CD, Flux 같은 CI/CD 플랫폼을 말하며,빌드, 테스트, 릴리즈, 배포, 보안 스캔 등 애플리케이션의 전체 자동화 관리 라이프사이클을 다룬다. 범용 CI/CD 플랫폼 외에도, 컨테이너 이미지를 생성하기 위한 더 특화된 오케스트레이터를 사용할 수 있다.
| Build Orchestrator | 특징 |
|---|---|
| OpenShift Builds | K8s 클러스터 내 빌드 중 가장 오래되고 성숙한 방식 |
| kbld | Kubernetes에서 빌드, 구성, 배포를 위한 툴셋인 Carvel의 일부 컨테이너 빌드 후 YAML의 image 필드를 새 이미지 경로로 자동 업데이트 |
| Kubernetes Job | 표준 K8s Job으로 빌드 트리거 빌드 Pod는 source repository에서 코드를 가져와 클러스터 내 빌더로 이미지 생성 |
모든 Build Orchestrator의 대표적인 작업 흐름은 다음과 같다.

Kaniko를 사용한 Pod 빌드
apiVersion: v1
kind: Pod
metadata:
name: build
spec:
# 빌드 단계는 initContainer로 순차 실행 보장
initContainers:
# [1단계] 원격 Git 저장소에서 소스 코드 체크아웃
- name: git-sync
image: k8s.gcr.io/git-sync/git-sync
args: [
"--one-time", # 1회 실행 후 종료
"--depth", "1", # 최신 커밋만 가져옴 (shallow clone)
"--root", "/workspace",
"--repo", "https://github.com/k8spatterns/random-generator.git",
"--dest", "main",
"--branch", "main"
]
volumeMounts:
- name: source
mountPath: /workspace # 소스 코드를 공유 볼륨에 저장
# [2단계] Kaniko로 이미지 빌드 & 레지스트리 푸시
- name: build
image: gcr.io/kaniko-project/executor
args:
- "--context=dir:///workspace/main/" # 소스 코드 위치
- "--destination=index.docker.io/k8spatterns/random-generator-kaniko" # 푸시할 레지스트리 경로
- "--image-name-with-digest-file=/workspace/image-name" # 빌드된 이미지 digest를 파일로 저장 (다음 단계에서 사용)
securityContext:
privileged: false # rootless 빌드 (Pod 자체는 비특권)
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker # Kaniko가 인증 정보를 찾는 고정 경로
- name: source
mountPath: /workspace # 소스 코드 및 digest 파일 공유
containers:
# [3단계] 빌드된 이미지로 Deployment 업데이트
- name: image-update
image: k8spatterns/image-updater
args:
- "random" # 업데이트할 Deployment 이름
- "/opt/image-name" # Kaniko가 저장한 이미지 digest 파일 경로
volumeMounts:
- name: source
mountPath: /opt # digest 파일 접근을 위해 공유 볼륨 마운트
volumes:
# Docker Hub 인증 정보 (registry-creds Secret에서 로드)
- name: kaniko-secret
secret:
secretName: registry-creds
items:
- key: .dockerconfigjson
path: config.json # Kaniko가 기대하는 파일명
# 컨테이너 간 데이터 공유용 임시 볼륨 (노드 로컬 파일시스템)
- name: source
emptyDir: {}
# Deployment를 patch할 수 있는 권한을 가진 ServiceAccount
serviceAccountName: build-pod
# 빌드는 1회성 작업이므로 재시작 불필요
restartPolicy: Never
Red Hat OpenShift는 Kubernetes의 엔터프라이즈 배포판으로 Kubernetes 기능 + 통합 컨테이너 이미지 레지스트리 + 싱글 사인온(SSO) 지원 + 새로운 UI 등 엔터프라이즈 관련 기능을 추가하고, Kubernetes에 네이티브 이미지 빌드 기능도 추가한다.
OpenShift Build는 Kubernetes가 관리하는 클러스터 통합 방식으로 이미지를 직접 빌드하는 최초의 방법이며, 이미지 빌드를 위한 여러 전략을 지원한다:
Build input source의 종류는 다음과 같다. Input을 어떻게 설정하고 사용할지는 빌드 위 전략에 따라 달라진다.
Openshift Build의 핵심 리소스/개념은 다음과 같다.
| 개념 | 설명 |
|---|---|
| BuildConfig | 모든 빌드 정보를 담는 중앙 리소스. oc CLI로 정의 및 트리거 |
| ImageStream | 컨테이너 이미지 참조 목록 (Docker 저장소와 유사) |
| ImageStreamTag | ImageStream 내 태그된 개별 이미지 참조 |
| trigger | 이벤트에 대한 일종의 리스너 (imageChange 트리거는 ImageStreamTag 변경에 반응)이미지 재빌드, Pod 재배포를 트리거하는데 사용 |
클러스터 내부에서 컨테이너 이미지를 빌드하는 두 가지 방식을 살펴봤다.
모든 build system에서 실행해야하는 핵심적인 작업은 다음과 같다.
소스 코드 가져오기
-> 소스 코드에서 실행 가능한 아티팩트 생성
-> 애플리케이션 아티팩트를 포함하는 컨테이너 이미지 생성
-> 이미지 레지스트리에 푸시
-> 새로 생성된 이미지를 레지스트리에서 가져오도록 Deployment 업데이트
build orchestrator가 다뤄야할 manual 작업이 많기 때문에, 바로 production 레벨에서 사용하기는 쉽지 않다.
ImageStream 트리거를 통해 여러 빌드를 연결
-> 빌드가 애플리케이션 컨테이너 이미지를 업데이트
-> 애플리케이션자동 재배포
빌드와 배포를 잘 통합했기 때문에 CD의 궁극적인 목표에 한 걸음 다가갔다고 할 수 있지만, Kubernetes Openshift 배포판을 사용할 때만 사용이 가능하다.