Kubernetes ConfigMap & Secret

신동수·2024년 5월 16일
0

K8S

목록 보기
13/14

쿠버네티스 환경변수

애플리케이션은 대부분 여러가지 환경변수(설정값)들을 정의해야 한다. 간단한 예를 들어보면, 로깅 레벨을 정의할 때 LOG_LEVEL=INFO처럼 단순히 키-값 형태의 설정값이 되든지, 아니면 Nginx 웹 서버가 사용하는 nginx.conf처럼 완전한 하나의 설정 파일 형태가 되든지 환경변수를 정의해야 한다.

이러한 환경변수를 우리의 애플리케이션에 전달하는 가장 확실하고 직관적인 방법은 도커 이미지 내부에 설정값 또는 설정 파일을 정적으로 저장해두는 것이다. 그러나 이러한 방식은 단점이 있는데, 도커 이미지는 한번 빌드가 완료되면 불변의 상태이기 때문에 설정 옵션을 유연하게 변경할 수 없다.

파드 정의 YAML 파일을 활용한 환경변수 설정

쿠버네티스에서는 다음과 같이 파드 정의 YAML 파일에서 env를 통해 컨테이너에 환경변수를 직접 하드 코딩 방식으로 전달할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: simple-webapp-color
spec:
  containers:
    - name: simple-webapp-color
      image: simple-webapp-color
      ports:
        - containerPort: 8080

      # 아래 env 부분에서 환경 변수를 설정한다.
      env:
        - name: APP_COLOR # 컨테이너가 사용할 수 있는 환경 변수의 이름
          value: pink # 환경 변수의 값

이와 같은 방식을 Plain Key Value라고 부른다. 나쁜 방식은 아니지만, 상황에 따라서 환경변수의 값만 다르고 내용은 동일한 YAML 파일을 여러 개 사용해야 하는 경우도 있다. 이 경우, 파드 정의 YAML 파일에서 환경변수만을 분리해서 관리하면 한결 편리할 것이다.

쿠버네티스는 YAML 파일과 환경변수를 분리할 수 있는 방식으로 컨피그맵(ConfigMap)과 시크릿(Secret) 오브젝트를 제공한다.

컨피그맵(ConfigMap)

앞서 YAML 파일에서 환경 변수를 정의하는 방식을 살펴보았다. 그런데, YAML 파일이 많아지면, 다양한 파일들에 정의되어 있는 환경변수들 또한 관리하기 어려워진다. 따라서 파드 정의 YAML 파일 밖에서 환경변수들을 관리하는 방식인 컨피그맵(ConfigMap)이 필요하다.

컨피그맵은 환경변수 데이터를 키-값(key-value)의 쌍으로 전달하기 위해 사용된다. 컨피그맵은 파드가 생성될 때 파드에 주입되고, 이렇게 주입된 키-값 쌍의 환경변수들은 파드 내 컨테이너에서 호스트되는 애플리케이션에서 접근할 수 있게 된다. 즉, 다음 두 단계를 거치는 것이다.

  • 컨피그맵 생성하기
  • 파드에 컨피그맵 주입하기

컨피그맵 생성하기

컨피그맵은 다른 쿠버네티스 오브젝트들과 마찬가지로 명령형(imperative) 방식과 선언형(declarative) 방식으로 생성할 수 있다.

