7. 컨피그맵(ConfigMap) 및 컨테이너 환경 변수
책/Kubernetes In Action

7. 컨피그맵(ConfigMap) 및 컨테이너 환경 변수

728x90
반응형

7.1 컨테이너화된 애플리케이션 설정

  • 컨테이너화된 APP 에서 설정을 APP 에 전달할 때, 환경변수를 이용하는 방법도 있다.
    그렇다면 왜 환경변수 사용이 컨테이너 환경에서 널리 사용되는 이유는 무엇일까?
  • 도커 컨테이너 내부에는 설정 파일을 사용하는 것이 까다롭기 때문이다.
    • 내부에서 사용한다고 가정하면
      설정 파일을 만약 컨테이너 이미지 안에 포함 혹은 파일이 포함돼 있는 볼륨을 컨테이너에 마운트하는 행위이고,
      이는 파일을 이미지 안에 넣고 빌드하는 것이 기 때문에 소스 코드에 설정 내용을 넣고 하드코딩하는 것과 비슷한 격이다.
    • 또한 인증 정보 혹은 암호화 키와 같은 내용이 들어간다면, 해당 이미지에 접근하는 것으로 해당 내용들을 볼 수 있다.

git Repo 를 볼륨 설정 소스로 사용하는 방법도 존재한다.

하지만, 더욱 간단한 방법으로는 설정 데이터를 최상위 레벨인 k8s 리소스에 저장하고, 이를 기타 다른 리소스 정의와 마찬가지로 저장할 수 있는데 이러한 K8s 리소스를 ConfigMap 이라 칭한다. 또한 암호화 / 자격증명과 같은 리소스는 Secret 이란 오브젝트를 제공한다.

 

7.2 컨테이너에 명령줄 인자 전달

ENTRYPOINTCMD 이해

  • ENTRYPOINT : 컨테이너가 시작될 떄 호출될 명령어 정의
  • CMD : ENTRYPOINT 에 전달되는 인자를 정의한다.

CMD 를 사용해 이미지가 실행될 때 실행할 명령어를 지정할 수 있지만, 올바른 방법은 다음과 같다 .
ENTRYPOINT 를 실행하고 기본 인자를 정의하려는 경우에만 CMD 를 지정하는 것이다.
해당 방법을 통해 아무런 인자도 지정하지 않고 이미지를 실행할 수 있다.
$ docker run <image>

혹은 추가 인자를 지정해 Dockerfile 안의 CMD 에 정의된 값을 재정의 가능
$ docker run <image> <arguments>

 

 

shell 과 exec 형식 간 차이점

  • shell 형식 : ex_ ENTRYPOINT node app.js
  • exec 형식 :ex_ ENTRYPOINT ["node", "app.js"]

차이점은 내부에서 정의된 명령을 shell 로 호출하는 지 여부 (exec 은 shell 이 아닌, 컨테이너 내부에서 직접 실행)

쿠버네티스에서 명령과 인자 재정의

  • 쿠버네티스에서 컨테이너 정의시, ENTRYPOINT 와 CMD 둘다 재정의가능
kind: Pod
spec:
  containers:
  - image: some/image
    command: ["/bin/command"]
    args: ["arg1", "arg2", "arg3"]

 

명령줄 인자를 통한 인자 지정 및 전달 pod 정의 예시 (인자 지정)

apiVersion: v1
kind: Pod
metadata:
  name: fortune2s
spec:
  containers:
  - image: luksa/fortune:args
    args: ["2"]
    name: html-generator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs
...

컨테이너 정의에 args 배열 추가 → 파드 생성 후 실행 시 배열 값이 컨테이너에 명령줄 인자로 전달된다

 

7.3 컨테이너의 환경변수 설정

  • 컨테이너화된 어플리케이션은 종종 환경변수를 설정 옵션의 소스로 사용한다.
  • 컨테이너 명령이나 인자와 마찬가지로 환경변수 목록도 파드 생성 이후에는 업데이트 할 수는 없다.
  • 컨테이너 별로 환경변수 설정은 가능

7.3.1 컨테이너 정의에 환경변수 지정

  • 새로운 이미지를 생성 후 도커 허브로 푸시 했다고 가정하자.
  • 이후 새 파드를 만들 떄 다음과 같이 환경변수를 컨테이너 정의에 포함해 스크립트에 전달할 수 있다.
    (환경변수는 파드 레벨이 아닌, 컨테이너 정의 안에서 설정)
  • 각 컨테이너 설정 시, 쿠베는 자동으로 동일한 네임스페이스에 안에 있는 각 서비스에 환경변수를 노출한다.
  • 이러한 환경변수는 기본적으로 auto-injected 설정이다.
# fortune-pod-env.yaml
kind : Pod
spec: 
    containers:
    - image : luksa/fortune:env
        env: # 환경변수 목록에 단일 변수 추가 
        - name: INTERBAL 
            value: "30"
        name : html-generator
        ...

7.3.2 변수값에서 다른 환경변수 참조

  • 이미 정의된 환경변수 혹은 기타 기존 변수도 참조가 가능하다.
env: 
- name: FIRST_VAR
    value: "foo"
