본문 바로가기
Cloud/Kubernates

설정값 전달 : ConfigMap, Secret

by 민휘 2023. 10. 29.

설정값을 파드에 전달하기

 

🌱 설정값 타입

  • Key Value
  • 설정 파일

 

🌱 설정값이나 설정파일을 애플리케이션에 전달하는 다양한 방법

  • 도커 이미지에 설정 정보를 정적으로 저장 → 유연하지 않음
  • yaml 파일에 설정값 하드 코딩 → 설정 환경마다 다른 yaml 파일 존재
  • yaml 파일과 설정값 분리 → 보안값은 시크릿, 일반 환경설정값은 컨피그맵에 저장

 

🌱 yaml 파일과 설정값을 분리하는 방식의 장점

  • 설정값 변경에 유리 : 애플리케이션에 필요한 설정이 바뀌어도 설정값 파일만 관리하면 되기 때문에, 간단하고 실수 없이 변경할 수 있다.
  • 환경에 따른 설정값 분리 : 운영, 개발, 테스트 환경에서 사용하는 설정값을 분리하면, 같은 yaml 파일에 설정값만 바꿔서 실행할 수 있다.
  • 설정값 재사용 : 설정 값을 따로 분리하여 관리하면, 여러 개의 YAML 파일에서 같은 설정 값을 사용할 수 있다.
  • 보안 : 설정값을 분리하면 이 파일만 git ignore에 추가하면 되므로 공개 저장소에 설정값이 노출되는 일을 막을 수 있다. 또 보안에 민감한 값은 시크릿을 사용해 안전하게 관리할 수 있다.

 

컨피그맵

 

컨피그맵은 네임스페이스에 속하므로, 네임스페이스별로 컨피그맵이 존재한다. 다음과 같은 실습을 진행한다.

  • 컨피그맵 생성과 확인
  • 전체 혹은 일부 컨피그맵을 컨테이너의 환경변수로 등록
  • 전체 혹은 일부 컨피그맵을 파드 내부에 마운트하여 사용
  • 설정파일이나 yaml 파일로부터 컨피그맵 생성

 

컨피그맵 생성과 확인

--from-literal 옵션으로 간단하게 key와 value만으로 컨피그맵을 생성할 수 있다. 여러개의 kv 쌍을 생성할 때는 --from-literal 옵션을 여러개 사용한다.

  • 1개의 kv 쌍 : kubectl create configmap log-level-configmap **--from-literal LOG_LEVEL=DEBUG**
  • 여러개의 kv 쌍 : kubectl create configmap start-k8s **--from-literal k8s=kubernates --from-literal container=docker**
  • 컨피그맵의 값 확인 : kubectl describe configmap log-level-컨피그맵이름
minhwi@minhwiui-MacBookPro  ~/kubernetes  kubectl describe configmap log-level-configmap
Name:         log-level-configmap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
**LOG_LEVEL:
----
DEBUG**

BinaryData
====

Events:  <none>
 minhwi@minhwiui-MacBookPro  ~/kubernetes  kubectl describe configmap start-k8s
Name:         start-k8s
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
**container:
----
docker
k8s:
----
kubernates**

BinaryData
====

Events:  <none>

 

 

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

 

🌱 컨피그맵 전체를 컨테이너의 환경변수로 사용

apiVersion: v1
kind: Pod
metadata:
  name: container-env-example
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      envFrom:
        - configMapRef:
            name: log-level-configmap
        - configMapRef:
            name: start-k8s
  • envFrom : 아래 항목으로 가져온 컨피그맵의 모든 항목을 환경 변수로 가져온다.
  • configMapRef.name : 이름으로 컨피그맵을 찾는다.

 

🌱 컨테이너 내부에서 환경변수 출력하기

  • pod 실행하고 env 명령어 실행 : kubectl exec container-env-example env
  • 위에서 등록한 컨피그맵의 key value 설정값들이 설정된 것을 볼 수 있다.
  • KUBERNETES_로 시작하는 환경변수는 디폴트로 사용하는 kubernates 서비스에 대한 것이다.
