Kubernetes ConfigMap
목차
- 개발·테스트·운영 환경에 사용되는 각기 다른 환경 값의 분리가 필요한 상황으로, 애플리케이션 Image는 동일하게 사용하고 필요한 환경 구성값을 configMap으로 만들어 사용
- 개발 환경은 SSH를 통한 보안 접근 해제
- 테스트 환경은 지정된 USER 및 Key를 이용한 SSH 보안 접근 사용
- 운영 환경은 테스트 환경과 다르게 지정된 USER 및 Key를 이용한 보안 접근 허용
- 기밀이 요구되는 데이터는 Secret으로 생성해 Pod에 적용해서 사용
- 애플리케이션 레벨이 아닌 Object 레벨의 환경 설정 관리할 때 사용
- 애플리케이션 레벨에서 환경 구성 변경 시 소스코드와의 의존성이 높고, 설정 값 변경 시마다 코드 수정이 불가피하여 개발 속도가 지연될 수 있다.
- 민첩성을 강조하는 Cloud Native 환경에서 애플리케이션 개발은 애플리케이션 코드와 분리된 configMap, Secret object 사용을 통해 신속하게 적용 가능
- configMap, Secret은 중앙 관리 방식으로 애플리케이션 코드에서 구성 및 민감한 정보를 분리하도록 설계된 Kubernetes API object →
kubectl api-resources
실습 예제 — Node.js 앱으로 ConfigMap 테스트
Dockerfile
FROM node:21-slim
EXPOSE 8000
COPY runapp.js .
CMD node runapp.js
# node21 이미지에
# 8000 port 개방하고
# 현재 폴더에서 runapp.js 카피
# 그 파일을 실행runapp.js
var http = require('http');
const apiKey = process.env.API_KEY;
if (!apiKey) {
console.log('API_KEY is not set in the environment variables.');
http.createServer(function (req, res) {
res.setHeader('Content-Type', 'text/plain');
res.end("API_KEY is not set in the environment variables." + "\n");
}).listen(8000);
} else {
console.log('API_KEY:', apiKey);
http.createServer(function (req, res) {
res.setHeader('Content-Type', 'text/plain');
res.end("Welcome to ConfigMap Kubernetes" + "\n");
}).listen(8000);
}
// 환경변수에서 API_KEY 있는지 확인하여 결과물 다르게 표출
configMap 테스트 — 이미지 빌드 및 테스트
$ docker build -t crimsonpinus/configmaptest:latest --nocache .
# Dockerfile 빌드
$ docker run -d --name nodetest -p 8000:8000 crimsonpinus/configmaptest
$ curl localhost:8000
API_KEY is not set in the environment variables.
$ docker stop nodetest
$ docker rm nodetest
$ docker run -d --name nodetest -e API_KEY hello -p 8000:8000 crimsonpinus/configmaptest
$ curl localhost:8000
Welcome to ConfigMap Kubernetes
# kubernetes에서 사용하기 위해 본인의 계정에 업로드
$ docker push crimsonpinus/configmaptest:latestcmtest-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: cmtest-pod
name: cmtest-pod
spec:
containers:
- image: crimsonpinus/configmaptest
name: cmtest-pod
ports:
- containerPort: 8000
envFrom:
- configMapRef:
name: api-key
# cm-test-pod 생성후 위 envFrom 부분 추가configMap 사용
$ kubectl run cmtest --image crimsonpinus/configmaptest --port 8000
$ kubectl get po,svc -o wide | grep cmtest
pod/cmtest 1/1 Running 0 13s 10.111.156.89 k8s-node1 <none> <none>
$ curl 10.111.156.89:8000
API_KEY is not set in the environment variables.
$ kubectl delete po cmtest
pod "cmtest" deleted
# configMap 생성
$ kubectl create cm api-key --from-literal=API_KEY=k8scm
configmap/api-key created
$ kubectl get cm
NAME DATA AGE
api-key 1 26s
kube-root-ca.crt 1 7d20h
kubeshark-config-map 22 7d16h
kubeshark-nginx-config-map 1 7d16h
$ kubectl describe cm api-key
Name: api-key
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
API_KEY:
----
k8scm
BinaryData
====
Events: <none>
# configMap 사용 - cmtest-pod.yaml 파일 생성
$ kubectl run cmtest --image crimsonpinus/configmaptest --port 8000 --dry-run=client -o yaml > cmtest-pod.yaml
# cmtest-pod.yaml 파일 참조하여 수정
$ kubectl apply -f cmtest-pod.yaml
$ kubectl get po,svc -o wide | grep cmtest
pod/cmtest-pod 1/1 Running 0 98s 10.111.156.90 k8s-node1 <none> <none>
$ curl 10.111.156.90:8000
Welcome to ConfigMap Kubernetes
$ kubectl exec -it cmtest-pod -- env | grep -i api
API_KEY=k8scmconfigMap 값 변경
$ kubectl edit cm api-key
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
API_KEY: k8scm-edit # 값 변경
kind: ConfigMap
metadata:
creationTimestamp: "2024-04-12T04:56:56Z"
name: api-key
namespace: default
resourceVersion: "1320379"
uid: 56d43ca7-3a6e-47b7-ab6a-1460a0725bc7
$ kubectl exec -it cmtest-pod -- env | grep -i api
API_KEY=k8scm
# 변경 안되었음
# 강제 재시작
$ kubectl replace --force -f ./cmtest-pod.yaml
pod "cmtest-pod" deleted
pod/cmtest-pod replaced
$ kubectl exec -it cmtest-pod -- env | grep -i api
API_KEY=k8scm-editconfigMap 활용
생성 방법
- 선언형: YAML 코드 작성 —
kubectl api-resources | grep configmap - 명령형:
kubectl create configmap(or cm) configmap_name {설정}- 설정1:
--from-literal key=value [--from-literal key2=value2] ... - 설정2:
--from-file file_name(파일 안에 다수의 설정값 저장) - 설정3:
--from-env-file file_name(key=value의 환경 변수가 저장된 파일)
- 설정1:
- 부가기능 — 불변(immutable)
immutable: true- 실행 중인 애플리케이션의 값이 변경될 경우 의도치 않은 중단을 야기하는 값에 사용
- 불변 설정으로 configMap에 대한 APIserver의 감시 중단, 클러스터 성능 향상에 기여
configMap.yaml 예시
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
string-value: "Hello, world!" # 스트링 형식, 공백이 없으면 따옴표 없어도 됨
number-value: "42" # 숫자 형식
boolean-value: "true" # 불린 타입은 따옴표 무조건 필요
multiline-value: | # | 표시는 아래 줄과 이어진다는 표시
This is a multiline value
that spans multiple lines
list-value: |
- item1
- item2
- item3
object-value: |
key1: value1
key2: value2
json-value: |-
{
"key": "value",
"array": [1, 2, 3],
"nested": {
"innerKey": "innerValue"
}
}
yaml-value: |-
key: value
array:
- 1
- 2
- 3적용 방식
- Pod 속 환경 변수로 등록 →
envFrom.configMapRef.name - Pod Volume으로 mount →
volumes.configMap.namemountPath: 해당 디렉토리 전체를 업데이트 (mount된 configMap, Secret은 업데이트 시 Pod에 자동 반영)subPath: 해당 디렉토리 안의 지정된 파일만 업데이트
- Pod 속 컨테이너의 환경변수 값으로 KEY 지정
valueFrom.configMapKeyRef.namevalueFrom.configMapKeyRef.key
$ kubectl create configmap k8s-env \
--from-literal orchestrator=kubernetes \
--from-literal runtime=containerd
$ kubectl describe cm k8s-env
Name: k8s-env
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
orchestrator:
----
kubernetes
runtime:
----
containerd
BinaryData
====
Events: <none>
# yaml로 보기
$ kubectl get cm k8s-env -o yaml
apiVersion: v1
data:
orchestrator: kubernetes
runtime: containerd
kind: ConfigMap
metadata:
creationTimestamp: "2024-04-12T05:51:16Z"
name: k8s-env
namespace: default
resourceVersion: "1326898"
uid: 3bcdf040-6174-497f-903e-a6b3bedf9db2
# JSON으로 보기
$ kubectl get cm k8s-env -o json
{
"apiVersion": "v1",
"data": {
"orchestrator": "kubernetes",
"runtime": "containerd"
},
"kind": "ConfigMap",
"metadata": {
"creationTimestamp": "2024-04-12T05:51:16Z",
"name": "k8s-env",
"namespace": "default",
"resourceVersion": "1326898",
"uid": "3bcdf040-6174-497f-903e-a6b3bedf9db2"
}
}
# YAML 파일로 생성
$ kubectl create configmap k8s-env \
--from-literal orchestrator=kubernetes \
--from-literal runtime=containerd \
--dry-run=client -o yaml > k8s-env.yaml
$ kubectl apply -f k8s-env.yamlVolume Mount
cm-volume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: cm-volume-pod
name: cm-volume-pod
spec:
containers:
- image: nginx:1.25.3-alpine
name: cm-volume-pod
ports:
- containerPort: 80
volumeMounts:
- name: cm-volume
mountPath: /etc/config
volumes:
- name: cm-volume
configMap:
name: k8s-env
key: orchestrator # key를 이용하여 일부의 값만 가져올 수 있음활용
$ kubectl apply -f cm-volume-pod.yaml
pod/cm-volume-pod created
$ kubectl get po,svc -o wide | grep cm
pod/cm-volume-pod 1/1 Running 0 31s 10.109.131.17 k8s-node2 <none> <none>
$ kubectl exec cm-volume-pod -- ls -la /etc/config
total 0
drwxrwxrwx 3 root root 95 Apr 12 06:11 .
drwxr-xr-x 1 root root 52 Apr 12 06:11 ..
drwxr-xr-x 2 root root 41 Apr 12 06:11 ..2024_04_12_06_11_12.4261600263
lrwxrwxrwx 1 root root 32 Apr 12 06:11 ..data -> ..2024_04_12_06_11_12.4261600263
lrwxrwxrwx 1 root root 19 Apr 12 06:11 orchestrator -> ..data/orchestrator
lrwxrwxrwx 1 root root 14 Apr 12 06:11 runtime -> ..data/runtime
$ kubectl exec cm-volume-pod -- cat /etc/config/orchestrator
kubernetes변경 후 Pod restart 없이 반영
$ kubectl edit cm k8s-env
# orchestrator: k8s 로 변경
# nginx 리로드
$ kubectl exec cm-volume-pod -- nginx -s reload
2024/04/12 06:18:19 [notice] 46#46: signal process started
$ kubectl exec cm-volume-pod -- cat /etc/config/orchestrator
k8s다중 환경 Volume Mount
redis.conf
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11cmfile-volume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: cmfile-volume-pod
name: cmfile-volume-pod
spec:
containers:
- image: nginx:1.25.3-alpine
name: cmfile-volume-pod
ports:
- containerPort: 80
volumeMounts:
- name: redis-volume
mountPath: /opt/redis/config
volumes:
- name: redis-volume
configMap:
name: redis-config
# 녹색 부분 추가활용
$ kubectl create cm redis-config --from-file=redis.conf
configmap/redis-config created
$ kubectl get cm
NAME DATA AGE
k8s-env 2 30m
kube-root-ca.crt 1 7d22h
kubeshark-config-map 22 7d17h
kubeshark-nginx-config-map 1 7d17h
redis-config 1 9s
$ kubectl describe cm redis-config
Name: redis-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
redis.conf:
----
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11
BinaryData
====
Events: <none>
$ kubectl apply -f cmfile-volume-pod.yaml
$ kubectl exec cmfile-volume-pod -- ls -l /opt/redis/config
$ kubectl exec cmfile-volume-pod -- cat /opt/redis/config/redis.conf