0518_Kubernetes_Pod Lifecycle, Container Probe, Workload Resource(Replication Controller / ReplicaSets)

HYOJU DO·2022년 5월 18일
0

Kubernetes

목록 보기
5/13
post-thumbnail

Pod Lifecycle / Lifetime (생명 주기)


$ kubectl get, $ kubectl describe 등에서 확인 가능

✔️ pod의 상태 != container의 상태
(container의 상태는 pod의 상태 반영)

Pod 상태

🎈 정의

  • pending : 스케줄링 되기 전, 이미지 받기 전, 컨테이너가 준비되기 전
  • running : 컨테이너가 실행 중, 실행 전, 재시작 중
  • succeeded : 정상 종료 (RC, EC(error code), ES : 0)
  • failed : 비정상 종료 (!0)
  • unknown : 노드의 통신 문제로 상태 알 수 없음

🎈 상태 설명

🌟 Pending 발생 원인 경우의 수 ( 파악 필수 !! )
기본적으로 파드가 k8s 클러스터에서 승인은 되어있음

  1. kubectl describe이미지 다운 받았는지 안받았는지 이벤트 로그 확인 가능
    ➜ 다운 받았는데도 pending 이면 문제가 있는 것
  2. 스케줄링 (어떤 노드에 배치될 것인지)이 안되는 상태
    ex. 모든 노드가 전부 full인 상태면 스케줄링을 할 수 x
    ➜ insufficient node ....라는 로그 발생
  3. 이미지를 잘못 지정하거나, private 이미지 레지스트리 인증을 잘못 받은 경우
  4. 이미지를 다운 받았지만 컨테이너가 실행할 준비 상태 x
    ex. 볼륨이 연결 안 된 상태

Container 상태

  • waiting : 이미지 받기 전, 볼륨 연결되기 전 (파드의 이미지 받기 전, 컨테이너가 준비되기 전이 이 상태)
  • running : 실행 중
    - 레지스트리에서 컨테이너 이미지 가져오는 중
    - 시크릿 데이터 적용하는 작업 중 (➜ 볼륨 연결)
    - postStart Hook 실행 완료
  • terminated : 종료

➕ Hook (Hooking) : 정상적인 순서로 실행하고 있는데 중간에 밀어넣는 것
- postStart : 작업 후에 사용
- preStop : 컨테이너를 실행하기 전에 작업하는 것

$ kubectl delete$ kubectl get pods 확인하면  Terminating 이 표시
➜ SIGTERM 15 (정상 종료)
➜ 30초 기다린 후 9번 시그널 날림
(terminating은 엄밀히 따지면 상태 x -> terminated 가 되기 전 과정)


Container 재시작 정책

$ kubectl explain pods.spec.restartPolicy

pods.spec.restartPolicy : 책에 이런 식으로 적혀있으면 $ kubectl explain 에서 검색하는 형태

파드의 spec 에는 restartPolicy 필드 존재
사용 가능한 값 : Always / OnFailure / Never ( Default: Always )

➕ Camel Pattern
yaml 파일의 다중 명사 중 첫 번째 명사소문자, 두 번째부터대문자로 표현
ex. restartPolicy


Log Back-off (지수 백오프)

백오프 == 원래대로 돌아감

$ kubectl get pods --watch
NAME    READY   STATUS             RESTARTS   AGE
myweb   0/1     ImagePullBackOff   0          25s
myweb   0/1     ErrImagePull       0          46s
myweb   0/1     ImagePullBackOff   0          61s
myweb   0/1     ErrImagePull       0          80s
myweb   0/1     ImagePullBackOff   0          94s
myweb   0/1     ErrImagePull       0          2m22s
myweb   0/1     ImagePullBackOff   0          2m39s
myweb   0/1     ErrImagePull       0          3m57s
myweb   0/1     ImagePullBackOff   0          4m12s

