코알못

[kubernetes] MapConfig 소개 및 실습 본문

ETC

[kubernetes] MapConfig 소개 및 실습

코린이s 2023. 6. 4. 17:19
728x90

지금까지 쿠버네티스 yaml 파일에 config를 설정 하고 값 수정시 yaml 파일을 수정 하였으며 이는 소스 소스코드가 아닌 설정을 수정하는 것임에도 불구하고 배포를 다시 해야하여 어플리케이션에 영향을 줄 수 있다.

영향을 주지 않도록 Config를 분리 하는 방법인 ConfigMap 오브젝트를 실습 해보자!

 ConfigMap은 이름에서 보여지는것과 같이 설정값을 Config 키/값 쌍으로 관리한다.

ConfigMap을 생성 하는 방법은 2가지가 있다.

  1. 리터럴 방식 : 생성시 Key/Value 지정
  2. 파일 방식 : 생성시 Config 가 있는 파일의 디렉토리 지정

ConfigMap을 사용하는 방법은 3가지가 있다.

  1. 컨테이너에서 ConfigMap 일부 Key 값 불러오기
  2. 컨테이너에서 ConfigMap 모든 Key 값 불러오기
  3. 파드 볼륨 생성시 해당 ConfigMap을 바라보도록 하여 컨테이너에서 볼륨 마운트하여 사용하기

ConfigMap을 생성 해보자!

우선 리터럴 방식은 아래와 같이 --from-literal 옵션을 통해 정의하여 생성한다.

$ kubectl create configmap greeting-config --from-literal=STUDENT_NAME=corin --from-literal=MESSAGE=hello
configmap/greeting-config created

생성한 configmap을 확인하기 위해서는 아래와 같이 확인하며 정상적으로 MESSAGE, STUDENT_NAME 키값이 정의 되었다.

$ kubectl get configmap greeting-config -o yaml
apiVersion: v1
data:
  MESSAGE: hello
  STUDENT_NAME: corin
kind: ConfigMap
metadata:
  creationTimestamp: "2023-06-04T04:20:14Z"
  name: greeting-config
  namespace: default
  resourceVersion: "21809122"
  uid: 3ab155b7-bd75-4375-9cf6-fcb84f56a359

이제 configmap 생성하는 방법중 file 로 생성하는 방법을 알아보자!

우선 설정이 담길 configs 디렉토리를 생성 하고 이동 한다.

$ mkdir configs
$ cd configs

그 다음 아래와 같이 디렉토리에 설정할 Key값으로 파일을 생성하면 해당 파일명으로 Key가 생성되며 파일에 입력된 데이터가 Key에 대한 값이 된다.  

$ touch MESSAGE
$ touch STUDENT_NAME
$ echo "hi" >> MESSAGE
$ echo "corin" >> STUDENT_NAME
$ cat MESSAGE
hi
$ cat STUDENT_NAME
corin

이제 생성한 디렉토리를 --from-file 에 지정하여 configMap 을 생성해보면

$ kubectl create configmap greeting-config-file --from-file=configs
configmap/greeting-config-file created

아래와 같이 정상적으로 불러오는것을 확인 할 수 있다.

$ kubectl get configmap greeting-config-file -o yaml
apiVersion: v1
data:
  MESSAGE: |
    hi
  STUDENT_NAME: |
    corin
kind: ConfigMap
metadata:
  creationTimestamp: "2023-06-04T05:49:30Z"
  name: greeting-config-file
  namespace: default
  resourceVersion: "21856375"
  uid: 2637c10b-4f13-41b2-9007-73b1154bb7b1

해당 ConfigMap 을 불러오기 위한 방법중 하나씩 불러오는 방법은 'configMapKeyRef'를 사용하면 되며 원하는 Key 값을 정의하면 env.name 이라는 Key 값에 매핑 된다.

hello-app 이라는 이미지는 GREETING 이라는 환경 변수의 값을 불러와 화면에 띄워준다. 

apiVersion: v1
kind: Pod
metadata:
  name: hello-app
  labels:
    app: hello-app