명령형(imperative) 방식

  1. kubectl create configmap {컨피그맵 이름} --from-literal={키}={값}
    - 예) kubectl create configmap app-config --from-literal=APP_COLOR=blue --from-literal=APP_MODE=prod
    위와 같이 --from-literal 옵션을 사용하여 컨피그맵에 환경변수를 키-값 형태로 전달할 수 있다. 또한, --from-literal 옵션을 여러 번 사용하여 여러 개의 요소들을 한번에 입력할 수도 있다.
  2. kubectl create configmap {컨피그맵 이름} --from-file={파일의 경로}
    - 예) kubectl create configmap app-config --from-file=app_config.properties
    위와 같이 파일의 경로를 지정해주는 방식도 가능하다.
  3. kubectl create configmap {컨피그맵 이름} --from-literal={키}={값} --from-file={파일의 경로} - 예) kubectl create configmap app-config --from-literal=APP_COLOR=blue --from-file=app_config.properties`
    또한, 키-값과 파일의 경로로 함께 융합해서 사용도 가능하다.
# app_config.properties

APP_COLOR=blue
APP_MODE=prod

선언형(declarative) 방식

# config-map.yaml

apiVersion: v1
kind: ConfigMap # kind는 ConfigMap으로 설정한다.
metadata:
  name: app-config
data: # 아래 부분에 ConfigMap 내용을 적어준다.
  APP_COLOR: blue
  APP_MODE: prod

이후 kubectl create -f config-map.yaml 명령어를 입력한다.
kubectl get configmaps 또는 kubectl describe configmaps 명령어를 통해 현재의 ConfigMap을 확인할 수 있다.

파드에 컨피그맵 주입하기

# pod-definition.yaml

apiVersion: v1
kind: Pod
metadata:
  name: simple-webapp-color
spec:
  containers:
    - name: simple-webapp-color
      image: simple-webapp-color
      ports:
        - containerPort: 8080

      # 아래 envFrom 부분을 통해 생성된 ConfigMap을 파드에 주입(설정)한다.
      envFrom:
        - configMapRef:
            name: app-config # ConfigMap 정의 YAML 파일의 metadata 이름을 적는다.

컨피그맵을 생성했다면, 생성된 컨피그맵을 파드에 주입해야 우리가 따로 설정한 환경변수를 활용할 수 있다.
이후 kubectl create -f pod-definition.yaml 명령어를 통해 파드를 생성하면, 컨피그맵을 통해 환경변수 설정이 주입된 파드가 실행될 것이다.
이러한 방식 외에도 컨피그맵을 주입하는 방식은 아래와 같이 몇 가지 더 있다.

파드에 컨피그맵을 주입하는 여러 방법

# 기본적인 방식
envFrom:
  - configMapRef:
      name: app-config # ConfigMap 정의 YAML 파일의 metadata 이름을 적는다.
# 하나의 키 값만 가져오는 경우
env:
  - name: APP_COLOR
    valueFrom:
      configMapKeyRef:
        name: app-config # ConfigMap 정의 YAML 파일의 metadata 이름을 적는다.
        key: APP_COLOR # 가져오고자 하는 키 값을 입력한다.
# 볼륨에서 전체 데이터를 파일로 가져오는 경우
volumes:
- name: app-config-volume
  configMap:
    name: app-config # ConfigMap 정의 YAML 파일의 metadata 이름을 적는다.

컨피그맵 실습

$ tree build
build
|-- Dockerfile
`-- genid.sh

0 directories, 2 files

$ cat Dockerfile
FROM ubuntu:18.04
RUN apt-get update ; apt-get -y install rig boxes
ENV INTERVAL 5
ENV OPTION stone
ADD genid.sh /bin/genid.sh
RUN chmod +x /bin/genid.sh
ENTRYPOINT ["/bin/genid.sh"]

$ cat genid.sh
#!/bin/bash
mkdir -p /webdata
while true
do
  /usr/bin/rig | /usr/bin/boxes -d $OPTION  > /webdata/index.html
  sleep $INTERVAL
done

위의 코드에서 Dockerfile을 사용하여 실행 가능한 Ubuntu 이미지를 만들고, genid.sh 스크립트를 실행하여 /webdata 디렉토리에 주기적으로 ASCII 아트를 생성하여 저장하는 이미지이다.

# config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: config
data:
  INTERVAL: "2"
  OPTION: "boy"
  nginx-config.conf: |
    server {
        listen   80;
        server_name  www.example.com;

        gzip on;
        gzip_types text/plain application/xml;

        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    }

실습에서 사용할 configmap YAML 파일은 위와 같으며, 해당 yaml 로 실습을 진행하겠다.

컨피그맵 일부분 적용

# genid.yaml
apiVersion: v1
kind: Pod
metadata:
  name: genid-stone