포그라운드 상태로 상태가 변하면 화면에 출력
시간을 두고 봐야함 (기본 재시작 정책이 always이기 때문)
재시작 시간 간격 점차 길어짐 10s, 20, 40, 80, ... 300s (5min)
== 아이폰 잠금 해제 오류 시 처음엔 1분, 5분, 15분, 1시간 으로 점점 잠금 해제 못하는 시간 늘어남

🎈 지수 백오프 하는 이유
➜ 재시작 시간 간격 증가 없이 무한 재시작을 하게 되면 계속해서 리소스 소모

➕ 실행 안되었던 컨테이너들이 모두 동시에 실행되면 동일한 시점에 한 번에 많은 리소스를 사용하기 때문에
모두 약간의 편차(jitter)를 두고 실행


컨테이너 Probe (프로브)

컨테이너 상태 체크
필수로 선언

언제 프로브를 사용해야하는가?

프로브 종류

실행 시점이 다름

  • livenessProbe : 애플리케이션 실행 / 작동 여부
  • readinessProbe
  • startupProbe : 애플리케이션이 시작되었는지 확인 / 성공하지 않으면 나머지 프로브 비활성화

livenessProbe
➜ 시점 : app이 실행 된 이후부터 작동
어플리케이션 이 살아있는지 죽어있는지 명확하게 판단

  • 컨테이너가 생성만 되면 살아있다(live)라고 판단
  • 컨테이너가 생성 된 것과 어플리케이션이 실행 되는 것은 별개
  • 어플리케이션이 실행되는 중에 오류가 나서 종료 될 수도 있음
  • livenessProbe를 사용하지 않으면 어플리케이션 오류는 살아있다고 판단

🌟 프로브 매커니즘 (진단 방법)

pods.spec.containers.livenessProbe.xxx

  • httpGet
    : 컨테이너에서 실행하는 어플리케이션이 Web, Web app인 경우
    HTTP GET 성공 시, 응답 코드 2XX, 3XX 돌아옴
$ curl https://velog.io/@xxomlete -I
HTTP/2 200

$ curl https://kubernetes.io/ko/docs/concepts/workloads/pods/pod-lifecycle -I
HTTP/2 301
  • tcpSocket
    : 해당 포트 TCP 연결
    웹 서비스가 아닌 서비스에 대해 TCP 검사(3-way-handshake) 수행
  • grpc
    : grpc 프로토콜 연결
  • exec
    : 명령 실행 / 종료 코드 0
    웹도 아니고 네트워크를 이용하는 서비스도 x
    명령어를 실행시켜서 상태 코드 확인
    ex. mysql, mariadb ➜ mysqladmin ping 명령어 사용하면 컨테이너가 실행되고 있는지 확인 가능
    ➜ 어플리케이션 자체에서 명령어 제공

  • periodSeconds
    : 초 단위 주기
    ➜ period가 너무 짧으면 부하가 걸릴 수 있기 떄문에 적당한 간격 두기
  • successThreshold
    : 임계값
    프로브 신호를 보내서 정상응답 신호가 돌아오는 과정을 연속 으로 몇 번을 성공해야하는가
    (Default == 1번)
    ex. 3으로 지정했을 때, 2번하고 1번 실패하고 다음에 성공하면 실패로 판단 ➜ 다시 3번 연속 성공해야함
  • failureThreshold
    : 실패 신호가 돌아오면 실패로 간주하고 재시작
    (Default == 3번)
  • initialDelaySeconds 🌟
    : 프로브 유예 기간
    최초에 이 어플리케이션이 실행될 때 프로브 신호를 보내기 전 여유시간 부여
    원래 실행 시간이 긴 어플리케이션인 경우, Probe 주기를 짧게 설정하면 계속 실패로 간주 ➜ 계속 재시작
  • timeoutSeconds : 프로브 신호를 전송해서 응답이 돌아오는데까지 걸리는 시간
    (Default == 1초)

