Skip to content

Split View: Helm 플러그인과 테스트 전략: 확장성과 품질 보장

|

Helm 플러그인과 테스트 전략: 확장성과 품질 보장


1. 플러그인 시스템

1.1 플러그인 구조

Helm 플러그인은 plugin.yaml 매니페스트로 정의됩니다:

# plugin.yaml
name: 'my-plugin'
version: '1.0.0'
usage: 'A custom Helm plugin'
description: 'This plugin does something useful'
command: '$HELM_PLUGIN_DIR/bin/my-plugin'
hooks:
  install: '$HELM_PLUGIN_DIR/scripts/install.sh'
  update: '$HELM_PLUGIN_DIR/scripts/update.sh'
  delete: '$HELM_PLUGIN_DIR/scripts/cleanup.sh'
platformCommand:
  - os: linux
    arch: amd64
    command: '$HELM_PLUGIN_DIR/bin/my-plugin-linux-amd64'
  - os: darwin
    arch: arm64
    command: '$HELM_PLUGIN_DIR/bin/my-plugin-darwin-arm64'

1.2 플러그인 관리

# 플러그인 설치
helm plugin install https://github.com/example/helm-my-plugin
helm plugin install https://github.com/example/helm-my-plugin --version 1.0.0

# 플러그인 목록
helm plugin list

# 플러그인 업데이트
helm plugin update my-plugin

# 플러그인 삭제
helm plugin uninstall my-plugin

# 플러그인 환경 변수
# HELM_PLUGIN_DIR: 플러그인 디렉터리
# HELM_PLUGIN_NAME: 플러그인 이름
# HELM_BIN: helm 바이너리 경로

1.3 주요 플러그인

helm-diff

변경사항을 미리 확인할 수 있는 핵심 플러그인:

# 설치
helm plugin install https://github.com/databus23/helm-diff

# 업그레이드 전 변경사항 미리보기
helm diff upgrade my-release ./my-chart -f values.yaml

# 특정 리비전 간 비교
helm diff revision my-release 2 3

# 롤백 시 변경사항 미리보기
helm diff rollback my-release 2

helm-secrets

Secret 값을 안전하게 관리:

# 설치
helm plugin install https://github.com/jkroepke/helm-secrets

# SOPS로 암호화된 values 파일 사용
helm secrets install my-release ./my-chart -f secrets.yaml

# 값 암호화/복호화
helm secrets enc secrets.yaml
helm secrets dec secrets.yaml
helm secrets view secrets.yaml

helm-unittest

차트 유닛 테스트:

# 설치
helm plugin install https://github.com/helm-unittest/helm-unittest

# 테스트 실행
helm unittest ./my-chart
helm unittest ./my-chart -f 'tests/*_test.yaml'

2. 차트 테스트

2.1 helm test

Helm에 내장된 테스트 메커니즘으로, 릴리스 후 클러스터 내에서 실행됩니다:

# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
  name: {{ include "my-chart.fullname" . }}-test-connection
  labels:
    {{- include "my-chart.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": test
spec:
  restartPolicy: Never
  containers:
    - name: wget
      image: busybox
      command: ['wget']
      args: ['{{ include "my-chart.fullname" . }}:{{ .Values.service.port }}']
# 테스트 실행
helm test my-release

# 타임아웃 지정
helm test my-release --timeout 5m

# 테스트 로그 조회
helm test my-release --logs

2.2 helm-unittest

클러스터 없이 로컬에서 실행되는 유닛 테스트:

# tests/deployment_test.yaml
suite: test deployment
templates:
  - deployment.yaml
tests:
  - it: should create deployment with correct replicas
    set:
      replicaCount: 3
    asserts:
      - isKind:
          of: Deployment
      - equal:
          path: spec.replicas
          value: 3

  - it: should set correct image
    set:
      image:
        repository: nginx
        tag: '1.25'
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: 'nginx:1.25'

  - it: should not create ingress when disabled
    template: ingress.yaml
    set:
      ingress:
        enabled: false
    asserts:
      - hasDocuments:
          count: 0

  - it: should have resource limits
    asserts:
      - isNotNull:
          path: spec.template.spec.containers[0].resources.limits

  - it: should match snapshot
    asserts:
      - matchSnapshot: {}

2.3 ct(chart-testing) 도구

CI/CD 파이프라인에서 차트 변경 감지와 테스트 자동화:

# 설치
# ct는 별도 바이너리로 설치 (Homebrew, Docker 등)

# 변경된 차트 감지 (Git diff 기반)
ct list-changed --target-branch main

# 차트 린트
ct lint --target-branch main

# 차트 설치 테스트 (Kind 클러스터에서)
ct install --target-branch main

# 린트 + 설치 테스트
ct lint-and-install --target-branch main

ct 설정 파일:

# ct.yaml
remote: origin
target-branch: main
chart-dirs:
  - charts
chart-repos:
  - bitnami=https://charts.bitnami.com/bitnami
helm-extra-args: --timeout 600s
validate-maintainers: false

3. 린팅(Linting)

3.1 helm lint

# 기본 린트
helm lint ./my-chart

# 엄격 모드
helm lint ./my-chart --strict

# values 파일과 함께 검증
helm lint ./my-chart -f production-values.yaml

# set 옵션과 함께
helm lint ./my-chart --set replicaCount=3

helm lint가 검사하는 항목:

  • Chart.yaml 필수 필드 존재 여부
  • 템플릿 렌더링 오류
  • values.yaml 유효성
  • 차트 이름과 버전 규칙 준수
  • 레이블과 어노테이션 권장 사항

3.2 yamllint와 kubeval/kubeconform

# YAML 문법 검사
helm template my-release ./my-chart | yamllint -

# Kubernetes 스키마 검증 (kubeconform)
helm template my-release ./my-chart | kubeconform \
  -strict \
  -kubernetes-version 1.29.0 \
  -summary

4. 스키마 검증(Schema Validation)

4.1 values.schema.json

JSON Schema로 values의 유효성을 검증합니다:

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["replicaCount", "image"],
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Number of pod replicas"
    },
    "image": {
      "type": "object",
      "required": ["repository"],
      "properties": {
        "repository": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9._/-]*$"
        },
        "tag": {
          "type": "string",
          "default": "latest"
        },
        "pullPolicy": {
          "type": "string",
          "enum": ["Always", "IfNotPresent", "Never"]
        }
      }
    },
    "service": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": ["ClusterIP", "NodePort", "LoadBalancer"]
        },
        "port": {
          "type": "integer",
          "minimum": 1,
          "maximum": 65535
        }
      }
    },
    "resources": {
      "type": "object",
      "properties": {
        "limits": {
          "type": "object",
          "properties": {
            "cpu": { "type": "string" },
            "memory": { "type": "string" }
          }
        },
        "requests": {
          "type": "object",
          "properties": {
            "cpu": { "type": "string" },
            "memory": { "type": "string" }
          }
        }
      }
    }
  }
}

스키마는 helm install, helm upgrade, helm lint, helm template 실행 시 자동으로 검증됩니다.


5. OCI 레지스트리 고급 사용

5.1 OCI 아티팩트로 차트 관리

# 패키징
helm package ./my-chart

# OCI 레지스트리에 푸시
helm push my-chart-1.0.0.tgz oci://ghcr.io/myorg/charts

# OCI에서 직접 설치
helm install my-release oci://ghcr.io/myorg/charts/my-chart --version 1.0.0

# OCI에서 풀
helm pull oci://ghcr.io/myorg/charts/my-chart --version 1.0.0

# 차트 정보 조회
helm show chart oci://ghcr.io/myorg/charts/my-chart --version 1.0.0
helm show values oci://ghcr.io/myorg/charts/my-chart --version 1.0.0

5.2 CI/CD에서의 OCI 활용

# GitHub Actions 예시
# .github/workflows/helm-publish.yaml
name: Publish Helm Chart
on:
  push:
    tags: ['v*']
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Login to GHCR
        run: echo "$GITHUB_TOKEN" | helm registry login ghcr.io -u $ --password-stdin
      - name: Package and Push
        run: |
          helm package ./charts/my-app
          helm push my-app-*.tgz oci://ghcr.io/$GITHUB_REPOSITORY_OWNER/charts

6. 차트 서명과 검증

6.1 Provenance 파일

# GPG 키로 차트 서명
helm package --sign --key 'my-key' --keyring ~/.gnupg/secring.gpg ./my-chart

# 서명 검증
helm verify my-chart-1.0.0.tgz

# 설치 시 검증
helm install my-release my-chart-1.0.0.tgz --verify

6.2 .prov 파일 구조

패키징 시 my-chart-1.0.0.tgz.prov 파일이 생성되며, 차트의 무결성과 출처를 증명합니다.


7. 정리

Helm의 확장성과 품질 보장:

  1. 플러그인 시스템: helm-diff, helm-secrets, helm-unittest 등으로 기능 확장
  2. 다층 테스트: helm test(통합), unittest(유닛), ct(CI/CD) 조합
  3. 린팅: helm lint, yamllint, kubeconform으로 다각도 검증
  4. 스키마 검증: values.schema.json으로 입력값 유효성 보장
  5. OCI 레지스트리: 컨테이너 이미지와 동일한 워크플로우로 차트 배포
  6. 서명/검증: 차트의 무결성과 출처 증명