spec:
  containers:
  - image: smlinux/genid:env
    env:
    - name: INTERVAL
      valueFrom:
        configMapKeyRef:
          name: config
          key: INTERVAL
    name: fakeid
    volumeMounts:
    - name: html
      mountPath: /webdata
  - image: nginx:1.14
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
  volumes:
  - name: html
    emptyDir: {}

첫 번째 컨테이너

  • 이미지: smlinux/genid:env
  • 이름: fakeid
  • 환경 변수:
    - INTERVAL: ConfigMap에서 가져온 값을 사용한다. ConfigMap의 이름은 config이며 키는 INTERVAL 이며, 값은 2 이다.
  • 볼륨 마운트:
    - 이름이 html인 볼륨을 해당 컨테이너에 있는 /webdata 경로에 마운트한다.

두 번째 컨테이너

  • 이미지: nginx:1.14
  • 이름: web-server
  • 포트: 80번 포트 사용
  • 읽기 전용으로 /usr/share/nginx/html 경로에 html 볼륨을 마운트한다.
# configmap, pod 생성
$ kubectl apply -f config.yaml
$ kubectl apply -f genid.yaml

# pod 확인
$ kubectl get all -o wide
NAME              READY   STATUS    RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
pod/genid-stone   2/2     Running   0          8m31s   172.16.221.148   w1-k8s   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE     SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   6d18h   <none>

# pod 환경 변수 확인 (INTERVAL값 확인)
$ kubectl exec genid-stone -- env
Defaulted container "fakeid" out of: fakeid, web-server
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=genid-stone
INTERVAL=2
OPTION=stone
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
HOME=/root

# fakeid 컨테이너 환경 변수
$ kubectl exec genid-stone -c fakeid -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=genid-stone
INTERVAL=2
OPTION=stone
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
HOME=/root

# web-server 컨테이너 환경 변수
$ kubectl exec genid-stone -c web-server -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=genid-stone
NGINX_VERSION=1.14.2-1~stretch
NJS_VERSION=1.14.2.0.2.6-1~stretch
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
HOME=/root

# pod 호출 (2초마다 값이 변경)
$ curl 172.16.221.148
+----------------------+
| Tracy Mcgowan        |
| 53 Orange West       |
| Sunnyvale, CA  94086 |
| (408) xxx-xxxx       |
+----------------------+
$ curl 172.16.221.148
+-----------------------+
| Bert Rogers           |
| 386 Midland St        |
| Binghamton, NY  13902 |
| (607) xxx-xxxx        |
+-----------------------+

위 Dockerfile 에서는 INTERVAL 값이 5 였지만, 생성된 파드에서 확인된 환경변수에서 INTERVAL 값이 2 가 되어 있는 것을 확인할 수 있었고, curl 호출 시 2초마다 값이 변경이 되는 것을 확인하였다.

컨피그맵 전체를 적용

# genid-whole.yaml
apiVersion: v1
kind: Pod
metadata:
  name: genid-boy
spec:
  containers:
  - image: smlinux/genid:env
    envFrom:
    - configMapRef:
        name: config
    name: fakeid
    volumeMounts:
    - name: html
      mountPath: /webdata
  - image: nginx:1.14
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
  volumes:
  - name: html
    emptyDir: {}

첫 번째 컨테이너

  • 이미지: smlinux/genid:env
  • 이름: fakeid
  • 환경 변수:
    - configMapRef: 여기서는 config라는 이름의 ConfigMap에서 환경 변수를 가져온다.
  • 볼륨 마운트:
    - 이름이 html인 볼륨을 해당 컨테이너에 있는 /webdata 경로에 마운트한다.

두 번째 컨테이너

  • 이미지: nginx:1.14
  • 이름: web-server
  • 포트: 80번 포트 사용
  • 읽기 전용으로 /usr/share/nginx/html 경로에 html 볼륨을 마운트한다.
# configmap, pod 생성
$ kubectl apply -f genid-whole.yaml

# pod 확인
$ kubectl get all -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP               NODE     NOMINATED NODE   READINESS GATES
pod/genid-boy   2/2     Running   0          5s    172.16.221.149   w1-k8s   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE     SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   6d18h   <none>

