본문 바로가기
Kubernetes

K8s from scratch - 3. 파드 생성 및 삭제, Self-Healing

by Hyeon Cloud 2023. 10. 25.

파드를 생성하는 방법

이번 포스트부터, kubectl 을 k로 지정한 alias를 사용하겠습니다. 또한 명령어의 단축어를 사용하도록하겠습니다. 예를들어, po는 pods의 단축어입니다.

 

kubectl run명령을 사용하면 쉽게 파드를 생성할 수 있습니다. 다음 명령에서 run 다음에 나오는 nginx는 파드의 이름이고, —image=nginx는 생성할 이미지 이름입니다.

ubuntu@master001:~$ k run nginx-pod --image=nginx
pod/nginx-pod created
ubuntu@master001:~$ k get po
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          2s
ubuntu@master001:~$

 

create 기능을 사용하여 동일하게 파드를 생성 할 수 있습니다. 대신 deployment를 추가하여 실행해야합니다.

ubuntu@master001:~$ k create nginx --image=nginx
error: unknown flag: --image
See 'kubectl create --help' for usage.
ubuntu@master001:~$ k create deployment deployment-nginx --image=nginx
deployment.apps/deployment-nginx created
ubuntu@master001:~$ k get po
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-75b9c76897-cs96q   1/1     Running   0          4s
nginx-pod                           1/1     Running   0          2m8s
ubuntu@master001:~$

 

생성한 파드 둘다 동일한 nginx 웹서버를 출력하는것을 확인할 수 있습니다.

ubuntu@master001:~$ k get po -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP          NODE       NOMINATED NODE   READINESS GATES
deployment-nginx-75b9c76897-cs96q   1/1     Running   0          2m26s   10.36.0.1   slave002   <none>           <none>
nginx-pod                           1/1     Running   0          4m30s   10.44.0.1   slave001   <none>           <none>
ubuntu@master001:~$ curl 10.36.0.1 | tail
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   300k      0 --:--:-- --:--:-- --:--:--  600k
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
ubuntu@master001:~$ curl 10.44.0.1 | tail
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   300k      0 --:--:-- --:--:-- --:--:--  300k
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
ubuntu@master001:~$

 

run으로 파드를 생성하면 단일파드 1개만 생성되고 관리됩니다. create deployment로 파드를 생성하면 Deployment라는 관리그룹 내에서 파드가 생성됩니다.

오브젝트란?

파드와 디플로이먼트는 스펙과 상태등의 값을 가지고있습니다. 이러한 값을 가지고있는 파드와 디플로이먼트 개별속성을 포함해 부르는 단위를 오브젝트라고 합니다.

  • 파드
    • 쿠버네티스에서 실행되는 최소단위, 서비스를 구동하는데 필요한 최소단위
    • 독립적인 공간과 사용가능한 IP를 가지고있음
    • 하나의 파드는 1개이상의 컨테이너를 가지며 여러기능을 묶어 하나의 목적으로 사용할 수도 있음
    • 범용으로는 1개파드에 1개의 컨테이너를 적용함
  • 네임스페이스
    • 클러스터에서 사용되는 리소스들을 구분해 관리하는 그룹
    • 기본으로 할당되는 네임스페이스로는 default, 쿠버네티스 시스템에서 사용되는 kube-system, 온프렘에서 사용하는 경우 외부에서 접속하기위한 metallb-systemem등이 존재합니다.
  • 볼륨
    • 파드가 생성될때 파드에서 사용할 수 있는 디렉토리를 제공
    • 파드는 영속되는 개념이 아니기때문에 제공되는 디렉토리도 임시로 사용
    • 파드가 사라지더라도 저장과 보존이 가능한 볼륨 오브젝트를 통해 생성하고 사용 할 수 있음.
  • 서비스
    • 파드는 클러스터 내에서 유동적이기때문에 접속 정보가 고정일 수 없음
    • 파드 접속을 안정적으로 유지하도록 서비스를 통해 내/외부로 연결됨
    • 서비스는 새롭게 파드
    • 기존 인프라에서 로드밸런서, 게이트웨이와 비슷한 역할을 함

  • 디플로이먼트
    • 기본오브젝트만으로 쿠버네티스를 사용할 수 있지만 한계가 있기때문에 효율적으로 작동하도록 기능을 조합하고 추가해 구현한것이 디플로이먼트입니다.
    • 데몬셋, 컨피그맵, 레플리카셋, PV, PVC, 스테이트풀셋 등이 있습니다.
    • 레플리카셋은 레플리케이션 컨트롤러가 발전한 형태입니다.

