쿠버네티스를 이용한 서비스 운용
제공된 실습파일을 사용하여 서비스 운용해보기
1. 디렉토리 안에 해당 파일들 넣어두기
requirement.txt
app.py
deployment.yaml
service.yaml
Dockerfile
site.conf
start.sh
2. Flask 응용 실행에 필요한 패키지를 지정
1
2
3
| cat requirement.txt
Flask
|
3. niginx 웹 서버를 이용하여 우리가 만든 flask 응용 실행
1
2
3
4
5
6
7
8
9
10
| cat site.conf
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/access.log main;
location / {
proxy_pass http://127.0.0.1:5000;
}
}
|
4. 컨테이너가 생성될 때 웹 서버(nginx)와 flask 응용을 구동하기 위한 셸 스크립트 실행
1
2
3
4
| cat start.sh
service nginx start
/flaskapp/venv/bin/flask --app app run --host 0.0.0.0
|
5. 제공된 도커파일을 사용하여 도커 빌드하기
1
2
3
4
5
6
7
8
9
| docker build -t hostname:latest .
[+] Building 140.2s (19/19) FINISHED docker:default
=> [internal] load build definition from Dockerfile ...
=> => writing image sha256:d6397a4a68f9d81eb7747d0fc11cb3503b133c10b34be53baad99f7b8a839c7b 0.0s
=> => naming to docker.io/library/hostname:latest 0.0s
What's Next?
View a summary of image vulnerabilities and recommendations → docker scout quickview
|
6. 도커 이미지를 가져다가 컨테이너 만들기
1
2
3
4
5
6
7
| docker tag hostname:latest hyeem66/hostname:latest
docker push hyeem66/hostname:latest
The push refers to repository [docker.io/hyeem66/hostname]
8b9e5cc45d59: Preparing
....
latest: digest: sha256:e64 size: 4490
|
a 만약 denied가 되었다면 docker login
명령어를 사용해서 docker hub에 로그인을 하고, 다시 명령어를 입력하면 제대로 push된다.
7. 매니페스트 사용해서 delpoyment 만들기
1
| kubectl apply -f deployment.yaml
|
1
2
3
4
5
| kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dpy-hname-77db446c5-hlbzl 1/1 Running 0 40s 10.1.0.20 docker-desktop <none> <none>
dpy-hname-77db446c5-j8ghr 1/1 Running 0 40s 10.1.0.18 docker-desktop <none> <none>
dpy-hname-77db446c5-xjp56 1/1 Running 0 40s 10.1.0.19 docker-desktop <none> <none>
|
8. 매니페스트를 사용하여 service 만들기
1
2
3
| kubectl apply -f service.yaml
service/svc-hname created
|
1
2
3
4
5
| kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
svc-hname NodePort 10.110.98.191 <none> 80:30000/TCP 8s
|
9. localhost:30000 포트에 요청보내고 응답 받기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-xjp56</p><p>IPv4 Address: 10.1.0.19</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-hlbzl</p><p>IPv4 Address: 10.1.0.20</p>
|
매번 동일한 포트에서 실행되지 않음
10. 요청을 반복하는 스크립트 만들기
1
2
3
4
5
6
7
| i=1
while true
do
sleep 1
echo $((i++)) `curl --silent --connect-timeout 0.1 localhost:30000`
done
|
1
2
3
4
5
6
| $i=0
while($true){
% { $i++; write-host -NoNewline "$i $_" }
(Invoke-RestMethod "http://localhost:30000")-replace '\n', " "
Start-Sleep -Seconds 1
}
|
11. deployment.yaml 파일을 수정하여 레플리카셋의 크기를 1로 수정하기
1
2
3
| kubectl apply -f deployment.yaml
deployment.apps/dpy-hname configured
|
1
2
3
4
5
6
| kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dpy-hname-77db446c5-hlbzl 1/1 Terminating 0 20m 10.1.0.20 docker-desktop <none> <none>
dpy-hname-77db446c5-j8ghr 1/1 Running 0 20m 10.1.0.18 docker-desktop <none> <none>
dpy-hname-77db446c5-xjp56 1/1 Terminating 0 20m 10.1.0.19 docker-desktop <none> <none>
|
- 같은 포트에서만 응답이 오는 것을 확인할 수 있음
1
2
3
4
5
6
7
8
9
10
11
| curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-j8ghr</p><p>IPv4 Address: 10.1.0.18</p>
|
12. pod를 삭제하고 localhost:30000
에 다시 요청해보기
1
2
3
4
5
| kubectl delete pod dpy-hname-77db446c5-j8ghr
pod "dpy-hname-77db446c5-j8ghr" deleted
|
이전과 다른 포트에서 응답이 오는 것을 확인할 수 있음
1
2
3
4
5
| curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-8twbq</p><p>IPv4 Address: 10.1.0.21</p>
curl localhost:30000
<p>Hostname: dpy-hname-77db446c5-8twbq</p><p>IPv4 Address: 10.1.0.21</p>
|
결과
deployment에 의하여 포드들이 배포된 상태에서 이 중 하나의 포드가 사멸하면, 쿠버네티스는 새로운 포드를 생성하고 같은 종류의 컨테이너를 실행함
- 포드가 사멸하면 쿠버네티스는 새로운 포드를 생성함으로써 디플로이먼트에 선언된 “의도된 상태”를 유지하려고 함
- 클러스터 외부에는 별도의 서비스에 의하여 노출되므로 개별 포드의 클러스터 내 IP주소 등에 대해서는 사용자가 관리할 필요 없음
- 포드는 언제든지 죽을 수 있는 오브젝트이므로 컨테이너 기반한 응용을 개발함에 있어 상태를 띠지 않는(stateless) 방식으로 만들어야 함