ConfigMap

개요

보안에 민감하지는 않으면서 동적으로 다루는 데이터를 보관하는 오브젝트.
여기에서의 데이터는 클러스터를 관리할 때 필요한 데이터를 말한다.
파드에서는 컨피그맵을 환경변수, 명령어 인자, 볼륨 등으로 가져와 활용할 수 있다.
컨테이너 이미지와 별개로 두어 이식성을 높일 수 있다.

어플리케이션에서 어떤 환경변수를 사용하는데 이게 사용환경마다 달라야 한다고 생각해보자.
가령 데이터베이스 주소를 운영 환경과 개발 환경을 나누고 있는 것이다.
이렇게 상황마다 동적으로 활용할 데이터를 담을 때 활용하는 것이다.

특징

컨피그맵을 직관적으로 이해하는 방법은, 그냥 데이터베이스에 저장되는 데이터라고 이해하는 것이다.
그 실제 저장소가 클러스터의 모든 정보를 담고 관리하는 Etcd일 뿐이다.
크기도 작고 빠르게 변경하면서 클러스터 네이티브하게 관리할 데이터를 저장하는 리소스가 컨피그맵이라 보면 되겠다.

사용법

다음의 네 가지 방법으로 파드에서 사용할 수 있다.

위의 3가지 방식은 kubelet이 설정해준다.
네번째 방식은 동적으로 변화를 추적하고, 다른 네임스페이스의 데이터까지 얻어내는데 유용하다.

      env:
        - name: PLAYER_INITIAL_LIVES
          valueFrom:
            configMapKeyRef:
              name: game-demo           # The ConfigMap this value comes from.
              key: player_initial_lives # The key to fetch.
        - name: UI_PROPERTIES_FILE_NAME
          valueFrom:
            configMapKeyRef:
              name: game-demo
              key: ui_properties_file_name

환경변수를 쓸 때는 .spec.containers[*].env[*].valueFrom.configMapKeyRef라는 방식이다.

  volumes:
  # You set volumes at the Pod level, then mount them into containers inside that Pod
  - name: config
    configMap:
      # Provide the name of the ConfigMap you want to mount.
      name: game-demo
      # An array of keys from the ConfigMap to create as files
      items:
      - key: "game.properties"
        path: "game.properties"
      - key: "user-interface.properties"
        path: "user-interface.properties"

볼륨은 이런 식이다.
items가 없으면 컨맵의 모든 값이 파일로 들어간다.

동적 업데이트

마운팅된 컨피그맵은 자동으로 kubelet이 추적해서 업데이트해준다.
근데 컨피그맵의 현재 값을 얻기 위해 로컬 캐시를 쓴다.

kubeletConfiguration의 configMapAndSecretChangeDetectionStrategy에 지정된다.
watch, ttl이나 api서버의 리디렉팅으로 전파된다.
결과적으로는 전체 지연 시간은 kubelet의 동기화 주기 + 캐시 전파 지연 시간에 결정될 것이다.
그런데 환경변수로 들어간 컨피그맵은 동적인 업데이트가 지원되지 않는다.

환경 변수

  containers:
    - name: app
      command: ["/bin/sh", "-c", "printenv"]
      image: busybox:latest
      envFrom:
        - configMapRef:
            name: myconfigmap

envFrom이라고 쓸 수도 있다.
이렇게 하면 해당 컨피그맵의 내용을 통째로 가져온다.
모든 값을 가져오는 걸 바라지 않는다면 env에서 특정키만 가져오는 식으로 하면 된다.
그리고 어떤 키값인지도 내가 맘대로 지정할 수 있다는 장점도 있다.
뭐 이건 알아서 선택하면 되는 부분.

근데 이렇게 할 때 검증 과정은 없다.
그래서 실제로 해당 컨피그맵에 그런 키가 없더라도 파드는 실행될 것이다.

양식 작성법

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"
  game.properties: |
    enemy.types=aliens,monsters
  user-interface.properties: |
    color.good=purple
    allow.textmode=true    

보통의 오브젝트들은 .spec에 내용들을 넣지만, 이 놈은 완전히 다르다.
data, binaryData를 넣을 수 있다.

immutable

컨피그맵을 동적으로 관리할 수 있다는 것이 장점 같지만, 한편으로 관리 복잡성을 높일 수도 있다.
그래서 아예 불변하게 만드는 방법도 존재한다.
그리고 이렇게 하면 watch를 안하게 되니 api 서버의 부담이 줄어들기까지 한다.
immutable=True를 걸면된다.

관련 문서

이름 noteType created
ConfigMap knowledge 2025-01-12
E-projected 볼륨 - 동적 업데이트, 중복 활용 topic/explain 2025-03-10
T-마운트 전파 Bidirectioal topic/temp 2025-02-28

참고