kustomize: 비밀이 있는 경량 배포를 위한 Helm의 대안

내 여정은 애플리케이션 중 일부를 도커 환경에서 일부 마이크로서비스용으로 구성한 kubernetes 클러스터로 옮기고 싶다는 단순한 바람에서 시작되었습니다.

목차


  • Why I looked for an alternative to Helm
  • kustomize as an alternative
  • The proposed deployment
  • Using system environment variables

  • 내 생각의 대상 애플리케이션은 소규모 애플리케이션, 특히 Discord 봇이었습니다. 이러한 애플리케이션에는 배포에 따라 변경될 수 있는 토큰 및 기타 자격 증명과 같은 몇 가지 비밀이 필요합니다.

    Helm의 대안을 찾은 이유

    Since I was already used to utilising Helm 빠르고 쉬운 배포를 위해 Discord 봇과 같은 마이크로 서비스에도 사용하는 것이 합리적으로 보였습니다. Helm을 모르는 사람들을 위해 Helm은 수십 개의 기사가 포함된 완전히 성장한 kubernetes용 패키지 관리자입니다.

    "완전히 성장한 패키지 관리자"라고 언급했듯이 매우 간단한 응용 프로그램에 대해 불필요한 부풀림을 많이 배송하는 단점도 있습니다. 이를 이해하기 위해 helm create 명령을 사용하여 기본 템플릿 또는 Helm 차트를 생성할 수 있습니다. 이 매우 기본적인 부트스트랩 차트는 이미 10개의 파일과 함께 제공되며 3개의 디렉토리에 분산되어 있습니다(아래 참조).

    |-- Chart.yaml
    |-- charts
    |-- templates
    |   |-- NOTES.txt
    |   |-- _helpers.tpl
    |   |-- deployment.yaml
    |   |-- hpa.yaml
    |   |-- ingress.yaml
    |   |-- service.yaml
    |   |-- serviceaccount.yaml
    |   `-- tests
    |       `-- test-connection.yaml
    `-- values.yaml
    


    나는 약간 순수주의자일 수 있지만 서비스가 필요하지 않은 애플리케이션 배포를 위한 10개의 파일은 부풀려진 것처럼 들립니다. 물론 불필요한 템플릿의 차트 정리를 시작하고 버전 관리와 같은 Helm 이점을 유지할 수 있습니다. 이것은 상당한 시간이 걸리고 혼란을 실제로 제거하지 않습니다.

    대안으로 kustomize

    kustomize은 필요한 경우 배치를 패치할 수 있는 내장형 구성 관리 시스템입니다. 또한 주어진 소스에서 비밀을 동적으로 생성할 수 있는 secretGenerator라는 편리한 도구를 제공합니다. 이 예에서는 이 도구에 크게 의존할 것입니다.

    꽤 일찍 깨달은 kustomize에 대한 한 가지 슬픈 점은 문서가 여전히 매우 열악하고 이미 구현된 많은 기능이 부족하다는 것입니다.

    제안된 배포

    It's recommended to structure a kustomize deployment into two folders base for the default deployment and overlays for the patching deployments.

    The simplest deployment that infuses our secrets can look like the following:

    base
    ├── deployment.yaml
    ├── kustomization.yaml
    └── secrets.env
    

    The deployment.yaml contains the kubernetes manifest that we'll use for the deployment.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-app
      labels:
        app: my-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          containers:
          - name: my-app
            image: ghcr.io/staubrein/myapp
            imagePullPolicy: Always
            env:
            - name: TOKEN
              valueFrom:
                secretKeyRef:
                  name: my-app-secrets
                  key: TOKEN
    

    This manifest expects a secret my-app-secret with a key TOKEN and adds it to the container environment.

    The content of this secret can be read from a casual .env file or in our case secrets.env .

    TOKEN=XXXXXXXXXYXYYXYXYXYXYXYXYXYXXYXXXXXXXXYYY
    

    To generate the secret from the file (and also system environment variables!) we first need to write the kustomize.yaml

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    
    resources:
      - deployment.yaml
    
    secretGenerator:
    - name: my-app-secrets
      env: secrets.env
    

    This kustomize file takes the deployment.yaml as resource and combines it with generated secret from the secretGenerator .
    It takes the values from the given secrets.env file into context and creates a secret with the given name my-app-secrets . It's important to import the file via the env key and not the file key, since file will turn the whole file into a secret while env makes all containing keys of the secrets.env accessible.

    We can take a look at the finished manifests with kubectl kustomize base .

    apiVersion: v1
    data:
      TOKEN: |
        T888as8d8dja8sdjjajd8ahjjdknkasndanddnasd8a8sda8sd
    kind: Secret
    metadata:
      name: my-app-secrets-fmk84tgkh5
    type: Opaque
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: my-app
      name: my-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          containers:
          - env:
            - name: TOKEN
              valueFrom:
                secretKeyRef:
                  key: TOKEN
                  name: my-app-secrets-fmk84tgkh5
            image: ghcr.io/staubrein/myapp
            imagePullPolicy: Always
            name: my-app
    

    The secretGenerator of kustomize dynamically generated a secret from the secrets.env file with base64 encoded values and those are accessible within the container.

    시스템 환경 변수 사용

    The best part on this solution, what makes it also very interesting for usage in pipelines or environments that don't use variables from files, is that it also works with system environment variables.

    By not assigning a value to the key in a environment file, it will automatically try to read out the value for this key from the system environment. Let's demonstrate this in a simple example and add another key to the secrets.env .

    TOKEN=XXXXXXXXXYXYYXYXYXYXYXYXYXYXXYXXXXXXXXYYY
    FOO
    

    It is important, that there is no equal sign after the key, otherwise the value will be considered empty and not overwritten with a system environment variable.
    Let's fill this variable locally with export FOO=bar and generate the secret with kustomize by running kubectl kustomize base .

    apiVersion: v1
    data:
      FOO: YmFy
      TOKEN: WFhYWFhYWFhYWVhZWVhZWFlYWVhZWFlYWVhZWFhZWFhYWFhYWFhZWVk=
    kind: Secret
    metadata:
      name: dailyottr-secrets-h7b26g7c74
      namespace: my-app
    type: Opaque
    

    As seen in the output above, it set the variable FOO with the value we set in the system environment variable :)

    The deployment can be triggered via kubectl kustomize base | kubectl apply -f - .

    To fully show the potential of kustomize, especially the functionality of merging and overwriting different environments, I'll write another article soon that patches the base deployment.

    좋은 웹페이지 즐겨찾기