kubernetes 리소스의 관리와 설정 - Configmap, Secret

2020. 2. 19. 14:00devops/kubernetes

애플리케이션을 만들면 초기 설정 값이 필요한 오브젝트들이 있을 것입니다. ex) DB, Nginx 등등 도커에서 이러한 설정 값을 넘겨 주는데 -e옵션을 사용하거나 Dokcerfile을 작성했습니다. 이러한 방법이 좋은 방법이 될 수 있지만 상황에 따라서는 나쁜 선택이 될 수 있습니다. 그래서 kubernetes에서는 yaml 파일과 설정값을 분리할 수 있는 configmap, secret이라는 오브젝트를 제공합니다. 

 

configmap은 설정 값을 secret은 노출되서는 안되는 값을 넣어 줄 때 사용합니다. 

 

configmap 사용해보기

configmap은 namespace에 속하기 떄문에 namespace별로 configmap이 존재합니다. 

 

kubectl create configmap <컨피그맵 이름> <각종 설정들>
kubectl create configmap log-level-configmap --from-literal LOG_LEVEL=DEBUG

yaml 파일로도 생성할 수 있지만 명령어로 생성하면 더욱 쉽게 생성할 수 있습니다. --from-literal을 사용하여 여러 개의 컨피그 맵을 생성할 수 있습니다. 

 

kubectl create configmap start-k8s --from-literal k8s=kubernetes \ 
--from-literal container=docker

 

다른 오브젝트들과 같이 describe, get등으로 정보를 출력할 수 있습니다.

kubectl get cm or configmap // 생성된 컨피그맵 확인
NAME        DATA   AGE
start-k8s   2      16s

kubectl describe configmap start-k8s // 상세 정보 확인
Name:         start-k8s
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
container:
----
docker
k8s:
----
kubernetes
Events:  <none>

kubectl get configmap start-k8s -o yaml  //yaml 스타일로 출력
apiVersion: v1
data:
  container: docker
  k8s: kubernetes
kind: ConfigMap
metadata:
  creationTimestamp: "2020-02-19T04:54:02Z"
  name: start-k8s
  namespace: default
  resourceVersion: "131204"
  selfLink: /api/v1/namespaces/default/configmaps/start-k8s
  uid: c6e371a8-ee6e-42df-9199-cee6f73286f0

 

configmap 포드에 사용하기 

1. 컨피그맵의 값을 컨테이너의 환경 변수로 사용

2. 컨피그맵의 값을 포드 내부의 파일로 마운트해 사용 

 

컨피그맵의 데이터를 컨테이너의 환경변수로 가져오기 

apiVersion: v1
kind: Pod
metadata:
  name: config-pod
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      envFrom:
      - configMapRef:
          name: start-k8s

configMapRef를 통해 configmap 이름과 name을 일치시켜서 가져올 수 있습니다. 

 

kubectl exec config-pod env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-pod
container=docker
k8s=kubernetes
....

해당 오브젝트 안에 container, k8s 등이 생긴 것을 확인할 수 있습니다. 

 

컨피그맵의 내용을 파일로 포드 내부에 마운트하기

 

애플리케이션이 nginx.conf, mysql.conf 등과 같은 특정 파일로부터 설정값을 읽어온다면 컨피그맵의 데이터를 포드 내부의 파일로 마운트해 사용할 수 있습니다. 

apiVersion: v1
kind: Pod
metadata:
  name: config-volume-pod
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      volumeMounts: 
      - name: configmap-volume
        mountPath: /etc/config
  volumes:
    - name: configmap-volume
      configMap: 
        name: start-k8s
kubectl apply -f volume-mount-configmap.yaml
kubectl exec configmap-volume-pod ls /etc/config
container
k8s
kubectl exec configmap-volume-pod cat /etc/config/k8s
kubernetes

이렇게 전체를 다 마운트 할 수 있지만 원하는 데이터만 선택하여 마운트할 수도 있습니다. 

 volumeMounts: 
      - name: configmap-volume
        mountPath: /etc/config
  volumes:
    - name: configmap-volume
      configMap: 
        name: start-k8s
        items: 
        - key: k8s // 원하는 키만 가져올 수 있음
          path: k8s_fullname // 해당 키 - 값이 위치할 폴더 이름 지정

kubectl exec selective-volume-pod ls /etc/config
k8s_fullname
kubectl exec selective-volume-pod ls /etc/config
kubernetes

파일로부터 configmap 생성

 

위와 같이 문자열 만을 사용하여 컨피그맵을 제공할 수 있지만 파일 또한 제공해줄 수 있습니다. 

kubectl create configmap <컨피그 맵 이름> --from-file <파일 이름> 

index.html
<html>
	<head>
	</head>
	<body>
		<h1> Hello Hoony </h1>
	</body>
</html>


kubectl create configmap index-file --from-file index.html

 

확인

kubectl create configmap index-file --from-file index.html // configmap 생성 후

kubectl describe configmap index-file // 확인
Name:         index-file
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
index.html:
----
<html>
  <head>
  </head>
  <body>
    <h1> Hello Hoony </h1>
  </body>
</html>

 

YAML 파일로 컨피그맵 정의하기

 

