티스토리 뷰

IT/Devops

[cicd] 1주차 - Image Build

Hayley Shim 2025. 10. 19. 01:05

안녕하세요, CICD 학습을 위해 CloudNetaStudy 스터디 모임을 통해 진행한 내용을 정리하였습니다.

 

1주차는 [GitOps Cookbook] 1~4장(84p) - 도커/K8S 기반 컨테이너 빌드, Kustomize 에 대해 중점적으로 학습합니다.

 

[개념]

GitOps란?

  • Git 저장소를 단일 소스로 사용하여 인프라를 코드로 제공. DevOps 가 애자일 소프트웨어 개발 프로세스를 보완한다면, GitOps는 인프라 자동화 및 애플리케이션 수명 주기 관리 측면에서 DevOps를 보완

GitOps 3가지 중요 원칙

  • Git을 신뢰할 수 있는 단일 소스로 취급 Git is the single source of truth
  • 모든 것은 코드로 표현 Treat everything as code
  • 작업은 Git 워크플로 workflow를 통해 수행 Operations are performed through Git workflows

쿠버네티스 CI/CD

  • CI Continuous Integration 지속적 통합CD Continuous Delivery 지속적 배포는 앱 개발의 각 단계에 자동화를 도입하여 앱을 더 자주 배포할 수 있도록 하는 방법론 → CI/CD 파이프라인은 GitOps 의 가장 일반적인 use cases.
  • 쿠버네티스를 사용하면 클러스터 내부에 CI/CD 파이프라인을 쉽게 구현가능

쿠버네티스에 GitOps를 접목한 앱 배포 방법

  • GitOps 엔진은 CI/CD 파이프라인의 CD 부분을 담당하며, 4가지 주요 작업으로 구성된 GitOps 생명 주기를 구현함
    • 배포 Deploy : Git에 저장된 매니페스트를 배포한다.
    • 모니터링 Monitor : Git 저장소나 클러스터 상태를 모니터링한다.
    • 변화 감지 Detect drift : Git에 설명된 내용과 클러스터의 실제 구성 사이의 차이를 감지한다.
    • 반영 Take action
      • Git에 있는 내용을 클러스터에 반영하는 작업 (롤백 또는 3-way diff)을 실행한다.
      • Git 저장소의 내용만을 신뢰 가능한 정보로 본다.
      • 모든 변경은 Git 워크플로를 통해 수행한다.

데브옵스 및 기민성 Agility

  • DevOps 가 애자일 소프트웨어 개발 프로세스를 보완한다면, GitOps는 인프라 자동화 및 애플리케이션 수명 주기 관리 측면에서 DevOps를 보완
  • 애자일 방법론의 가장 중요한 점 가운데 하나는 납기 lead time 를 줄인다는 것
  • DevOps 철학과 마찬가지로 GitOps 역시 사업 프로세스에 문화로 스며들어야 한다.
  • 애플리케이션 배포나 인프라 변경 같은 모든 작업은 Git 워크플로를 통해서만 할 수 있어야 하는데, 그러려면 개발 문화 자체가 달라져야 한다.

 

 

[실습 환경]

- 컨테이너 레지스트리에 등록 : docker hub 혹은 quay.io 퀘이 가입

- https://github.com/gitops-cookbook/gitops-cookbook-sc 접속하여여 소스 코드 복제

git clone https://github.com/gitops-cookbook/chapters

 

- 로컬 쿠버네티스 클러스터 생성 : kind k8s - v1.32.8 (최근 3개 버전 release branches 패치 지원) - Link , kind_docker_hub

- Docker Hub - Docs

  • 사용자들은 도커 허브에 이미지를 업로드하고, 다른 곳에서 자유롭게 재사용(다운로드)할 수 있습니다.
  • 도커 허브(Docker Hub)는 도커 이미지 원격 저장소입니다.
 

Docker Hub

Get an overview on Docker Hub to find and share container images

docs.docker.com