✔️ 복수로 사용 가능
➜ 둘 다 success 여야 최종적으로 success

IANA : 포트 검색 공식 사이트


프로브 결과

  • success : 진단 통과
    probe 신호를 보냈을 때, 결과가 돌아 옴
  • failure : 진단 실패
    probe 신호를 보냈을 때, 결과가 돌아는 왔지만 잘못된 값
  • unknown : 진단 자체 실패
    probe 신호를 보냈지만 아무 응답이 돌아오지 x



livenessProbe 실습

myweb-liveness.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myweb-liveness
spec:
  containers:
    - name: myweb
      image: httpd
      ports:
        - containerPort: 80
          protocol: TCP
      livenessProbe:
        httpGet:
          path: "/"
          port: 80

myweb-liveness-err.yaml ➜ 오류 발생
80이 아닌 8080 포트로 HTTP 연결 성공 시 Probe 성공하게 설정

apiVersion: v1
kind: Pod
metadata:
  name: myweb-liveness-err
spec:
  containers:
    - name: myweb
      image: httpd
      ports:
        - containerPort: 80
          protocol: TCP
      livenessProbe:
        httpGet:
          path: "/"
          port: 8080 ✔️

몇 초 단위로 liveness Probe 재시작하는지 확인하기 (Containers 항목)
➜ 약 10초 단위로 재시작

$ kubectl get pods --watch

NAME                 READY   STATUS    RESTARTS   AGE
myweb-liveness       1/1     Running   0          85s
myweb-liveness-err   1/1     Running   0          16s
myweb-liveness-err   1/1     Running   1 (11s ago)   54s
myweb-liveness-err   1/1     Running   2 (13s ago)   94s

startupProbe 실습

오류 발생 myweb-startup.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myweb-startup
spec:
  containers:
    - name: myweb
      image: httpd
      ports:
        - containerPort: 80
          protocol: TCP
      livenessProbe:
        httpGet:
          path: "/"
          port: 80
      startupProbe:
        exec:         # ✔️ 해당 경로 존재 x 
		  ###: 
		  path: /tmp/abc

정상 실행 myweb-startup.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myweb-startup
spec:
  containers:
    - name: myweb
      image: httpd
      ports:
        - containerPort: 80
          protocol: TCP
      livenessProbe:
        httpGet:
          path: "/"
          port: 80
      startupProbe:
        httpGet:
          path: "/"
          port: 80

생성 된 파드 확인

$ kubectl get po  
NAME                 READY   STATUS             RESTARTS       AGE
myweb-liveness       1/1     Running            0              29m
myweb-liveness-err   0/1     CrashLoopBackOff   13 (50s ago)   29m
myweb-startup        1/1     Running            0              22m   # 정상 생성



Workload Resource == Controller

  • 레거시 리소스 : BM, VM 등 옛날 리소스
    ➜ 보통 나쁜 의미로 많이 사용 (무조건 나쁘진 x ➜ 오버엔지니어링 방지를 위해 사용하는 경우 존재)
  • 최신 리소스 : 컨테이너

Workload == Application 실행
➜ pod로 실행 (singletone pod) / Controller로 실행

  • 워크로드 == 파드의 집합
  • 파드 == 컨테이너의 집합

🎈 Pod 생성 과정

Contoller 생성 (사용자👷🏻‍♂️) ➜ Depoloyments 생성(컨트롤러⚓) ➜ Replicasets 생성(Depoloyments ⚓) ➜ Pods 생성 (Replicasets⚓)

사용자는 Controller 생성 시, pod를 선언하고 Controller가 알아서 다음 과정 실행
🌟 파드가 종료되면 controller가 self-healing 진행


Replication Controller

Legacy Resource (Replicasets 권장)

