✔️ Wordload - Pod
파드 : 컨테이너의 모음
k8s가 관리할 수 있는 가장 작은 워크로드는 Pod이다.
k8s은 컨테이너를 직접 컨트롤하지 않는다.
✔️ 파드 생성 및 관리
vagrant@k8s-node1:~$ kubectl run myweb --image httpd
pod/myweb created
vagrant@k8s-node1:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myweb 1/1 Running 0 19s
Docker Hub의 httpd 이미지를 myweb이라는 Pod로 생성한다.
READY 1/1 - 준비된 컨테이너의 개수 / 컨테이너의 총 개수
현재 Pod에 하나의 컨테이너만 있는 것이며 해당 컨테이너는 httpd 이미지로 생성되어 작동 중이다.
재시작 횟수는 없으며 지금으로부터 19초 전에 생성되었다.
vagrant@k8s-node1:~$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myweb 1/1 Running 0 2m48s 10.233.92.1 node3 <none> <none>
-o wide
옵션을 통해 상세한 정보를 볼 수 있다.
Pod의 IP, Pod는 어떤 노드에 배치되었는지를 추가로 볼 수 있다.
vagrant@k8s-node1:~$ kubectl get pods -o yaml
vagrant@k8s-node1:~$ kubectl get pods -o json
k8s의 모든 정보는 etcd
에 저장되어 있다.
etcd에 저장되어 있는 Raw Data를 가져온 것이다.
kubectl run 명령어로 만든 리소스는 ectd에 저장되며 그 Raw Data를 보는 것이다.
yaml 또는 json 형식으로 볼 수 있다.
kubectl describe pods myweb
상세 정보를 깔끔한 형태로 출력한다.
vagrant@k8s-node1:~$ kubectl describe pods myweb
Name: myweb
Namespace: default
Priority: 0
Node: node3/192.168.100.102
Start Time: Tue, 17 May 2022 01:37:26 +0000
Labels: run=myweb
Annotations: cni.projectcalico.org/containerID: 5c8c836976f5199ef7c8d37ecd4b86f28eb31766a640774ecfa02df335964fcf
cni.projectcalico.org/podIP: 10.233.92.1/32
cni.projectcalico.org/podIPs: 10.233.92.1/32
Status: Running
IP: 10.233.92.1
IPs:
IP: 10.233.92.1
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m58s default-scheduler Successfully assigned default/myweb to node3
Normal Pulling 6m58s kubelet Pulling image "httpd"
Normal Pulled 6m45s kubelet Successfully pulled image "httpd" in 12.446583157s
Normal Created 6m43s kubelet Created container myweb
Normal Started 6m43s kubelet Started container myweb
Describe에서 확인해야 하는 중요 정보는 Events이다.
Events는 Describe에서만 확인할 수 있는 정보이다.
✔️ Events란 ?
Events는 myweb 파드라는 리소스의 LifeCycle
에 관한 정보이다.
Events는 log라고도 할 수 있는데, myweb의 App의 로그가 아니라
이 리소스를 만들기 위해서 k8s에서 해당 리소스가 언제 만들어졌는지 무엇이 변경되었는지를 기록한 리소스 자체에 대한 이벤트 로그이다.
시간 순서로 출력되며 가장 위에 있는 것이 가장 오래된 것이다.
이벤트를 자세히 살펴보자.
- type은 normal
- 이 이벤트가 발생한 이유는 스케줄링 되었기 때문이다.
- 누구로부터 이 이벤트가 발생했는가 ? default-scheduler에 의해서 발생되었다.
- kubelet으로부터 발생한 메세지는 해당 파드가 node3에 할당되었다는 것이다.
해당 정보를 통해 알 수 있는 것은 Pod를 만들기 위해서는
- Scheduling이 필요하다.
- kubelet은 node1, 2, 3 중에 어디의 kubelet일까 ? 스케줄링을 node3에게 하라고 했으므로 node3의 kubelet이다.
- kubelet이 httpd 이미지를 pulling 한다.
- httpd 이미지가 pulled 완료됨 (
12.446583157s
소요) - kubelet으로부터 메세지가 발생했다.
- kubelet이 myweb이라는 컨테이너를 create
- myweb이라고 하는 컨테이너를 start
파드가 제대로 작동하지 않을 때 확인해봐야할 것
- 파드 리소스 자체가 정상적으로 생성되었는지
- 컨테이너 내의 어플리케이션에 문제가 있는지 -> App의 log를 봐야한다.
vagrant@k8s-node1:~$ kubectl logs myweb
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.233.92.1. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.233.92.1. Set the 'ServerName' directive globally to suppress this message
[Tue May 17 01:37:41.120820 2022] [mpm_event:notice] [pid 1:tid 140046997339456] AH00489: Apache/2.4.53 (Unix) configured -- resuming normal operations
[Tue May 17 01:37:41.120908 2022] [core:notice] [pid 1:tid 140046997339456] AH00094: Command line: 'httpd -D FOREGROUND'
로그를 볼 수 있는 것은 파드밖에 없다. 따라서 별도로 pods 지정어를 지정하지 않는다.
vagrant@k8s-node1:~$ kubectl run myubuntu --image ubuntu:focal
pod/myubuntu created
vagrant@k8s-node1:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myubuntu 0/1 CrashLoopBackOff 2 (27s ago) 53s
myweb 1/1 Running 0 20m
vagrant@k8s-node1:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myubuntu 0/1 Completed 3 (32s ago) 58s
myweb 1/1 Running 0 20m
vagrant@k8s-node1:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myubuntu 0/1 CrashLoopBackOff 3 (19s ago) 74s
myweb 1/1 Running 0 20m
기본적으로 Pod는 종료되지 않는 App을 실행하는 것이 원칙이다.
위의 상태는 컨테이너가 종료되어 CrashLoopBackOff
상태가 된다.
k8s는 기본적으로 detach
모드로 실행하는 것을 원칙으로 한다.-it
옵션은 관리, 디버깅, 이미지를 만드는 중간 단계에서 사용하는 옵션이다.-it
옵션으로 서비스를 실행하려고 하는 것은 아니다.
vagrant@k8s-node1:~$ kubectl run myubuntu2 --image ubuntu:focal -it bash
If you don't see a command prompt, try pressing enter.
root@myubuntu2:/# exit
exit
Session ended, resume using 'kubectl attach myubuntu2 -c myubuntu2 -i -t' command when the pod is running
vagrant@k8s-node1:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myubuntu 0/1 CrashLoopBackOff 5 (59s ago) 3m59s
myubuntu2 1/1 Running 1 (5s ago) 21s
myweb 1/1 Running 0 23m
vagrant@k8s-node1:~$ kubectl delete pods myubuntu myubuntu2
pod "myubuntu" deleted
pod "myubuntu2" deleted
✔️ YAML 파일로 파드 정의
apiversion:
kind:
metadata:
spec:
일반적으로 다음 구성으로 YAML 파일을 정의한다.
kubectl create -f myweb.pod
pod를 생성한다.
kubectl get -f myweb.yaml
myweb의 상태를 확인한다.
kubectl describe -f myweb.yaml
myweb의 자세한 정보를 확인한다.
kubectl delete -f myweb.yaml
myweb을 삭제한다.
kubectl get pods myweb
myweb의 상태를 확인한다.
vagrant@k8s-node1:~$ mkdir pod
vagrant@k8s-node1:~$ cd pod
vagrant@k8s-node1:~/pod$ vi myweb.pod
vagrant@k8s-node1:~/pod$ cat myweb.pod
apiVersion: v1
kind: Pod # kubectl api-resources
metadata:
name: myweb
spec:
containers:
- name: myweb
image: httpd
vagrant@k8s-node1:~/pod$ kubectl create -f myweb.pod
pod/myweb created
vagrant@k8s-node1:~/pod$ kubectl get pods
vagrant@k8s-node1:~/pod$ kubectl get pods -o yaml
vagrant@k8s-node1:~/pod$ kubectl describe pods myweb
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 87s default-scheduler Successfully assigned default/myweb to node3
Normal Pulling 87s kubelet Pulling image "httpd"
Normal Pulled 86s kubelet Successfully pulled image "httpd" in 1.771981965s
Normal Created 85s kubelet Created container myweb
Normal Started 85s kubelet Started container myweb
node3에 배치되었다.1.771981965s
은 아주 짧은 시간이다. 로컬에 존재하기 때문에 이미지를 받지 았음을 의미한다.
vagrant@k8s-node1:~/pod$ kubectl logs myweb
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.233.92.5. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.233.92.5. Set the 'ServerName' directive globally to suppress this message
[Tue May 17 07:07:57.003426 2022] [mpm_event:notice] [pid 1:tid 140447789903168] AH00489: Apache/2.4.53 (Unix) configured -- resuming normal operations
[Tue May 17 07:07:57.004487 2022] [core:notice] [pid 1:tid 140447789903168] AH00094: Command line: 'httpd -D FOREGROUND'
vagrant@k8s-node1:~/pod$ mv myweb.pod myweb.yaml
vagrant@k8s-node1:~/pod$ ls
myweb.yaml
vagrant@k8s-node1:~/pod$ kubectl get -f myweb.yaml
NAME READY STATUS RESTARTS AGE
myweb 1/1 Running 0 3m27s
vagrant@k8s-node1:~/pod$ kubectl describe -f myweb.yaml
이렇게 -f
옵션을 붙이고 봐도 상관없다.
즉, 명령형과 구성 파일을 사용하는 형태를 섞어써도 상관없다.
✔️ kubectl 명령의 서브 명령
- create
- get
- describe
- logs
- delete
- replace
- patch
- apply
- diff
⭐ 파드를 사용할 때의 주의점
문서에보면 일반적으로 싱글톤 파드를 포함하여 파드를 직접 만들 필요가 없다고 나와있다.
싱글톤 파드란 무엇인가 ? 우리가 직접 파드를 만드는 것을 말한다.
파드라는 리소스를 직접 create
할 일은 거의 없다.
우리는 컨트롤러를 정의해서 만들고 컨트롤러가 파드를 생성한다.
쿠버네티스의 클러스터의 파드 사용 방식
- 단일 컨테이너를 실행하는 파드
- 함께 작동해야 하는 여러 컨테이너를 실행하는 파드
파드는 컨테이너의 모음
이라고 했다.
컨테이너를 여러개 지정할 수 있다는 뜻이다.
하나의 파드에 두개의 컨테이너가 있는 것을 멀티 컨테이너라고 한다.
이제 하나의 파드에 하나의 컨테이너만 넣을 것인가 여러개의 컨테이너를 넣을 것인가를 고민해볼 수 있다.
wordpress(wp), mysql 이미지를 생각해보자
하나의 pod 안에 1개씩의 wp, mysql 컨테이너를 둔다고 하면 두개의 컨테이너를 하나의 pod로 관리할 수 있다.
하지만 이런 방식의 구성은 절대 해서는 안된다 → Anti Pattern
파드는 상대적으로 밀접하게 결합된 하나 이상의 애플리케이션 컨테이너가 포함된다 라고 정의되어 있다.
하나의 파드 내에 어플리케이션(컨테이너)을 여러개 띄울 수 있는데 그 둘은 밀접하게 결합되어 있어야 한다.
그렇다면 밀접하다
라고 말할 수 있는 척도는 무엇인가 ?
우선 결론적으로 wp, mysql 이미지는 밀접한 관계가 아니다.
하나의 파드에는 하나의 메인 어플리케이션만 있어야 한다.
그리고 컨테이너를 여러개 배치하는 주된 용도 중 하나는 메인 App을 도와야 하는 정말 밀접하게 결합되어야 하는 것만 배치시키는 것이다.
외부의 git 서버나 S3 서버가 있을 때 웹 컨텐츠를 가지고 와서(보조적인 기능) Main App인 Apache(주 기능)에 제공해야 하거나 Main App에서 발생한 로그를 다른 log 서버로 전송시켜야할 때가 있다.
App의 로그를 외부로 반출시키는 어플리케이션은 Apache를 도와줄 뿐 주된 기능은 아니다.
하지만 두 App은 다른 곳에 떨어져 있을 때는 의미가 없다.
우리는 ReplicaSets을 통해 Pod의 복제본 개수를 늘이고 줄일 수 있다. 직접 컨테이너 개수를 늘일 수는 없다.
Pod를 한 세트 더 늘일 수 있다. 하지만 Apache만을 늘리는 것은 의미가 없다.
이럴 때는 다른 보조 App까지 함께 늘어나야 의미가 있다.
Apache와 Mysql DB는 전혀 다른 성격의 App이다. 가능하면 떨어뜨려 놔야 한다.
별도의 VM이나 별도의 컨테이너로 분리시켜야 한다. 이를 k8s에서는 Pod로 떨어뜨려놔야 한다.
다시말하면 우리는 Pod만 관리할 수 있다. 컨테이너만 늘일 수 있는 방법이 없다.
그래서 절대로 하나의 파드에 Apahce, Mysql (메인 App)을 두면 안된다.
우리는 기능을 분리시키기 위해 컨테이너를 사용하는데 이 목적을 무시하고 다시 뭉쳐야 할 이유가 없다.
하나의 Pod는 항상 하나의 host에만 배치된다.
파드에 컨테이너가 5개 정의되어 있다면 5개의 컨테이너는 하나의 호스트에 배치된다.
node1, 2, 3가 있을 때 Pod는 특정 노드에 배치된다.
Pod에 5개의 컨테이너가 있다고 하면 모든 컨테이너는 node3에 배치되는 것이다.
권장하지 않지만 Apache와 Mysql 컨테이너가 구성된 하나의 Pod를 배치한다고 하면 세트가 하나의 node에 배치된다.
만약 해당 노드가 장애가 나면 ? 심각한 문제가 생긴다.
여기서 또 생각해볼 수 있는 것은 그러면 동일한 Pod를 복제하면 되지 않을까?
물론 Pod1, Pod2를 구성할 수도 있지만 Pod 배치시 node1에 쏠려서 배치될 가능성이 있으므로 해당 노드에 장애가 발생하면 매우 critical해진다.
따라서 메인 어플리케이션을 같은 Pod에 배치하는 것은 Anti-Pattern이다.
'DevOps > Kubernetes' 카테고리의 다른 글
[Kubernetes] Namespace ( + 오브젝트의 이름와 UID) (0) | 2022.05.18 |
---|---|
[Kubernetes] Pod Design (0) | 2022.05.17 |
[Kubernetes] Object의 정의와 관리 (0) | 2022.05.17 |
[Kubernetes] Kubernetes Objects(오브젝트) (0) | 2022.05.16 |
[Kubernetes] Kubespray로 쿠버네티스 설치하기 (0) | 2022.05.16 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!