반응형

목차

  1. 들어가며
  2. 도커에서 명령어와 인자 정의
  3. shell과 exec 형식 간의 차이점
  4. fortune 이미지에서 간격을 설정할 수 있도록 만들기
  5. 쿠버네티스에서 명령과 인자 재정의
  6. 사용자 정의 주기로 fortune 파드 실행

쿠버네티스 컨피그맵과 시크릿을 다루기 전에 일반적으로 컨테이너화된 애플리케이션이 어떻게 구성되는지 살펴보려고 합니다. 이번 포스팅과 다음 포스팅에서는 컨테이너에 명령줄 인자를 전달하고 환경변수 설정에 대해 다뤄보도록 하겠습니다.

 

이전 쿠버네티스 포스팅들에서 컨테이너 이미지에 정의된 기본 명령을 실행하는 컨테이너를 만들었지만, 쿠버네티스는 파드 컨테이너 정의에 지정된 실행 명령 대신 다른 실행파일을 실행하거나 다른 명령줄 인자를 사용해 실행하는 것이 가능합니다. 어떻게 하는지 살펴보겠습니다.


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

가장 먼저 설명해야 할 것은 컨테이너에서 실행하는 전체 명령이 명령어와 인자의 두 부분으로 구성돼 있다는 것입니다.

Dockerfile에서 두 부분은 다음과 같습니다.

 

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

 

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

 

$ docker run <image>

 

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

 

$ docker run <image> <arguments>


shell과 exec 형식 간의 차이점

두 명령어는 두 가지 서로 다른 형식을 지원합니다.

 

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

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

 

ENTRYPOINT ["node", "app.js"]

 

이렇게 하면 셸 내부가 아닌 컨테이너 내부에서 node 프로세스를 직접 실행합니다. 컨테이너 내부에서 실행 중인 프로세스 목록을 나열해 직접 실행된 것을 볼 수 있울 것입니다. 해당 명령어는 아래와 같습니다.

 

$ docker exec 4675d ps x
PID  TTY      STAT     TIME COMMAND
 1        ?         Ss1       0:00  node app.js
...

 

만약 shell 형식(ENTRYPOINT node app.js)을 사용했을 경우 컨테이너의 프로세스 목록 출력하는 명령어는 아래와 같습니다.

 

$ docker exec -it e4bad ps x
PID  TTY      STAT     TIME COMMAND
 1        ?         Ss        0:00  /bin/sh -c node app.js
 7        ?         S1        0:00  node app.js
...

위 예시에서 볼 수 있는 것처럼 메인 프로세스(PID 1)는 node 프로세스가 아닌 shell 프로세스입니다. 노드 프로세스(PID 7)는 shell에서 시작됩니다. shell 프로세스는 불필요하므로 ENTRYPOINT 명령에서 exec 형식을 사용해 실행합니다.


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

fortune 스크립트와 이미지에서 반복하는 주기를 변경할 수 있도록 수정해보겠습니다. INTERVAL변수를 추가하고 첫 번째 명령줄 인자의 값으로 초기화합니다.

#!/bin/bash
trap "exit" SIGINT
INTERVAL=$1
echo Configured to generate new fortune every $INTERVAL seconds
mkdir -p /var/htdocs
while :
do
    echo $(date) Writing fortune to /var/htdocs/index.html
    /usr/games/fortune>/var/htdocs/index.html
    sleep $INTERVAL
done

추가하거나 수정한줄을 굵은 글꼴로 표시했습니다. Dockerfile을 수정해 exec 버전 ENTRY POINT 명령을 사용하도록 하고 기본 간격으로 10초를 CMD 명령으로 지정합니다.

FROM ubuntu:latest
RUN apt-get update; apt-get-y install fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT ["/bin/fortuneloop.sh"]                 <  exec 형태의 ETNRYPOINT 명령
CMD ["10"]                                                          <  실행할 때 사용할 기본 인자

이제 이미지를 빌드하고 도커 허브에 푸시할 수 있습니다. 이번에는 이미지 태그를 latest 대신 args로 지정합니다.

 

$ docker build -t docker.io/luksa/fortune:args .    < 늘 강조하지만 빌드할 때 마지막에 .(온점)도 꼭 붙여 주셔야 합니다.

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

 

로컬에서 도커로 이미지를 실행해 테스트할 수 있습니다.

 

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

Configured to generate new fortune every 10 seconds

Fri May 19 10:39:44 UTC 2017 Writing fortune to /var/htdocs/index.html

  

또한 기본 sleep 시간 간격을 인자로 전달해 재정의할 수 있습니다.

 

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

Configured to generate new fortune every 15 seconds

 

이미지가 전달된 인자를 제대로 가져온 것을 확인했으니, 파드에서 이 인자들을 어떻 게 사용하는지 알아보겠습니다.


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

쿠버네티스에서 컨테이너를 정의할 때, ENTRYPOINT와 CMD 둘 다 재정의할 수 있습니다. 그러기 위해 다음과 같이 컨테이너 정의 안에 command와 args 속성을 지정합니다. 이 때 command와 args 필드는 파드 생성 이후에 업데이트할 수 없다는 점을 주의해서 잘 작성해주어야 합니다.

kind: Pod
spec:
  containers:
  - image: some/image
    command: ["/bin/command"]
    args: ["arg1", "arg2", "arg3"]

대부분 사용자 정의 인자만 지정하고 명령을 재정의하는 경우는 거의 없습니다(ENTRYPOINT 를 정의하지 않는 busybox와 같은 범용 이미지는 제외).

 

두 개의 Dockerfile 명령과 그에 상응하는 파드 사양 필드는 아래 표에 정리했습니다.

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

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

fortune 파드를 사용자 정의 지연 간격으로 실행하려면 이름을 변경해 복사하고 다음 예제와 같이 수정합니다. 이름을 정의하실 때에는 fortune-pod.yaml이나 fortune-pod-args.yaml처럼 어떤 역할인지 이름을 명시하는 것이 좋습니다. 실제 업무를 진행할 때 작업을 혼자한다면 스스로 편하게 이름을 정해 사용하면 되지만 보통은 그렇지는 않을 것이고, 누군가에게 인수인계 해야할 상황이 올 수 있습니다. 때문에 이름은 세밀하고 어떤 역할인지 누가봐도 구분이 가능하게 해주면 좋습니다. 물론, 이름을 지정하는 법같은게 있는 것은 아닙니다. 사담은 여기까지하고 예제로 넘어가 봅시다.

 

해당 예제는 이 페이지에서 작성된 emptyDir 파드 생성 YAML을 기반으로 합니다.

apiVersion: v1
kind: Pod
metadata:
  name: fortune2s                      <  파드 이름 변경
spec:
  containers:
  - image: luksa/fortune:args      <  fortune:latest 대신에 fortune:args 이미지 사용
    args: ["2"]                                <  스크립트가 2초마다 새로운 fortune 메시지를 생성하도록 인자 지정
    name: html-generator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs
...

 

컨테이너 정의에 args 배열을 추가했다. 파드를 생성하고 실행하면 배열 값들이 컨테이너에 명령줄 인자로 전달됩니다. 위 목록에서 사용한 배열 표기법은 하나 혹은 몇 개의 인자를 가진 경우 유용합니다. 여러 인자를 가졌을 때는 다음 표기법을 사용할 수 있습니다.

args:
- foo
- bar
- "15"

이 때 문자열 값을 따옴표로 묶을 필요는 없자만 숫자일 경우는 묶어야 합니다.

 

 

반응형