HOSTNAME=container-env-example
**LOG_LEVEL=DEBUG
container=docker
k8s=kubernates**
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.8.0.1
KUBERNETES_SERVICE_HOST=10.8.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.8.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.8.0.1:443
HOME=/root

 

🌱 컨피그맵 일부를 컨테이너의 환경변수로 사용

apiVersion: v1
kind: Pod
metadata:
  name: container-env-example
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      env:
      - name: ENV_KEYNAME_1
        valueFrom:
          configMapKeyRef:
            name: log-level-configmap
            key: LOG_LEVEL
      - name: ENV_KEYNAME_2
        valueFrom:
          configMapKeyRef:
            name: start-k8s
            key: k8s
  • env : name에 해당하는 Key로 환경변수를 등록한다.
  • env.name : 환경변수의 Key
  • env.valueFrom : Key와 매핑되는 Value. 컨피그맵 안의 key로 value를 찾아서 등록한다.
  • 파드 실행해서 환경변수 확인 : kubectl exec container-env-example env | grep ENV
ENV_KEYNAME_1=DEBUG
ENV_KEYNAME_2=kubernates

 

컨피그맵을 파드 내부의 파일로 마운트해서 사용

 

🌱 컨피그맵 전체를 파드 내부의 파일로 마운트해서 사용

 

컨피그맵을 파일로 마운트하면, 각 key value 쌍에 대해서 key 이름을 가지며 내용으로 value 값을 가지는 파일들이 생성된다.

apiVersion: v1
kind: Pod
metadata:
  name: container-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**
  • spec.volumes : 파드에서 사용하는 볼륨을 정의한다. start-k8s 이름을 가진 컨피그맵을 볼륨에서 사용한다.
  • spec.containers:volumeMounts : 컨테이너 내부에서 컨피그맵을 통해 정의된 볼륨을 해당 경로에 마운팅해서 사용한다.
  • 파드를 만들어서 마운트 경로의 파일을 출력해보면 start-k8s 컨피그맵의 key 이름을 가진 파일을 확인할 수 있다. kubectl exec container-volume-pod ls /etc/config
container
k8s

 

🌱 컨피그맵 일부를 파드 내부의 파일로 마운트해서 사용

apiVersion: v1
kind: Pod
metadata:
  name: container-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
        items:
          - key: k8s
            path: k8s_fullname**
  • items : 컨피그맵에서 가져올 key-value 목록을 의미한다. 여기서는 k8s라는 키만 가져오도록 명시했다.
  • path : 최종적으로 디렉터리에 위치할 파일의 이름을 입력한다.
  • 파드 실행해서 마운트된 경로 확인 : kubectl exec container-volume-pod ls /etc/config
k8s_fullname # path로 지정한 파일 이름

 

 

파일로부터 컨피그맵 생성

 

🌱 텍스트를 가진 파일로부터 컨피그맵 생성

  • 파일 생성 : echo Hello >> index.html
  • 파일명을 키로, 파일 내용을 값으로 갖는 컨피그맵 생성 : kubectl create configmap index-file --from-file index.html
  • 확인 : kubectl describe configmap index-file
Data
====
**index.html:
----
Hello**
  • 키의 이름 직접 지정해서 컨피그맵 생성 : kubectl create configmap index-file --from-file **myindex=index.html**
  • 확인 : kubectl describe configmap index-file
Data
====
**myindex:
----
Hello**

 

🌱 여러개의 키-값으로 구성된 설정 파일로 컨피그맵 생성

# multiple-keyvalue.env
mykey1=myvalue1
mykey2=myvalue2
mykey3=myvalue3
  • 설정파일로 컨피그맵 생성 : kubectl create configmap from-envfile **--from-env-file multiple-keyvalue.env**
  • 확인 : kubectl get cm from-envfile -o yaml
