Kubernetes 인 액션 7장 컨피그맵과 시크릿: 애플리케이션 설정
Devops/Kubernetes

Kubernetes 인 액션 7장 컨피그맵과 시크릿: 애플리케이션 설정

뉴비뉴 2023. 6. 19.

다루는 내용

  • 컨테이너의 주 프로세스 변경
  • 애플리케이션에 명령줄 옵션 전달
  • 애플리케이션에 노출되는 환경변수 설정
  • 컨피그맵으로 애플리케이션 설정
  • 시크릿으로 민감한 정보 전달

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

왜 환경변수를 사용하는 것이 컨테이너에서 널리 사용될까?

도커 컨테이너 내부에 있는 설정 파일을 사용하는 것은 약간 까다롭다.

설정 파일을 컨테이너 이미지 안에 포함하거나 파일이 포함돼 있는 볼륨을 컨테이너에 마운트해야 하기 때문이다.

설정 데이터를 저장하는 쿠버네티스 리소스를 컨피그맵(ConfigMap) 이라고 한다.

  • 컨테이너에 명령줄 인수 전달
  • 각 컨테이너를 위한 사용자 정의 환경변수 지정
  • 특수한 유형의 볼륨을 통해 설정 파일을 컨테이너에 마운트

자격증명, 개인 암호화 키, 보안을 유지해야 하는 유사한 데이터가 포함된다. 이런 종류의 정보는 특별히 주의를 기울려 처리해야 하는데, 이를 위해 쿠버네티스 시크릿(Secret) 이라는 또 다른 유형의 중요한 오브젝트를 제공한다.

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

7.2.1 도커에서 명령어와 인자 정의

ENTRYPOINT와 CMD 이해

  • ENTRYPOINT는 컨테이너가 시작될 때 호출될 명령어를 정의한다.
    • ENTRYPOINT 명령어는 오버라이딩이 어렵다.
  • CMD는 ENTRYPOINT에 전달되는 인자를 정의한다.
    • CMD 명령어는 오버라이딩이 쉽다.

CMD 명령어를 사용해 이미지가 실행될 때 실행할 명령어를 지정할 수 있지만, 올바른 방법은 ENTRYPOINT 명령어로 실행하고 기본 인자를 정의하려는 경우에만 CMD를 지정하는 것이다. 그러면 아무런 인자도 지정하지 않고 이미지를 실행할 수 있다.

$ docker run <image>

  • CMD: 실행 명령어가 있으면 CMD 명령어에 써준 내용은 무시된다.
FROM centos:7
CMD ["echo", "Hello, Darwin"]

docker build -t hello:cmd
docker run hello:cmd
Hello, Darwin
docker run hello:cmd TIM
*TIM
  • ENTRYPOINT: 명령어는 무시되지 않고 대신 명령의 인수로 취급하여 매개변수로 추가된다.
FROM centos:7
ENTRYPOINT ["echo", "Hello, Darwin"]

docker build -t hello:entrypoint
docker run hello:entrypoint
Hello, Darwin
docker run hello:entrypoint TIM
*Hello, Darwin TIM

또는 추가 인자를 지정해 Dockerfile 안에 CMD에 정의된 값을 재정의 한다.

$ docker run <image> <arguments>

항상 실행해야 하는 명령을 사용하여 실행 가능한 도커 이미지를 빌드할 때는 ENTRYPOINT를 사용한다. CMD 명령어는 도커 컨테이너가 실행될 때 Command line에 명시적으로 인자값을 지정하지 않는 경우에 기본 명령어 역할을 하는 인자를 설정하는 데에 사용한다.

shell과 exec 형식 간의 차이점

  • shell 형식 - 예: ENTRYPOINT node app.js
  • exec 형식 - 예: ENTRYPOINT [”node”, “app.js”]

차이점은 내부에서 정의된 명령을 셀로 호출하는지 여부다.

이렇게 하면 컨테이너 내부에서 node 프로세스를 직접 실행한다.

fortune 이미지에서 간격을 설정할 수 있도록 만들기

trap “exit” SIGINT 는 쉘 스크립트에서 사용되는 신호 처리(trap) 구문 입니다. 예를 들어 사용자가 Ctrl+C를 눌러 인터럽트를 발생시키는 경우에 SIGINT(Interrupt signal)가 발생합니다. /usr/games/fortune > /var/htdocs/index.html 여기서 ‘>’ 는 리다이렉트를 의미 따라서 ‘/usr/games/fortune’ 명령의 출력을 받아서 ‘/var/htdocs/index.html’ 파일에 저장하는 명령어 입니다.