다음 글에서는 Helm 차트 설계 Best Practices를 다룹니다.

Helm Plugins and Testing Strategies: Extensibility and Quality Assurance


1. Plugin System

1.1 Plugin Structure

# plugin.yaml
name: 'my-plugin'
version: '1.0.0'
usage: 'A custom Helm plugin'
description: 'This plugin does something useful'
command: '$HELM_PLUGIN_DIR/bin/my-plugin'
hooks:
  install: '$HELM_PLUGIN_DIR/scripts/install.sh'
  update: '$HELM_PLUGIN_DIR/scripts/update.sh'
  delete: '$HELM_PLUGIN_DIR/scripts/cleanup.sh'

1.2 Plugin Management

helm plugin install https://github.com/example/helm-my-plugin
helm plugin list
helm plugin update my-plugin
helm plugin uninstall my-plugin

1.3 Key Plugins

helm-diff: Preview changes before upgrade

helm plugin install https://github.com/databus23/helm-diff
helm diff upgrade my-release ./my-chart -f values.yaml
helm diff revision my-release 2 3

helm-secrets: Secure secret management

helm plugin install https://github.com/jkroepke/helm-secrets
helm secrets install my-release ./my-chart -f secrets.yaml
helm secrets enc secrets.yaml

helm-unittest: Chart unit testing

helm plugin install https://github.com/helm-unittest/helm-unittest
helm unittest ./my-chart

2. Chart Testing

2.1 helm test

Built-in test mechanism that runs in-cluster after release:

# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
  name: {{ include "my-chart.fullname" . }}-test-connection
  annotations:
    "helm.sh/hook": test
spec:
  restartPolicy: Never
  containers:
    - name: wget
      image: busybox
      command: ['wget']
      args: ['{{ include "my-chart.fullname" . }}:{{ .Values.service.port }}']
helm test my-release --timeout 5m --logs

2.2 helm-unittest

Local unit tests without a cluster:

# tests/deployment_test.yaml
suite: test deployment
templates:
  - deployment.yaml
tests:
  - it: should create deployment with correct replicas
    set:
      replicaCount: 3
    asserts:
      - isKind:
          of: Deployment
      - equal:
          path: spec.replicas
          value: 3

  - it: should set correct image
    set:
      image:
        repository: nginx
        tag: '1.25'
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: 'nginx:1.25'

  - it: should not create ingress when disabled
    template: ingress.yaml
    set:
      ingress:
        enabled: false
    asserts:
      - hasDocuments:
          count: 0

2.3 ct (chart-testing) Tool

Automated chart change detection and testing in CI/CD:

ct list-changed --target-branch main
ct lint --target-branch main
ct install --target-branch main
ct lint-and-install --target-branch main

3. Linting

helm lint ./my-chart --strict
helm lint ./my-chart -f production-values.yaml

# Kubernetes schema validation
helm template my-release ./my-chart | kubeconform -strict -kubernetes-version 1.29.0

4. Schema Validation

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["replicaCount", "image"],
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "image": {
      "type": "object",
      "required": ["repository"],
      "properties": {
        "repository": { "type": "string" },
        "tag": { "type": "string", "default": "latest" },
        "pullPolicy": { "type": "string", "enum": ["Always", "IfNotPresent", "Never"] }
      }
    },
    "service": {
      "type": "object",
      "properties": {
        "type": { "type": "string", "enum": ["ClusterIP", "NodePort", "LoadBalancer"] },
        "port": { "type": "integer", "minimum": 1, "maximum": 65535 }
      }
    }
  }
}

Schema is automatically validated during helm install, helm upgrade, helm lint, and helm template.


5. OCI Registry Advanced Usage

helm package ./my-chart
helm push my-chart-1.0.0.tgz oci://ghcr.io/myorg/charts
helm install my-release oci://ghcr.io/myorg/charts/my-chart --version 1.0.0
helm pull oci://ghcr.io/myorg/charts/my-chart --version 1.0.0

6. Chart Signing and Verification

helm package --sign --key 'my-key' --keyring ~/.gnupg/secring.gpg ./my-chart
helm verify my-chart-1.0.0.tgz
helm install my-release my-chart-1.0.0.tgz --verify

7. Summary

Helm extensibility and quality assurance:

  1. Plugin system: Extend functionality with helm-diff, helm-secrets, helm-unittest
  2. Multi-layer testing: Combine helm test (integration), unittest (unit), ct (CI/CD)
  3. Linting: Multi-angle validation with helm lint, yamllint, kubeconform
  4. Schema validation: Ensure input validity with values.schema.json
  5. OCI registry: Deploy charts using the same workflow as container images
  6. Signing/verification: Prove chart integrity and provenance