spec:
  containers:
  - name: hello-app
    image: yoonjeong/hello-app:1.0
    ports:
    - containerPort: 8080
    env:
    - name: STUDENT_NAME
      valueFrom:
        configMapKeyRef:
          key: STUDENT_NAME
          name: greeting-config
    - name: MESSAGE
      valueFrom:
        configMapKeyRef:
          key: MESSAGE
          name: greeting-config
    - name: GREETING
      value: $(MESSAGE) $(STUDENT_NAME)
    resources:
      limits:
        memory: "64Mi"
        cpu: "50m"

클러스터에 적용 한다.

$ kubectl apply -f configmap.yaml
pod/hello-app created

파드를 보면 정상적으로 띄워졌다.

$ kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
hello-app   1/1     Running   0          2m30s

포트 포워딩을 하여 테스트해보자!

$ kubectl port-forward hello-app 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

브라우저로 호출하면 아래와 같이 GREETING 에 정의한 키에대한 값이 나오는것을 확인할 수 있다.

이제 생성한 파드를 제거한다.

$ kubectl delete -f configmap.yaml

이제 ConfigMap의 키값을 모두 불러오는 실습을 진행해보자!

아래와 같이 'configMapRef' 를 통해 불러오며 가져온 키값을 GREETING에 매핑해보자!

# configmap-v2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hello-app
  labels:
    app: hello-app
spec:
  containers:
  - name: hello-app
    image: yoonjeong/hello-app:1.0
    ports:
    - containerPort: 8080
    envFrom:
    - configMapRef:
        name: greeting-config
    env:
    - name: GREETING
      value: $(MESSAGE) ! $(STUDENT_NAME)
    resources:
      limits:
        memory: "64Mi"
        cpu: "50m"

클러스터에 적용한다.

$ kubectl apply -f configmap-v2.yaml
pod/hello-app created

파드를 확인하면 정상적으로 기동 되었다.

$ kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
hello-app   1/1     Running   0          21s

포트 포워딩을 진행하여 테스트해보자!

$ kubectl port-forward hello-app 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

정상적으로 변수의 값을 불러 오는것을 알 수 있다.

실습한 파드를 제거한다.

$ kubectl delete -f configmap-v2.yaml

위에서는 리터럴 방식으로 생성한 ConfigMap 을 확인하였으니 이번에는 파일로 지정하여 생성한 ConfigMap 을 불러와보자!

방식은 동일하며 configMapRef.name 인 불러올 ConfigMap 이름만 변경해주자!

# configmap-v3.yaml

apiVersion: v1
kind: Pod
metadata: 
  name: hello-app
  labels:
    app: hello-app
spec:
  containers:
  - name: hello-app
    image: yoonjeong/hello-app:1.0
    ports:
    - containerPort: 8080
    envFrom:
    - configMapRef:
        name: greeting-config-file
    env:
    - name: GREETING
      value: $(MESSAGE)! $(STUDENT_NAME)
    resources:
      limits:
        memory: "64Mi"
        cpu: "50m"

클러스터에 적용 한다.

$ kubectl apply -f configmap-v3.yaml
pod/hello-app created

테스트를 위해 포트 포워딩 하며

$ kubectl port-forward hello-app 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

정상적으로 불러오는것을 확인할 수 있다.

이제 ConfigMap을 Pod 볼륨을 통해 설정을 불러와보자!

방법을 간단하게 보면 파드 볼륨을 정의하고 해당 볼륨이 바라볼 ConfigMap을 지정한뒤 각 컨테이너에서 해당 볼륨을 마운팅하면 컨테이너에 해당 Key값으로 파일이 생성 된다.

spec:
  volumes: # Pod 에서 사용할 볼륨
  - name: app-config # 컨테이너에서 참조할 볼륨 이름
    configMap:
      name: nginx-config # 참조할 configMap 이름
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts: # 컨테이너에서 마운트할 볼륨
    - name: app-config # 마운팅할 볼륨명
      mountPath: /etc/nginx/conf.d # 마운팅 경로

우리는 nginx 80 포트로 띄우고 /etc/nginx/conf.d/server.conf (파드 볼륨 마운트 설정) 설정에 /myapp 으로 넘어올시 my-app 파드의 8080포트로 넘기도록 한다.

우선 설정이 담길 디렉토리 nginx-config 를 생성하고 /myapp 으로 넘기는 설정을 정의할 파일 server.conf를 생성한다.

$ mkdir nginx-config
$ cd nginx-config
$ touch server.conf

