본문 바로가기
문제해결

Helm hooks을 사용하여 Namespace에 istio-injection label 설정하기

by NEMNE 2022. 9. 25.

문제점

Istio를 사용하려면 Istio 환경 설치 외에도 Istio(Envoy) Proxy를 각각의 파드에 Sidecar에 주입해서 사용해야 한다.

 

Sidecar를 주입하기 위해서는 다양한 방법이 존재하는데 일반적으로 Namespace에 istio-injection=enabled 라벨을 추가하여 자동으로 Sidecar를 주입하는 방법이 있다.

 

파드를 생성하는 워크로드에도 라벨을 추가하여 파드가 생성할 때 사이드카를 자동으로 주입하도록 할 수 있다.

그러나 Helm을 통해 작성된 여러 차트 같은 경우에는 네임스페이스를 “생성”만 해주는 기능만 있을 뿐 위 같은 커스텀 라벨을 붙일 수 없다.

 

그렇다고 Namespace를 Helm Chart에 넣자니 해당 릴리스가 삭제되면 해당 네임스페이스에 있는 릴리스 외 리소스들도 모두 삭제되는 경우가 발생하게 된다.

 

Helm hooks와 hyperkube

먼저 Helm에서는 릴리스의 생명 주기에 특정 행동을 할 수 있도록 hooks 기능을 제공하고 있다.

 

제공하고 있는 hooks는 릴리스 리소스 생성 전/후, 릴리스 삭제, 업그레이드, 롤백 전/후에 대해 hook을 제공하고 있다.

사용하는 방법은 어노테이션에 몇 줄 정도 추가하면 되는 수준이라 매우 간단하게 사용할 수 있다.

 

그다음으로는 hyperkube이다. hyperkube는 kubernetes에 필요한 컴포넌트들이 다 포함되어 있는 일체형 바이너리이다.

Helm에서 종종 사용하게 되는데 그 이유 중 하나는 hyperkube를 통해 kubectl 명령어로 쿠버네티스 리소스를 생성할 수 있기 때문이다.

 

따라서 위 2가지를 이용하여 릴리스 리소스가 생성되기 전에 hyperkube를 통해 특정 Namespace에 istio-injection=enabled를 추가하려고 한다. 해당 방법은 다음과 같이 작성하면 된다.

 

해결 방법

먼저 job.yaml을 작성해준다.

Command에는 kubectl label ns {{ .Release.Namespace }} istio-injection=enabled --overwrite을 적어준다.

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  annotations:
    "helm.sh/hook": pre-install
    "helm.sh/hook-weight": "3"
    "helm.sh/hook-delete-policy": hook-succeeded,hook-failed
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}"
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
      annotations:
        sidecar.istio.io/inject: "false"
    spec:
      restartPolicy: Never
      serviceAccountName: namespace-labeler-sa
      containers:
      - name: labeler
        image: gcr.io/google_containers/hyperkube:v1.9.7
        resources:
          requests:
            cpu: 50m
            memory: 100Mi
        command: ["/bin/bash", "-c"]
        args:
            kubectl label ns {{ .Release.Namespace }} istio-injection=enabled --overwrite;
      {{- with .Values.preInstall.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}

 

hyperkube 컨테이너에서 kubectl를 통해서 내 클러스터를 조작하려면 RBAC 설정이 필요하다. cluster-admin 권한을 부여해준다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: backend-namespace-labeler-rolebinding
  annotations:
    "helm.sh/hook": pre-install
    "helm.sh/hook-weight": "2"
    "helm.sh/hook-delete-policy": hook-succeeded,hook-failed
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: namespace-labeler-sa
    namespace: {{ .Release.Namespace  }}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: namespace-labeler-sa
  annotations:
    "helm.sh/hook": pre-install
    "helm.sh/hook-weight": "1"
    "helm.sh/hook-delete-policy": hook-succeeded,hook-failed

 

참고

37. Kubernetes hyperkube container

차트 훅(hooks)