Kubernetes 드라이버
Kubernetes 드라이버 (Kubernetes driver)
Kubernetes 드라이버는 로컬 개발 환경이나 CI 환경을 Kubernetes 클러스터의 빌더에 연결해, 더 강력한 컴퓨팅 리소스에 접근할 수 있게 해 주는 드라이버예요. 여러 네이티브 아키텍처를 선택적으로 사용할 수도 있어요.
출처: 문서
본문
Kubernetes 드라이버는 로컬 개발 또는 CI 환경을 Kubernetes 클러스터 안의 빌더에 연결해 더 강력한 컴퓨팅 리소스에 접근할 수 있게 해 줘요. 선택적으로 여러 네이티브 아키텍처를 사용할 수도 있어요.
동작 방식 (Synopsis)
kube라는 이름의, Kubernetes 드라이버를 쓰는 새 빌더를 만들려면 다음 명령을 실행해요:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=[key=value,...]
다음 표는 --driver-opt에 넘길 수 있는 드라이버별 옵션을 설명해요:
| Parameter | Type | Default | Description |
| image | String | | BuildKit 실행에 사용할 이미지를 설정해요. |
| namespace | String | 현재 Kubernetes 컨텍스트의 namespace | Kubernetes namespace를 설정해요. |
| default-load | Boolean | false | 이미지를 Docker Engine 이미지 저장소에 자동으로 로드해요. |
| replicas | Integer | 1 | 생성할 파드 레플리카 수를 설정해요. BuildKit 스케일링 참고. |
| requests.cpu | CPU units | | 요청 CPU 값을 Kubernetes CPU 단위로 지정해요. 예: requests.cpu=100m 또는 requests.cpu=2 |
| requests.memory | Memory size | | 요청 메모리 값을 바이트 또는 유효한 접미사로 지정해요. 예: requests.memory=500Mi 또는 requests.memory=4G |
| requests.ephemeral-storage | Storage size | | 요청 임시 스토리지(ephemeral-storage) 값을 바이트 또는 유효한 접미사로 지정해요. 예: requests.ephemeral-storage=2Gi |
| persistent-volume-claim.requests.storage | Storage size | | 영구 볼륨 클레임(persistent volume claim)의 요청 크기를 설정해요. 설정하면 Buildx가 StatefulSet을 만들고 BuildKit 빌드 캐시를 클레임에 저장해요. 예: persistent-volume-claim.requests.storage=20Gi |
| limits.cpu | CPU units | | 제한 CPU 값을 Kubernetes CPU 단위로 지정해요. 예: requests.cpu=100m 또는 requests.cpu=2 |
| limits.memory | Memory size | | 제한 메모리 값을 바이트 또는 유효한 접미사로 지정해요. 예: requests.memory=500Mi 또는 requests.memory=4G |
| limits.ephemeral-storage | Storage size | | 제한 임시 스토리지 값을 바이트 또는 유효한 접미사로 지정해요. 예: requests.ephemeral-storage=100M |
| buildkit-root-volume-memory | Memory size | 일반 파일 시스템 사용 | /var/lib/buildkit을 메모리 기반 emptyDir 볼륨에 마운트하고, SizeLimit을 값으로 사용해요. 예: buildkit-root-folder-memory=6G |
| nodeselector | CSV string | | 파드의 nodeSelector 라벨을 설정해요. 노드 할당 참고. |
| annotations | CSV string | | Deployment 또는 StatefulSet과 파드에 추가 annotation을 설정해요. |
| labels | CSV string | | Deployment 또는 StatefulSet과 파드에 추가 라벨을 설정해요. |
| tolerations | CSV string | | 파드의 taint 허용(toleration)을 구성해요. 노드 할당 참고. |
| serviceaccount | String | | 파드의 serviceAccountName을 설정해요. |
| schedulername | String | | 파드 스케줄링을 담당하는 스케줄러를 설정해요. |
| timeout | Time | 120s | 빌드 전에 파드가 프로비저닝될 때까지 Buildx가 기다릴 시간 제한을 설정해요. |
| rootless | Boolean | false | 컨테이너를 비-root 사용자로 실행해요. 루트리스 모드 참고. |
| loadbalance | String | sticky | 로드 밸런싱 전략(sticky 또는 random)이에요. sticky로 설정하면 컨텍스트 경로의 해시로 파드를 선택해요. |
| qemu.install | Boolean | false | 멀티 플랫폼 지원을 위한 QEMU 에뮬레이션을 설치해요. QEMU 참고. |
| qemu.image | String | tonistiigi/binfmt:latest | QEMU 에뮬레이션 이미지를 설정해요. QEMU 참고. |
BuildKit 스케일링 (Scaling BuildKit)
Kubernetes 드라이버의 주요 장점 중 하나는 빌더 레플리카 수를 늘렸다 줄였다 해서 늘어난 빌드 부하를 처리할 수 있다는 거예요. 스케일링은 다음 드라이버 옵션으로 구성할 수 있어요:
replicas=N— BuildKit 파드 수를 원하는 크기로 조정해요. 기본적으로 파드를 하나만 만들 뿐이지만, 레플리카 수를 늘리면 클러스터의 여러 노드를 활용할 수 있어요.requests.cpu,requests.memory,requests.ephemeral-storage,limits.cpu,limits.memory,limits.ephemeral-storage— 공식 Kubernetes 문서에 따라 각 BuildKit 파드가 사용할 수 있는 리소스를 요청·제한할 수 있게 해 줘요.
예를 들어 BuildKit 파드 4개를 만들려면:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,replicas=4
파드를 나열하면 이렇게 보여요:
$ kubectl -n buildkit get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kube0 4/4 4 4 8s
$ kubectl -n buildkit get pods
NAME READY STATUS RESTARTS AGE
kube0-6977cdcb75-48ld2 1/1 Running 0 8s
kube0-6977cdcb75-rkc6b 1/1 Running 0 8s
kube0-6977cdcb75-vb4ks 1/1 Running 0 8s
kube0-6977cdcb75-z4fzs 1/1 Running 0 8s
또한 레플리카가 여러 개일 때 로드 밸런싱 동작을 제어하려면 loadbalance=(sticky|random) 옵션을 사용할 수 있어요. random은 노드 풀에서 무작위 노드를 선택해 레플리카 간에 워크로드를 고르게 분산해요. sticky(기본값)는 동일한 빌드를 여러 번 수행해도 매번 같은 노드에 연결하도록 시도해 로컬 캐시를 더 잘 활용해요.
스케일링에 대한 자세한 내용은 docker buildx create의 옵션을 참고하세요.
영구 스토리지 (Persistent storage)
persistent-volume-claim.requests.storage 드라이버 옵션을 설정하면 BuildKit 빌드 캐시를 파드 파일시스템이 아니라 영구 볼륨 클레임에 저장해요. 이 옵션을 설정하면 Buildx는 Deployment 대신 StatefulSet을 만들어요.
replicas도 설정하면 각 레플리카가 각자 자신의 영구 볼륨 클레임을 가져요. 이렇게 하면 재시작 후에도 빌드 캐시가 각 파드에 로컬하게 유지돼요.
예를 들어 레플리카당 20GiB 영구 스토리지를 가진 빌더를 만들려면:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,replicas=4,persistent-volume-claim.requests.storage=20Gi
노드 할당 (Node assignment)
Kubernetes 드라이버는 nodeSelector와 tolerations 드라이버 옵션으로 BuildKit 파드의 스케줄링을 제어할 수 있게 해 줘요. 아예 커스텀 스케줄러를 쓰고 싶다면 schedulername 옵션도 설정할 수 있어요.
annotations와 labels 드라이버 옵션으로 빌더를 호스팅하는 Deployment 또는 StatefulSet과 파드에 추가 메타데이터를 적용할 수 있어요.
nodeSelector 파라미터의 값은 키-값 쌍의 쉼표로 구분된 문자열이에요. 여기서 키는 노드 라벨이고 값은 라벨 텍스트예요. 예: "nodeselector=kubernetes.io/arch=arm64"
tolerations 파라미터는 taint의 세미콜론으로 구분된 목록이에요. Kubernetes 매니페스트와 같은 값을 받아들여요. 각 tolerations 항목은 taint 키와 값, operator 또는 effect를 지정해요. 예: "tolerations=key=foo,value=bar;key=foo2,operator=exists;key=foo3,effect=NoSchedule"
이 옵션들은 CSV로 구분된 문자열을 값으로 받아요. 셸 명령의 따옴표 규칙 때문에 값을 작은따옴표로 감싸야 해요. --driver-opt 전체를 작은따옴표로 감쌀 수도 있어요. 예:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
'--driver-opt="nodeselector=label1=value1,label2=value2","tolerations=key=key1,value=value1"'
멀티 플랫폼 빌드 (Multi-platform builds)
Kubernetes 드라이버는 QEMU를 사용하거나 노드의 네이티브 아키텍처를 활용해 멀티 플랫폼 이미지를 만들 수 있어요.
QEMU
docker-container 드라이버처럼 Kubernetes 드라이버도 QEMU(사용자 모드)를 사용해 네이티브가 아닌 플랫폼용 이미지를 빌드할 수 있어요. --platform 플래그를 포함해 출력할 플랫폼을 지정해요.
예를 들어 amd64와 arm64용 리눅스 이미지를 빌드하려면:
$ docker buildx build \
--builder=kube \
--platform=linux/amd64,linux/arm64 \
-t <user>/<image> \
--push .
Warning
QEMU는 네이티브가 아닌 플랫폼에 대해 전체 CPU 에뮬레이션을 수행하므로 네이티브 빌드보다 훨씬 느려요. 컴파일이나 압축·해제처럼 계산량이 많은 작업은 성능 저하가 클 수 있어요.
커스텀 BuildKit 이미지를 사용하거나 빌드에서 네이티브가 아닌 바이너리를 호출할 때는 빌더를 만들 때 qemu.install 옵션으로 QEMU를 명시적으로 켜야 할 수 있어요:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,qemu.install=true
네이티브 (Native)
다른 아키텍처의 클러스터 노드에 접근할 수 있다면 Kubernetes 드라이버가 이들을 네이티브 빌드에 활용할 수 있어요. 그러려면 docker buildx create의 --append 플래그를 사용해요.
먼저 단일 아키텍처(예: amd64)를 명시적으로 지원하는 빌더를 만들어요:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--platform=linux/amd64 \
--node=builder-amd64 \
--driver-opt=namespace=buildkit,nodeselector="kubernetes.io/arch=amd64"
그러면 builder-amd64라는 단일 빌더 노드를 가진 kube라는 Buildx 빌더가 만들어져요. --node로 노드 이름을 지정하는 건 선택사항이에요. 지정하지 않으면 Buildx가 무작위 노드 이름을 생성해요.
Buildx의 노드 개념은 Kubernetes의 노드 개념과 같지 않다는 점에 주의하세요. 이 경우 Buildx 노드는 같은 아키텍처의 Kubernetes 노드 여러 개를 함께 연결할 수 있어요.
kube 빌더가 만들어졌으면 --append로 다른 아키텍처를 추가할 수 있어요. 예를 들어 arm64를 추가하려면:
$ docker buildx create \
--append \
--bootstrap \
--name=kube \
--driver=kubernetes \
--platform=linux/arm64 \
--node=builder-arm64 \
--driver-opt=namespace=buildkit,nodeselector="kubernetes.io/arch=arm64"
빌더를 나열하면 kube 빌더의 두 노드가 모두 보여요:
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
kube kubernetes
builder-amd64 kubernetes:///kube?deployment=builder-amd64&kubeconfig= running linux/amd64*, linux/amd64/v2, linux/amd64/v3, linux/386
builder-arm64 kubernetes:///kube?deployment=builder-arm64&kubeconfig= running linux/arm64*
이제 빌드 명령에서 플랫폼을 함께 지정해 멀티 아키텍처 amd64·arm64 이미지를 빌드할 수 있어요:
$ docker buildx build --builder=kube --platform=linux/amd64,linux/arm64 -t <user>/<image> --push .
지원하고 싶은 아키텍처 수만큼 docker buildx create --append 명령을 반복할 수 있어요.
루트리스 모드 (Rootless mode)
Kubernetes 드라이버는 루트리스 모드를 지원해요. 루트리스 모드가 동작하는 방식과 요구사항에 대한 자세한 내용은 루트리스 Buildkit 문서를 참고하세요.
클러스터에서 켜려면 rootless=true 드라이버 옵션을 사용해요:
$ docker buildx create \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,rootless=true
그러면 securityContext.privileged 없이 파드가 만들어져요.
Kubernetes 버전 1.19 이상이 필요해요. 호스트 커널로 Ubuntu를 사용하는 것을 권장해요.
예시: Kubernetes에서 Buildx 빌더 만들기 (Creating a Buildx builder in Kubernetes)
이 가이드는 다음 방법을 보여줘요:
- Buildx 리소스를 위한 namespace 만들기
- Kubernetes 빌더 만들기
- 사용 가능한 빌더 나열하기
- Kubernetes 빌더로 이미지 빌드하기
사전 요구사항:
-
기존 Kubernetes 클러스터가 있어야 해요. 없다면 minikube를 설치해 따라 하면 돼요.
-
연결하려는 클러스터가
kubectl명령으로 접근 가능해야 해요. 필요하면KUBECONFIG환경 변수를 적절히 설정해요. -
buildkit namespace를 만들어요. 별도의 namespace를 만들면 Buildx 리소스를 클러스터의 다른 리소스와 분리해서 관리할 수 있어요.
$ kubectl create namespace buildkit namespace/buildkit created -
Kubernetes 드라이버로 새 빌더를 만들어요.
$ docker buildx create \ --bootstrap \ --name=kube \ --driver=kubernetes \ --driver-opt=namespace=buildkitNote
드라이버 옵션에 namespace를 반드시 지정하세요.
-
docker buildx ls로 사용 가능한 빌더를 나열해요.$ docker buildx ls NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS kube kubernetes kube0-6977cdcb75-k9h9m running linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386 default * docker default default running linux/amd64, linux/386 -
kubectl로 빌드 드라이버가 만든 실행 중인 파드를 검사해요.$ kubectl -n buildkit get deployments NAME READY UP-TO-DATE AVAILABLE AGE kube0 1/1 1 1 32s $ kubectl -n buildkit get pods NAME READY STATUS RESTARTS AGE kube0-6977cdcb75-k9h9m 1/1 Running 0 32s빌드 드라이버는 지정된 namespace(이 경우
buildkit)에 필요한 리소스를 클러스터에 만들어 주면서, 드라이버 구성 자체는 로컬에 유지해요. -
Buildx 명령을 실행할 때
--builder플래그를 포함해 새 빌더를 사용해요. 예:# Replace <registry> with your Docker username # and <image> with the name of the image you want to build docker buildx build \ --builder=kube \ -t <registry>/<image> \ --push .
이제 끝이에요. Buildx를 사용해 Kubernetes 파드에서 이미지를 빌드했습니다.