ConfigMap

ConfigMap

ConfigMap은 기밀성이나 암호화를 제공하지 않아요. 저장하려는 데이터가 기밀이라면 ConfigMap 대신 Secret을 사용하거나, 추가(타사) 도구를 사용해 데이터를 비공개로 유지하세요.

출처: 문서

본문

동기 (Motivation)

ConfigMap을 사용해 구성 데이터를 애플리케이션 코드와 분리해 설정하세요.

예를 들어 자신의 컴퓨터(개발용)와 클라우드(실제 트래픽 처리용)에서 실행할 수 있는 애플리케이션을 개발 중이라고 상상해 보세요. DATABASE_HOST라는 환경 변수를 찾도록 코드를 작성합니다. 로컬에서는 그 변수를 localhost로 설정합니다. 클라우드에서는 데이터베이스 구성 요소를 클러스터에 노출하는 쿠버네티스 Service를 참조하도록 설정합니다. 이렇게 하면 클라우드에서 실행되는 컨테이너 이미지를 가져와 필요할 때 정확히 같은 코드를 로컬에서 디버깅할 수 있습니다.

ConfigMap은 큰 데이터 덩어리를 보관하도록 설계되지 않았습니다. ConfigMap에 저장된 데이터는 1 MiB를 초과할 수 없습니다. 이 제한보다 큰 설정을 저장해야 한다면 볼륨을 마운트하거나 별도의 데이터베이스 또는 파일 서비스를 사용하는 것을 고려할 수 있습니다.

ConfigMap 객체

ConfigMap은 다른 객체가 사용할 구성을 저장할 수 있게 해주는 API 객체입니다. spec을 가진 대부분의 쿠버네티스 객체와 달리, ConfigMap은 databinaryData 필드를 가집니다. 이 필드들은 값으로 키-값 쌍을 받습니다. data 필드와 binaryData 모두 선택 사항입니다. data 필드는 UTF-8 문자열을 포함하도록 설계되었고, binaryData 필드는 base64 인코딩 문자열로 된 바이너리 데이터를 포함하도록 설계되었습니다.

ConfigMap의 이름은 유효한 DNS 서브도메인 이름이어야 합니다.

data 또는 binaryData 필드 아래의 각 키는 영숫자 문자, -, _ 또는 .로 구성되어야 합니다. data에 저장된 키는 binaryData 필드의 키와 겹치면 안 됩니다.

v1.19부터 ConfigMap 정의에 immutable 필드를 추가해 불변 ConfigMap을 만들 수 있습니다.

ConfigMap과 파드

ConfigMap을 참조하고 그 ConfigMap의 데이터를 기반으로 그 파드의 컨테이너를 구성하는 파드 spec을 작성할 수 있습니다. 파드와 ConfigMap은 같은 네임스페이스에 있어야 합니다.

Static Pod의 spec은 ConfigMap이나 다른 API 객체를 참조할 수 없습니다.

다음은 일부 키는 단일 값이고, 다른 키는 값이 구성 형식의 조각처럼 보이는 예시 ConfigMap입니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: game-demo
data:
  # property-like keys; each key maps to a simple value
  player_initial_lives: "3"
  ui_properties_file_name: "user-interface.properties"

  # file-like keys
  game.properties: |
    enemy.types=aliens,monsters
    player.maximum-lives=5
  user-interface.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true

ConfigMap을 사용해 파드 안의 컨테이너를 구성하는 네 가지 방법이 있습니다:

  1. 컨테이너 명령과 인자 안
  2. 컨테이너의 환경 변수
  3. 애플리케이션이 읽을 수 있도록 읽기 전용 볼륨에 파일 추가
  4. 쿠버네티스 API를 사용해 ConfigMap을 읽는 코드를 파드 안에서 실행하도록 작성

이러한 다양한 방법은 소비되는 데이터를 모델링하는 다양한 방식에 적합합니다. 처음 세 가지 방법의 경우 kubelet이 파드의 컨테이너를 시작할 때 ConfigMap의 데이터를 사용합니다.

네 번째 방법은 ConfigMap과 그 데이터를 읽는 코드를 작성해야 함을 의미합니다. 그러나 쿠버네티스 API를 직접 사용하기 때문에 애플리케이션은 ConfigMap이 변경될 때마다 업데이트를 받도록 구독하고, 그때 반응할 수 있습니다. 쿠버네티스 API에 직접 접근하면 다른 네임스페이스의 ConfigMap에도 접근할 수 있습니다.

