Configmap
Kubernetes에서는 여러 호스트에서 컨테이너를 실행한다. 컨테이너는 어떤 어플리케이션을 실행하게 될 텐데, 내 컴퓨터에서라면 설정 파일이 로컬에 있으므로 어플리케이션에 설정을 제공하는 것이 간단하지만, 어떤 호스트에서 동작할지 모르는 컨테이너에 설정을 어떻게 제공하는가가 문제가 된다. 이럴 때 Kubernetes의 ConfigMap
을 사용해볼 수 있다.
Configmap의 작성과 간단한 테스트
기본적으로 이런 모양을 지니게 된다. 리소스 이름을 ConfigMap
이다.
apiVersion: v1
kind: ConfigMap
metadata:
name: testconfigmap
namespace: default
data:
testvalue: "1"
optionaltestvalue: "optional"
testfile: |
address=0.0.0.0
port=8080
간단히 이런 식으로 작성하고 등록하면 다음과 같은 화면을 볼 수 있다.
$ kubectl create -f testconfigmap.yaml
configmap/testconfigmap created
$ kubectl get configmap
NAME DATA AGE
testconfigmap 2 6s
이를 사용해서 컨테이너에 데이터를 전달해 보자.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: testconfig
mountPath: /opt/test
volumes:
- name: testconfig
configMap:
name: testconfigmap
items:
- key: testfile
path: testfilepath
volumes의 Configmap에서는 testconfigmap의 data 중, 키 testfile을 testfilepath라는 경로로 매핑한다. 이 Configmap은 testconfig라는 볼륨으로 선언되어 있으므로, 이를 containers의 volumeMounts에서 name으로 사용한다. mountPath는 어느 경로에 마운트할지를 정한다.
따라서 /opt/test/testfilepath
에 파일이 마운트가 될 것이다.
이 팟을 생성해서 실제로 보면 다음과 같다.
$ kubectl create -f testnginx.yaml
pod/nginx created
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 61s
$ kubectl exec -t -i nginx /bin/bash
$ cat /opt/test/testfilepath
address=0.0.0.0
port=8080
Configmap testconfigmap
의 testfile
내용이 그대로 파일로 지정된 것을 확인할 수 있다.
Configmap을 환경 변수에 연결하기
이번엔 Configmap
의 내용을 환경 변수에 연결해보자. 먼저 간단한 팟 nginx2를 만들자.
apiVersion: v1
kind: Pod
metadata:
name: nginx2
labels:
env: test
spec:
containers:
- name: nginx2
image: nginx
imagePullPolicy: IfNotPresent
env:
- name: testenv
value: THIS_IS_TEST_VALUE
- name: testenvfromconfigmap
valueFrom:
configMapKeyRef:
name: testconfigmap
key: testvalue
- name: testoptionalenvfromconfigmap
valueFrom:
configMapKeyRef:
name: testconfigmap
key: optionaltestvalue
- name: testoptionalenvfromconfigmap2
valueFrom:
configMapKeyRef:
name: testconfigmap
key: optionaltestvalue2
optinal: true
env
는 name/value 페어를 이룬다. value는 바로 매핑해도 되고 valueFrom을 통해 어딘가로부터 값을 가져오도록 지정할 수도 있다. 우선 여기서는 Configmap에서 가져오는 것만 보면, 그 방법으로는 configMapkeyRef
를 사용하면 된다. 환경 변수의 이름은 testenvfromconfigmap
이 되고, configMapKeyRef.name은 실제 Configmap의 이름, configMapKeyRef.key는 Configmap의 키가 된다.
컨테이너를 생성한 후 다음과 같이 확인해 보자.
$ kubectl describe pod nginx2
Name: nginx2
Namespace: default
Priority: 0
...
Containers:
...
Ready: True
Restart Count: 0
Environment:
testenv: THIS_IS_TEST_VALUE
testenvfromconfigmap: <set to the key 'testvalue' of config map 'testconfigmap'> Optional: false
testoptionalenvfromconfigmap: <set to the key 'optionaltestvalue' of config map 'testconfigmap'> Optional: false
testoptionalenvfromconfigmap2: <set to the key 'optionaltestvalue2' of config map 'testconfigmap'> Optional: true
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-5g2zn (ro)
...
$ kubectl exec -t -i nginx2 /bin/bash
$ echo $testenv
THIS_IS_TEST_VALUE
$ echo $testenvfromconfigmap
1
위와 같이 환경변수 testenvfromconfigmap
가 1의 값을 가지는 것을 볼 수 있다. optional
은 값이 없어도 되는 경우를 뜻하는데, 위 케이스에서는 Configmap의 testoptionalenvfromconfigmap2
키가 없어도 컨테이너를 생성하는 것에 아무런 문제가 없도록 지정했다. 만약 저 optional을 지정하지 않았다면?
$ kubectl describe pod nginx2
Name: nginx2
Namespace: default
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
...
Warning Failed 7s (x2 over 7s) kubelet, node-00005 Error: couldn't find key optionaltestvalue2 in ConfigMap default/testconfigmap
Configmap 심화과정
Configmap이 업데이트되는 경우?
Configmap
이 업데이트되는 경우 해당 Configmap을 마운트한 팟에서는 결국 업데이트된 대로 내용이 변경된다. 하지만 업데이트 즉시 팟에 반영되지는 않는다.
$ cat /opt/test/testfilepath
address=0.0.0.0
port=8080
$ cat /opt/test/testfilepath
address=0.0.0.0
port=8081
같은 컨테이너에서 cat
으로 파일 내용을 찍다가 변경되는 순간을 적어 보았다. 변경은 Kubernetes의 각 노드에 설치되는 kubelet
이 처리해 주는데, 바로 변경해주지는 않고 적당한 TTL 이후 변경해 준다고 한다. 특히나 inotify
등으로 변경점을 바로 캐치할 수 있으므로, configmap을 사용하는 컨테이너가 변경점을 바로 적용하여 실행하도록 어플리케이션을 잘성할 수도 있겠다.
As a result, the total delay from the moment when the ConfigMap is updated to the moment when new keys are projected to the pod can be as long as kubelet sync period (1 minute by default) + ttl of ConfigMaps cache (1 minute by default) in kubelet.
특히 알아둘 것은 subPath로 Configmap을 지정한 경우 자동 업데이트가 되지 않는다는 것이다. 따라서 최대한 subPath를 사용하지 않는 것이 좋겠다.