apiVersion: v1
data:
  mykey1: myvalue1
  mykey2: myvalue2
  mykey3: myvalue3
kind: ConfigMap
metadata:
  creationTimestamp: "2023-04-04T05:09:07Z"
  name: from-envfile
  namespace: default
  resourceVersion: "5134851"
  uid: 5bd5f4e7-3537-4980-8665-f82c6b5088fe

 

 

🌱 yaml 파일로 컨피그맵 생성

  • 설정값 → 컨피그맵 Yaml : kubectl create configmap my-configmap **--from-literal mykey=myvalue --dry-run -o yaml** > my-config.yaml
  • my-config.yaml 내용 확인
mykey3: myvalue3
apiVersion: v1
**data:
  mykey: myvalue
kind: ConfigMap**
metadata:
  creationTimestamp: null
  name: my-configmap
  • Yaml로 컨피그맵 생성 : kubectl apply -f my-config.yaml
  • 컨피그맵 내용 확인 : kubectl describe configmap my-configmap

 

시크릿

시크릿 사용 용도

시크릿은 SSH 키, 비밀번호와 같이 민감한 정보를 저장하기 위한 용도로 사용하며, 네임스페이스에 종속되는 오브젝트다. 시크릿과 컨피그맵은 사용 방법이 비슷하다.

generic 타입 시크릿

generic 타입은 Opaque 타입에 해당하는 종류이다. Opaque는 내부의 데이터를 들여다볼 수 없는 타입이다. 사용자가 정의하는 데이터를 저장하는 일반적인 목적의 시크릿이다. base 64로 인코딩한다.

 

🌱 시크릿 생성하고 값 확인하기


리터럴로 생성하기

  • kubectl create secret generic my-password --from-literal password=1q2w3e4r
  • kubectl get secret my-password -o yaml
apiVersion: v1
data:
  password: MXEydzNlNHI= # base64로 인코딩됨
kind: Secret
metadata:
  creationTimestamp: "2023-04-04T11:41:40Z"
  name: my-password
  namespace: default
  resourceVersion: "5329815"
  uid: f9e1f29c-2078-468e-82b4-c95c716c1299
type: Opaque # 내부 데이터를 들여다볼 수 없는 타입. general도 Opaque에 속함.

 

파일로 생성하기

  • echo mypassword > pw1 && echo yourpassword > pw2
  • kubectl create secret generic out-password --from-file pw1 --from-file pw2
  • kubectl describe secret my-password
apiVersion: v1
data:
  pw1: bXlwYXNzd29yZAo=
  pw2: eW91cnBhc3N3b3JkCg==
kind: Secret
metadata:
  creationTimestamp: "2023-04-04T11:43:03Z"
  name: out-password
  namespace: default
  resourceVersion: "5330552"
  uid: 264ccee5-8195-4e2c-ae2f-8d2b6e8b03d2
type: Opaque

 

yaml로부터 시크릿 생성

  • 시크릿을 사용하는 yaml 만들어서 출력 : kubectl create secret generic my-password --from-literal password=1q2w3e4r --dry-run -o yaml
  • 시크릿을 사용하는 yaml 저장 : kubectl create secret generic my-password --from-literal password=1q2w3e4r --dry-run -o yaml > my-secret.yaml
apiVersion: v1
data:
  password: MXEydzNlNHI= # base64 인코딩
kind: Secret
metadata:
  creationTimestamp: null
  name: my-password

 

 

🌱 파드의 환경변수로 가져오기

# 시크릿의 전체 키 값 쌍 불러오기
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-example
spec:
  containers:
  - name: my-conatiner
    image: busybox
    args: ['tail', '-f', '/dev/null']
    **envFrom:
    - secretRef:
        name: my-password**
# 시크릿의 일부 키 값 쌍 불러오기
apiVersion: v1
kind: Pod
metadata:
  name: selective-secret-env-example