다음은 game-demo의 값을 사용해 파드를 구성하는 예시 파드입니다:

ConfigMap은 단일 줄 속성 값과 여러 줄 파일형 값을 구분하지 않습니다. 중요한 것은 파드와 다른 객체가 그 값을 어떻게 소비하는가입니다.

이 예시에서 볼륨을 정의하고 demo 컨테이너 안에 /config로 마운트하면 ConfigMap에 네 개의 키가 있는데도 /config/game.properties/config/user-interface.properties 두 파일이 생성됩니다. 이는 파드 정의가 volumes 섹션에 items 배열을 지정하기 때문입니다. items 배열을 완전히 생략하면 ConfigMap의 모든 키가 키와 같은 이름의 파일이 되어 4개의 파일을 얻습니다.

ConfigMap 사용하기

ConfigMap은 데이터 볼륨으로 마운트될 수 있습니다. ConfigMap은 파드에 직접 노출되지 않고도 시스템의 다른 부분에서 사용될 수도 있습니다. 예를 들어 ConfigMap은 시스템의 다른 부분이 구성에 사용해야 하는 데이터를 보관할 수 있습니다.

ConfigMap을 사용하는 가장 일반적인 방법은 같은 네임스페이스의 파드에서 실행되는 컨테이너의 설정을 구성하는 것입니다. ConfigMap을 별도로 사용할 수도 있습니다.

예를 들어 ConfigMap을 기반으로 동작을 조정하는 컨트롤러나 조정자를 만날 수 있습니다.

파드에서 ConfigMap을 파일로 사용하기

파드의 볼륨에서 ConfigMap을 소비하려면:

  1. ConfigMap을 만들거나 기존 것을 사용한다. 여러 파드가 같은 ConfigMap을 참조할 수 있다.
  2. .spec.volumes[] 아래에 볼륨을 추가하도록 파드 정의를 수정한다. 볼륨에 무엇이든 이름을 짓고, .spec.volumes[].configMap.name 필드가 ConfigMap 객체를 참조하도록 설정한다.
  3. ConfigMap이 필요한 각 컨테이너에 .spec.containers[].volumeMounts[]를 추가한다. .spec.containers[].volumeMounts[].readOnly = true를 지정하고 .spec.containers[].volumeMounts[].mountPath를 ConfigMap이 나타나길 원하는 사용하지 않는 디렉터리 이름으로 지정한다.
  4. 프로그램이 그 디렉터리에서 파일을 찾도록 이미지나 명령줄을 수정한다. ConfigMap data 맵의 각 키는 mountPath 아래의 파일 이름이 된다.

볼륨에 ConfigMap을 마운트하는 파드의 예시:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    configMap:
      name: myconfigmap

사용하려는 각 ConfigMap은 .spec.volumes에서 참조되어야 합니다.

파드에 여러 컨테이너가 있다면 각 컨테이너는 자신의 volumeMounts 블록이 필요하지만, ConfigMap당 .spec.volumes는 하나만 필요합니다.

마운트된 ConfigMap은 자동으로 업데이트됩니다

볼륨에서 현재 소비되는 ConfigMap이 업데이트되면, 투영된 키도 결국 업데이트됩니다. kubelet은 매 주기적 동기화마다 마운트된 ConfigMap이 최신인지 확인합니다. 그러나 kubelet은 ConfigMap의 현재 값을 얻기 위해 자신의 로컬 캐시를 사용합니다. 캐시의 유형은 KubeletConfiguration 구조체configMapAndSecretChangeDetectionStrategy 필드를 사용해 구성할 수 있습니다. ConfigMap은 watch(기본값), ttl 기반, 또는 모든 요청을 API 서버로 직접 리디렉션하는 것으로 전파될 수 있습니다. 결과적으로 ConfigMap이 업데이트된 순간부터 새 키가 파드에 투영되는 순간까지의 총 지연은 kubelet 동기화 주기 + 캐시 전파 지연만큼 길 수 있습니다. 여기서 캐시 전파 지연은 선택한 캐시 유형에 따라 다릅니다(각각 watch 전파 지연, 캐시의 ttl, 또는 0과 같음).

환경 변수로 소비되는 ConfigMap은 자동으로 업데이트되지 않으며 파드 재시작이 필요합니다.

