Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

Azure Kubernetes Service 애플리케이션 배포 2부 – ConfigMap을 활용한 고급 구성

소개

이전 글에서는 AKS(Azure Kubernetes Service)에 Redis 마스터를 배포하면서 Deployment, ReplicaSet, Pod 간의 관계를 살펴보았습니다. 이번 2부에서는 한 단계 더 나아가, ConfigMap을 활용해 환경별 설정값을 외부에서 주입하는 방법을 다룹니다. 실무에서 컨테이너화된 애플리케이션을 운영할 때 반드시 알아야 할 핵심 개념이니 끝까지 따라와 보세요.

이 글에서 다룰 내용

  • ConfigMap이란 무엇인가?
  • ConfigMap을 적용한 Redis 마스터 배포
  • 파일로부터 ConfigMap 생성하기
  • YAML 파일로부터 ConfigMap 생성하기
  • ConfigMap을 사용해 구성 데이터 읽어오기

사전 준비 사항

  • AKS 애플리케이션 배포 시리즈 1부를 완료했거나, 동일한 환경(Redis 마스터 Deployment가 배포된 AKS 클러스터)이 준비되어 있어야 합니다.

시리즈 1부에서는 Redis 마스터 Deployment를 생성하고, Deployment가 ReplicaSet과 연결되고 다시 Pod와 연결되는 구조를 확인했습니다. 이번 2부에서는 ConfigMap으로 제공되는 환경별 구성 정보를 적용하여 Redis 마스터를 다시 배포해 보겠습니다. 그 전에 먼저 ConfigMap이 무엇인지 알아보겠습니다.

ConfigMap이란?

ConfigMap은 Pod에 구성 정보를 전달하기 위해 사용하는 쿠버네티스 오브젝트입니다. 가장 큰 장점은 설정값을 컨테이너 이미지 밖으로 분리할 수 있다는 점입니다. 즉, 환경마다 다른 설정이 필요하더라도 이미지를 새로 빌드할 필요 없이 ConfigMap만 교체하면 됩니다. 이렇게 만든 ConfigMap을 Deployment에 연결하면 애플리케이션이 해당 구성 데이터를 읽어 사용할 수 있습니다.

ConfigMap을 적용한 Redis 마스터

사실 이전 글에서 만든 Deployment 자체에는 문제가 없었습니다. 하지만 실제 운영 환경에서는 아무런 설정 없이 애플리케이션을 실행하는 경우가 거의 없습니다. 여기서는 redis-master의 설정값을 ConfigMap으로 지정해 보겠습니다.

ConfigMap은 환경별로 특수한 이미지를 만들 필요 없이 컨테이너를 유연하게 구성할 수 있는 휴대 가능한(portable) 방식입니다. 데이터는 키-값(key-value) 쌍 형태로 저장됩니다. 참고로 ConfigMap은 민감하지 않은(non-secret) 구성 정보에 사용하고, 비밀번호처럼 중요한 데이터는 별도의 오브젝트인 Secret을 사용해야 합니다.

이번 예제에서는 다음과 같은 내용을 담은 ConfigMap을 만들 것입니다. 키는 redis-config이고 값은 아래 두 줄입니다.

maxmemory: "2mb"
maxmemory-policy: "allkeys-lru"

ConfigMap을 생성하는 방법은 두 가지가 있습니다.

  • 파일로부터 ConfigMap 생성하기
  • YAML 파일로부터 ConfigMap 생성하기

각 방법을 하나씩 자세히 살펴보겠습니다.

파일로부터 ConfigMap 생성하기

다음 단계를 따라 파일 기반으로 ConfigMap을 생성할 수 있습니다.

1단계. Azure Cloud Shell 터미널에 code redis-config를 입력해 코드 편집기를 열고, 아래 두 줄을 붙여 넣은 뒤 redis-config라는 이름으로 저장합니다.

maxmemory: "2mb"
maxmemory-policy: "allkeys-lru"

2단계. 다음 명령어로 ConfigMap을 생성합니다.

kubectl create configmap example-redis-config --from-file=redis-config

정상적으로 생성되면 아래와 같은 출력이 나타납니다.

configmap/example-redis-config created

3단계. 같은 명령어로 생성된 ConfigMap의 상세 정보를 확인합니다.

kubectl describe configmap/example-redis-config

출력 결과에서 redis-config 키와 함께 maxmemory 관련 설정값이 포함되어 있는지 확인하세요.

YAML 파일로부터 ConfigMap 생성하기

이번 섹션에서는 앞서 만든 ConfigMap을 YAML 선언형 방식으로 다시 생성해 보겠습니다. 실무에서는 버전 관리와 재현성을 위해 YAML 파일 방식이 더 권장됩니다.

1단계. 먼저 이전에 생성한 ConfigMap을 삭제합니다.

kubectl delete configmap/example-redis-config

2단계. 아래 내용을 example-redis-config.yaml이라는 파일에 붙여 넣고 저장합니다.

apiVersion: v1
data:
 redis-config: |-
 maxmemory 2mb
 maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
 name: example-redis-config
 namespace: default

3단계. 다음 명령어로 ConfigMap을 다시 생성합니다.

kubectl create -f example-redis-config.yaml

정상적으로 생성되면 아래와 같은 출력이 나타납니다.

configmap/example-redis-config created

4단계. kubectl describe configmap/example-redis-config 명령어를 실행하면 파일 방식으로 생성했을 때와 동일한 결과를 확인할 수 있습니다.

이처럼 YAML 파일을 사용해서도 완전히 동일한 ConfigMap을 만들 수 있습니다.