🎈 기본 원칙
➜ replicasets에도 동일하게 적용

  • 지정된 레플리카 갯수보다 파드가
    많이 생성되면 파드를 지우고
    부족하면 파드를 생성
    ➜ 🌟 원하는 대로 구현이 안될 수도 있지만, 최대한 맞추려고 부단히 노력
    (ex. 노드의 cpu 용량, 메모리 용량 부족 / 노드 장애 등)
  • 노드가 장애 나서 죽어버리면 Replication Controller도 같이 죽음

🌟✔️ 교체 == 새로 생성 (기존 것 대체하는 것 x)
🌟✔️ desired : 사용자가 요구, 요청, 선언 한 것


🎈 파드 탬플릿 : 컨트롤러가 새로 만들 파드를 선언하는 탬플릿

$ kubectl explain rc.spec.template
  • rc.spec.template.metadata.* == pod.metadata.*
  • rc.spec.template.spec.* == pod.spec.*

💡 label ➜ 내가 관리하는 파드가 누구의 파드 인가 판단
컨트롤러에 의해 관리되는 모든 파드에는 (동일한) label 붙어있어야함
수많은 pod 중에서 원하는 label을 selecting 해야 함

🎈 label에 따른 레플리카 파드 변화

myweb-rc.yaml

apiVersion: v1
kind: ReplicationController
metadate:
  name: myweb-rc  # 이름은 한 번 바꾸면 다시 못바꿈
spec:
  replicas: 3
  selector:
    app: web  # label에 있는 값과 동일해야함 (필수)
# pod 관련 설정 -> 수정은 가능하나 탬플릿은 새로 만들어질 때 적용 (replace로만은 적용 안 됨)
  template:
    metadata:
      # name 부여 말이 안 됨 -> 항상 controller 이름/random한 이름 형태의 이름으로 자동 지정
      labels:  # 필수
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
              protocol: TCP
          # 원래는 여기에 livenessProbe, startupProbe 필수 지정
  • 대부분의 리소스는 한 번 지정하면 변경 불가
  • Pod Configure template은 yaml 파일에서 수정은 가능하지만 replace로 적용 불가
    ➜ 해당 탬플릿으로 새로운 컨테이너 생성할 때 적용 됨 ( 수정사항 적용 도 생성 때만 가능)
  • 🌟 Selector의 key-value 값은 metadata>labels 의 key-value 값과 같아야 함
  • metadata에 name 부여 x ➜ 항상 controller 이름/random한 이름 형태로 자동 지정
  • 원래는 탬플릿에 livenessProbe, startupProbe 지정 필수 (현재 실습에서는 지정 x)

터미널 1

label에 따라 pod 및 컨트롤러 상태가 어떻게 바뀌는지 실시간 확인

$ watch kubectl get rc,pods --show-labels

터미널 2

레플리카의 label 변경

$ kubectl label pods myweb-rc-28g49 app=database --overwrite

➜ 지정해 준 기존 레플리카의 label 변경 + app=web 레플리카 새로 생성

$ kubectl label pods myweb-rc-28g49 app=web --overwrite

➜ 지정해 준 기존 레플리카의 label 변경 + 새로 생성되었던 레플리카 삭제


RC 스케일링

🎈 명령형 오브젝트

스케일링

$ kubectl scale

myweb-rc에 해당하는 파드의 레플리카를 5개로 유지

$ kubectl scale rc myweb-rc --replicas=5

오브젝트 재구성

$ kubctl replace

해당 정보로 구성 교체

$ kubctl replace -f myweb-rc.yaml 

scale로 인해 5개로 늘어났던 파드가 다시 3개로 감소한 것 확인

파드 삭제

label 이용

$ kubectl delete pods -l app=web

-all -> 레이블과 상관 없이 모두 삭제

$ kubectl delete pods -all

♢ Patch (패치)

patch는 json 형태로만 지정 가능
-p 옵션 : 변경사항 명시

$ kubectl patch -f myweb-rc.yaml -p '{"spec": {"replicas": 2}}' 
$ kubectl patch rc myweb-rc.yaml --patch-file replicas.json

replicas.json

