Kubernetes 상에서 소스코드를 구동할 때, 코드베이스를 변경하지 않으면서 코드의 동작을 컨트롤하기 위한 방법으로 환경변수가 흔히 이용됩니다.
Kubernetes 컨테이너에 환경변수를 주입하는 다양한 방식과, 여러 방식을 동시에 이용하여 충돌이 발생했을 때의 우선순위에 관헤 알아보겠습니다.
key-value 직접 명시
가장 직관적인 방식으로, container spec 내부에 직접 key-value로 환경변수를 명시하는 방식입니다.
apiVersion: v1
kind: Pod
metadata:
name: pod-with-env
spec:
containers:
- name: container-with-env
image: nginx:1.14.2
env:
- name: SOME_ENV_KEY
value: "some env value"
- name: SOME_ENV_KEY_2
value: "another env value"
외부 리소스로부터 값 로드
직접 value를 명시하지 않고, 외부 리소스로부터 환경변수를 주입할 수도 있습니다. 대표적으로 보안이 필요한 경우 Secret 리소스에 별도로 값을 관리하거나, 특정 값들을 ConfigMap 리소스로 분리하여 관리하는 경우가 있습니다.
외부 리소스에서 값을 로드할 때는 key-value 직접 명시할 때와 동일하게 env
필드를 이용할 수도 있고,
envFrom
필드를 통해 외부 리소스의 모든 값을 한번에 로드할 수도 있습니다.
우선 다음과 같이 container-secret
이라는 Secret 리소스를 생성했다고 가정해보겠습니다.
apiVersion: v1
kind: Secret
metadata:
name: container-secret
stringData:
SOME_SECRET_KEY: "abcdef"
SOME_SECRET_TOKEN: "qwer123asdf456"
이때, env
필드에 container-secret
을 참조하여 SOME_SECRET_KEY
환경변수를 주입할 수 있습니다.
...
env:
- name: SOME_SECRET_KEY # SOME_SECRET_KEY 값 로드
valueFrom:
secretKeyRef:
name: container-secret
key: SOME_SECRET_KEY
...
envFrom
필드를 활용하면 container-secret
의 모든 값을 한번에 로드합니다.
...
envFrom:
- secretRef: # SOME_SECRET_KEY, SOME_SECRET_TOKEN 모두 주입
name: container-secret
...
configMap으로부터 value를 로드할 때는, secretKeyRef
대신 configMapKeyRef
, secretRef
대신 configMapRef
를 이용해 동일하게 작성합니다.
외부 리소스로부터 값을 로드해 사용하는 경우, 외부 리소스에서 값을 수정하더라도 container에 바로 적용되지 않습니다. 수정된 값을 적용하기 위해서는 pod을 재시작해야 합니다.
stakater/reloader와 같은 도구를 이용하면, 외부 리소스의 변경을 감지하여 pod을 자동으로 재시작할 수 있습니다.
Pod config로부터 값 로드
container를 운영하다보면, pod의 이름이나 선언된 다른 환경변수 등의 메타데이터를 환경변수에 주입하고 싶은 상황이 발생합니다.
메타데이터를 환경변수로 주입하려면, env
필드에 fieldRef
를 이용합니다.
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
환경변수의 경우, value에 $(VAR_NAME)
포맷을 이용하여 보다 간편하게 값을 주입할 수 있습니다.
env:
- name: REF_KEY
value: "123"
- name: SOME_ENV_KEY
value: "Ref value is $(REF_KEY)" # Ref value is 123
$(VAR_NAME) 포맷을 활용할 때, 환경변수 선언 순서가 영향을 끼칩니다. 해당 환경변수보다 아래에 선언된 환경변수를 참조할 수 없습니다.
환경변수 선언 간 우선순위
관리의 용이성을 위해 가능한 환경변수를 한 종류의 리소스로만 관리하는게 이상적이겠으나, 실제로는 여러 리소스로부터 환경변수를 주입받아 사용하는 경우가 많습니다. 이때, 서로 다른 리소스에서 동일한 key를 선언하게 되면 충돌이 발생하는데요, 충돌이 발생했을 때의 우선순위는 다음과 같습니다.
- pod에서 직접 수정된 환경변수
env
필드를 통해 선언된 환경변수envFrom
필드를 통해 로드된 환경변수
envFrom
으로 여러 외부 리소스를 로드했거나 env
로 중복된 환경변수를 선언할 경우, 마지막으로 선언된 리소스가 우선권을 갖습니다.