레플리카셋으로 파드수 관리하기

많은 사용자를 대상으로 웹서비스를 하려면 다수의 파드가 필요한데, 쿠버네티스에서는 다수의 파드를 만드는 레플리카셋 오브젝트를 제공합니다. 하지만 레플리카셋은 파드수를 보장하는 기능만 제공하기때문에 롤링업데이트 기능이 추가된 디플로이먼트를 추가하여 파드 수를 관리하기를 권장합니다.

현재 파드 상태를 확인하고 nignx-pod에 대해, replicas 를 수정하여 scale-out 해보도록 하겠습니다.

ubuntu@master001:~$ k get po
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-75b9c76897-cs96q   1/1     Running   0          40m
nginx-pod                           1/1     Running   0          42m
ubuntu@master001:~$ k scale pod nginx-pod --replicas=3
Error from server (NotFound): the server could not find the requested resource
ubuntu@master001:~$

 

리소스를 찾을 수 없다고합니다. nginx-pod는 create deployment 명령어가 아닌 run명령어로 생성되었고, 디플로이먼트 오브젝트에 속하지 않기때문입니다.

이번에는 디플로이먼트로 생성된 deployment-nginx에 적용해보도록 하겠습니다.

ubuntu@master001:~$ k scale deployment deployment-nginx --replicas=3
deployment.apps/deployment-nginx scaled
ubuntu@master001:~$ k get po
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-75b9c76897-2d2dk   1/1     Running   0          3s
deployment-nginx-75b9c76897-cs96q   1/1     Running   0          43m
deployment-nginx-75b9c76897-drpj4   1/1     Running   0          3s
nginx-pod                           1/1     Running   0          45m
ubuntu@master001:~$

 

정상적으로 스케일 아웃이 된 것을 확인할 수 있습니다. delete명령으로 디플로이먼트를 삭제합니다. 삭제하게되면, 스케일아웃되었던 파드 3개가 모두 삭제됩니다.

ubuntu@master001:~$ k delete deployments.apps deployment-nginx
deployment.apps "deployment-nginx" deleted
ubuntu@master001:~$ k get po
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          46m
ubuntu@master001:~$

스펙을 지정해 오브젝트 생성하기

스펙을 지정하여 오브젝트를 생성하려면, 필요한 내용을 파일로 작성해야합니다. 이때 작성하는 파일을 오브젝트 스펙이라고 합니다. 일반적으로 yaml문법으로 작성합니다.

3개의 nginx 파드를 디플로이먼트 오브젝트로 만들어보겠습니다.

  • METADATA
    • 디플로이먼트이름
      • echo-hname
    • 디플로이먼트 레이블
      • nginx
  • SPEC
    • 레플리카 셋을 몇개 생성할지 결정
      • replicas: 1
    • 셀렉터의 레이블 지정
    • 템플릿의 레이블 지정
    • 템플릿에서 사용할 컨테이너 이미지 지정
ubuntu@master001:~$ vi echo-hname.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-hname
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: echo-hname
        image: sysnet4admin/echo-hname

 

생성한 파일을 사용하여 디플로이먼트를 생성해보겠습니다.

