문제해결

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

NEMNE 2022. 9. 25. 18:34

문제점

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)