개발강의정리/DevOps

[데브옵스를 위한 쿠버네티스 마스터] 애플리케이션 스케줄링과 라이프사이클 관리 - 애플리케이션 변수 관리

nineDeveloper 2021. 1. 19.
728x90

애플리케이션 변수 관리

도커 컨테이너의 환경 설정

  • 쿠버네티스의 환경 변수는 YAML 파일이나 다른 리소스로 전달
  • 하드 코딩된 환경 변수는 여러 환경에 데이터를 정의하거나 유지, 관리가 어려움
  • ConfigMap은 외부에 컨테이너 설정을 저장할 수 있음


환경변수를 포드에 저장하는 방법

https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/#define-an-environment-variable-for-a-container

envars.yaml

apiVersion: v1
kind: Pod
metadata:
  name: envar-demo
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: envar-demo-container
    image: gcr.io/google-samples/node-hello:1.0
    env:
    - name: DEMO_GREETING
      value: "Hello from the environment"
    - name: DEMO_FAREWELL
      value: "Such a sweet sorrow"

envars.yaml 파일 생성 및 kubectl 로 create

$ vi envars.yaml
$ kubectl create -f envars.yaml
pod/envar-demo created

pod 생성 확인

$ kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
envar-demo   1/1     Running   0          5s

envar-demo 접속 후 printenv 명령으로 환경변수 확인

$ kubectl exec -it envar-demo -- bash
root@envar-demo:/# printenv
NODE_VERSION=4.4.2
HOSTNAME=envar-demo
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
TERM=xterm
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.96.0.1
NPM_CONFIG_LOGLEVEL=info
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
DEMO_FAREWELL=Such a sweet sorrow
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
DEMO_GREETING=Hello from the environment
_=/usr/bin/printenv

아래의 명령으로 바로 해당 pod 의 환경변수를 읽어올 수 있다

$ kubectl exec -it envar-demo -- printenv DEMO_GREETING
Hello from the environment

환경변수를 ConfigMap에 저장하는 방법

  • kubectl 명령어를 사용하여 바로 저장할 수 있음
$ kubectl create configmap <map-name> <data-source>
  • test 파일을 생성하고 그 파일을 환경 변수로 저장
  • --from-file을 여러개 지정해서 한번에 여러개의 파일을 환경 변수로 저장할 수 있음
$ echo –n 1234 > test
$ kubectl create configmap map-name --from-file=test
configmap/map-name created
  • 저장한 내용 확인
$ kubectl get configmap map-name -o yaml
apiVersion: v1
data:
  test: "1234"
kind: ConfigMap
...

envars.yaml을 copy 해서 envars-configmap.yaml 파일 생성

$ cp envars.yaml envars-configmap.yaml

configMap 파일의 데이터를 DEMO_GREETING 환경변수로 전달

apiVersion: v1
kind: Pod
metadata:
  name: envar-configmap
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: envar-demo-container
    image: gcr.io/google-samples/node-hello:1.0
    env:
    - name: DEMO_GREETING
      valueFrom:
        configMapKeyRef:
          name: map-name
          key: test

kubectl create 후 실행 확인

$ kubectl create -f envars-configmap.yaml
pod/envar-configmap created

$ kubectl exec -it envar-configmap -- bash
root@envar-configmap:/# printenv DEMO_GREETING
1234

YAML을 사용하여 환경변수를 ConfigMap에 저장하는 방법


ConfigMap의 모든 Key와 Value를 가져오는 방법

https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables

configMapKeyRef로 Key를 지정하지 않으면 ConfigMap의 모든 Key의 데이터를 가져옴

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - configMapRef:
          name: special-config
  restartPolicy: Never

ConfigMap 데이터를 Volume에 전달하는 방법

https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#add-configmap-data-to-a-volume

configmap-multikeys.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  SPECIAL_LEVEL: very
  SPECIAL_TYPE: charm

kubectl 명령으로 생성

$ kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
configmap/special-config created

설정 내용 확인

$ kubectl get configmaps special-config -o yaml
apiVersion: v1
data:
  SPECIAL_LEVEL: very 
  SPECIAL_TYPE: charm
...

envars-configmap.yaml 파일을 volumes-configmap.yaml 파일로 복사하여 사용

$ cp envars-configmap.yaml volumes-configmap.yaml

https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#populate-a-volume-with-data-stored-in-a-configmap

내용 참조해서 volumes-configmap.yaml 파일 설정 내용 수정

apiVersion: v1
kind: Pod
metadata:
  name: volumes-configmap
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: envar-demo-container
    image: gcr.io/google-samples/node-hello:1.0
    volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
        name: special-config

kubectl 로 생성 후 확인

$ kubectl create -f volumes-configmap.yaml
pod/volumes-configmap created

$ kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
volumes-configmap   1/1     Running   0          6s

pod 접속 후 volume에 저장된 환경변수 파일 내용 확인

$ kubectl exec -it volumes-configmap -- bash

root@volumes-configmap:/etc/config# cat /etc/config/SPECIAL_LEVEL
very
root@volumes-configmap:/etc/config# cat /etc/config/SPECIAL_TYPE
charm