spec:
  containers:
  - name: my-conatiner
    image: busybox
    args: ['tail', '-f', '/dev/null']
    **env:
    - name: YOUR_PASSWORD
      valueFrom:
        secretKeyRef:
          name: our-password
          key: pw2**
# 최종 시크릿 형태 : YOUR_PASSWORD = encoded(yourpassword)

 

🌱 파드 볼륨에 마운팅하기

 

# 전체 키 값 쌍을 볼륨에 마운트
apiVersion: v1
kind: Pod
metadata:
  name: container-volume-pod-secret
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      volumeMounts: # 컨테이너에 볼륨 마운트
      - name: secret-volume
        mountPath: /etc/secret
  **volumes: # 파드 볼륨 정의
    - name: secret-volume
      secret:
        name: out-password**
# 일부 키 값을 볼륨에 마운트
apiVersion: v1
kind: Pod
metadata:
  name: container-volume-pod-secret
spec:
  containers:
    - name: my-container
      image: busybox
      args: ['tail', '-f', '/dev/null']
      volumeMounts:
      - name: secret-volume
        mountPath: /etc/secret
  **volumes:
    - name: secret-volume
      secret:
        secretName: our-password
        items:
        - key: pw1
          path: password1**
# 최종 파일 이름 : password1
# 최종 파일 내용 : our-password 시크릿의 인코딩된 pw1 value

 

docker-registry 타입 시크릿

 

비공개 레지스트리에 접근할 때 사용하는 인증 설정 시크릿이다. 디플로이먼트 또는 파드 등에서 사설 레지스트리로부터 이미지를 받아올 때 사용할 수 있다.

 

🌱 config.json으로 시크릿 생성

  • 도커 로그인으로 config.json 생성 : docker login
  • 시크릿 생성 : kubectl create secret **generic** registry-auth **--from-file=.dockerconfigjson=/root/.docker/config.json** --type=kubernates.io/dockerconfig.json

 

🌱 문자열로 시크릿 생성

  • 도커 허브의 사설 레지스트리 : kubectl create secret docker-registry registry-auth-by-cmd --docker-username=alicek106 --docker-password=1q2w3e4r
  • 다른 사설 레지스트리 : kubectl create secret docker-registry registry-auth-by-cmd --docker-username=alicek106 --docker-password=1q2w3e4r --docker-server=alicek106.registry.com

 

🌱 시크릿 타입 확인

 

🌱 디플로이먼트에서 사설 레지스트리로부터 이미지 받아오기

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      name: my-nginx-pod
      labels: 
        app: my-nginx
    spec:
      containers:
      - name: test-container
        image: <비공개 이미지>
        ports:
        - containerPort: 80
      **imagePullSecrets:
      - name: registry-auth-registry**

 

 

tls 타입 시크릿

TLS 연결에 사용되는 공개키, 비밀키 등을 쿠버네티스에 자체적으로 저장하는 시크릿이다. 파드 내부의 애플리케이션이 보안 연결을 위해 인증서나 비밀키를 가져와야할 때 시크릿의 값을 파드에 제공하는 방식으로 사용한다.

 

🌱 키 페어 생성

openssl req -new -newkey rsa:4906 -days 365 -nodes -x509 -subj “/CN=example.com” -keyout cert.key -out cert.crt
  • req: 인증서 요청 명령을 실행합니다.
  • new: 새로운 인증서 요청을 만듭니다.
  • newkey rsa:4906: 새 RSA 비공개 키를 생성합니다. 4906은 키 길이를 나타냅니다.
  • days 365: 인증서의 유효 기간을 1년으로 설정합니다.
  • nodes: 비밀번호 없이 키를 생성합니다.
  • x509: 인증서 생성을 위해 X.509 표준을 사용합니다.
  • subj: 인증서 주체를 정의합니다. 이 경우 "/CN=example.com"으로 설정되어 있으며, Common Name(CN)을 example.com으로 설정합니다.
  • keyout cert.key: 비공개 키를 cert.key 파일에 작성합니다.
  • out cert.crt: 생성된 SSL 인증서를 cert.crt 파일에 작성합니다.

 