- kind  : ‘도커 IN 도커 docker in docker’로 쿠버네티스 클러스터 환경을 구성 - Link

 

- 실습을 위한 kind 로 k8s 배포

# 클러스터 배포 전 확인
docker info
docker ps


# Create a cluster with kind
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
- role: worker
EOF


# 확인
docker images
kind get nodes --name myk8s
kubens default

# kind 는 별도 도커 네트워크 생성 후 사용 : 예) docker 기본값 172.18.0.0/16 , orbstack 192.168.97.0/24
docker network ls
docker inspect kind | jq

# k8s api 주소 확인 : 어떻게 로컬에서 접속이 되는 걸까?
kubectl cluster-info
docker ps

# 노드 정보 확인 : CRI 는 containerd 사용
kubectl get node -o wide

# 파드 정보 확인 : CNI 는 kindnet 사용
kubectl get pod -A -o wide

# 네임스페이스 확인 >> 도커 컨테이너에서 배운 네임스페이스와 다릅니다!
kubectl get namespaces

# 컨트롤플레인/워커 노드(컨테이너) 확인 : 도커 컨테이너 이름은 myk8s-control-plane , myk8s-worker 임을 확인
docker ps
docker images
docker exec -it myk8s-control-plane ss -tnlp

# 디버그용 내용 출력에 ~/.kube/config 권한 인증 로드
kubectl get pod -v6

# kube config 파일 확인
cat ~/.kube/config
혹은
cat $KUBECONFIG

# 클러스터 삭제
kind delete cluster --name myk8s
docker ps
cat ~/.kube/config

 

 

[Container]

- 컨테이너는 애플리케이션을 배포 목적으로 패키징할 때 널리 사용되는 표준형식

 

1. 도커를 사용한 컨테이너 (이미지) 빌드 : layer , image build / push

- Dockerfile : “사용자가 이미지를 조립하기 위해 명령행에서 호출하는 모든 명령을 담은 텍스트 문서”

  • 각 컨테이너 이미지는 기반 레이어 layer 에 적용된 변경 사항들로 구성
  • 새로운 변경이 적용될 때마다 레이어가 하나씩 추가로 커밋 commit 됨

 

도커파일 확인 - Code , Base_python39 (참고로 ubi8/python-39 컨테이너 이미지는 ‘25년 11월에 만료 예정)

컨테이너 이미지 빌드

  • 도커파일에 지정된 명령을 실행할 때마다 새 레이어를 추가한다.
  • 각각의 레이어는 컨테이너 캐시 container cache 또는 도커 캐시 docker cache 라 부르는 특별한 로컬 저장소에 보관된다.
  • 이전에 만든 적 있는 레이어가 캐시에 있으면 재사용하고, 없으면 새로 만든다.

 

컨테이너 이미지 레이어 확인

 

공개 레지스트리에 푸시 후 확인

 

공개 레지스트리에 이미지로 컨테이너 실행 확인

 

2. 1도커가 필요 없는 Jib을 사용한 컨테이너 빌드

- Jib로 자바 컨테이너 빌드 소개 - Docs , Blog1 , Blog2 , Blog3

- Jib는 Dockerfile을 사용하지 않거나 Docker를 설치할 필요 없이 컨테이너를 빌드함 → 예를 들어 젠킨스 컨테이너 내부에 도커 설치 필요 X

 

jib를 활용하여 젠킨스 파이프라인 구성하기(GitOps + SpringBoot + Gradle )

jib 소개jib는 Google에서 제공하는 Maven/Gradle 플러그인으로, Dockerfile 없이 Java 애플리케이션을 컨테이너 화할 수 있는 도구이다.Jib(지브)라는 의미에 단어의 의미처럼 돛이 배의 방향을 조정하고 민

hackjsp.tistory.com

 

3. 빌다 Buildah (+Podman) 를 사용한 컨테이너 빌드 - Home, Docs, Github , KrBlog