컨피그맵을 꼭 명령어로만 생성해야하는 것은 아닙니다. --dry-run과 -o yaml 옵션을 사용하면 컨피그맵을 생성하지 않은 채로 YAML 파일의 내용을 출력할 수 있습니다. 

kubectl create configmap my-config --from-literal mykey=myvalue --dry-run -o yaml

apiVersion: v1
data:
  mykey: myvalue
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: my-config

--dry-run과 -o yaml 옵션을 사용하면 컨피그맵을 생성하지 않은 채로 yaml 파일의 내용을 출력할 수 있습니다. 그런 다음 이 내용을 yaml 파일로 저장한 다음 kubectl apply -f 명령어로 configmap을 생성할 수 있습니다. 

 

 

시크릿(Secret)

시크릿은 SSH 키, 비밀번호와 같이 민감한 정보를 저장하기 위한 용도로 사용됩니다. 컨피그 맵과 사용법이 비슷하지만 좀 더 보안이 중요한 만큼 세분화된 사용방법을 제공합니다. 

kubectl create secret generic my-password --from-literal password=1q2w3e4r

확인

kubectl get secret my-password -o yaml                                                                                                             ✔  10152  15:32:34
apiVersion: v1
data:
  password: MXEydzNlNHI=
kind: Secret
metadata:
  creationTimestamp: "2020-02-19T06:32:34Z"
  name: my-password
  namespace: default
  resourceVersion: "137505"
  selfLink: /api/v1/namespaces/default/secrets/my-password
  uid: 213dfffe-a275-4ef5-9f8e-60233e0da1f6
type: Opaque

password의 데이터가 1q2w3e가 아닌 MXEydzNlNHI=으로 base64로 인코딩된 것을 확인할 수 있습니다. 

 

또한 컨피그맵과 같이 yaml 파일을 만들 수 있습니다. 컨피그맵과의 차이점은 kind가 Secret으로 나옵니다. 

kubectl create secret generic my-password --from-literal password=1q2w3e4r --dry-run -o yaml                                                      
apiVersion: v1
data:
  password: MXEydzNlNHI=
kind: Secret
metadata:
  creationTimestamp: null
  name: my-password

 

또한 환경변수도 똑같이 넣어 줄 수 있습니다.

apiVersion: v1
kind: Pod
metadata:
  name: config-volume-pod
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      envFrom:
      - secretRef:
      	name: my-password

or 원하는 key 값 가져오기
	env: 
    - name: YOUR_PASSWORD
   	  valueFrom: 
      	secretKeyRef:
        	name: our-password
            key: pw2

or volumeMount 하기
      volumeMounts: 
      - name: secret-volume
        mountPath: /etc/secret
  volumes:
    - name: secret-volume
      secret: 
        secretName: my-password
        
or volume 값 중에 원하는 거 가져오기
	volumeMounts: 
      - name: secret-volume
        mountPath: /etc/secret
  volumes:
    - name: secret-volume
      secret: 
        secretName: our-password
        items: 
        	-key: pw1
             path: password1

 

Docker-registry 타입의 시크릿 사용하기

docker에서 로컬환경으로 사용할 때는 docker login이면 되었지만 쿠버네티스에서는 추가 작업이 필요합니다. docker login 대신 레지스트리의 인증 정보를 저장하는 별도의 시크릿을 생성해 사용합니다. 

 

1. docker 로그인 성공시 생기는 config.json 사용하기 위치는 ~/.docker/config.json

kubectl create secret generic registry-auth \
--from-file=.dockerconfigjson=~/.docker/config.json \
--type=kubernetes.io/dockerconfigjson

 

2. 직접 id와 password를 입력하기

kubectl create secret docker-registry registry-auth-by-cmd \
--docker-username=id \
--docker-password=1q2w3e4r
option
--docker-server=사설 레지스트리 주소

--docker-server는 사설레지스트리를 이용하고 있으면 option으로 해당 레지스트리 주소를 입력하면 됩니다. 

 

위에서 만든 시크릿은 kubernetes.io/dockerconfigjson이라는 타입으로 기록됩니다. 

 

TLS 키를 저장할 수 있는 tls 타입의 시크릿 사용하기

시크릿은 TLS 연결에 사용되는 공개키, 비밀키 등을 쿠버네티스에서 자체적으로 저장할 수 있도록 tls 타입을 지원합니다. 

kubectl create secret tls my-tls-secret \
--cert cert.crt --key cert.key

여기에 key, crt 값도 모두 base64로 인코딩되어 저장됩니다. 

 

kustomize 

위에서와 같이 직접 secret이나 configmap을 명령어로 만들거나 yaml 파일로 만드는데 크게 불편함은 없었지만 양이 많아질 수록 관리도 만들기도 힘들어집니다. 그럴때 데이터를 yaml 파일로 분리할 수 있는 kustomize 기능을 사용할 수 있습니다. 

secretGenerator:
  - name: kustomize-secret
    type: kubernetes.io/tls
    files:
    - tls.crt=cert.crt
    - tls.key=cert.key

위와 같이 yaml 파일을 작성 후 아래와 같은 명령어를 통해 시크릿을 만들 수 있습니다. 

kubectl apply -k ./