{
  "spec":
    {"replicas": 3}
}

명령형 커맨드로 일부분만 수정 가능하므로 유용
--patch-file [파일이름] : json 파일로도 적용 가능

-f 옵션을 쓰는 이유
이 파일로 생성 된 리소스를 수정한다는 것을 지칭
수정 된 파일을 적용시킨다는 뜻 x

💡Replace vs Patch

  • replace 는 수정하고자 하는 완전한 오브젝트 제공해야함
    ➜ yaml 파일 구조로 새로 저장 된 값
  • patch 는 우리가 변경하고자 하는 일부분 만 제공하면 됨

vi 에디터 형식으로 실시간 리소스 편집

$ kubectl edit
etcd에서 가져 온 값 수정

$ kubectl edit -f myweb-rc.yaml
$ kubectl edit rc myweb-rc
$ kubectl edit rc/myweb-rc      # 이러한 명령 형태는 다른 명령어에서도 적용 가능

변경사항 저장 시 검증 진행
변경할 수 없는 값을 변경했다고 검증되면 수정되지 않음 ➜ 오류 출력

🎈 선언형 오브젝트

$ kubectl apply
없으면 만들어주고 변경하면 변경시켜 줌

$ kubectl apply -f myweb-rc.yaml

기본적으로 logs는 오브젝트의 종류 지정 x (이름을 찾는 형식)

$ kubectl logs ✔️rc myweb-rc                             
Error from server (NotFound): pods "rc" not found

컨트롤러가 관리하는 로그 정보 확인

$ kubectl logs ✔️rc/myweb-rc # ➜ 잘 사용하는 형태 x
Found 2 pods, using pod/myweb-rc-pxwz8
2022/05/18 05:13:12 Start MyWeb Application
2022/05/18 05:13:12 Listen:  0.0.0.0:8080

컨트롤러 삭제
➜ 컨트롤러 삭제 시, 파드도 같이 삭제

$ kubectl delete rc myweb-rc
$ kubectl delete rc myweb-rc --cascade=orphan

--cascade=orphan : 컨트롤러만 삭제하고 파드는 남김



ReplicaSets

레플리케이션 컨트롤러 ➜ ReplicaSets
부하 분산 시, 백앤드는 보통 ReplicaSets로 구성

Replicasets에 대한 리소스 정보 확인

$ kubectl api-resources | grep replicasets
replicasets                       rs           apps/v1                                true         ReplicaSet

apps/v1 그룹에 속한 리소스 확인
➜ apps 그룹에 속한 것은 모두 워크로드

$ kubectl api-resources | grep apps/v1
controllerrevisions                            apps/v1                                true         ControllerRevision
daemonsets                        ds           apps/v1                                true         DaemonSet
deployments                       deploy       apps/v1                                true         Deployment
replicasets                       rs           apps/v1                                true         ReplicaSet
statefulsets                      sts          apps/v1                                true         StatefulSet

Replicasets의 Selector 정보 확인

$ kubectl explain rs.spec.selector 

rc와 다르게 하위 필드가 존재

$ kubectl explain rs.spec.selector.matchLabels

🎈 Replicasets 실습

myweb-rs.yaml

matchLabels 부분만 추가되었지 RC와 동작원리 동일

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-rs
spec:
  replicas: 3
  selector:
    matchLabels: ✔️
      app: web
      env: dev
  template:
    metadata:
      labels:
        app: web
        env: dev
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
              protocol: TCP

Replicasets 생성

$ kubectl create -f myweb-rs.yaml

Replicasets 상세 정보 확인

$ kubectl get rs -o wide 
$ kubectl describe rs myweb-rs   

♢ 집합성(set base) 기준의 Label Selector

  • 일치성
    matchlabels
    키와 벨류 모두 매칭 ➜ 키만 매칭되면 안됨

  • 집합성
    키만 매칭 가능 (exists, doesnotexists)
    matchlabels 대신 matchExpressions 사용