- 도커 없이 컨테이너 이미지를 만들 수 있도록 하는 솔루션은 로컬 개발 또는 CI/CD 시스템 등에 유용

 

4. 빌드팩 Buildpacks 을 통한 컨테이너 빌드 - Home , Docs , Github

- 도커파일 Dockerfile 을 사용하는 개발 환경은 대규모 scale 개발 환경에서는 적용하기 까다로울 수 있음

- 도커파일 Dockerfile 없이도 애플리케이션 소스 코드를 검사하여 컨테이너 이미지를 생성할 수 있는 도구가 필요

- 클라우드 네이티브 빌드팩 Cloud Native Buildpacks (CNB)은 앱 소스 코드를 검사하여 애플리케이션 빌드 및 실행 계획을 생성하는 실행 파일들을 제공하는 오픈 소스 프로젝트

 

5. 십라이트 Shipwrite 와 카니코 kaniko or 빌다 Buildah 를 사용한 쿠버네티스 기반 컨테이너 빌드 - Home , Intro

- 십라이트 Shipwrite 는 쿠버네티스에서 컨테이너 이미지를 빌드하는 확장 가능 프레임워크 - Home , Intro

솔루션 주요 특징 장점 및 사용 사례
Jib Dockerfile 없이 Java 애플리케이션을 컨테이너화하는 Google의 Maven/Gradle 플러그인.
Java 특화. 도커 설치가 필요 없으므로 Jenkins 컨테이너 내부에서 도커를 설치할 필요가 없음. 빠르고 재현 가능한 빌드 가능.
Buildah
(+ Podman)
도커 데몬 없이 컨테이너 이미지를 생성하고 관리하는 도구.
도커 없이 이미지 빌드 및 관리가 가능하여 로컬 개발이나 CI/CD 시스템에서 유용. 루트 권한 없이 이미지 빌드 가능.
Buildpacks
(Cloud Native Buildpacks, CNB)
Dockerfile 없이 애플리케이션 소스 코드를 검사하여 컨테이너 이미지를 생성.
대규모 개발 환경에서 Dockerfile 관리가 어려울 때 유용. 앱 소스 코드만으로 빌드 및 실행 계획을 자동 생성.
Shipwright
& Kaniko/Buildah
쿠버네티스(Kubernetes) 환경 내에서 컨테이너 이미지를 빌드하는 확장 가능 프레임워크.
쿠버네티스 기반 환경에 특화되어 컨테이너 빌드를 네이티브하게 처리. CI/CD 파이프라인을 쿠버네티스 위에서 효율적으로 구축.

 

 

[Kustomize]

- Kustomize - Home , Docs , Intro , Components , Extending , Example , Blog

 

Blog | Dragonfly

Blog

d7y.io

- 쿠버네티스 클러스터에 배포한다는 것은 결국 YAML 파일들을 클러스터에 적용하고 결과를 확인하는 단순한 작업

- 어려운 부분은 이 YAML 파일의 첫 버전을 개발

- 그 이후에는 보통 컨테이너 이미지 태그 버전을 바꾸거나, replicas 수 또는 configuration values 변경 등의 작은 업데이트만 발생

- 일부 도구는 자주 변경되지 않는 기본 쿠버네티스 매니페스트를 하나 두고, 자주 변경되는 파라미터를 설정하기 위한 파일만 환경별로 하나씩 정의할 수 있게 해준다.

- 이러한 도구 중 하나가 커스터마이즈 Kustomize 다 - Home , Guides , Docs

- 커스터마이즈는 기본 YAML 파일의 설정치를 병합 전략이나 JSON 패치 표현식을 통해 템플릿을 사용하지 않고도 재정의할 수 있도록 하는 간단한 도구

 

 

Kustomize 실습 : 환경별 설정 관리

다음은 Kustomize를 사용하여 기본(Base) 배포 설정을 두고, 개발(Dev) 환경과 운영(Prod) 환경에서 설정을 다르게 적용하는 기본적인 실습

 

1. 프로젝트 구조