Dockerfile을 수정해 exec 버전 ENTRYPOINT 명령을 사용하도록 하고 기본 간격으로 10초를 CMD 명령으로 지정한다.

INTERVAL=$1 이 명령으로 CMD [”10”] 으로 입력하면 INTERVAL=10 설정 됨

$ docker build -t docker.io/luksa/fortune:args .

$ docker push docker.io/luksa/fortune:args

로컬에서 도커로 이미지를 실행해 테스트할 수 있다. 또한 기본 sleep 시간 간격을 인자로 전달해 재정의할 수 있다.

$ docker run -it docker.io/luksa/fortune.args 15

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

ENTRYPOINT 와 CMD 둘 다 재정의할 수 있다. 그러기 위해 다음과 같이 컨테이너 정의 안에 command와 args 속성을 지정한다.

|노트| command와 args 필드는 파드 생성 이후에 업데이트할 수 없다.

도커 Kubernetes 설명
ENTRYPOINT command 컨테이너 안에서 실행되는 실행파일
CMD args 실행파일에 전달되는 인자

사용자 정의 주기로 fortune 파드 실행

일반적으로 ‘args’ 는 컨테이너 실행 시에 변하는 값을 전달하기 위해 사용됩니다.

컨테이너 정의에 args 배열을 추가했다. 파드를 생성하고 실행하면 배열 값들이 컨테이너에 명령줄 인자로 전달된다.

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

컨테이너 별로 환경변수를 설정할 수 있다.

환경변수로 fortune 이미지 안에 간격을 설정할 수 있도록 만들기

$INTERVAL 은 환경변수를 가져오는 것 Python os.environ[’INTERVAL’]

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

7.4 컨피그맵으로 설정 분리

7.4.1 컨피그맵 소개

Kubernetes 에서는 설정 옵션을 컨피그맵이라고 부르는 별도 오브젝트로 분리할 수 있다.

컨피그맵은 짧은 문자열에서 전체 설정 파일에 이르는 값을 가지는 키/값 쌍으로 구성된 맵이다.

파드는 컨피그맵을 환경변수나 컨피그맵 볼륨을 통해 사용할 수 있다.

7.4.2 컨피그맵 생성

kubectl create configmap 명령 사용

$ kubectl create configmap fortune-config --from-literal=sleep-interval=25

configmap “fortune-config” created

여러 문자열 항목을 가진 컨피그맵을 생성하려면 여러 개의 --from-literal 인자를 추가한다.

$ kubectl create configmap myconfigmap --from-literal=foo=bar --from-literal=bar=baz --from-literal=one=two

파일 내용으로 컨피그맵 생성

$ kubectl create configmap my-config --from-file=config-file.conf

$ kubectl create configmap my-config --from-file=customkey=config-file.conf

디렉터리에 있는 파일로 컨피그맵 생성

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

  • 단일 파일 foo.json
  • 사용자 정의 키 밑에 파일 저장 foobar.conf
  • 전체 디렉터리 config-opts/
  • 문자열 값 some=thing

7.4.3 컨피그맵 항목을 환경변수로 컨테이너에 전달

valueFrom 필드

환경변수를 컨피그맵에서 가져오는 파드 선언 valueFrom 사용

|노트| 컨피그맵 참조를 옵션으로 표시할 수도 있다.
(configMapKeyRef.optional: true로 지정) 이런 경우에는 컨피그맵이 존재하지 않아도 컨테이너는 시작한다.

7.4.4 컨피그맵의 모든 항목을 한 번에 환경변수로 전달

env 대신 envFrom 사용 prefix: 접두사 모든 환경변수는 CONFIG_ 접두사를 가짐
이 컨테이너 안에는 CONFIG_FOO 와 CONFIG_BAR가 존재한다.

# 여러 개의 prefix 를 사용하고 싶다면
envFrom:
  - prefix: CONFIGMAP1
    configMapRef:
      name: configmap1
  - prefix: CONFIGMAP2
    configMapRef:
      name: configmap2

7.5 시크릿으로 민감한 데이터를 컨테이너에 전달

설정 안에는 보안이 유지돼야 하는 자격증명과 개인 암호화 키와 같은 민감한 정보도 포함돼 있다.

7.5.1 시크릿 소개

