로컬 Helm 차트 배포

KubernetesBeginner
지금 연습하기

소개

이전 배포 실습에서는 원시 (raw) Kubernetes 매니페스트를 직접 사용했습니다. Helm 은 이러한 매니페스트를 감싸는 패키징 계층을 추가합니다. Helm 차트는 관련 Kubernetes 템플릿을 함께 저장하고, values.yaml을 통해 재사용 가능한 설정을 노출하며, 렌더링된 객체를 이름이 지정된 릴리스로 설치합니다.

이번 실습에서는 저장소에서 차트를 다운로드하는 대신, 직접 소규모 로컬 차트를 빌드합니다. 차트 메타데이터, 값 (values), Deployment 템플릿, Service 템플릿을 작성하고, 설치 전 차트를 렌더링한 뒤, 값을 변경하여 릴리스를 업그레이드합니다. 이 과정을 통해 로컬 차트가 어떻게 일반적인 Kubernetes 객체로 변환되는지 이해함으로써 CKAD 핵심 역량을 강화합니다.

Helm 작업 공간 준비

이 단계에서는 네임스페이스를 준비하고 로컬 Helm 차트 워크플로우에 필요한 도구들을 확인합니다.

/home/labex/project에서 시작합니다. 이 실습에서는 차트 디렉터리, 생성된 매니페스트, 모든 명령어를 이 작업 공간 내에서 관리합니다.

mkdir -p /home/labex/project
cd /home/labex/project

Kubernetes API 서버에 접근 가능한지 확인합니다. VM 이 막 시작되어 노드가 아직 준비되지 않았다면, 몇 초 기다린 후 명령어를 다시 실행하세요.

kubectl get nodes --request-timeout=5s

예상 출력은 다음과 같습니다:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

클러스터 네트워킹 Pod 가 준비 (Ready) 상태가 될 때까지 기다립니다. 차트가 Service 를 생성하므로, 트래픽 테스트가 의미 있으려면 애플리케이션 Pod 이전에 클러스터 네트워킹이 먼저 준비되어야 합니다.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

예상 출력:

pod/calico-node-... condition met

ckad-prep-helm이라는 이름의 네임스페이스를 생성하고 현재 네임스페이스로 설정합니다:

kubectl create namespace ckad-prep-helm
kubectl config set-context --current --namespace=ckad-prep-helm

현재 네임스페이스와 Helm 클라이언트를 확인합니다. Helm 3 는 별도의 서버 측 Tiller 구성 요소 없이 현재 kubeconfig 를 사용하여 Kubernetes 와 직접 통신합니다.

kubectl config view --minify --output 'jsonpath={..namespace}'; echo
helm version --short

예상 출력은 다음과 같습니다:

ckad-prep-helm
v...

로컬 차트 생성 및 렌더링

이 단계에서는 최소한의 로컬 Helm 차트를 생성하고, 설치하기 전에 렌더링해 봅니다.

차트 디렉터리에는 몇 가지 중요한 구성 요소가 있습니다. Chart.yaml은 차트 자체를 설명합니다. values.yaml은 기본 설정을 포함합니다. templates/ 아래의 파일들은 {{ .Values.replicaCount }}와 같은 템플릿 표현식이 포함된 Kubernetes 매니페스트입니다. Helm 은 차트를 렌더링하거나 설치할 때 이러한 표현식을 구체적인 값으로 대체합니다.

차트 디렉터리를 생성합니다:

mkdir -p local-web-chart/templates

Chart.yaml을 작성합니다. 차트 이름은 릴리스 이름과 다릅니다. 릴리스 이름은 나중에 차트를 설치할 때 선택합니다.

cat > local-web-chart/Chart.yaml <<'EOF'
apiVersion: v2
name: local-web
description: A small local chart for CKAD deployment practice
type: application
version: 0.1.0
appVersion: "1.0"
EOF

values.yaml을 작성합니다. 이 기본값들은 Pod 수, 컨테이너 이미지, Service 포트, 애플리케이션이 제공하는 메시지를 제어합니다.

cat > local-web-chart/values.yaml <<'EOF'
replicaCount: 2
image:
  repository: busybox
  tag: "1.36"
service:
  port: 80
  targetPort: 8080
message: helm-v1
EOF

Deployment 템플릿을 생성합니다. 템플릿은 객체 이름과 레이블에 릴리스 이름을 사용하므로, 동일한 차트를 서로 다른 릴리스 이름으로 설치할 수 있습니다.

cat > local-web-chart/templates/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-web
  labels:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ .Chart.Name }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ .Chart.Name }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: web
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: IfNotPresent
        command:
        - /bin/sh
        - -c
        - |
          mkdir -p /www
          echo {{ .Values.message | quote }} > /www/index.html
          httpd -f -p {{ .Values.service.targetPort }} -h /www
        ports:
        - containerPort: {{ .Values.service.targetPort }}
        readinessProbe:
          httpGet:
            path: /
            port: {{ .Values.service.targetPort }}
          initialDelaySeconds: 1
          periodSeconds: 2
