쿠버네티스에서 디플로이먼트, 레플리카셋 등 오브젝트의 spec 변경시 자동으로 업데이트를 진행한다.
이는 쿠버네티스 컨트롤러가 클러스터의 상태를 지속적으로 확인 후 필요한 오브젝트를 생성 또는 변경한다.
각 오브젝트마다 컨트롤러가 존재하며 각 컨트롤러는 명시한 상태를 유지시키려고 노력한다.
디플로이먼트(Deployment) 또한 디플로이먼트 컨트롤러가 루프를 돌면서 명시된 상태를 유지한다.
예시
환경설정
kubectl autocomplete & kubectl alias k
1
2
3
4
source <(kubectl completion bash) # setup autocomplete in bash into the current shell, bash-completion package should be installed first.
echo "source <(kubectl completion bash)" >> ~/.bashrc # add autocomplete permanently to your bash shell.
alias k=kubectl
complete -F __start_kubectl k
이미지 변경 시
sync-nginx 디플로이먼트의 이미지를 nginx:1.18로 지정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ k create deployment my-nginx --image=nginx:1.18
deployment.apps/my-nginx created
$ k get pod,rs,deployment
NAME READY STATUS RESTARTS AGE
pod/my-nginx-dd78ddf67-qmhg6 1/1 Running 0 10m
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-nginx-dd78ddf67 1 1 1 10m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-nginx 1/1 1 1 10m
$ k describe pod | grep image
Normal Pulling 10m kubelet Pulling image "nginx:1.18"
Normal Pulled 10m kubelet Successfully pulled image "nginx:1.18" in 2.1321321s
sync-nginx 디플로이먼트의 이미지를 nginx:1.19로 변경
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ k set image deployment/my-nginx nginx=nginx:1.19
deployment.apps/my-nginx image updated
$ k get pod,rs,deployment
NAME READY STATUS RESTARTS AGE
pod/my-nginx-655998ff6d-5pqqw 1/1 Running 0 42s
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-nginx-655998ff6d 1 1 1 42s
replicaset.apps/my-nginx-dd78ddf67 0 0 0 14m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-nginx 1/1 1 1 14m
$ k describe pod | grep image
Normal Pulling 12m kubelet Pulling image "nginx:1.19"
Normal Pulled 12m kubelet Successfully pulled image "nginx:1.19" in 2.8686335s
위와같이 새로운 ReplicaSet이 생기면서 pod 새로 생성되었다.
리로더(Reloader)
디플로이먼트에서 참조하고있는 컨피그맵 변경시 컨테이너 내부에서 값은 변경돼있으나 보통 프로세스는 설정파일의 적용을 위해 재시작 해줘야한다.
일반적인 시스템에서 프로세스의 재시작은 큰문제가 없으나 컨테이너 환경에서는 지정된 프로세스가 죽게되면 컨테이너는 종료된다.
컨피그맵 변경시 값은 바뀌어 있으나 프로세스가 해당 파일을 적용시키지 못하는 문제가 발생한다.
이러한 문제를 Stacker/Reloader를(이하 리로더) 사용하여 해결할 수 있다.
리로더는 Stacker에서 만든 오픈소스로 커스텀 컨트롤러역할을 하며 컨피그맵, 시크릿 값변경시 디플로이먼트를 롤링업데이트 시켜준다.
요구사항
- kubernetes ≥ 1.19은 조치없이 바로 사용가능
환경설정
kubectl autocomplete & kubectl alias k
1
2
3
4
source <(kubectl completion bash) # setup autocomplete in bash into the current shell, bash-completion package should be installed first.
echo "source <(kubectl completion bash)" >> ~/.bashrc # add autocomplete permanently to your bash shell.
alias k=kubectl
complete -F __start_kubectl k
설치
1
k apply -k https://github.com/stakater/Reloader/deployments/kubernetes
검증
1
2
3
$ k get pod
NAME READY STATUS RESTARTS AGE
reloader-reloader-6c887d48d-pw4nz 1/1 Running 0 10m
Pod Running 중인지 확인
사용법
컨피그맵이나 시크릿을 사용하는 디플로이에 .metadata.annotations 에 값 추가
어노테이션 종류 (a | b).example은 a.exaple OR b.example 둘중 한개
- reloader.stakater.com/auto: "true" : 디플로이먼트의 컨피그맵, 시크릿 변경시 자동으로 롤아웃
- reloader.stakater.com/search: "true" : 디플로이먼트의 컨피그맵, 시크릿 중 reloader.stakater.com/match: "true" 어노테이션을 가진 오브젝트 변경시 롤아웃
- (configmap | secret).reloader.stakater.com/reload: "foo" : foo라는 이름을 가진 컨피그맵 또는 시크릿 변경시 롤아웃
예시
아래 명령어를 사용하여 ConfigMap을 읽어서 값을 출력하는 두개의 디플로이먼트가 있다.
no-reloader는 리로더의 어노테이션을 사용하지 않고 use-reloader는 어노테이션을 지정해줬다.
이름과 어노테이션을 제외하고는 동일한 디플로이먼트이다.
배포
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
k apply -f - <<EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: no-reloder
name: no-reloder
spec:
replicas: 1
selector:
matchLabels:
app: no-reloder
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: no-reloder
spec:
containers:
- command: ["/bin/sh","-c"]
args: ['cat /var/config.yaml >> /tmp/text.yaml && watch cat /tmp/text.yaml']
image: busybox
name: busybox
resources: {}
volumeMounts:
- name: config
mountPath: /var
volumes:
- name: config
configMap:
name: config
items:
- key: config.yaml
path: config.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
annotations:
reloader.stakater.com/auto: "true"
labels:
app: use-reloder
name: use-reloder
spec:
replicas: 1
selector:
matchLabels:
app: use-reloder
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: use-reloder
spec:
containers:
- command: ["/bin/sh","-c"]
args: ['cat /var/config.yaml >> /tmp/text.yaml && watch cat /tmp/text.yaml']
image: busybox
name: busybox
resources: {}
volumeMounts:
- name: config
mountPath: /var
volumes:
- name: config
configMap:
name: config
items:
- key: config.yaml
path: config.yaml
---
kind: ConfigMap
apiVersion: v1
metadata:
name: config
data:
config.yaml: |
value: A
---
EOF
팟의 출력확인(이때 팟의 이름은 노드마다 다름)
1
2
3
4
5
6
7
8
9
10
11
12
$ k get pod
NAME READY STATUS RESTARTS AGE
no-reloder-8c54d96ff-d9csv 1/1 Running 0 3m40s
use-reloder-55b4545b4c-wvvrz 1/1 Running 0 3m40s
$ k logs use-reloder-55b4545b4c-wvvrz
Every 2.0s: cat /var/config.yaml 2020-12-29 20:11:33
value: A
$ k logs no-reloder-8c54d96ff-d9csv
Every 2.0s: cat /var/config.yaml 2020-12-29 20:13:44
value: A
위와같이 모두 컨피그맵에 적혀있는 value: A를 출력하고있다.
컨피그맵 변경 테스트
컨피그맵 값 변경
1
2
3
4
5
6
7
8
9
k apply -f - <<EOF
kind: ConfigMap
apiVersion: v1
metadata:
name: config
data:
config.yaml: |
value: B
EOF
팟을 조회하니 use-reloader의 팟이 롤링 업데이트 진행중임을 알 수있다. 잠시 시간이 흐르면 위의 wvvrz팟을 사라지고 d58tq만 남게된다.
1
2
3
4
5
6
7
8
9
10
$ k get pod
NAME READY STATUS RESTARTS AGE
no-reloder-8c54d96ff-d9csv 1/1 Running 0 16m
use-reloder-55b4545b4c-wvvrz 1/1 Running 0 16m
use-reloder-745b4c6cc-d58tq 0/1 ContainerCreating 0 2s
##수십초뒤
$ k get pod
NAME READY STATUS RESTARTS AGE
no-reloder-8c54d96ff-d9csv 1/1 Running 0 20m
use-reloder-745b4c6cc-d58tq 1/1 Running 0 3m15s
출력 조회
1
2
3
4
5
6
7
8
9
10
$ k logs no-reloder-8c54d96ff-d9csv
Every 2.0s: cat /tmp/text.yaml 2020-12-29 20:53:03
value: A
$ k logs use-reloder-745b4c6cc-d58tq
Every 2.0s: cat /tmp/text.yaml 2020-12-29 20:54:50
value: B
어노테이션을 사용한 디플로이먼트만 값이 변경되었음을 알 수 있다.