ubuntu@master001:~$ k create -f echo-hname.yaml
deployment.apps/echo-hname created
ubuntu@master001:~$ k get po
NAME                          READY   STATUS              RESTARTS   AGE
echo-hname-5746bc5cb9-579jz   0/1     ContainerCreating   0          3s
echo-hname-5746bc5cb9-ddl6s   0/1     ContainerCreating   0          3s
echo-hname-5746bc5cb9-fdt2j   0/1     ContainerCreating   0          3s
nginx-pod                     1/1     Running             0          60m
ubuntu@master001:~$ k get po
NAME                          READY   STATUS    RESTARTS   AGE
echo-hname-5746bc5cb9-579jz   1/1     Running   0          11s
echo-hname-5746bc5cb9-ddl6s   1/1     Running   0          11s
echo-hname-5746bc5cb9-fdt2j   1/1     Running   0          11s
nginx-pod                     1/1     Running   0          61m
ubuntu@master001:~$

디플로이먼트가 정상적으로 생성되었고, 파드가 3개인것을 확인 할 수 있습니다.

 

이번에는 yaml파일을 수정하여 파드를 늘려보도록 하겠습니다. vi를 사용하여 편집할 수 있지만, sed명령을 사용하여 수정 해보도록 하겠습니다.

image: sysnet4admin/echo-hname
ubuntu@master001:~$ sed -i 's/replicas: 3/replicas: 6/' echo-hname.yaml
ubuntu@master001:~$ cat echo-hname.yaml | grep replicas
  replicas: 6
ubuntu@master001:~$

 

변경 내용을 적용해보도록 하겠습니다.

ubuntu@master001:~$ k create -f echo-hname.yaml
Error from server (AlreadyExists): error when creating "echo-hname.yaml": deployments.apps "echo-hname" already exists
ubuntu@master001:~$

이미 존재하는 디플로이이기때문에 에러메세지가 발생합니다.

apply를 사용하여 오브젝트 생성하고 관리하기

create로 디플로이먼트를 생성하면 앞에서 확인한 것 처럼 파일의 변경사항을 바로 적용할 수 없다는 단점이 있습니다. 이런경우 apply 명령어를 사용하여 변경사항을 적용할 수 있습니다.

 

replicas를 수정한 yaml 파일을 apply 명령으로 적용합니다.

ubuntu@master001:~$ k apply -f echo-hname.yaml
Warning: resource deployments/echo-hname is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
deployment.apps/echo-hname configured
ubuntu@master001:~$

 

오브젝트를 처음부터 apply로 생성한것이 아니기때문에 경고가 뜨지만 현재는 무시하도록 하겠습니다. 이처럼 오브젝트를 생성시에는 apply로 생성하는것이 좋습니다.

 

파드갯수가 증가했는지 확인해봅시다

ubuntu@master001:~$ k get po
NAME                          READY   STATUS    RESTARTS   AGE
echo-hname-5746bc5cb9-579jz   1/1     Running   0          167m
echo-hname-5746bc5cb9-btdfk   1/1     Running   0          3m5s
echo-hname-5746bc5cb9-ddl6s   1/1     Running   0          167m
echo-hname-5746bc5cb9-f7z6d   1/1     Running   0          3m5s
echo-hname-5746bc5cb9-fdt2j   1/1     Running   0          167m
echo-hname-5746bc5cb9-ltrzz   1/1     Running   0          3m5s
nginx-pod                     1/1     Running   0          3h48m
ubuntu@master001:~$

 

명령어를 정리해보면 다음과 같습니다.

구분 run create apply
명령실행 제한적 가능함 안됨
파일실행 안됨 가능함 가능함
변경가능 안됨 안됨 가능함
실행편의 매우좋음 매우좋음 좋음
기능유지 제한적 지원함 다양하게 지원함

파드의 컨테이너 자동 복구 방법 (Self-Healing)

쿠버네티스는 모든 부분이 자동복구 되도록 설계되어있습니다. 파드의 자동 복구기술은 Self-Healing이라고 불리는데, 제대로 동작하지 않는 컨테이너를 다시 실행하거나 교체하여 파드가 정상적으로 작동하게 합니다.

 

파드의 ip를 확인합니다.