server.conf 는 아래와 같이 정의하면 되며 'location /myapp' 부분을 보면 '/myapp' 으로 호출시 쿠버 DNS를 통해 my-app이라는 서비스 IP의 8080로 넘기도록 설정 되어 있다.

# server.conf

server {
    listen 80;
    listen [::]:80;
    server_name localhost;
    access_log /var/log/nginx/host.access.log;

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

    location /myapp {
        proxy_pass http://my-app:8080;
    }

    error_page 500 502 503 504 /50X.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

이제 configmap을 위에 생성한 디렉토리를 바라보도록 생성한다.

$ kubectl create configmap nginx-config --from-file=nginx-config
configmap/nginx-config created

확인 해보면 정상적으로 설정 되었다.

$ kubectl get configmap nginx-config
NAME           DATA   AGE
nginx-config   1      5s
$ kubectl get configmap nginx-config -o yaml
apiVersion: v1
data:
  server.conf: |-
    server {
        listen 80;
        listen [::]:80;
        server_name localhost;
        access_log /var/log/nginx/host.access.log;

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

        location /myapp {
            proxy_pass http://my-app:8080;
        }

        error_page 500 502 503 504 /50X.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2023-06-04T07:14:39Z"
  name: nginx-config
  namespace: default
  resourceVersion: "21901594"
  uid: 0d4944ff-25b8-42ce-b069-a92b3dee9f83

이제 테스트를 위한 my-app 서비스 1개, my-app 컨테이너 2개, nginx 컨테이너 1개를 생성한다.

파드 볼륨으로 환경설정을 읽어 오도록 app-config 볼륨을 생성하고 해당 볼륨이 'nginx-config' ConfigMap을 읽어오도록 configMap.name에 정의한다.

그리고 nginx 컨테이너에서 'app-config' 볼륨을 마운트 하면 해당 마운트한 경로 'mountPath'에 환경 설정한 Key 명으로 파일이 value 데이터를 가지고 생성 될 것이다. 

# web-server.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  selector:
    app: my-app
  ports:
  - port: 8080
    targetPort: 8080
---
apiVersion: v1
kind: Pod
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  containers:
    - name: my-app
      image: yoonjeong/my-app:1.0
      ports:
      - containerPort: 8080
      resources:
        limits:
          memory: "64Mi"
          cpu: "50m"
---
apiVersion: v1
kind: Pod
metadata:
  name: web-server
  labels:
    name: nginx
spec:
  volumes:
  - name: app-config
    configMap:
      name: nginx-config
  containers: 
    - name: nginx
      image: nginx
      ports:
      - containerPort: 80
      volumeMounts:
      - name: app-config
        mountPath: /etc/nginx/conf.d
      resources:
          limits:
            memory: "64Mi"
            cpu: "50m"
    - name: my-app
      image: yoonjeong/my-app:1.0
      ports:
      - containerPort: 8080
      resources:
        limits:
          memory: "64Mi"
          cpu: "50m"

클러스터에 적용한다.

$ kubectl apply -f web-server.yaml
service/my-app created
pod/my-app created
pod/web-server created

파드가 정상적으로 떴다.

$ kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
my-app       1/1     Running   0          51s
web-server   2/2     Running   0          50s

테스트를 위해 포트 포워딩 한다.

$ kubectl port-forward web-server 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

/myapp 으로 호출하면 정상적으로 서비스를 호출 하는것을 볼 수 있다. 이는 nginx 에 server.conf 환경 설정한 부분이 정상적으로 불러와졌음을 의미한다. 

$ curl localhost:8080/myapp
Welcome to Version 1!

===== Host Info =====
HostIP: 10.100.3.97
HostName: my-app

실제 컨테이너에 설정이 잘 되어 있는지 확인하면 아래와 같이 우리가 정의한 server.conf 내용이 정상적으로 나오는것을 볼 수 있다.

$ kubectl exec web-server -c nginx -- cat /etc/nginx/conf.d/server.conf
server {
    listen 80;
    listen [::]:80;
    server_name localhost;
    access_log /var/log/nginx/host.access.log main;

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

    location /myapp {
        proxy_pass http://my-app:8080/;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

이제 실습을 종료하며 생성된 오브젝트를 모두 제거한다.

$ kubectl delete -f web-server.yaml
service "my-app" deleted
pod "my-app" deleted
pod "web-server" deleted

끝!

728x90
Comments