컨테이너 설정파일을 관리하는 방법으로는 컨테이너 이미지를 빌드할때에 복사하거나, 컨테이너를 실행했을 때에 외부 호스트에서 파일을 연결해주는 방법이 있다.
쿠버네티스에서는 ConfigMap 리소스를 통해 설정파일을 관리하는 방법을 제공한다.
ConfigMap
컨테이너의 환경설정 값을 저장하기 위한 리소스로 키-값 쌍의 데이터를 저장한다.
ConfigMap에는 주로 Application의 설정값, 컨테이너의 환경변수, 설정파일과 같은 데이터를 저장한다.
아래는 ConfigMap을 정의하는 Manifest이다.
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
NGINX_PORT: "8080"
NGINX_SERVER_NAME: "my-nginx"
NGINX_ROOT: "/usr/share/nginx/html"
위와 같이 키-값 형태로 정의된 상태로 YAML 파일을 작성해 ConfigMap을 작성할 수 있다.
파드를 생성할 때, ConfigMap을 환경변수로 컨테이너에 전달하는 Manifest이다.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx
env: # 컨테이너의 환경변수를 설정
- name: PORT # PORT 환경변수 설정
valueFrom:
configMapKeyRef: # configMap에서 키를 가져옴
name: nginx-config # configMap의 이름
key: NGINX_PORT # 해당 configMap에서 키 값을 가져옴
- name: SERVER_NAME
valueFrom:
configMapKeyRef:
name: nginx-config
key: NGINX_SERVER_NAME
- name: ROOT
valueFrom:
configMapKeyRef:
name: nginx-config
key: NGINX_ROOT
환경변수가 아닌 설정파일을 넣어주어야하는 경우가 있다. 이 경우 ConfigMap에 설정파일의 내용을 넣어서 생성하고 파드에 Volume으로 ConfigMap을 주입해 줄 수 있다.
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
아래는 파드를 생성할때, 정의된 ConfigMap을 Volume으로 주입하는 Manifest이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/conf.d # Volume을 해당 경로에 마운트
volumes:
- name: nginx-config-volume
configMap: # ConfigMap을 volume으로 사용
name: nginx-config
Secret
Password, SSH Key와 같은 민감한 정보를 저장하기 위한 목적을 가진 리소스
Secret도 ConfigMap과 동일하게 키-값 쌍의 데이터를 저장하지만, 데이터가 base64로 인코딩되어 저장된다는 점이 있다.
아래는 Secret을 생성하는 Manifest이다.
apiVersion: v1
kind: Secret
metadata:
name: mariadb-secret
data:
password: cGFzc3dvcmQ=
userpass: dXNlcnBhc3M=
이렇게 생성한 Secret을 환경변수로 불러오는 Manifest는 아래와 같다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mariadb
...
spec:
containers:
- name: mariadb
image: mariadb
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef: # Secret의 키를 참조하여 가져옴
name: mariadb-secret # Secret의 이름
key: password # 해당 Secret의 키(password)를 가져옴
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mariadb-secret
key: userpass
...
env 항목으로 환경변수를 생성하는데, valueFrom으로 SecretKeyRef를 통해 Secret의 특정 키를 참조한다.
반대로 Secret의 모든 내용을 한번에 불러오는 방법은 아래와 같다.
...
spec:
containers:
- name: mariadb
image: mariadb
envFrom:
- secretRef: # mariadb-secret의 내용을 모두 로드
name: mariadb-secret
...
여기서 알아두어야하는 것이 Secret이라는 이름에 무색하게 내용이 암호화되지 않는다는 것이다.
인코딩은 결코 암호화가 될 수 없다.
워커노드나 etcd에 접근할 수 있는 경우, Secret을 별 다른 노력없이 바로 읽을 수 있다.
그리고 Secret 내용을 yml 파일에 바로 담아서 사용하는 선언식 관리의 경우, git과 같은 버전관리 시스템에 포함하기에 적절하지 않다.
따라서, 안전하게 민감정보를 주입하고 사용하기위해서는 Secret과 etcd를 암호화하거나 다른 3rd party 솔루션이나 오픈소스 등을 사용하는 방법이 존재한다.
이렇게 쿠버네티스에서 설정파일을 파드에 배포하는 리소스인 ConfigMap과 Secret에 대해 알아보았다.