참고. kubectl get 명령어에는 -o 옵션이 있어 오브젝트를 YAML 또는 JSON 형식으로 출력할 수 있습니다. 시스템에 수동 변경을 가한 후 그 결과 오브젝트를 YAML로 확인하고 싶을 때 매우 유용합니다. 다음 명령어로 현재 ConfigMap을 YAML 형식으로 조회할 수 있습니다.

kubectl get -o yaml configmap/example-redis-config

ConfigMap 정의가 준비되었으니, 이제 실제로 사용해 보겠습니다.

ConfigMap을 사용해 구성 데이터 읽기

이 섹션에서는 redis-master Deployment가 ConfigMap에서 구성 정보를 읽어오도록 재구성합니다.

1단계. redis-master-deployment.yaml 파일을 아래와 같이 수정하여 ConfigMap을 사용하도록 변경합니다. 코드 설명은 소스 아래에 이어집니다.

참고. GitHub에서 소스 코드를 받았다면 'Application deployment on AKS' 폴더 안의 deployment 디렉터리에 redis-master-deployment_Modified.yaml 파일이 있으며, 이 파일에는 필요한 변경 사항이 이미 적용되어 있습니다.

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
 name: redis-master
 labels:
 app: redis
spec:
 selector:
 matchLabels:
 app: redis
 role: master
 tier: backend
 replicas: 1
 template:
 metadata:
 labels:
 app: redis
 role: master
 tier: backend
 spec:
 containers:
 - name: master
 image: k8s.gcr.io/redis:e2e
 command:
 - redis-server
 - "/redis-master/redis.conf"
 env:
 - name: MASTER
 value: "true"
 volumeMounts:
 - mountPath: /redis-master
 name: config
 resources:
 requests:
 cpu: 100m
 memory: 100Mi
 ports:
 - containerPort: 6379
 volumes:
 - name: config
 configMap:
 name: example-redis-config
 items:
 - key: redis-config
 path: redis.conf

주요 섹션별로 자세히 살펴보겠습니다.

24~26행 – command

Pod가 시작될 때 실행될 명령어를 지정합니다. 여기서는 특정 구성 파일을 가리키며 redis-server를 시작하도록 설정했습니다.

command:
 - redis-server
 - "/redis-master/redis.conf"

27~29행 – env(환경 변수)

실행 중인 컨테이너에 구성 데이터를 전달하는 방법 중 하나로, 환경 변수를 사용합니다. Docker로 표현하면 docker run -e "MASTER=true" --name master -p 6379:6379 ... kubernetes/redis:v1과 동일합니다. 이렇게 하면 MASTER 환경 변수가 true로 설정되고, 애플리케이션은 이 값을 읽어 구성에 활용할 수 있습니다.

env:
 - name: MASTER
 value: "true"

30~32행 – volumeMounts

config라는 이름의 볼륨(39~45행에서 정의)을 실행 중인 컨테이너의 /redis-master 경로에 마운트합니다. 이로써 원본 컨테이너의 /redis-master 경로에 있던 내용은 덮어쓰기 됩니다. Docker로 비유하면 docker run -v config:/redis-master ...와 같습니다.

volumeMounts:
 - mountPath: /redis-master
 name: config

40행 – 볼륨 이름

볼륨의 이름을 config로 지정합니다. 이 이름은 해당 Pod 범위 내에서 참조됩니다.

name: config

41~42행 – configMap 참조

이 볼륨이 example-redis-config라는 ConfigMap으로부터 로드되어야 함을 선언합니다. 당연히 이 ConfigMap은 시스템에 미리 존재해야 하는데, 우리는 이미 앞서 생성했으므로 문제없습니다.

configMap:
 name: example-redis-config

43~45행 – items(키-경로 매핑)

redis-config 키의 값(maxmemory 관련 두 줄 설정)을 redis.conf라는 파일로 로드합니다.

items:
 - key: redis-config
 path: redis.conf

2단계. 수정된 Deployment를 생성합니다.

kubectl create -f redis-master-deployment_Modified.yml

정상적으로 생성되면 아래와 같은 출력이 나타납니다.

deployment.apps/redis-master created

3단계. 구성이 성공적으로 적용되었는지 확인합니다. 먼저 Pod 이름을 조회합니다.

kubectl get pods

4단계. Pod 내부로 접속(exec)하여 설정이 적용되었는지 검증합니다.

kubectl exec -it redis-master-<pod-id> redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
 1) "maxmemory"
 2) "2097152"
127.0.0.1:6379> CONFIG GET maxmemory-policy
 "maxmemory-policy"
 "allkeys-lru"
127.0.0.1:6379> exit

출력 결과를 보면 maxmemory가 2097152바이트(2MB), maxmemory-policy가 allkeys-lru로 설정된 것을 확인할 수 있습니다. ConfigMap의 값이 실제로 Redis에 반영된 것입니다.

마무리

지금까지 클라우드 네이티브 애플리케이션 구성에서 중요하면서도 까다로운 부분을 수행했습니다. 눈치채셨겠지만, 애플리케이션이 구성 값을 동적으로 읽어오도록 설계되어야 한다는 점도 중요합니다. 애플리케이션에 구성을 적용한 뒤, 실행 중인 컨테이너에 접속해 실제 구성 상태를 직접 검증까지 완료했습니다.

이번 2부에서는 Redis 마스터가 ConfigMap으로부터 구성 데이터를 로드하도록 설정했습니다. 다음 마지막 3부에서는 전체 애플리케이션을 엔드투엔드(end-to-end)로 배포해 보겠습니다.