# pod 환경 변수 확인 (INTERVAL값 확인)
$ kubectl exec genid-stone -- env
Defaulted container "fakeid" out of: fakeid, web-server
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=genid-boy
INTERVAL=2
OPTION=boy
nginx-config.conf=server {
    listen   80;
    server_name  www.example.com;

    gzip on;
    gzip_types text/plain application/xml;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
HOME=/root

# pod 호출 (2초마다 값이 변경)
$ curl 172.16.221.149
         .-"""-.
        / .===. \
        \/ 6 6 \/
        ( \___/ )
  __ooo__\_____/______
 /                    \
| Arthur Orr           |
| 223 Cedarwood Ln     |
| Knoxville, TN  37901 |
| (615) xxx-xxxx       |
 \_______________ooo__/
        |  |  |
        |_ | _|
        |  |  |
        |__|__|
        /-'Y'-\
       (__/ \__)
$ curl 172.16.221.149
          .-"""-.
         / .===. \
         \/ 6 6 \/
         ( \___/ )
  ___ooo__\_____/_______
 /                      \
| Dorian Miller          |
| 442 Spring County Blvd |
| Orlando, FL  32802     |
| (407) xxx-xxxx         |
 \________________ooo___/
         |  |  |
         |_ | _|
         |  |  |
         |__|__|
         /-'Y'-\
        (__/ \__)

해당 결과도 동일하게 INTERVAL 값이 2 가 되어 있는 것을 확인할 수 있었고, curl 호출 시 2초마다 값이 변경이 되는 것을 확인하였다. 다만, kubectl exec genid-stone -- env 명령어를 통해 확인하였을 때 config.yaml 의 내용이 파드에 적용이 된 것을 확인할 수 있었다.

컨피그맵 볼륨으로 적용

# genid-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: genid-volume
spec:
  containers:
  - image: smlinux/genid:env
    env:
    - name: INTERVAL
      valueFrom:
        configMapKeyRef:
          name: config
          key: INTERVAL
    name: fakeid-generator
    volumeMounts:
    - name: html
      mountPath: /webdata
  - image: nginx:1.14
    name: web-server
    ports:
    - containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    - name: config
      mountPath: /etc/nginx/conf.d
      readOnly: true
  volumes:
  - name: html
    emptyDir: {}
  - name: config
    configMap:
      name: config
      items:
      - key: nginx-config.conf
        path: nginx-config.conf

첫 번째 컨테이너

  • 이미지: smlinux/genid:env
  • 이름: fakeid
  • 환경 변수:
    - INTERVAL: ConfigMap에서 가져온 값을 사용한다. ConfigMap의 이름은 config이며 키는 INTERVAL 이며, 값은 2 이다.
  • 볼륨 마운트:
    - 이름이 html인 볼륨을 해당 컨테이너에 있는 /webdata 경로에 마운트한다.

두 번째 컨테이너

  • 이미지: nginx:1.14
  • 이름: web-server
  • 포트: 80번 포트 사용
  • /usr/share/nginx/html 경로에 html 볼륨을 읽기 전용으로 마운트한다.
  • /etc/nginx/conf.d 경로에 config 볼륨을 읽기 전용으로 마운트한다. 이 볼륨은 ConfigMap의 nginx-config.conf 항목의 내용을 가지고 있다.
# configmap, pod 생성
$ kubectl apply -f genid-volume.yaml

# pod 확인
$ kubectl get all -o wide
NAME               READY   STATUS    RESTARTS        AGE   IP               NODE     NOMINATED NODE   READINESS GATES
pod/genid-volume   2/2     Running   0               7s    172.16.103.151   w2-k8s   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d    <none>


# pod 환경 변수 확인 (INTERVAL값 확인)
$ kubectl exec genid-volume -- env
Defaulted container "fakeid-generator" out of: fakeid-generator, web-server
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=genid-volume
INTERVAL=2
OPTION=stone
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOME=/root

# pod 호출 (2초마다 값이 변경)
$ curl 172.16.103.151
+-----------------------+
| Lindsey Schroeder     |
| 764 Henly Dr          |
| Plainfield, NJ  07061 |
| (908) xxx-xxxx        |
+-----------------------+
$ curl 172.16.103.151
+--------------------+
| Janell York        |
| 57 Sharon Rd       |
| Raleigh, NC  27611 |
| (919) xxx-xxxx     |
+--------------------+

# mount 확인
$ kubectl exec -it genid-volume -c web-server /bin/bash
root@genid-volume:/# cd /etc/nginx/conf.d/
root@genid-volume:/etc/nginx/conf.d# ls -al
total 0
drwxrwxrwx. 3 root root  84 May 16 05:08 .
drwxr-xr-x. 3 root root 177 Mar 26  2019 ..
drwxr-xr-x. 2 root root  31 May 16 05:08 ..2024_05_16_05_08_33.542510199
lrwxrwxrwx. 1 root root  31 May 16 05:08 ..data -> ..2024_05_16_05_08_33.542510199
lrwxrwxrwx. 1 root root  24 May 16 05:08 nginx-config.conf -> ..data/nginx-config.conf
root@genid-volume:/etc/nginx/conf.d# cat nginx-config.conf
server {
    listen   80;
    server_name  www.example.com;

    gzip on;
    gzip_types text/plain application/xml;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

/etc/nginx/conf.d 경로에서 nginx-config.conf 파일을 확인한다면 conf 파일의 내용이 이전에 만들었던 내용과 동일하게 되어 있는 것을 확인할 수 있으며, 심볼릭 링크로 볼륨이 컨피그맵에서 지원해주는 data로 마운튼 되어 있는 것 또한 확인할 수 있다.

시크릿(Secret)

지금까지 쿠버네티스에서 컨테이너의 환경변수를 관리하기 위해 컨피그맵을 생성하고 이를 파드에 주입하는 것을 살펴보았다. 그런데, 환경변수에는 사용자의 비밀번호와 같이 민감한 정보들이 있을 수 있다.

컨피그맵의 한계, 그리고 시크릿의 필요성

# app.py
from flask import Flask
import pymysql

app = Flask(__name__)
app.secret_key = 'sample_secret'

def connectsql():
    conn = pymysql.connect(host='mysql', user = 'root', passwd = 'passwrd', db = 'userlist')
    return conn

if __name__=="__main__":
    app.run(host="0.0.0.0", port="8080")

위와 같은 app.py 파일이 있다고 해보자. mysql 데이터베이스에 접근하는 코드를 살펴보면, user=rootpassword=passwrd 같은 민감한 정보들이 있다. 이러한 변수들을 단순히 컨피그맵을 통해서 표현하면 다음과 같이 민감한 정보들이 노출된다.

# config-map.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DB_Host: mysql
  DB_User: root
  DB_Password: passwrd

이러한 문제를 해결하기 위해서 시크릿(Secret)이 활용된다. 먼저, 시크릿의 생김새부터 간단히 살펴보면 다음과 같이 사람이 알아볼 수 없는 hashed format으로 값들이 표현되어 있는 것을 알 수 있다.

# app_secret.properties

DB_Host: bXlzcWw=
DB_User: cm9vdA==
DB_Password: cGFzd3JK

ConfigMap과 마찬가지로 Secret 또한 다음 두 단계를 거친다.

  • 시크릿 생성하기
  • 파드에 시크릿 주입하기

시크릿 생성하기

컨피그맵과 마찬가지로 명령형(imperative) 방식과 선언형(declarative)방식으로 시크릿을 생성할 수 있다.

시크릿 생성하기 : 명령형(imperative) 방식

  1. kubectl create secret generic {시크릿 이름} --from-literal={키}={값}
    - 예) kubectl create secret generic app-secret --from-literal=DB_Host=mysql --from-literal=DB_User=root --from-literal=DB_Password=passwrd
    컨피그맵과 마찬가지로, 위와 같이 --from-literal 옵션을 사용하여 시크릿에 환경변수를 키-값 형태로 전달할 수 있다. 또한, --from-literal 옵션을 여러 번 사용하여 여러 개의 요소들을 한번에 입력할 수도 있다.
  2. kubectl create secret generic {시크릿 이름} --from-file={파일의 경로}
    - 예) kubectl create secret generic app-secret --from-file=app_secret.properties
    컨피그맵과 마찬가지로, 위와 같이 파일의 경로를 지정해주는 방식도 가능하다.