시크릿은 키-값 쌍을 가진 맵으로 컨피그맵과 매우 비슷하다.

  • 환경변수로 시크릿 항목을 컨테이너에 전달
  • 시크릿 항목을 볼륨 파일로 노출

Kubernetes 는 시크릿에 접근해야 하는 파드가 실행되고 있는 노드에만 개별 시크릿을 배포해 시크릿을 안전하게 유지한다.
또한 노드 자체적으로 시크릿을 항상 메모리에만 저장되게 하고 물리 저장소에 기록되지 않도록 한다.

왜냐하면 물리 저장소는 시크릿을 삭제한 후에도 디스크를 완전시 삭제 하는 작업이 필요하기 때문이다.

마스터 노드(구체적으로 etcd) 에는 시크릿을 암호화되지 않은 형식으로 저장하므로, 시크릿에 저장한 민감한 데이터를 보호하려면 마스터 노드를 보호하는 것이 필요하다.

etcd가 시크릿을 암호화된 형태로 저장해 시스템을 좀 더 안전하게 만든다.

  • 민감하지 않고, 일반 설정 데이터는 컨피그맵을 사용한다
  • 본질적으로 민감한 데이터는 시크릿을 사용해 키 아래에 보관하는 것이 필요하다. 만약 설정 파일이 민감한 데이터와 그렇지 않은 데이터를 모두 가지고 있다면 해당 파일을 시크릿 안에 저장해야 한다.

7.5.2 기본 토큰 시크릿 소개

모든 파드에는 secret 볼륨이 자동으로 연결돼 있다.

시크릿은 리소스이기 때문에 kubectl get secrets 명령어로 목록을 조회하고 거기서 default-token 시크릿을 찾을 수 있다.

시크릿이 갖고 있는 세 가지 항목(ca.crt, namespace, token)은 파드 안에서 쿠버네티스 API 서버와 통신할 때 필요한 모든 것을 나타낸다.

7.5.3 시크릿 생성

인증서와 개인 키를 만들어야 한다. 개인 키는 안전하게 유지해야 하므로 개인 키와 인증서를 시크릿에 넣자.

$ openssl genrsa -out https.key 2048

$ openssl req -new -x509 -key https.key -out https.cert -days 3650 -subj /CN=www.kubia-example.com

7.5.4 컨피그맵과 시크릿 비교

쿠버네티스 개발자들이 시크릿을 지원하다가 컨피그맵을 생성하게 한 이유다.

시크릿 항목의 내용은 Base64 인코딩 문자열로 표시되고, 컨피그맵의 내용은 일반 텍스트로 표시된다.

시크릿은 각 항목을 설정하고 읽을 때마다 인코딩과 디코딩을 해야 하기 때문이다.

바이너리 데이터 시크릿 사용

Base64 인코딩을 사용하는 까닭은 간단하다.

시크릿 항목에 일반 텍스트뿐만 아니라 바이너리 값도 담을 수 있기 때문이다.

Base64 인코딩을 바이너리 데이터를 일반 텍스트 형식인 YAML 이나 JSON 안에 넣을 수 있다.

stringData 필드 소개

stringData 필드는 쓰기 전용이다. 값을 설정할 때만 사용할 수 있다.

kubectl get -o yaml 명령으로 시크릿의 YAML 정의를 가져올 때, stringData 필드는 표시되지 않는다.

data 항목 아래에 다른 모든 항목처럼 Base64로 인코딩돼 표시된다.

시크릿을 파드에 마운트

volumeMounts 에서 certs(secret)을 마운트 했다. 시크릿 볼륨을 해당 위치에 마운트

환경변수로 시크릿 항목 노출

볼륨을 사용하는 대신 컨피그맵에서 sleep-interval 항목을 노출한 것 처럼, 시크릿의 개별 항목을 환경변수로 노출할 수 있다.

7.6 요약

  • 컨테이너 이미지에 정의된 기본 명령어를 파드 정의 안에 재정의
  • 주 컨테이너 프로세스에 명령줄 인자 전달
  • 컨테이너에서 사용할 환경변수 설정
  • 파드 사양에서 설정을 분리해 컨피그맵 안에 넣기
  • 민감한 데이터를 시크릿 안에 넣고 컨테이너에 안전하게 전달
  • docker-registry 시크릿을 만들고 프라이빗 이미지 레지스트리에서 이미지를 가져올 때 사용

댓글

💲 추천 글