EOF

Service 템플릿을 생성합니다. Service 셀렉터가 Pod 템플릿과 동일한 레이블을 사용한다는 점에 주목하세요.

cat > local-web-chart/templates/service.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
  labels:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  selector:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
  ports:
  - port: {{ .Values.service.port }}
    targetPort: {{ .Values.service.targetPort }}
EOF

helm lint를 실행하여 차트 구조와 템플릿 문제를 확인합니다:

helm lint ./local-web-chart

예상 출력은 다음과 같습니다:

1 chart(s) linted, 0 chart(s) failed

차트를 로컬에서 렌더링합니다. helm template은 Helm 이 API 서버로 보낼 Kubernetes YAML 을 출력하지만, 실제로 객체를 생성하지는 않습니다.

helm template local-web ./local-web-chart | sed -n '1,120p'

예상 출력에는 local-web이라는 이름의 Service 와 local-web-web이라는 이름의 Deployment 가 포함됩니다.

차트를 릴리스로 설치

이 단계에서는 로컬 차트를 ckad-prep-helm 네임스페이스에 설치합니다.

차트를 설치하면 Helm 릴리스가 생성됩니다. 이 실습에서 릴리스 이름은 local-web입니다. Helm 은 릴리스 메타데이터를 기록하고, Kubernetes 는 Deployment 및 Service 와 같은 일반적인 객체를 수신합니다.

차트를 설치합니다:

helm install local-web ./local-web-chart

예상 출력은 다음과 같습니다:

NAME: local-web
STATUS: deployed

차트에 의해 생성된 Deployment 가 준비될 때까지 기다립니다:

kubectl rollout status deployment/local-web-web --timeout=120s

예상 출력:

deployment "local-web-web" successfully rolled out

릴리스와 생성된 Kubernetes 객체를 검사합니다:

helm list
kubectl get deployment,service -l app.kubernetes.io/instance=local-web

예상 출력은 다음과 같습니다:

local-web
deployment.apps/local-web-web
service/local-web

클라이언트 Pod 를 생성하고 Service 에 요청을 보냅니다. 이는 차트가 단순히 객체를 생성하는 것뿐만 아니라, 설치된 애플리케이션이 실제로 접근 가능한 상태임을 확인하는 과정입니다.

kubectl run chart-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/chart-client --timeout=120s
kubectl exec chart-client -- wget -qO- http://local-web

예상 출력:

helm-v1

새로운 값으로 릴리스 업그레이드

이 단계에서는 차트 값을 재정의하여 기존 릴리스를 업그레이드합니다.

차트에는 이미 재사용 가능한 템플릿이 포함되어 있습니다. 메시지나 복제본 (replica) 수를 변경하기 위해 템플릿 파일을 수정할 필요가 없습니다. helm upgrade는 새로운 값을 사용하여 동일한 차트를 다시 렌더링하고, Kubernetes 객체를 업데이트하며, 새로운 릴리스 리비전을 기록합니다.

3 개의 복제본에서 helm-v2 메시지를 제공하도록 릴리스를 업그레이드합니다:

helm upgrade local-web ./local-web-chart --set message=helm-v2 --set replicaCount=3

예상 출력은 다음과 같습니다:

Release "local-web" has been upgraded.
STATUS: deployed

업그레이드된 Deployment 가 준비될 때까지 기다립니다:

kubectl rollout status deployment/local-web-web --timeout=120s

예상 출력:

deployment "local-web-web" successfully rolled out

릴리스 기록과 현재 릴리스에 저장된 값을 검사합니다:

helm history local-web
helm get values local-web

예상 출력에는 두 개의 리비전과 재정의된 값이 포함됩니다:

REVISION
1
2
message: helm-v2
replicaCount: 3

실행 중인 Deployment 와 애플리케이션 응답을 확인합니다:

kubectl get deployment local-web-web
kubectl exec chart-client -- wget -qO- http://local-web

예상 출력은 다음과 같습니다:

3/3
helm-v2

요약

차트 메타데이터, 기본값, Kubernetes 템플릿을 사용하여 로컬 Helm 차트를 생성했습니다. 설치 전 차트를 렌더링하고, 릴리스로 설치하고, Service 를 테스트한 뒤, 값을 재정의하여 릴리스를 업그레이드했습니다. 핵심은 Helm 이 반복 가능한 애플리케이션 배포 작업을 패키징하면서도, kubectl로 검사할 수 있는 일반적인 Kubernetes 객체를 생성한다는 점입니다.