$ kubectl get secrets app-secret -o yaml
apiVersion: v1
data:
  app_secret.properties: REJfSG9zdDogYlhsemNXdz0KREJfVXNlcjogY205dmRBPT0KREJfUGFzc3dvcmQ6IGNHRnpkM0pLCg==
kind: Secret
metadata:
  creationTimestamp: "2024-05-16T06:47:53Z"
  name: app-secret
  namespace: default
  resourceVersion: "94861"
  uid: 35a07ea5-d58b-49e3-ad99-968e8b475dde
type: Opaque

파일로 지정 후 secrets을 생성 후 확인을 한다면 data부분이 확인이 어려운 것을 확인할 수 있다.

시크릿 생성하기 : 선언형(declarative) 방식

# secret-data.yaml

apiVersion: v1
kind: Secret
metadata:
  name: app-secret
data:
  DB_Host: bXlzcWw= # 참고 : echo -n 'mysql' | base64
  DB_User: cm9vdA== # 참고 : echo -n 'root' | base64
  DB_Password: cGFzd3Jk # 참고 : echo -n 'passwrd' | base64

kubectl get secrets 또는 kubectl describe secrets 명령어를 통해 생성된 시크릿을 확인할 수 있다. kubectl get secret app-secret -o yaml 명령어를 통해 YAML 형식으로도 확인할 수 있다.

