이번 chapter에서는 ConfigMaps
와 Secrets
라는 kubernetes object에 대해서 알아보도록 한다.
kubernetes에서는 configuration을 가장 중요한 요소로 생각하여 두 가지 resource를 만들어냈다. 하나는 ConfigMaps
이고 하나는 Secrets
이다.
application과 configuration을 분리하는 것은 매우 중요하다.
kubernetes를 사용할 때 우리는 application이 가능한 portable했으면 한다. 가장 좋은 방법은 application을 configuration으로부터 분리하는 것이다.
예전에는 application과 configuration을 하나로 묶어내어 application을 만들어냈었다. 이는 하나의 environment에서 배포가 이루어졌기 때문인데, 이러한 application의 경우 portability가 부족하다는 문제가 있다. 오늘 날에는 다양한 환경에서의 배포가 이루어지며, 환경에 따라 configuration을 자유자재로 바꾸고 업데이트하는 경우들이 많이 생겼다. 가령 다음의 상황을 보자
MySQL
endpoint가 test환경에서의 endpoint와 다르다.여기에는 두 가지 가능성이 있다.
MySQL
이 하드코딩되어있고 applicatio ncode에 번들링되어있을 가능성이 있다. 때문에 매 환경마다 application code를 새로 만들고 빌드해야한다.MySQL
endpoint를 다르게 인식한다.portablility
의 핵심 개념은 application code는 application이 동작하는 infrastructure와 독립적이어야 한다. 이를 달성할 수 있는 가장 좋은 방법은 application code와 configuration을 분리하는 것이다.
kubernetes에서 application code
는 pod
가 되고, configuration
이 바로 ConfigMap
과 Secrets
object가 된다. 이 둘은 모두 configuration data
를 전달하기위해 설계되었으며, 이를 application code
인 pod
에 연결시켜주어야 한다.
configuration value를 docker images의 한 부분으로 포함시키지 말자.
Dockerfile
은 application code를 빌드할 뿐이지, 설정(configure)하는 것은 아니다. container를 빌드할 때 설정값들을 넣으면 application과 configuration 사이에 강한 relationship이 생긴다. 이는 container의 portability를 감소시킨다.
ConfigMap
은 보안에 중요하지 않는 설정값들을 담는 기능을 한다. 반면에 Secrets
는 global하게 같지만, 보안에 민감한 정보들을 담는다. 가령, database password 등이 있다.
즉, ConfigMap
과 Secret
은 key/value pair들로 이루어진 repository로 생각하면 된다. 따라서, pod가 생성될 때 ConfigMap
또는 Secret
의 이름을 정하고 이를 pod
에 링킹할 수 있다. 이를 통해, 해당 configuration 값들은 pod에 동작하는 container에 노출시킬 수 있는 것이다.
다음의 순서를 따르도록 하자.
다음을 따름으로서, pod를 환경에 따라 portable하게 만들 수 있는 것이다.
kubernetes외에 다른 현대의 containerized application은 다음의 두 가지 방식으로 configuration을 사용한다.
다음의 두 가지 방법을 선호하는 이유는 Docker와 같은 container 프로그램에서 configuration 값을 override하기 좋고, application이 configuration 값을 읽기 좋기 때문이다.
kubernetes world로 들어와서는 ConfigMaps
와 Secrets
로 configuration 설정을 할 수 있다. 위의 두 가지 방법을 그저 kubernetes의 ConfigMap
과 Secret
이 해주는 것일 뿐이다. 다음의 두 가지 방식으로 사용된다.
즉, ConfigMap
과 Secret
의 하나 또는 그 이상의; configuration value는 환경 변수로 injected될 수 있다.
ConfigMap
과 Secret
은 또한 volume mounts와 같이 동작할 수 있다. ConfigMap
을 volume으로 마운트하면 모든 configuration value를 container의 directory안에 포함되도록 할 수 있다. 만약 full configuration file들을 ConfigMap
안에 저장한다면, 이 방법이 가장 좋다.
그러나, ConfigMap
과 Secret
은 서로 동작하는 방식이 다르다. 또한 ConfigMap
은 보안에 민감하지 않는 정보를 담는 반면, Secret
은 보안에 민감한 정보를 담는다는 차이도 있다. 이제 이들에 대해서 더 자세히 알아보도록 하자.
먼저 현재 kubernetes cluster에서 ConfigMap
을 가져오는 방법을 알아보자. kubectl get pod
와 마찬가지로 kubectl get configmaps
를 사용하면 된다.
kubectl get configmaps
kubectl get cm
kubectl get cm -A
configmaps
라는 object이름이 너무 길다면 cm
과 같은 축약어를 사용할 수 있다. -A
옵션은 전체 namespace에 관계없이 모든 configmaps
를 리스팅하라는 것이다. namespace
에 대해서는 추후에 알아보도록 하자.
현재는 configmaps
가 없기 때문에 위의 명령어를 실행해도 나오는 것이 없다. 이제 ConfigMap
을 만들어보도록 하자.
다른 kubernetes object들과 마찬가지로 ConfigMaps
도 imperatively 또는 declaratively하게 생성가능하다.
먼저, 명령어로 imperative하게 configmap을 생성하는 방법에 대해서 알아보자.
kubectl create configmap my-first-configmap
...
configmap/my-first-configmap created
kubectl create pod <pod-name>
을 했듯이 kubectl create configmap <configmap-name>
을 사용하면 된다.
일단, 해당 명령어가 실행되면 kubectl get cm
으로 확인가능하다.
kubectl get cm
...
NAME DATA AGE
my-first-configmap 0 56s
잘 만들어진 것을 볼 수 있다.
declarative하게 configmap을 생성하는 방법은 다음과 같다. 먼저 my-second-configmap.yaml
파일을 만들고 다음의 코드를 넣어주도록 하자.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-second-configmap
kind
부분에 pod
가 아닌 ConfigMap
으로 kubernetes object를 바꿔주면 된다. pod 생성시와 크게 다를바가 없다. 생성하는 부분도 pod
를 만들 때와 크게 다를 바 없다.
kubectl create -f my-second-configmap.yaml
...
configmap/my-second-configmap created
해당 명령어를 실행하면 성공적으로 ConfigMap
이 만들어진 것이다. 리스팅 시에 잘 나오는 지 확인해보도록 하자.
kubectl get cm
...
NAME DATA AGE
my-first-configmap 0 6s
my-second-configmap 0 78s
두 ConfigMap
모두 성공적으로 배포되었다. 그러나 DATA
column을 보면 아무것도 없다는 것을 알 수 있다.
즉, configuration value가 없다는 것이다. 이는 우리가 생성 시에 데이터가 없는 빈 ConfigMap
을 생성하였기 때문이다. 이제 데이터를 처음부터 가지고 있는 configmap
을 만들어주도록 하자.
value가 없는 ConfigMap
을 만드는 것은 매우 무의미한 일이다. value를 채운 ConfigMap
을 만들어보도록 하자. 먼저 imperatively한 방식으로 value가 있는 ConfigMap
을 만들어보도록 하자.
kubectl create cm <configmap-name> --from-literal=<key=value>
방식으로 사용하면 된다. --from-literal
에 key=value
를 적어내면 되는 것이다.
다음과 같이 color
라는 key는 blue
라는 value를 갖도록 만들 수 있다.
kubectl create cm my-third-configmap --from-literal=color=blue
...
configmap/my-third-configmap created
또한, --from-literal
을 여러번 써서 여러 개의 key=value
를 저장할 수 있다.
kubectl create cm my-fourth-configmap --from-literal=color=blue --from-literal=version=1 -
-from-literal=environment=prod
...
configmap/my-fourth-configmap created
위는 3개의 configuration value를 만든 것이다.
이전에 kubectl get cm
명령어에서 DATA
column이 실제로 configmap이 가진 confiuguration value라고 하였다. 몇 개가 설정되어 있는 지 알아보도록 하자.
kubectl get cm
NAME DATA AGE
my-first-configmap 0 71m
my-fourth-configmap 3 109s
my-second-configmap 0 72m
my-third-configmap 1 3m25s
my-third-configmap
은 1개, my-fourth-configmap
은 3개인 것을 확인하였다.
declaratively하게 위와 동일한 configuration value를 가진 configmap을 만들 수 있다. 굉장히 간단한데, data
속성을 만들고 key:value
로 만들어주면 된다.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-fifth-configmap
data:
color: "blue"
version: "1"
environment: "prod"
data.key: value
형식으로 써주면 되는 것이다. kubect create -f <filename>
으로 배포해보도록 하자.
kubectl create -f my-fifth-configmap.yaml
...
configmap/my-fifth-configmap created
다음으로 kubectl get cm
으로 DATA
가 의도한 대로 3개가 맞는 지 확인하도록 하자.
kubectl get cm
NAME DATA AGE
my-fifth-configmap 3 5s
my-first-configmap 0 74m
my-fourth-configmap 3 4m50s
my-second-configmap 0 75m
my-third-configmap 1 6m26s
my-fifth-configmap
이 DATA
로 3개를 갖고있는 것을 볼 수 있다.
이전에 언급했듯이, ConfigMap
에 파일 그 자체를 저장할 수 있다. 즉, literal value
에만 국한되지 않는 것이다. kubectl
명령어에 file의 위치만 적어주면 된다. 그러면 해당 파일의 내용이 ConfigMap
의 value
에 적히게 낸다. 즉, key
는 file이름이 되고, value
는 해당 파일의 내용이 되는 것이다.
$HOME/configfile.txt
파일을 ConfigMap
의 value로 가져오도록 해보자. 먼저 $HOME/configfile.txt
를 만들어주도록 하자.
echo "I'm just a dummy config file" >> $HOME/configfile.txt && cat $HOME/configfile.txt
I'm just a dummy config file
잘 저장된 것을 확인할 수 있다. 참고로 예제에서는 txt
파일을 사용했지만, yaml, toml
등 상관없이 잘된다.
이제 해당 파일을 ConfigMap
에 import해야한다. 새로운 ConfigMap
을 만들고 --from-file
flag를 사용해서 file
을 적재하도록 하자.
kubectl create cm my-sixth-configmap --from-literal=color=yellow --from-file=$HOME/configfile.txt
configmap/my-sixth-configmap created
kubectl get cm
명령어를 사용하여 sixth configmap
이 만들어졌는 지 확인해보도록 하자. 우리가 잘 만들었다면 2개의 DATA
가 있을 것이다.
kubectl get cm
NAME DATA AGE
my-fifth-configmap 3 15m
my-first-configmap 0 89m
my-fourth-configmap 3 19m
my-second-configmap 0 90m
my-sixth-configmap 2 47s
my-third-configmap 1 21m
my-sixth-configmap
은 두 개의 DATA
를 가진 것을 볼 수 있다. 특히 하나는 --from-file
을 통해서 만든 file value이다.
imperatively하게 명령어를 사용하여 ConfigMap
을 만들어냈으니 declaratively하게 ConfigMap
을 만들어보도록 하자.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-seventh-configmap
data:
color: "green"
configfile.txt: |
I'm another configuration file.
다음과 같이 data
부분에 file
의 이름을 key로 하고 내용을 value로 하여 만들 수 있다.
그러나 다음과 같이 만들지는 말자
...
configfile.txt: $HOME/configfile.txt
이렇게하면 $HOME/configfile.txt
라는 경로가 configfile.txt
에 그대로 저장되지 configfile.txt
의 내용이 value
에 들어가지 않는다.
kubectl get cm
명령어로 DATA
가 2개 만들어졌는 지 확인해보도록 하자
kubectl get cm
NAME DATA AGE
my-fifth-configmap 3 23m
my-first-configmap 0 97m
my-fourth-configmap 3 28m
my-second-configmap 0 98m
my-seventh-configmap 2 79s
my-sixth-configmap 2 9m5s
my-third-configmap 1 29m
다음으로 ConfigMap
을 생성하는 마지막 방법은 env
파일로부터 ConfigMap
을 만드는 방법을 알아보도록 하자.
imperatively한 방법으로 --from-env-file 옵션을 사용하면
env파일을 통해
ConfigMap`을 만들 수 있다.
env
파일은 key=value
형식의 파일로 각 key는 line break로 나누어져 있다. env
파일은 kubernetes가 있기 전부터 많이 사용된 configuration 방식이기 때문에 kubernetes에서도 이를 가져와 ConfigMap
으로 바꾸어 줄 수 있는 것이다.
다음의 env
파일이 있다고 하자.
my-env-file.txt
hello=world
color=blue
release=1.0
production=true
kubernetes는 해당 env
파일을 읽고 ConfigMap
의 key-value 쌍을 만들어낼 것이다.
다음의 명령어를 사용하여 env
파일을 읽고 이를 기반으로 ConfigMap
을 만들어낼 수 있다.
kubectl create cm my-eigth-configmap --from-env-file=my-env-file.txt
...
configmap/my-eigth-configmap created
kubectl get cm
을 통해서 잘 만들어졌는 지 확인해보도록 하자.
kubectl get cm my-eigth-configmap
NAME DATA AGE
my-eigth-configmap 4 7s
4개의 key-value 쌍이 잘 만들어졌음을 볼 수 있다.
ConfigMap
에는 민감한 정보를 넣어서는 안된다.ConfigMap
에 있는 데이터들은 보안과 관련된 정보가 없어야 하는데, 이는kubectl describe cm
명령어로 쉽게ConfigMap
에 있는 데이터를 볼 수 있기 때문이다. 보안과 관련된 민감한 정보는Secret
에 넣도록 하자.
그럼 데이터가 ConfigMap
에 들어간 것은 알겠다만, 어떻게 읽을 수 있는가?
kubectl describe
명령어를 사용해서 ConfigMap
에 있는 데이터를 가져올 수 있다. 예시로 my-fourth-configmap
에 어떤 데이터들이 저장되어 있는 지 확인하도록 하자.
kubectl describe cm my-fourth-configmap
Name: my-fourth-configmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
color:
----
blue
environment:
----
prod
version:
----
1
Events: <none>
굉장히 읽기 귀찮은 모습으로 나오지만 Data
부분을 기점으로 key
와 value
가 :
와 ----
라인 사이로 번갈아 나온다.
이 처럼, ConfigMap
은 굉장히 간단하게 data를 가져올 수 있으므로 절대로 민감한 정보를 포함해서는 안된다.
이제, 해당 데이터들을 pod들에서 사용하도록 링킹하는 방법에 대해서 알아보자.
먼저, ConfigMap
을 환경 변수(environment variables)로 삽입하는데 집중해보자. pod안의 container 환경 변수가 ConfigMap
에 상응하도록 하자. 즉, 연결시키자는 것이다.
두 가지 방법이 있다.
ConfigMap
들을 사용하여, pod안의 container 환경 변수 값을 설정 할 수 있다. 즉, 한개의 ConfigMap
이 모든 환경 변수를 다 설정하는 것이 아니라, N개의 환경 변수를 M개의 ConfigMap
으로 설정할 수 있다는 것이다. (N >= M)ConfigMap
을 가져, 모든 값들을 한 번에 container의 환경 변수로 설정하는 것이다.첫번째 방법은 관리에 있어 어려움은 있지만, 유연하다는 특징이 있다. 두 번째 방법은 하나의 pod 또는 하나의 application마다 하나의 ConfigMap
을 만들어 pod 또는 application 배포 시에 ConfigMap
을 배포 준비시킬 수 있다. 다만, 관리가 쉬운 장점이 있지만 유연하진 못하다.
하나씩 예제를 사용하여 알아보도록 하자.
ConfigMap
과Pod
를kubectl
의 imperative 방식으로는 연결시켜줄 수 없다. 왜냐하면kubectl run
명령어로는ConfigMap
을 링킹하는Pod
를 만들 수 없기 때문이다. 때문에pod
에ConfigMap
를 사용하는 yaml파일을 만들어야만 한다.
위에서 우리는 my-third-configmap
이라는 ConfigMap
을 만들었는데, color=blue
라는 데이터를 가졌었다. 이제 nginx:latest
image를 가지는 pod를 만들어 my-third-configmap
과 연결시켜 nginx container가 COLOR
라는 환경변수로 blue
라는 값을 갖도록 할 것이다. 다음의 YAML
manifest를 집중해보자.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-configmap
spec:
containers:
- name: nginx-container-with-configmap
image: nginx:latest
env:
- name: COLOR # Any other name works here.
valueFrom:
configMapKeyRef:
name: my-third-configmap
key: color
env:
부분을 잘 보도록 하자. name
부분은 nginx-container-with-configmap
에서 가장 환경변수의 key이다. value는 valueFrom
부분으로부터 연결시킬 수 있는데, configMapKeyRef
에는 ConfigMap
이름과 key
를 적어주는데, 이 key
에 해당하는 value이 COLOR
에 연결되는 것이다. 참고로 해당 방법은 직접 data 하나하나마다 ConfigMap
을 지정해줌으로 한 개의 ConfigMap에 한 개의 값에 해당한다.
pod
를 생성시켜주도록 하자.
kubectl create -f nginx-pod-with-configmap.yaml
...
pod/nginx-pod-with-configmap created
이제 nginx
pod가 만들어졌다. env
command로 환경변수를 불러와보도록 하자. 이전에 배웠던 kubectl exec
을 사용하면 된다.
kubectl exec nginx-pod-with-configmap -- env | grep "COLOR"
COLOR=blue
잘 설정된 것을 볼 수 있다.
이제, pod를 지우고 두 번째 방법(모든 값들을 하나의 ConfigMap으로)을 적용해보도록 하자.
kubectl delete pod nginx-pod-with-configmap
pod "nginx-pod-with-configmap" deleted
이제 또 다른 ConfigMap
인 my-fourth-configmap
을 연결시켜보도록 하자. 이번에는 하나하나씩 데이터를 환경변수에 설정하지 않고, ConfigMap
에 있는 모든 환경 변수를 적용시키도록 하고싶다. 다음과 같이 manifest
파일을 만들도록 하자.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-configmap
spec:
containers:
- name: nginx-container-with-configmap
image: nginx:latest
envFrom:
- configMapRef:
name: my-fourth-configmap
잘보면 이전과 달리 env
를 사용하지 않고 envFrom
을 사용하는 것을 볼 수 있다. 이는 env
로 개별적인 환경변수 key를 설정하지 않기 때문이다.
pod를 만들어 잘 설정되었는 지를 확인해보도록 하자.
kubectl create -f nginx-pod-with-configmap.yaml
...
pod/nginx-pod-with-configmap created
pod가 만들어졌다면 my-fourth-configmap
에 있는 환경변수가 잘 설정되었는지 보도록 하자. 참고로 이전에 kubectl describe
로 my-fourth-configmap
에 있는 환경변수를 가져왔었을 때 3가지로 이루어져있었다.
color=blue
version=1
environment=prod
다음의 3개가 pod에 설정되어 있는 지 확인하도록 한다.
kubectl exec nginx-pod-with-configmap -- env
..
HOSTNAME=nginx-pod-with-configmap
environment=prod
version=1
color=blue
...
nginx-pod-with-configmap
에 3개의 환경변수가 잘 설정되어있는 것을 볼 수 있다. 이 환경변수는 my-fourth-configmap
에 있는 데이터들로 이 값들이 해당 pod의 환경변수로 설정된 것을 볼 수 있다.
단, 이 방법으로는 pod에 저장되는 환경변수의 key 이름을 지정하지 못하고 ConfigMap
에 있는 데이터와 동일하게 간다는 것이 단점이다.
다음으로, ConfigMap
을 container의 volume으로 마운트하는 방법에 대해서 알아보도록 하자.
kubectl
은 pod안에 volume으로 ConfigMap
을 적재할 수 있도록 도와준다. 이는 ConfigMap
이 container의 파일시스템 안에 삽입하고 싶은 파일 내용을 가지고 있다면 매우 유용하다.
환경 변수들을 삽입했을 때와 같이, 이 방법은 imperatively한 방법으로는 불가능하다. yaml manifest file을 만들어야한다. ConfigMap
인 my-sixth-configmap
을 volume mount로 nginx-pod-with-configmap
pod에 마운트시키도록 하자.
먼저 cluster에서 이전에 배포했던 pod를 삭제하고 시작하도록 하자.
kubectl delete pod nginx-pod-with-configmap
...
pod "nginx-pod-with-configmap" deleted
이제, 우리의 pod manifest file을 수정하여 ConfigMap
을 volume mount로 nginx pod
에 추가하도록 하자.
nginx-pod-with-configmap-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-configmap-volume
spec:
volumes:
- name: configuration-volume
configMap:
name: my-sixth-configmap # Configmap name goes here
containers:
- name: nginx-container-with-configmap
image: nginx:latest
volumeMounts:
- name: configuration-volume
mountPath: /etc/conf
configuration volume
이라는 volume을 cotanienrs
와 동일한 level에서 선언하였고, spec.volumes.configMap
을 통해서 해당 volume은 my-sixth-configmap
이라는 ConfigMap
으로부터 만들어진다는 것을 알려주었다. 때문에 해당 manifest file을 적용할 때는 반드시 my-sixth-configmap
이라는 ConfigMap
이 먼저 kubernetes cluster에서 동작하고 있어야 한다.
마지막으로 해당 volume
을 nginx-container-with-configmap
container의 /etc/conf
에 적재하도록 한다. ConfigMap
에 있는 parameter는 반드시 특정 위치에 있어야함을 잊지말자.
이제 해당 manifest로 pod를 deploy해보도록 하자.
kubectl create -f nginx-pod-with-configmap-volume.yaml
pod/nginx-pod-with-configmap-volume created
pod가 만들어졌다면, ls
명령어를 통해 해당 디렉터리가 container에 마운팅되었는 지 확인해보도록 하자.
참고로, my-sixth-configmap
은 다음으로 이루어져있다.
kubectl describe cm my-sixth-configmap
...
Name: my-sixth-configmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
color:
----
yellow
configfile.txt:
----
I'm just a dummy config file
Events: <none>
data로 yellow
와 I'm just a dummy config file
로 이루어져 있다.
kubectl exec nginx-pod-with-configmap-volume -- ls /etc/conf
color
configfile.txt
확인한 결과 우리가 원한대로 /etc/conf
가 nginx-pod-with-configmap-volume
에 적재되었고, 이 안에는 my-sixth-configmap
의 data인 color
와 configfile.txt
가 있다. 이들의 내부 데이터를 얻어오면 다음과 같다.
kubectl exec nginx-pod-with-configmap-volume -- cat /etc/conf/color
yellow
...
kubectl exec nginx-pod-with-configmap-volume -- cat /etc/conf/configfile.txt
I'm just a dummy config file
ConfigMap
의 data가 volume
의 key-value pair로 저장되게 되는 것이다. 이와 같은 기능을 통해서 특정 디렉터리 위치에 있는 configuration을 읽어서 환경에 따른 application 배포 및 구동이 가능하다. 즉, 디렉터리 위치라는 인터페이스로 환경 변수들이 환경과 독립적으로 설정될 수 있는 것이다.
다음으로, ConfigMap
들을 삭제해보록 하자.
ConfigMap
삭제는 이전의 pod
삭제와 크게 다를바 없다. 그러나 한 가지 유의할 것은 ConfigMap
의 value가 특정 pod에서 사용되어도 ConfigMap
이 삭제된다는 것이다. 이는 pod가 시작되면 ConfigMap
object와 독립적이기 때문이다.
kubectl delete cm my-first-configmap
configmap "my-first-configmap" deleted
container에 의해 ConfigMap
의 value가 사용되고 있는 지와 상관없이, ConfigMap
은 바로 삭제된다. 조심해야할 것은 ConfigMap
을 삭제하면 이를 되돌릴 방법은 없다. 때문에 삭제할 때 두 번 정도 생각해서 결정하도록 하자.
또한, 동작중인 pod에서 사용중인 value가 있는 ConfigMap
을 삭제하는 것은 조심해야한다. 만약 pod가 크러싱이 발생하면 manifest file
을 수정하는 방법 외에는 다시 정상으로 되돌릴 방법이 없기 때문이다.
ConfigMap
을 수정하는 특별한 명령어는 딱히 없지만, edit
을 통해서 변경이 가능하다. 다만, 변경한다고 해서 pod
에 반드시 적용되지 않을 수 있다. 가령, pod
에서 환경변수를 읽어오는 특정 시점이 프로그램이 시작된 후 가장 첫 부분이라면 ConfigMap
의 data를 변경해도 적용되지 않는다.
따라서, 이럴 때는 pod를 재시작시켜주는 방법 밖에 없다.
ConfigMap
을 수정하는 방법은 다음과 같다.
kubectl edit cm my-third-configmap
(이후 `color` 데이터를 `blue`에서 `red`로 변경 후 :wq!로 저장)
my-third-configmap
을 수정할 수 있게되고, value와 key를 변경할 수 있다. 위의 예시에서는 color
key의 blue
를 red
로 변경하는 예이다.
앞서 이야기했듯이 이렇게 수정한다해서 pod
에 반드시 적용된다는 보장이 없기때문에 pod를 삭제했다가 다시 올려야한다.
secret object는 kubernetes에서 동작 중인 applicatio을 configuration할 수 있다. 이는 ConfigMap
과 동일하지만, Secret
은 인코딩되며 민감한 데이터를 가질 수 있다. 가령, password나 token, 또는 private API key들이 있다. 반면에 ConfigMap
은 민감하지 않는 configuration data을 가진다. 이 외에 이들은 사실상 거의 같다.
Secret
을 리스팅하는 방법은 다음과 같다.
kubectl get secret
ConfigMap
과 같이 DATA
column은 Secret
에 저장되고 해싱된 민감한 정보의 수를 표현한다.
이제 data를 가진 Secret
을 만들도록 하자.
Secret
은 imperatively하게 만들수도 있고, declaratively하게 만들 수도 있다. 먼저 imperatively하게 Secret
을 만드는 방법부터 알아보도록 하자. 우리는 database password인 my-db-password
를 Secret
object안에 저장하고 싶다면 --from-literal
플래그와 kubectl create secret
명령어를 사용하면 된다.
또한, kubectl create secret <secret-type> <secret-name>
를 쓰게되는데, secret-type
이 추가되었다. 이는 secret
이 어떤 목적에 따라 사용되냐를 적은 것인데, generic
이라고 적으면 Opaque
type이 되고, 이는 사용자 정의 타입을 말한다.
kubectl create secret generic my-first-secret --from-literal=db_password=my-db-password
만들었다면, kubectl get secrets
명령어로 Secret
의 list를 불러올 수 있다. 다음과 같이 나올 것이다.
kubectl get secrets
NAME TYPE DATA AGE
my-first-secret Opaque 1 3m7s
이제 Secret
을 declaratively하게 만드는 방법을 알아보도록 하자.
Secret
을 declarative한 방법으로 만들 수도 있는데, 이 경우에 한 가지 주의해야할 것은 data를 base64
로 인코딩한 다음 넣어야한다는 것이다. 이는 yaml file에 Secret
정보가 노출되는데, 인코딩되지 않은 상태에서는 민감한 정보가 그대로 하드코딩되기 때문이다.
imperative한 방법으로 Secret
을 만들 때는 --from-literal
을 사용하였는데, 이 플래그가 실행되면 kubernetes는 자동적으로 string을 base64
로 인코딩한다. 그러나, yaml manifest file을 통해서 Secret
을 만드는 경우는 인코딩 단계를 따로 kubernetes에서 동작해주지 않는다.
따라서, 우리가 넣을 데이터인 db_password=my-db-password
의 my-db-password
문자열을 base64
로 인코딩해주도록 하자.
echo 'my-db-password' | base64
bXktZGItcGFzc3dvcmQK
bXktZGItcGFzc3dvcmQK
는 my-db-password
의 base64
인코딩 결과이고, 이를 YAML file에 value로 써주면 된다.
apiVersion: v1
kind: Secret
metadata:
name: my-second-secret
type: Opaque
data:
db_password: bXktZGItcGFzc3dvcmQK
secret
은 type
을 가지는 데, type
필드는 Secret
이 어떤 목적으로 이루어져 있냐는 것이다. 즉, tls인지 ssh-auth인지 사용자 정의 데이터인지 등에 따라 다르다. Opaque
는 임의의 사용자 정의 데이터를 의미한다. https://kubernetes.io/ko/docs/concepts/configuration/secret/
data
부분에 key-value형식으로 데이터를 넣어주면된다.
이제 Secret
을 만들어보도록 하자.
kubectl create -f secret-from-file.yaml
secret/my-second-secret created
잘 만들어졌는 지 확인하도록 하자.
kubectl get secret
NAME TYPE DATA AGE
my-first-secret Opaque 1 20m
my-second-secret Opaque 1 26s
my-second-secret
이 잘 만들어졌음을 알 수 있다.
file에서의 content을 기반으로 Secret
을 만들 수 있다. file에 비밀번호를 넣고 이를 가져와 Secret
을 만들도록 하자.
먼저 비밀번호를 가진 Secret
을 만들도록 하자.
echo -n 'mypassword' > ./password.txt
해당 명령어를 실행하면 우리는 password.txt
라는 파일을 얻게 된다. 해당 파일에는 string으로 mypassword
라는 비밀번호를 가지고 있고 이는 Secret
의 value가 된다. -n
옵션을 써서 password.txt
가 어떠한 추가적인 blank line을 text의 끝에 갖지않도록 한다.
--from-file
플래그를 통해서 password.txt
의 위치를 넘겨줌으로서 kubectl create secret
명령어로 Secret을 만들어보도록 하자. 이는 mypassword
문자열의 base64
표현을 data로 갖게 될 것이다.
이제 kubectl create secret <secret-type> <secret-name> --from-literal
명령어로 Secret
을 만들어주도록 하자.
kubectl create secret generic my-password --from-file=password=./password.txt
secret/my-password created
key
가 password
이고 value
가 ./password.txt
인 data를 my-password
에 넣어 Secret
을 만들었다.
잘 만들어졌는 지 확인하기 위해서 kubectl get secret
명령어를 사용해보도록 하자.
get secret
NAME TYPE DATA AGE
my-password Opaque 1 81s
my-second-secret Opaque 1 35m
잘 만들어진 것을 확인할 수 있다.
Secret
은 보안상 민감한 데이터를 담고 있기 때문에 kubectl
output으로 가져올 수 없다. 이는 보안상의 민감한 데이터가 터미널에 로깅되거나, 접근하지 않아야할 누군가가 이를 볼 수 있기 때문이다.
이러한 이유로 Secret
의 data는 얻을 수 없다. 다만, 해당 data의 사이즈와 같은 정보들은 알 수 있따.
kubectl describe
명령어를 사용함으로서 Secret
의 data를 불러올 수 있다. 단지 보안상의 이유로 일부 정보만 가져올 수 있는 것이다.
ubectl describe secrets my-password
Name: my-password
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 10 bytes
Data
부분의 password
의 value가 단지 10 bytes
로만 나온 것은 민감한 정보인 password
의 value를 decoding하지 않기 때문이다. 물론 kubectl edit
을 통해서 Secret
자체에 접근하고 configuration value를 수정할 수 있지만, 이는 좋은 방법이 아니다.
이제, Secret
을 environmet variable로 사용해보도록 하자.
Secret
인 my-passwrod
에서 password
값을 만들었었다. 이 값을 pod의 nginx-container
container에 넣어주도록 하자.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-secret-env-variable
spec:
containers:
- name: nginx-container
image: nginx:latest
env:
- name: PASSWORD_ENV_VAR # name of env variable
valueFrom:
secretKeyRef:
name: my-password # name of secret
key: password # name of key in secret object
spec.containers.env
를 만들어주고 name
은 container
에서 사용할 이름으로 설정해주면 된다. valueFrom
을 통해 env
의 값을 설정해주는데, secretKeyRef
의 name
으로 Secret
의 이름을 정해주고, key
에 Secret
에서의 env
이름을 정해주면 된다.
이제 pod를 만들어 실행해보도록 하자.
kubectl create -f nginx-pod-with-secret-env-variable.yaml
pod/nginx-pod-with-secret-env-variable created
실행이 되었다면 env
가 잘 설정되었는지 확인해보도록 하자.
kubectl exec nginx-pod-with-secret-env-variable -- env | grep "PASS"
PASSWORD_ENV_VAR=mypassword
Secret
에 있는 env
가 잘 설정된 것을 볼 수 있다.
또 다른 방법은 envFrom
을 사용하는 것인데, Secret
에 있는 모든 env값들을 pod에 적용하는 것이다.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-secret-env-variable
spec:
containers:
- name: nginx-container
image: nginx:latest
envFrom:
- secretRef:
name: my-password # name of secret
이전보다 간단한데, env
부분을 envFrom
으로 변경하여 적용하면 secretRef
의 name
에 해당하는 Secret
의 모든 값들이 pod
에 적용된다.
실행시켜서 확인해보도록 하자.
kubectl delete pod nginx-pod-with-secret-env-variable
pod "nginx-pod-with-secret-env-variable" deleted
kubectl exec nginx-pod-with-secret-env-variable -- env | grep "pass"
password=mypassword
password=mypassword
가 잘 적용된 것을 볼 수 있다.
Secret
을 pod에 volume으로 사용할 수도 있다. 다만, declareative하게 사용할 때만 가능하다.
mypassword
라는 Secret
을 pod container의 /etc/passwords-mounted-path/password
에 적재하도록 하자.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-secret-volume
spec:
containers:
- name: nginx-container
image: nginx:latest
volumeMounts:
- name: mysecret-volume
mountPath: /etc/password-mounted-path
volumes:
- name: mysecret-volume
secret:
secretName: my-password
volumes
로 mysecret-volume
를 만들고 Secret
으로 my-password
를 타겟으로 한다. 그리고 이 volume
을 nginx-container
에 volumeMounts
로 마운팅하기만 하면 된다.
이제 pod를 만들어보고 volume
이 잘 적재되었는 지 확인해보도록 하자.
kubectl create -f nginx-pod-with-secret-volume.yaml
pod/nginx-pod-with-secret-volume created
kubectl exec nginx-pod-with-secret-volume -- ls /etc/password-mounted-path/
password
kubectl exec nginx-pod-with-secret-volume -- cat /etc/password-mounted-path/password
mypassword
password
라는 이름의 파일로 mypassword
값이 정확히 들어있는 것을 확인할 수 있다. 성공적으로 Secret
이 volume으로 적재된 것을 볼 수 있다.
이전 kubernetes object들과 마찬가지로 kubectl delete
명령어를 사용하면 된다.
kubectl delete secret my-first-secret
secret "my-first-secret" deleted
Secret을 수정하기 위해서는 Secret을 edit
으로 수정하고, 이와 관련된 pod를 재시작하면 된다. 그러나 추천하진 않는다.