ConfigMap을 subPath 볼륨 마운트로 사용하는 컨테이너는 ConfigMap 업데이트를 받지 못합니다.

ConfigMap을 환경 변수로 사용하기

파드의 환경 변수에서 ConfigMap을 사용하려면:

  1. 파드 명세의 각 컨테이너에 대해 사용하려는 각 ConfigMap 키에 대해 env[].valueFrom.configMapKeyRef 필드에 환경 변수를 추가한다.
  2. 지정된 환경 변수에서 값을 찾도록 이미지 및/또는 명령줄을 수정한다.

ConfigMap을 파드 환경 변수로 정의하는 예시입니다:

다음 ConfigMap(myconfigmap.yaml)은 username과 access_level 두 가지 속성을 저장합니다:

apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfigmap
data:
  username: k8s-admin
  access_level: "1"

다음 명령은 ConfigMap 객체를 만듭니다:

kubectl apply -f myconfigmap.yaml

다음 파드는 ConfigMap의 내용을 환경 변수로 소비합니다:

envFrom 필드는 쿠버네티스에 그 안에 중첩된 소스에서 환경 변수를 만들라고 지시합니다. 내부 configMapRef는 이름으로 ConfigMap을 참조하고 모든 키-값 쌍을 선택합니다. 파드를 클러스터에 추가한 다음 로그를 가져와 printenv 명령의 출력을 확인하세요. 이는 ConfigMap의 두 키-값 쌍이 환경 변수로 설정되었음을 확인해야 합니다:

kubectl apply -f env-configmap.yaml
kubectl logs pod/env-configmap

출력은 다음과 비슷합니다:

...
username: "k8s-admin"
access_level: "1"
...

때로 파드는 ConfigMap의 모든 값에 접근할 필요가 없을 수 있습니다. 예를 들어 ConfigMap의 username 값만 사용하는 다른 파드가 있을 수 있습니다. 이 사용 사례에서는 ConfigMap에서 개별 키를 선택할 수 있는 env.valueFrom 구문을 대신 사용할 수 있습니다. 환경 변수의 이름도 ConfigMap 내의 키와 다를 수 있습니다. 예:

apiVersion: v1
kind: Pod
metadata:
  name: env-configmap
spec:
  containers:
  - name: envars-test-container
    image: nginx
    env:
    - name: CONFIGMAP_USERNAME
      valueFrom:
        configMapKeyRef:
          name: myconfigmap
          key: username

이 매니페스트에서 만든 파드에서 환경 변수 CONFIGMAP_USERNAME이 ConfigMap의 username 값으로 설정된 것을 볼 수 있습니다. ConfigMap 데이터의 다른 키는 환경에 복사되지 않습니다.

파드의 환경 변수 이름에 허용되는 문자 범위는 제한된다는 점을 주목하는 것이 중요합니다. 어떤 키가 규칙을 충족하지 않으면 그 키는 컨테이너에서 사용할 수 없게 되지만, 파드는 시작이 허용됩니다.

불변 ConfigMap {#configmap-immutable}

쿠버네티스 기능 Immutable Secrets and ConfigMaps 는 개별 Secret과 ConfigMap을 불변으로 설정하는 옵션을 제공합니다. ConfigMap을 광범위하게 사용하는 클러스터(최소 수만 개의 고유한 ConfigMap→Pod 마운트)에서 데이터 변경을 방지하는 것은 다음 이점이 있습니다:

  • 애플리케이션 중단을 일으킬 수 있는 우발적(또는 원치 않는) 업데이트로부터 보호한다
  • 불변으로 표시된 ConfigMap에 대한 watch를 닫아 kube-apiserver의 부하를 크게 줄여 클러스터 성능을 개선한다

immutable 필드를 true로 설정해 불변 ConfigMap을 만들 수 있습니다. 예:

apiVersion: v1
kind: ConfigMap
metadata:
  ...
data:
  ...
immutable: true

ConfigMap이 불변으로 표시되면 이 변경을 되돌리거나 data 또는 binaryData 필드의 내용을 변경하는 것은 불가능 합니다. ConfigMap을 삭제하고 다시 만드는 것만 가능합니다. 기존 파드는 삭제된 ConfigMap에 마운트 지점을 유지하므로, 이 파드들을 다시 만드는 것이 권장됩니다.

더 알아보기 (Learn more)