ubuntu@master001:~$ k get po -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP          NODE       NOMINATED NODE   READINESS GATES
echo-hname-5746bc5cb9-579jz   1/1     Running   0          3h11m   10.36.0.2   slave002   <none>           <none>
echo-hname-5746bc5cb9-btdfk   1/1     Running   0          26m     10.44.0.3   slave001   <none>           <none>
echo-hname-5746bc5cb9-ddl6s   1/1     Running   0          3h11m   10.44.0.2   slave001   <none>           <none>
echo-hname-5746bc5cb9-f7z6d   1/1     Running   0          26m     10.44.0.4   slave001   <none>           <none>
echo-hname-5746bc5cb9-fdt2j   1/1     Running   0          3h11m   10.36.0.1   slave002   <none>           <none>
echo-hname-5746bc5cb9-ltrzz   1/1     Running   0          26m     10.36.0.3   slave002   <none>           <none>
nginx-pod                     1/1     Running   0          4h12m   10.44.0.1   slave001   <none>           <none>
ubuntu@master001:~$

 

kubectl exec 명령을 사용하여 파드 컨테이너의 쉘에 접속합니다. /bin/bash를 실행하면 접속할 수 있습니다.

ubuntu@master001:~$ k exec -it nginx-pod -- /bin/bash
root@nginx-pod:/#

 

쉘에 접속하면 nginx의 PID(Process ID)를 확인합니다. nginx의 PID는 항상 1 입니다.

root@nginx-pod:/# cat /run/nginx.pid
1
root@nginx-pod:/#

 

ls -l 명령으로 생성된 시간을 확인합니다.

root@nginx-pod:/# ls -l /run/nginx.pid
-rw-r--r-- 1 root root 2 Aug 14 01:19 /run/nginx.pid
root@nginx-pod:/#

 

터미널을 하나 더 띄우고 마스터노드에서 nginx-pod의 ip에서 돌아가는 웹페이지를 1초마다 요청하는 스크립트를 실행합니다. 이 스크립트로 상태를 체크하도록 하겠습니다.

ubuntu@master001:~$ k get po -o wide | grep nginx-pod
nginx-pod                     1/1     Running   0          4h19m   10.44.0.1   slave001   <none>           <none>
ubuntu@master001:~$ i=1; while true; do sleep 1; echo $((i++)) `curl --silent 10.44.0.1 | grep title` ; done
1 <title>Welcome to nginx!</title>
2 <title>Welcome to nginx!</title>
3 <title>Welcome to nginx!</title>
4 <title>Welcome to nginx!</title>

 

배시쉘에서 nginx PID인 1번을 kill하여 종료합니다.

root@nginx-pod:/# kill 1
root@nginx-pod:/# command terminated with exit code 137
ubuntu@master001:~$

 

kill명령에 의해 가져오지 못하다가 새롭게 self-healing된 파드에 의해 다시 출력됨을 확인할 수 있습니다.

27 <title>Welcome to nginx!</title>
28 <title>Welcome to nginx!</title>
29 <title>Welcome to nginx!</title>
30 <title>Welcome to nginx!</title>
31 <title>Welcome to nginx!</title>
32
33
34 <title>Welcome to nginx!</title>
35 <title>Welcome to nginx!</title>
36 <title>Welcome to nginx!</title>

 

앞에서 echo-hname에 속한 파드를 replicas에서 6개로 선언하였습니다. replicas 는 파드를 선언한 수대로 유지하도록 항상 파드의 수를 확인하고 부족하면 새로운 파드를 만들어냅니다.

디플로이먼트에 속한 파드는 상위 디플로이먼트를 삭제해야 파드가 삭제됩니다.

ubuntu@master001:~$ k delete deployment echo-hname
deployment.apps "echo-hname" deleted
ubuntu@master001:~$ k get po
NAME        READY   STATUS    RESTARTS      AGE
nginx-pod   1/1     Running   1 (39m ago)   5h
ubuntu@master001:~$