이 명령어를 실행하면, 자체 서명 SSL 인증서 파일이 생성되며, 이 파일을 사용하여 HTTPS를 지원하는 서버를 설정할 수 있습니다.

  • 🌱 시크릿 생성 : kubectl create secret tls my-tls-secret --cert cert.crt --key cert.key
  • 🌱 정보 확인 : kubectl get my-tls-secret 혹은 kubectl get my-tls-secret -o yaml

 

컨피그맵과 시크릿의 데이터를 yaml로부터 분리하기

지금까지는 컨피그맵이나 시크릿을 yaml 파일로 배포하려면 데이터를 직접 yaml 파일에 함께 저장했다. 그러나 시크릿 데이터가 많아질수록 yaml 파일에 직접 시크릿의 데이터를 저장하는 방법은 가독성이 떨어지고 데이터 관리도 불편하다. 이런 단점을 해결하려면 kustomize 기능을 사용할 수 있다.

 

🌱 시크릿 배포

# kubectl create secret generic my-password 
# --from-literal password=1q2w3e4r
secretGenerator:
- name: generic-secret
  type: generic
  literals:
  - password=1q2w3e4r

 

kustomize로부터 생성될 시크릿 정보 확인 : kubectl kustomize ./

apiVersion: v1
data:
  password: MXEydzNlNHI=
kind: Secret
metadata:
  name: generic-secret-kbkd6mkgmk
type: generic
  • kustomize로 시크릿 생성 : kubectl apply -k ./
  • kustomize로 시크릿 삭제 : kubectl delete -k ./

 

🌱 컨피그맵 배포

 

configMapGenerator:
- name: kustomize-configmap
  files:
  - tls.crt=cert.crt
  - tls.key=cert.key

 

kustomize로부터 생성될 컨피그맵 정보 확인 : kubectl kustomize ./

apiVersion: v1
data:
  tls.crt: |
    cert
  tls.key: |
    key
kind: ConfigMap
metadata:
  name: kustomize-configmap-6bck6fkcfk

 

  • kustomize로 시크릿 생성 : kubectl apply -k ./
  • kustomize로 시크릿 삭제 : kubectl delete -k ./

 

컨피그맵이나 시크릿을 업데이트해서 애플리케이션의 설정값 변경하기

 

컨피그맵이나 시크릿 데이터 업데이트 방법

  • kubectl edit
  • yaml 파일 변경후 kubectl apply
  • kubectl patch

 

바뀐 설정값을 파드에 반영

  • 환경변수 : 디플로이먼트의 파드를 다시 생성해야 반영됨
  • 파드 마운트 : 파드 안의 파일 내용이 자동 갱신됨

 

바뀐 설정값을 컨테이너에 반영

  • 내용이 변경됐다고 해서 파드에서 실행 중인 애플리케이션 설정이 자동으로 변경되는 것은 아니다. 결국 변경된 파일을 다시 읽어들이도록 별도의 로직을 구현해야함
  • 컨테이너 프로세스에 별도의 시그널을 보내는 사이드카 컨테이너를 파드에 포함시키기
  • 애플리케이션 소스코드 레벨에서 쿠버네티스 API를 사용해 컨피그맵, 시크릿의 데이터 변경에 대한 알림을 받고 자동으로 리로드하는 로직 구현하기

 

'Cloud > Kubernates' 카테고리의 다른 글

NameSpace 관리  (1) 2023.10.29
Service  (0) 2023.10.29
ReplicaSet, Deployment  (0) 2023.10.29
Pod, NameSpace  (1) 2023.10.29
쿠버네티스 시작하기 : 내부 구조  (0) 2023.10.29