- name: SECOND_VAR
    value: "$(FIRST_VAR)bar"
  • 여러 환경에서 동일한 파드 정의를 사용하기 위해서는 파드 정의에서 설정을 분리하는 것이 좋다.
  • 이는 이후에 configMap 을 통해 value → valueFrom 필드를 통해 사용가능하다.

7.4 ConfigMap

어플리케이션 구성의 요점은 환경에 따라 다르거나, 자주 변경되는 설정 옵션을 어플리케이션 소스 코드와 별도 유지하는 것.

만약 파드 정의를 애플리케이션 소스 코드로 생각한다면, 설정을 파드 정의에서 밖으로 이동시켜야한다는 것은 명확하다.(?)

  • MSA 아키텍처 안에서는 파드 정의가 실제로 그러하다. 개별 구성 요소를 기능 시스템으로 구성하는 방법을 규정하기 때문
  • +) 두번째 문장은 무슨 말이지? 애플리케이션 관점을 파드 관점으로 확장시켜서 파드 관련 configuration 을 파드 정의에서 밖에다 정의한다는 걸 그냥 비유한건가
  • configMap : k8s 에 대한 config option 을 별도 오브젝트로 분리한 것
    • config option 값들을 k/v 형태로 구성된 map 형태의 오브젝트
    • 애플리케이션에서 configmap 을 직접 읽거나, configmap을 모른다고 했을때는 container 환경 변수 또는 볼륨 파일로 configmap 의 내용을 어플리케이션에 전달
    • 또한 환경변수는 $(ENV_VAR) 구문을 사용해 명령줄 인수에서 참조할 수 있도록 프로세스 명령줄 인자로 전달 가능

  • 필요에 따라 어플리케이션에서 k8s REST API 엔드포인트를 통해 configMap 을 읽을 수 있지만, 추천하는 방식은 아님
  • 각각 다른 환경(dev, test, stg, prod) 에 맞게 동일한 configMap 에 관한 여러 manifest 유지 가능
    • 파드는 configmap 을 이름으로 참조하므로, 모든 환경에서 동일한 파드 정의를 사용하기 때문에 각 환경별 다른 설정 가능

 

configmap 생성

  • yaml 생성 혹은 kubectl create configmap ~ command 로 등록 가능
  • 이 때 configmap key는 유효한 DNS 서브도메인(영숫자, 대시, 밑줄, 점 포함 가능)이어야 한다.
    • ex) kubectl create configmap fortune-config -—from-literal=sleep-interval=25
  • 여러 configmap 생성 시, —-from-literal 여러 개 추가

yaml 방식

apiVersion: v1
kind: ConfigMap
metadata:
  name: fortune-config
data:
  sleep-interval: "25"

 

컨피그맵 생성 (file)

kubectl create -f fortune-config.yaml

 

컨피그맵 목록 조회

kubectl get cm

 

컨피그맵 정의 확인

kubectl get configmap fortune-config -o yaml

 

디렉토리에 있는 파일 통한 컨피그맵 생성

kubectl create configmap my-config --from-file=/path/to/dir

 

다양한 옵션 결합

kubectl create configmap my-config
    --from-file=foo.json                  # 단일 파일
    --from-file=bar=foobar.conf    # 사용자 정의 키 밑에 파일 저장
    --from-file=config-opts/          # 전체 디렉터리
    --from-literal=some=thing       # 문자열 값

 

7.4.3 configmap 항목 환경변수로 컨테이너에 전달

• 생성한 configmap의 값을 파드 안의 컨테이너를 전달할수 있는 방법

apiVersion: v1
kind: Pod
metadata:
  name: fortune-env-from-configmap
spec:
  containers:
  - image: luksa/fortune:env
    env:
    - name: INTERVAL               # INTERVAL 환경변수 설정
      valueFrom:
        configMapKeyRef:            # 컨피그맵 키에서 값을 가져와 초기화
          name: fortune-config     # 참조하는 컨피그맵 이름
          key: sleep-interval          # 컨피그맵에서 해당 키 아래에 저장된 값으로 변수 셋팅
    name: html-generator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs
  - image: nginx:alpine
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: html
    emptyDir: {}

  • html-generator 컨테이너 안에서 실행중인 프로세스는 INTERVAL 환경 변수 일을 때, configmap 의 value 를 읽어옴

파드에 존재하지 않는 컨피그맵 참조

  • 존재하지 않는 컨피그맵을 참조하려고 하면 컨테이너는 시작하는데 실패한다.
  • 하지만 참조하지 않는 다른 컨테이너는 정상적으로 시작된다.
    누락된 컨피그맵을 생성하면 실패했던 컨테이너는 파드를 다시 만들지 않아도 자동으로 시작된다.
  • 컨피그맵 참조를 옵션으로 표시할수도 있다. (configMapKeyRef.optional : true로 지정), - 컨피그맵이 존재하지 않아도 컨테이너가 시작
728x90
반응형

' > Kubernetes In Action' 카테고리의 다른 글

6. 쿠버네티스 볼륨  (1) 2023.12.30
5.5 Readiness Probe  (0) 2023.12.16
5.4 Ingress(인그레스)  (0) 2023.12.10