myweb-rs-set

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-rs-set
spec:
  replicas: 3
  selector:
    matchExpressions: ✔️   
      - key: app
        operator: In
        values:
          - web
      - key: env
        operator: Exists
  template:
    metadata:
      labels:
        app: web
        env: dev
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
              protocol: TCP

💡Controller는 동일한 label을 가진 pod들을 어떻게 구분할까?

yaml 형식으로 생성 된 파드 정보 확인

$ kubectl get pod/[pod 이름] -o yaml | more

어떤 컨트롤러에 의해서 실행이 되는지 메타데이터 필드 ownetReferences 부분의 Pod에 추가 되어있음

get all : 일반적으로 우리가 많이 확인하는 오브젝트 확인 가능

$ kubectl get all    

🌟 필요 항목만 골라보기

kube-system NS의 ReplicaSets

$ kubectl get -n kube-system rs
NAME                                DESIRED   CURRENT   READY   AGE
calico-kube-controllers-5788f6558   1         1         1       24h
coredns-8474476ff8                  2         2         1       24h
dns-autoscaler-5ffdc7f89d           1         1         1       24h

kube-system NS의 ReplicaSets 중 coredns 상세 정보

$ kubectl get -n kube-system rs coredns-8474476ff8 -o wide
NAME                 DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                              SELECTOR
coredns-8474476ff8   2         2         1       24h   coredns      k8s.gcr.io/coredns/coredns:v1.8.0   k8s-app=kube-dns,pod-template-hash=8474476ff8

kube-system NS에서 k8s-app=kube-dns 레이블을 가진 ReplicaSets

$ kubectl get -n kube-system rs -l k8s-app=kube-dns    
NAME                 DESIRED   CURRENT   READY   AGE
coredns-8474476ff8   2         2         1       24h



추가 Tip


🌟 오류 확인

대부분 오류는 이미지가 어플리케이션에 적용되지 못하는 상태이거나,
이미지를 받아올 때 오타를 낸 경우가 많음

명령어 실행 결과에 어떤 정보가 있는지 명확하게 파악할 수 있어야 함

$ kubectl describe pods [pod 이름]
🌟 Containers>[ pod ]>state에 최신 바로 이전 상태 출력
➜ 오류가 발생 시 오류에 대한 이유 출력

💡$ kubectl get pods -A
Default NS가 아닌 다른 NS에 pod가 있을 때 자동완성 기능(tab) 적용 x (NS 옵션 설정 안했기 떄문)
이 때는 NS 옵션을 먼저 써주고 파드 이름 입력하면 자동 완성 기능 사용 가능
ex. $ kubectl get -n dev pods -A
컨테이너 이름이 랜덤하게 배치되기 때문에 자동완성 기능을 잘 활용할 수 있어야 함

➕ $ kubectl get pods,nodes,services : 오브젝트 한번에 조회 가능

➕ $ kubectl get pods/pod/po (복수, 단수, shortname) 전부 가능

$ watch ➜ 유닉스 명령어
kubectl 의 --watch 옵션과 watch 명령어는 다른 것
➜ k8s를 windows에 설치하면 watch 명령어 사용 불가 (k8s 옵션으로만 기능 사용 가능)


💡 CSP (Cloud Service Provider)
➜ Megazone, Bespin Global ...

클라우드 생태계
쿠버네티스 생태계

💡 프로젝트 참고

k3s
IOT, Edge computing에 주로 사용
+) 라즈베리 파이 : ARM CPU에 리눅스를 올려서 사용하는 소형 컴퓨터

  • kine == etcd 용도
  • flannel == calico 용도
    Rancher : 여러 형태의 쿠버네티스 멀티/하이브리드 클러스터를 랜쳐 도구에서 모두 관리 가능 -> k3s에서 사용 가능



profile
Be on CLOUD nine! ☁️ ( 수정 예정 == 📌)

0개의 댓글