11. 애플리케이션 스케줄링과 라이프사이클 관리 (1)
이 문서는 인프런 강의 "데브옵스를 위한 쿠버네티스 마스터"을 듣고 작성되었습니다. 최대한 요약해서 강의 내용을 최소로 하는데 목표를 두고 있어서, 더 친절하고 정확한 내용을 원하신다면 강의를 구매하시는 것을 추천드립니다. => 강의 링크
컨테이너 환경 변수 전달 (1) YAML
k8s
에서 Pod
에 실행되는 컨테이너에 환경 변수를 전달하는 방법은 크게 3가지가 있다.
- Yaml 파일에 직접 명시 "spec.containers[*].env"
- Secret
- ConfigMap
이 절에서는 이 중 첫 번째 Yaml
로 전달하는 방식을 알아본다. env-yaml.yaml
을 다음과 같이 생성한다.
apiVersion: v1
kind: Pod
metadata:
name: env-yaml-mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: root
spec.containers[*].env
형식으로 키 이름과 값을 전달한 것을 확인할 수 있다. 이제 터미널에 다음을 입려하여 리소스를 생성한다.
$ kubectl create -f env-yaml.yaml
pod/env-yaml-mysql created
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
env-yaml-mysql 1/1 Running 0 4s
이제 mysql
컨테이너에 다음 명령어를 입력하여, 로그인해보자. 비밀번호는 "root"이다.
$ kubectl exec -it env-yaml-mysql -- mysql -u root -p
Enter password: # root 입력
성공적으로 로그인되었다면 다음 글을 확인할 수 있다.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.51 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
컨테이너 환경 변수 전달 (2) Secret
k8s
에서 Pod
에 실행되는 컨테이너에 환경 변수를 전달하는 방법은 크게 3가지가 있다.
- Yaml 파일에 직접 명시 "spec.containers[*].env"
- Secret
- ConfigMap
이 절에서는 이 중 두 번째 Secret
리소스를 생성하여 값을 전달하는 방식을 알아본다. env-secret.yaml
을 다음과 같이 생성한다.
apiVersion: v1
kind: Secret
metadata:
name: env-secret
type: Opaque
data:
MYSQL_ROOT_PASSWORD: cm9vdA==
---
apiVersion: v1
kind: Pod
metadata:
name: env-secret-mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: env-secret
key: MYSQL_ROOT_PASSWORD
먼저 Secret
리소스를 생성하는 부분을 살펴보자.
apiVersion: v1
kind: Secret
metadata:
name: env-secret
type: Opaque
data:
MYSQL_ROOT_PASSWORD: cm9vdA== # root를 인코딩한 값
타 리소스 생성할 때와 별로 다를게 없다. 같은 네임스페이스 안의 다른 리소스들이 참조할 수 있도록 metadata.name
을 지정해준다. 그 후 data
에서 해당 키 이름과 원하는 값을 인코딩한 값을 설정해주면 된다. 리눅스 계열이라면 다음과 같이 쉽게 인코딩할 수 있다.
# echo -n <원하는 값>|base64
$ echo -n root|base64
cm9vdA==
참고! data, stringData
"Secret"에서는 인코딩해서 data 필드에 키-값을 할당하는 것이 일반적이다. 하지만 그냥 평문을 전달하고 싶다면 stringData 필드를 쓰면 된다.
Secret
리소스를 지정했으면 Pod
내부의 Container
들이 이용하게 하려면 spec.containers[*].env[*].valueFrom.secretKeyRef
로 지정하면 된다.
apiVersion: v1
kind: Pod
metadata:
name: env-secret-mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: env-secret # 참조하는 Secret 이름
key: MYSQL_ROOT_PASSWORD # Secret 내부의 키
이제 다음 명령어를 통해서 리소스를 생성한다.
$ kubectl create -f env-secret.yaml
secret/env-secret created
pod/env-secret-mysql created
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
env-secret-mysql 1/1 Running 0 4s
리소스가 생성되었다면 생성된 Secret
을 다음 명령어로 확인해보자.
$ kubectl get secret
NAME TYPE DATA AGE
default-token-xs7mw kubernetes.io/service-account-token 3 4d22h
env-secret Opaque 1 89s
$ kubectl describe secret env-secret
Name: env-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
MYSQL_ROOT_PASSWORD: 4 bytes
이제 mysql
컨테이너에 다음 명령어를 입력하여, 로그인해보자. 비밀번호는 "root"이다.
$ kubectl exec -it env-secret-mysql -- mysql -u root -p
Enter password: # root 입력
성공적으로 로그인되었다면 다음 글을 확인할 수 있다.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.51 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
컨테이너 환경 변수 전달 (3) ConfigMap
k8s
에서 Pod
에 실행되는 컨테이너에 환경 변수를 전달하는 방법은 크게 3가지가 있다.
- Yaml 파일에 직접 명시 "spec.containers[*].env"
- Secret
- ConfigMap
이 절에서는 이 중 세 번째 ConfigMap
리소스를 생성하여 값을 전달하는 방식을 알아본다. env-configmap.yaml
을 다음과 같이 생성한다.
src/ch11/k8s/env-configmap-was.yaml
apiVersion: v1
kind: Service
metadata:
name: env-configmap-was
spec:
ports:
- port: 8080
targetPort: 8080
selector:
name: env-configmap-was
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: env-configmap-was
spec:
selector:
matchLabels:
name: env-configmap-was
replicas: 3
template:
metadata:
labels:
name: env-configmap-was
spec:
containers:
- name: env-configmap-was
image: gcr.io/google-samples/node-hello:1.0
ports:
- containerPort: 8080
protocol: TCP
env:
- name: DEMO_GREETING
valueFrom:
configMapKeyRef:
name: env-configmap-was
key: DEMO_GREETING
- name: DEMO_FAREWELL
valueFrom:
configMapKeyRef:
name: env-configmap-was
key: DEMO_FAREWELL
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-configmap-was
data:
DEMO_GREETING: "Hello from the environment with ConfigMap"
DEMO_FAREWELL: "Hi Firewall"
ConfigMap
은 다음과 같이 쉽게 생성할 수 있다.
apiVersion: v1
kind: ConfigMap
metadata:
name: env-configmap-was
data:
DEMO_GREETING: "Hello from the environment with ConfigMap"
DEMO_FAREWELL: "Hi Firewall"
Secret
과 거의 유사한데, Secret
과 달리 평문으로 전달되는게 ConfigMap
이라고 생각하면 된다. 이렇게 생성된 키-값 쌍은 다음과 같이 불러서 사용하면 된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: env-configmap-was
spec:
# ...
template:
# ...
spec:
containers:
- name: env-configmap-was
image: gcr.io/google-samples/node-hello:1.0
ports:
- containerPort: 8080
protocol: TCP
env:
- name: DEMO_GREETING
valueFrom:
configMapKeyRef:
name: env-configmap-was
key: DEMO_GREETING
- name: DEMO_FAREWELL
valueFrom:
configMapKeyRef:
name: env-configmap-was
key: DEMO_FAREWELL
Secret
의 값을 불러 올 때 secretKeyRef
으로 불러온 것처럼 ConfigMap
의 값을 불러 올 때는 configMapKeyRef
를 사용하면 된다. 이제 리소스를 생성해보자.
$ kubectl create -f env-configmap-was.yaml
service/env-configmap-was created
deployment.apps/env-configmap-was created
configmap/env-configmap-was created
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
env-configmap-was-77b58fc975-k6s79 0/1 ContainerCreating 0 6s
env-configmap-was-77b58fc975-nvtjr 0/1 ContainerCreating 0 6s
env-configmap-was-77b58fc975-rngql 0/1 ContainerCreating 0 6s
env-configmap-was-77b58fc975-k6s79 1/1 Running 0 31s
env-configmap-was-77b58fc975-nvtjr 1/1 Running 0 32s
env-configmap-was-77b58fc975-rngql 1/1 Running 0 32s
Pod
이 모두 생성되면 적당한 것을 골라서 다음 명령어를 입력해보자.
# 환경 변수 초기화 확인
$ kubectl exec -it env-configmap-was-77b58fc975-nvtjr -- printenv | grep "DEMO"
DEMO_GREETING=Hello from the environment with ConfigMap
DEMO_FAREWELL=Hi Firewall
# 서비스 연결 테스트
$ kubectl exec -it env-configmap-was-77b58fc975-nvtjr -- curl env-configmap-was:8080
Hello Kubernetes!
우리가 전달한 환경 변수가 잘 전달된 것을 확인할 수 있다. ConfigMap
은 또한 볼륨으로써 Pod
의 컨테이너들에게 부착될 수 있다. 예를 들어서 설정 파일 같은 것을 ConfigMap
으로 만들어서 컨테이너의 볼륨에 올릴 수 있다. 다음과 같이 env-configmap-web.yaml
을 생성한다.
src/ch11/k8s/env-configmap-web.yaml
apiVersion: v1
kind: Service
metadata:
name: env-configmap-web
spec:
ports:
- port: 80
targetPort: 80
selector:
name: env-configmap-web
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: env-configmap-web
spec:
selector:
matchLabels:
name: env-configmap-web
replicas: 3
template:
metadata:
labels:
name: env-configmap-web
spec:
containers:
- name: env-configmap-web
image: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nginx
subPath: nginx.conf
mountPath: /etc/nginx/nginx.conf
readOnly: true
volumes:
- name: nginx
configMap:
name: env-configmap-web
items:
- key: nginx.conf
path: nginx.conf
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-configmap-web
data:
nginx.conf: |
error_log /var/log/nginx/error.log warn;
pid /tmp/nginx.pid;
worker_rlimit_nofile 8192;
events {
worker_connections 4096; ## Default: 1024
}
http {
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$request_time"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
server {
listen 80;
location / {
proxy_pass http://env-configmap-was:8080;
}
}
}
ConfigMap.data
부분에서 "|" 밑으로 설정 파일을 만들었다. 이를 설정 파일로 취급하여 볼륨으로 마운트할 수 있다.
kind: Deployment
metadata:
name: env-configmap-web
spec:
# ...
spec:
containers:
- name: env-configmap-web
# ...
volumeMounts:
- name: nginx
subPath: nginx.conf # items[*].path와 같아야 한다.
mountPath: /etc/nginx/nginx.conf
readOnly: true
volumes:
- name: nginx
configMap:
name: env-configmap-web # ConfigMap 이름
items:
- key: nginx.conf # ConfigMap에서 가져올 key와 같아야 한다.
path: nginx.conf
이제 이 리소스들을 생성해보자.
$ kubectl create -f env-configmap-web.yaml
service/env-configmap-web created
deployment.apps/env-configmap-web created
configmap/env-configmap-web created
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
...
env-configmap-web-79fdfc5c8b-dr45r 1/1 Running 0 19s
env-configmap-web-79fdfc5c8b-fbqkf 1/1 Running 0 19s
env-configmap-web-79fdfc5c8b-wqx5z 1/1 Running 0 19s
그 후 하나의 Pod
을 골라 /etc/nginx/nginx.conf
에 ConfigMap
이 마운트 되었는지 확인해보자.
$ kubectl exec -it env-configmap-web-79fdfc5c8b-wqx5z -- cat /etc/nginx/nginx.conf
error_log /var/log/nginx/error.log warn;
pid /tmp/nginx.pid;
worker_rlimit_nofile 8192;
events {
worker_connections 4096; ## Default: 1024
}
http {
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$request_time"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
server {
listen 80;
location / {
proxy_pass http://env-configmap-was:8080;
}
}
}
잘 연결되었다면, Service
중 env-configmap-web
을 호출하면 upstream
설정을 통해서 env-configmap-was:8080
에게 전달되어서 다음 메세지가 보이게 될 것이다.
$ kubectl exec -it env-configmap-web-79fdfc5c8b-wqx5z -- curl env-configmap-web
Hello Kubernetes!
한 개의 Pod, 여러 개의 컨테이너
이전에 언급했듯이 한 개의 Pod
에 여러 컨테이너를 실행하게 할 수 있다. 권장되는 구조는 아니며 보통 해당 컨테이너의 리소스를 모니터링하기 위해서 이런 구조를 취한다.
이를 테면, NGINX
의 액세스 로그를 파싱하여 상태 코드, 응답 시간 등에 대한 지표를 제공해야 할 때가 있다. 이 때 nginx
컨테이너와 함께 액세스 로그를 저장할 볼륨과 이 볼륨을 파싱해서 메트릭을 노출시키는 prometheus-nginxlog-exporter
를 "SideCar" 형태로 제공하면 훌륭하게 이를 모니터링할 수 있다.
다음과 같이 one-pod-multi-container.yaml
을 생성한다.
src/ch11/k8s/one-pod-multi-container.yaml
apiVersion: v1
kind: Pod
metadata:
name: one-pod-multi-container
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- mountPath: /var/log/nginx/
name: accesslog
- name: prometheus-nginxlog-exporter
image: quay.io/martinhelmich/prometheus-nginxlog-exporter
ports:
- containerPort: 4040
protocol: TCP
volumeMounts:
- mountPath: /var/log/nginx/
name: accesslog
readOnly: true
- mountPath: /etc/prometheus-nginxlog-exporter.yml
name: exporter
subPath: prometheus-nginxlog-exporter.yaml
readOnly: true
command: ["/prometheus-nginxlog-exporter", "-config-file", "/etc/prometheus-nginxlog-exporter.yml"]
volumes:
- name: accesslog
emptyDir: {}
- name: exporter
configMap:
name: one-pod-multi-container
items:
- key: prometheus-nginxlog-exporter.yaml
path: prometheus-nginxlog-exporter.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: one-pod-multi-container
data:
prometheus-nginxlog-exporter.yaml: |
listen:
port: 4040
metrics_endpoint: "/metrics"
consul:
enable: false
namespaces:
- name: nginx
format: "$remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" \"$request_time\""
source:
files:
- /var/log/nginx/access.log
only_count: true
relabel_configs:
- target_label: request_uri
from: request
split: 2
separator: ' '
위에처럼 1개의 Pod
의 여러 개의 Container
를 설정할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: one-pod-multi-container
spec:
containers:
- name: nginx
# ...
- name: prometheus-nginxlog-exporter
# ...
nginx
는 accesslog
라는 볼륨과 prometheus-nginxlog-exporter
는 accesslog
, exporter
라는 볼륨과 연결된다. exporter
는 ConfigMap
과 연결된 설정 파일이다. 결과적으로 이 2개의 컨테이너는 accesslog
라는 볼륨을 공유하게 된다.
이제 다음 명령어를 이용하여 리소스를 생성해보자.
$ kubectl create -f one-pod-multi-container.yaml
pod/one-pod-multi-container created
configmap/one-pod-multi-container created
$ kubectl get pod
# READY가 2/2가 되야 실행이 된것이다.
NAME READY STATUS RESTARTS AGE
one-pod-multi-container 2/2 Running 0 16s
그 후 터미널에 다음을 입력해보자.
$ kubectl exec -it one-pod-multi-container -- curl localhost:4040/metrics
Defaulted container "nginx" out of: nginx, prometheus-nginxlog-exporter
# HELP nginx_parse_errors_total Total number of log file lines that could not be parsed
# TYPE nginx_parse_errors_total counter
nginx_parse_errors_total 0
원래 nginx
컨테이너는 4040번 포트에 아무것도 연결되지 않기 때문에 "connection refused" 에러가 떠야 정상이지만 현재 Pod
에는 prometheus-nginxlog-exporter
라는 컨테이너가 같이 실행되고 있으므로 에러는 뜨지 않는다. 현재 발생된 로그가 없기 때문에 메트릭은 수집된 것이 없다. 메트릭 수집을 위해 다음을 입력해보자.
$ for i in {1..5}; do kubectl exec -it one-pod-multi-container -- curl localhost; done
이렇게 하면 nginx
를 총 5번 호출하는 것과 같다. 먼저 볼륨에 로그 파일이 생성되었는지 확인해보자.
$ kubectl exec -it one-pod-multi-container -- cat /var/log/nginx/access.log
Defaulted container "nginx" out of: nginx, prometheus-nginxlog-exporter
::1 - - [16/Aug/2021:11:22:17 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
::1 - - [16/Aug/2021:11:22:17 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
::1 - - [16/Aug/2021:11:22:18 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
::1 - - [16/Aug/2021:11:22:18 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
::1 - - [16/Aug/2021:11:22:19 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
액세스 로그가 생성되었다. prometheus-nginxlog-exporter
가 이를 파싱해서 메트릭을 토축히키는지 확인해보자.
$ kubectl exec -it one-pod-multi-container -- curl localhost:4040/metrics
Defaulted container "nginx" out of: nginx, prometheus-nginxlog-exporter
# HELP nginx_http_response_count_total Amount of processed HTTP requests
# TYPE nginx_http_response_count_total counter
nginx_http_response_count_total{method="GET",request_uri="/",status="200"} 5
# HELP nginx_http_response_size_bytes Total amount of transferred bytes
# TYPE nginx_http_response_size_bytes counter
nginx_http_response_size_bytes{method="GET",request_uri="/",status="200"} 3060
# HELP nginx_parse_errors_total Total number of log file lines that could not be parsed
# TYPE nginx_parse_errors_total counter
nginx_parse_errors_total 0
이전과 다른 출력문을 확인할 수 있으며 nginx_http_response_count_total
가 5개 수집된 것을 알 수 있다.
초기 명령어 및 아규먼트 전달
Docker
에서 실행 시 초기 명령어 및 아규먼트 전달이 가능했다. 이미 지난 절을 진행하면서 Pod
에 command
를 주어 초기 명령어 실행을 전달하는 것을 확인할 수 있었다.
apiVersion: v1
kind: Pod
metadata:
name: one-pod-multi-container
spec:
containers:
- name: nginx
# ...
- name: prometheus-nginxlog-exporter
# ...
command: ["/prometheus-nginxlog-exporter", "-config-file", "/etc/prometheus-nginxlog-exporter.yml"]
위 prometheus-nginxlog-exporter
포드는 실행 시 다음 명령어가 실행된다.
$ /prometheus-nginxlog-exporter -config-file /etc/prometheus-nginxlog-exporter.yml
단순 명령어만 실행하는 것도 가능하지만 args
를 이용해 아규먼트 전달해서 명령어를 실행하는 것도 가능하다. command-args.yaml
을 다음과 같이 만들어보자.
src/ch11/k8s/command-args.yaml
apiVersion: v1
kind: Pod
metadata:
name: command-args
spec:
containers:
- name: command-args
image: debian
command: ["printenv"]
args: ["HOSTNAME", "KUBERNETES_PORT"]
restartPolicy: OnFailure
요령은 간단하다. spec.containers[*]
블록 밑에 command
와 args
를 정의해주면 된다. 위의 Pod
은 생성되면 다음 명령어를 실행한다고 보면 된다.
$ printenv HOSTNAME KUBERNETES_PORT
이제 리소스를 생성해보자.
$ kubectl create -f command-args.yaml
pod/command-args created
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
command-args 0/1 ContainerCreating 0 5s
command-args 0/1 Completed 0 7s
debian
이미지는 리눅스 그 자체이기 때문에 컨테이너를 유지시키는 명령어 없이는 Pod
가 유지되지 않는다. 계획대로면 단순히 명령어만 실행하고 종료되기 때문에 "Completed" 상태가 됐다면 컨테이너가 정상적으로 종료된 것으로 보면 된다. 이제 한 번 로그를 확인해보자.
$ kubectl logs command-args
command-args # HOSTNAME
tcp://10.24.0.1:443 # KUBERNETES_PORT
이런 비슷한 모양이 나왔다면 성공이다.
init 컨테이너
k8s
에서는 InitContainer
라는 특별한 목적을 지닌 컨테이너를 실행할 수 있다. 이 녀석은 Pod
의 앱 컨테이너들이 실행되기 전에 실행되는 특수한 컨테이너이며, 앱 이미지에는 없는 유틸리티 또는 설정 스크립트 등을 포함할 수 있다. 한 번 해보자. init-container.yaml
을 다음과 같이 만든다.
src/ch11/k8s/init-container.yaml
apiVersion: v1
kind: Service
metadata:
name: init-container
spec:
ports:
- port: 80
targetPort: 80
selector:
name: init-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: init-container
spec:
selector:
matchLabels:
name: init-container
replicas: 3
template:
metadata:
labels:
name: init-container
spec:
initContainers:
- name: init-container-busybox
image: busybox:1.28
command: [ 'sh', '-c', "until nslookup env-configmap-was; do echo waiting for env-configmap-was; sleep 2; done" ]
containers:
- name: init-container
image: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nginx
subPath: nginx.conf
mountPath: /etc/nginx/nginx.conf
readOnly: true
volumes:
- name: nginx
configMap:
name: init-container
items:
- key: nginx.conf
path: nginx.conf
---
apiVersion: v1
kind: ConfigMap
metadata:
name: init-container
data:
nginx.conf: |
error_log /var/log/nginx/error.log warn;
pid /tmp/nginx.pid;
worker_rlimit_nofile 8192;
events {
worker_connections 4096; ## Default: 1024
}
http {
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$request_time"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
server {
listen 80;
location / {
proxy_pass http://env-configmap-was:8080;
}
}
}
Init Container
는 Pod
의 spec.initContainers
에서 설정한다. 작성 요령은 spec.containers
와 동일하다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: init-container
spec:
# ReplicaSet
# POD
spec:
initContainers:
- name: init-container-busybox
image: busybox:1.28
command: [ 'sh', '-c', "until nslookup env-configmap-was; do echo waiting for env-configmap-was; sleep 2; done" ]
containers:
# ...
위 리소스는 env-configmap-web
이랑 동일한 리소스를 생성한다. 거기에 Init Container
를 이용하여 env-configmap-was
서비스가 실행되기 전까지 Pod
생성을 기다리는 부분을 추가했다. 이제 리소스를 생성해보자.
$ kubectl create -f init-container.yaml
service/init-container created
deployment.apps/init-container created
configmap/init-container created
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
init-container-6646dd9cc8-njpzk 0/1 Init:0/1 0 26s
init-container-6646dd9cc8-p4zmf 0/1 Init:0/1 0 26s
init-container-6646dd9cc8-s62f7 0/1 Init:0/1 0 26s
위 처럼 STATUS
가 "Init:0/1" 상태로 유지되는 것을 확인할 수 있다. env-configmap-was
라는 서비스가 존재하지 않기 때문이다.(매 2초마다 nslookup
명령어로 서비스를 찾는다.) 해당 서비스를 생성해보자.
$ kubectl create -f env-configmap-was.yaml
service/env-configmap-was created
deployment.apps/env-configmap-was created
configmap/env-configmap-was created
다시 한 번 Pod
의 상태를 확인한다.
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
...
# 상태가 "RUNNING"으로 변경됨
init-container-6646dd9cc8-njpzk 1/1 Running 0 89s
init-container-6646dd9cc8-p4zmf 1/1 Running 0 89s
init-container-6646dd9cc8-s62f7 1/1 Running 0 89s
이제 init-container
포드들이 실행되는 것을 확인할 수 있다.