먼저 다음과 같은 디렉토리 구조를 설정

.
├── base
│   ├── deployment.yaml   # 기본 배포 설정
│   ├── service.yaml      # 기본 서비스 설정
│   └── kustomization.yaml # 기본 리소스 목록
└── overlays
    ├── dev
    │   └── kustomization.yaml # 개발 환경 오버레이
    └── prod
        └── kustomization.yaml # 운영 환경 오버레이

 

 

2. Base (기본 설정) 정의

base/deployment.yaml (기본 배포)

이 파일은 모든 환경에서 공통으로 사용되는 기본 설정

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 2 # 기본 replicas 수
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-registry/my-app:v1.0.0 # 기본 이미지 태그
        ports:
        - containerPort: 8080

 

base/kustomization.yaml (기본 Kustomization 파일)

base 디렉토리에 포함된 리소스 파일들을 나열

resources:
  - deployment.yaml
  - service.yaml # (service.yaml이 있다고 가정)

# 모든 환경에 공통으로 적용할 라벨
commonLabels:
  app: my-app
  environment: base

 

3. Overlays (환경별 재정의) 정의

 

A. Development (개발 환경) 오버레이

개발 환경에서는 복제본 수를 1개로 줄이고, 이미지 태그를 최신 개발 버전으로 변경하고자 합니다.

overlays/dev/kustomization.yaml

이 파일은 base 설정을 상속받아 원하는 부분만 재정의합니다.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# 1. Base 지정: 기본 설정을 가져올 위치
bases:
  - ../../base

# 2. Patch(패치) 적용: deployment.yaml의 일부 필드만 수정
patchesStrategicMerge:
  - deployment-patch.yaml

# 3. 추가적인 라벨 적용
commonLabels:
  environment: dev # 환경 라벨을 'dev'로 재정의

# 4. 이미지 태그 재정의
images:
  - name: my-registry/my-app # 기본 이미지 이름
    newTag: dev-latest # 새로운 태그 적용

overlays/dev/deployment-patch.yaml (복제본 수 수정 패치)

**전략적 병합 패치 (Strategic Merge Patch)**를 사용하여 base/deployment.yaml의 일부 필드만 수정합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app # 대상 리소스 지정 (필수)
spec:
  replicas: 1 # base의 2 대신 1로 변경

 

 

B. Production (운영 환경) 오버레이

운영 환경에서는 복제본 수를 4개로 늘리고, 안정된 이미지 태그를 사용하며, 환경 설정을 'prod'로 변경하고자 합니다.

overlays/prod/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

bases:
  - ../../base

patchesStrategicMerge:
  - deployment-patch.yaml # 별도로 정의된 패치 파일

commonLabels:
  environment: prod # 환경 라벨을 'prod'로 재정의

images:
  - name: my-registry/my-app
    newTag: v2.0.0 # 안정적인 새 태그 적용

 

overlays/prod/deployment-patch.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 4 # base의 2 대신 4로 변경

 

4. 결과 확인 (Build & Apply)

이제 각 환경 디렉토리에서 kustomize build 명령을 실행하여 최종 YAML 파일을 확인합니다.

 

개발 환경 빌드:

kustomize build overlays/dev

결과 (일부): replicas: 1, image: my-registry/my-app:dev-latest, environment: dev 라벨이 적용된 YAML 출력.

 

운영 환경 빌드:

kustomize build overlays/prod

결과 (일부): replicas: 4, image: my-registry/my-app:v2.0.0, environment: prod 라벨이 적용된 YAML 출력.

 

클러스터에 적용:

# 개발 환경에 배포
kustomize build overlays/dev | kubectl apply -f -

# 운영 환경에 배포
kustomize build overlays/prod | kubectl apply -f -

 

Kustomize가 템플릿 구문 없이 기본 파일을 재활용하고, 환경별 변경 사항만 오버레이 파일에 명시하여 YAML 관리를 단순화하는 것을 확인할 수 있습니다.

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함