$ kubectl get secrets app-secret2 -o yaml
apiVersion: v1
data:
  DB_Host: bXlzcWw=
  DB_Password: cGFzd3Jk
  DB_User: cm9vdA==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"DB_Host":"bXlzcWw=","DB_Password":"cGFzd3Jk","DB_User":"cm9vdA=="},"kind":"Secret","metadata":{"annotations":{},"name":"app-secret2","namespace":"default"}}
  creationTimestamp: "2024-05-16T06:49:15Z"
  name: app-secret2
  namespace: default
  resourceVersion: "94984"
  uid: 1aa88122-9e92-456e-a75b-cbf92f87510d
type: Opaque

하지만 yaml 파일로 바로 정의 후 secrets를 만들게 된다면 data 부분을 확인이 가능한 차이점이 있다.

파드에 시크릿 주입하기

위의 방식대로 시크릿을 생성했다고 하면, 생성된 시크릿을 파드에 주입해야 한다.

# pod-definition.yaml

apiVersion: v1
kind: Pod
metadata:
  name: simple-webapp-color
spec:
  containers:
    - name: simple-webapp-color
      image: simple-webapp-color
      ports:
        - containerPort: 8080

      # 아래 envFrom 부분을 통해 생성된 Secret을 파드에 주입(설정)한다.
      envFrom:
        - secretMapRef:
            name: app-secret # Secret 정의 YAML 파일에 설정한 metadata 이름을 적는다.

이후 kubectl create -f pod-definition.yaml 명령어를 통해 파드를 생성하면, 시크릿을 통해 환경변수 설정이 주입된 파드가 실행될 것이다.

이러한 방식 외에도 시크릿을 주입하는 방식은 아래와 같이 몇 가지 더 있다.

파드에 시크릿을 주입하는 여러 방법

# 기본적인 방법
envFrom:
  - secretMapRef:
      name: app-secret # Secret 정의 YAML 파일에 설정한 metadata 이름을 적는다.
# 또는 하나의 키 값만 가져오는 경우
env:
  - name: DB_Password
    valueFrom:
      SecretKeyRef:
        name: app-secret # Secret 정의 YAML 파일에 설정한 metadata 이름을 적는다.
        key: DB_Password # 가져오고자 하는 키 값을 입력한다.
# 볼륨에서 전체 데이터를 파일로 가져오는 경우
volumes:
- name: app-secret-volume
  secret:
    name: app-secret # Secret 정의 YAML 파일에 설정한 metadata 이름을 적는다.
profile
조금씩 성장하는 DevOps 엔지니어가 되겠습니다. 😄

0개의 댓글

관련 채용 정보