환경변수를 Secret에 저장하는 방법

  • 비밀번호, OAuth 토큰 및 ssh 키와 같은 민감한 정보ㅏ
  • kubectl 명령어로 secret 설정하는 방법
$ echo -n 'admin' > ./username
$ echo -n '1f2d1e2e67df' > ./password
$ kubectl create secret generic db-user-pass --from-file=./username --from- file=./password
secret/db-user-pass created
  • echo -n 명령어를 실행하면 데이터가 개행문자(엔터)와 함께 출력됨
  • 마지막 명령어를 실행하면 db-user-pass 유저가 생성됨
  • secret 에는 DB의 user와 password와 같이 민감한 파일들이 base64 인코딩돼서 저장
  • 이 값이 안전한 것은 아니지만 공격자에게 혼란을 줄 수는 있음
$ kubectl get secret db-user-pass -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4= kind: Secret
...

YAML 파일로 환경변수를 Secret에 저장하는 방법

https://kubernetes.io/docs/concepts/configuration/secret/#use-cases

  • 수동으로 데이터를 만들어야 하는 경우에는 base64 인코딩을 수동으로 해줘야 한다
$ echo -n 'admin' | base64
YWRtaW4=

$ echo -n '1f2d1e2e67df'| base64
MWYyZDFlMmU2N2Rm
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

실습

db-user-pass secret 파일 생성 및 확인

$ echo -n admin > username
$ echo -n 1234qwerasdf > password

$ kubectl create secret generic db-user-pass --from-file=username --from-file=password
secret/db-user-pass created

$ kubectl get secret -o yaml db-user-pass
apiVersion: v1
data:
  password: MTIzNHF3ZXJhc2Rm
  username: YWRtaW4=
kind: Secret
...

암호화된 데이터를 디코딩하여 확인

$ echo YWRtaW4= | base64 --decode
admin%
$ echo MTIzNHF3ZXJhc2Rm | base64 --decode
1234qwerasdf%

envars-configmap.yaml 파일을 envars-secret.yaml 파일명으로 복사

$ cp envars-configmap.yaml envars-secret.yaml

secret 내용으로 수정

apiVersion: v1
kind: Pod
metadata:
  name: envar-secret
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: envar-demo-container
    image: gcr.io/google-samples/node-hello:1.0
    env:
    - name: user
      valueFrom:
        secretKeyRef:
          name: db-user-pass
          key: username
    - name: pass
      valueFrom:
        secretKeyRef:
          name: db-user-pass
          key: password

kubectl로 생성 및 확인
인코딩 데이터가 디코딩이 되어서 적용된 것이 보여짐

$ kubectl create -f envars-secret.yaml
pod/envar-secret created

$ kubectl exec -it envar-secret -- bash
root@envar-secret:/# printenv
NODE_VERSION=4.4.2
pass=1234qwerasdf
HOSTNAME=envar-secret
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
TERM=xterm
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.96.0.1
NPM_CONFIG_LOGLEVEL=info
user=admin
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
_=/usr/bin/printenv

연습문제

  • Kube-system에 존재하는 secret의 개수는 몇 개인가?
    • kubectl get secret -n kube-system | wc -l
    • 정답은 명령 결과에 -1 개
  • default-token의 개수는 몇 개인가?
    • kubectl get secret -n kube-system | grep defaul
    • 정답은 1개
  • default-token의 타입은 무엇인가?
    • kubectl get secret -n kube-system default-token-hcp55 -o yaml
    • type: kubernetes.io/service-account-token
  • Secret 데이터에는 어떤 secret data가 포함돼 있는가?
    • kubectl describe secret -n kube-system default-token-hcp55
    • token, ca.crt, namespace: kube-system
  • 다음과 같이 Mysql 서버를 지원하는 secret-mysql.yaml을 생성하자.
    • Secret Name: db-secret
    • Secret Data 1: DB_Password=Passw0rd!0
$ kubectl create secret generic db-secret --from-literal='DB_Password=Passw0rd!0' --dry-run=client -o yaml > secret-mysql.yaml

$ kubectl create -f secret-mysql.yaml
secret/db-secret created
  • Mysql 이미지를 하나 생성하고 앞서 만든 secret을 환경 변수 이름과 연결하자. ➢ Image: mysql:5.6
    • Port 번호: 3306
    • 환경 변수 name: MYSQL_ROOT_PASSWORD
    • 잘 적용됐는지 확인할 수 있는 명령어:
      • kubectl exec -it mysql -- mysql -u root -p
      • password: Passw0rd!0

https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates

mysql-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  containers:
  - name: mysql
    image: mysql:5.6
    ports:
    - containerPort: 3306
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: DB_Password

kubectl로 생성 및 확인

$ kubectl create -f mysql-pod.yaml
pod/mysql created

$ kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
mysql   1/1     Running   0          26s

mysql 접속 password 'Passw0rd!0' 입력

$ kubectl exec -it mysql -- mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.50 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

mysql>
728x90

댓글

💲 추천 글