Kubernetes cluster 를 생성하고, 사용자의 Application 을 설치하기 전 몇가지 plug-in/middleware 를 설치 해야 합니다. 예를 들면.. cert-manager, nginx-ingress, metrics-server, prometheus, grafana 같은 것들이 있습니다.

이것들을 설치하기 위해서는 여러 방법이 있지만 Helm Chart 로 설치 하는 것이 가장 빠르고, 쉽다고 생각 합니다.

하지만,

  • 설치하는 환경마다 변수 관리를 해야 합니다.
  • CRD/CR 를 먼저 설치 해야 하는 경우도 있습니다.
  • Chart 마다 Dependency 가 있어서 순서가 필요할 수 있습니다.
  • 그리고 이 모든것을 위하여 IaC 가 필요 합니다.

이것을 해결 할 수 있는 Tool 이 helmfile 입니다.

장점

  • 설치 Environment 마다 변수를 Code 에 관리할 수 있습니다.
  • Chart 가 설치 되는 동안 대기할 수 있습니다.
  • Hook 을 통해 Chart 를 설치 하기전 특정 작업을 수행할 수 있습니다. (CRD 설치 등)
  • 세트를 구성하여 여러 Chart 를 한번에 설치/관리가 가능 합니다.
  • apply 명령을 통해 변경된 경우에만 적용할 수 있습니다.

Tool 설치

Mac 을 예로 들겠습니다. kubectl, helm, helmfile 을 설치 합니다. AWS Cloud 에 배포 할 경우 awscli 를 설치 합니다. 기존 설치 되었던 chart 와 비교를 위해 helm-diff plug-in 을 설치 합니다.

brew install kubernetes-cli
brew install helm
brew install helmfile

pip install --upgrade --user awscli

helm plugin install https://github.com/databus23/helm-diff --version master

helmfile

cert-manager 를 예를 틀어 보겠습니다. (이미 Kubernetes cluster 가 생성되어 있고, 권한이 있다고 가정 합니다.)

다음과 같은 구조로 파일을 생성 합니다.

.
├── helmfiles.yaml
├── environments
│   ├── default.yaml
│   ├── eks-demo.yaml
├── releases
│   ├── cert-manager.yaml
│   ├── cert-manager.yaml.gotmpl
│   ├── cert-manager-issuers.yaml.gotmpl

helmfiles.yaml

메인 파일 입니다. environments, helmfiles 를 정의 합니다.

environments:
  default:
    values:
      - environments/default.yaml
  eks-demo:
    values:
      - environments/eks-demo.yaml

helmfiles:
  - releases/cert-manager.yaml

default.yaml

environments 를 정의 하지 않았을때 적용 될 환경 파일 입니다.

demo-env.yaml

demo-env 라는 Cluster 에 적용할 환경 파일 입니다.

cert-manager:
  issuer-email: my@domain.com

cert-manager.yaml

helm repository 로 jetstack, incubator 를 등록 합니다.

environments 은 default, eks-demo 를 등록 합니다.

releases 에 chart 정보를 입력 합니다.

Hook 을 통해 cert-manager 를 생성하기 전 kubectl apply -f ../00-crds.yaml 을 실행 합니다. cert-manager.yaml.gotmpl 를 values 로 사용하여 jetstack/cert-manager 를 생성 합니다.

cert-manager-issuers.yaml.gotmpl 를 values 로 사용하여 ClusterIssuer 를 생성 합니다.

repositories:
  - name: jetstack
    url: https://charts.jetstack.io
  - name: incubator
    url: https://kubernetes-charts-incubator.storage.googleapis.com

environments:
  default:
    values:
      - ../../environments/default.yaml
  eks-demo:
    values:
      - ../../environments/eks-demo.yaml

releases:
  - name: cert-manager
    namespace: kube-ingress
    chart: jetstack/cert-manager
    version: ~v0.13.0
    installed: true
    wait: true
    hooks:
      - events: ["presync"]
        showlogs: true
        command: "/bin/sh"
        args:
          - -c
          - kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.13/deploy/manifests/00-crds.yaml
    values:
      - cert-manager.yaml.gotmpl

  - name: cert-manager-issuers
    namespace: kube-ingress
    chart: incubator/raw
    version: ~0.1.0
    installed: true
    # wait: true
    # force: true
    # recreatePods: true
    values:
      - cert-manager-issuers.yaml.gotmpl

cert-manager.yaml.gotmpl

nameOverride: cert-manager

rbac:
  create: true

ingressShim:
  defaultIssuerName: letsencrypt-issuer
  defaultIssuerKind: ClusterIssuer

cert-manager-issuers.yaml.gotmpl

acme.emaildemo-env.yaml 에서 정의한 cert-manager.issuer-email 값을 치환 합니다.

resources:
  - apiVersion: cert-manager.io/v1alpha2
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-issuer
    spec:
      acme:
        # The ACME server URL
        server: https://acme-v02.api.letsencrypt.org/directory
        # Email address used for ACME registration
        email: '{ { .Values | getOrNil "cert-manager.issuer-email" | default "issuer@example.com" } }'
        # Name of a secret used to store the ACME account private key
        privateKeySecretRef:
          name: letsencrypt-issuer
        solvers:
          # An empty 'selector' means that this solver matches all domains
          - selector: {}
            http01:
              ingress:
                class: nginx

실행

  • sync : 선언된 모든 chart 를 재설치 합니다.
  • apply : 변경된 chart 만 재설치 합니다.
  • destroy : 모든 chart 를 삭제 합니다.
helmfile sync
helmfile destroy

helmfile -f helmfile.yaml -e eks-demo apply
helmfile -f helmfile.yaml -e eks-demo destroy

참고