Post

데브코스 TIL - 쿠버네티스를 이용한 서비스 운용

쿠버네티스를 이용한 서비스 운용

제공된 실습파일을 사용하여 서비스 운용해보기

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


  • localhost:30000에 다시 요청

이전과 다른 포트에서 응답이 오는 것을 확인할 수 있음

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) 방식으로 만들어야 함
This post is licensed under CC BY 4.0 by the author.