728x90

readinessProbe


readinessProbe란?

컨테이너 실행 후 실제로 서비스 요청에 응답할 수 있는지 진단

  • ready 상태 확인
  • 진단 실패 시 엔드포인트 컨트롤러는 해당 파드에 연결된 모든 서비스를 대상으로 엔드포인트 정보를 제거함

 

readinessProbe 종류

항목 설명
HTTP GET - 특정 경로에 HTTP GET 요청
- HTTP 응답 코드 2xx 또는 3xx인지 확인
TCP Socket 특정 TCP Port 연결 시도 (TCP syn, syn+ack, ack)
Exec 컨테이너 내부에 바이너리(명령)를 실행하고 종료 코드로 확인

 


 

실습

Ready 상태가 아닌 파드는 readinessProbe가 작동하여 엔드포인트에 연결되지 않음

  • 레플리카셋 생성 파일
$ cat myapp-rs-readiness.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-readiness
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs-readiness
  template:
    metadata:
      labels:
        app: myapp-rs-readiness
    spec:
      containers:
      - name: myapp
        image: ghcr.io/c1t1d0s7/go-myweb:alpine
        readinessProbe:
          exec:
            command:
              - ls
              - /var/ready
        ports:
        - containerPort: 8080

 

 

  • 서비스 생성 파일
$ cat myapp-svc-readiness.yml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-readiness
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs-readiness

 

  • 레플리카셋, 서비스 생성
$ kubectl create -f myapp-rs-readiness.yml -f myapp-svc-readiness.yml
replicaset.apps/myapp-rs-readiness created
service/myapp-svc-readiness created

 

실행 결과

  • 생성된 파드, 엔드포인트, 서비스 정보 확인
  • 생성된 파드의 READY가 0/1 상태임을 확인 => 준비된 상태가 아님
  • myapp-svc-readiness 서비스의 엔드포인트가 비어있음 => 트래픽을 받지 않음
$ kubectl get po,ep,svc -o wide

728x90
728x90

MetalLB


MetalLB란

온프레미스에서 로드밸런서를 제공하는 MetalLB

  • 온프레미스에서 로드밸런서를 사용하기 위해 내부에 로드밸런서 서비스를 받도록 구성하는데 필요함
  • 특별한 네트워크 설정이나 구성이 필요하지 않으며 기존의 L2(ARP/NDP), L3(BGP) 네트워크로 로드밸런서를 구현함

 

MetalLB 오브젝트

  • 컨트롤러: 작동 방식(프로토콜)을 정의하고 EXTERNAL-IP를 부여해 관리함
  • 스피커: 정해진 작동 방식(L2/ARP, L3/BGP)에 따라 경로를 만들 수 있도록 네트워크 정보를 광고하고 수집하여 각 파드의 경로를 제공함

 


 

MetalLB 설치

addon을 이용한 설치

  • addons.yml 파일 수정
vagrant@kube-master1:~/kubespray$ vi inventory/mycluster/group_vars/k8s-cluster/addons.yml

metrics_server_enabled: true
ingress_nginx_enabled: true
metallb_enabled: true
metallb_ip_range: "192.168.56.200-192.168.56.299"
metallb_protocol: "layer2"

 

 

  • k8s-cluster.yml 파일 수정
vagrant@kube-master1:~/kubespray$ vi inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml
kube_proxy_strict_arp: true

 

  • 플레이북 실행
ansible-playbook -i inventory/mycluster/inventory.ini -v --become --become-user=root cluster.yml

 

설치 완료

  • metallb-system 네임스페이스 확인
vagrant@kube-master1:~/kubespray$ kubectl get namespace
NAME              STATUS   AGE
default           Active   6d19h
ingress-nginx     Active   6d19h
kube-node-lease   Active   6d19h
kube-public       Active   6d19h
kube-system       Active   6d19h
metallb-system    Active   42s

 

  • metallb-system의 오브젝트 정보 확인
vagrant@kube-master1:~/kubespray$ kubectl get all -n metallb-system

 

로드밸런서 EXTERNAL-IP의 Pending 상태

  • 외부 IP를 부여받지 못함

 

 


 

MetalLB 재설치

설치된 MetalLB 삭제

  • 설치된 최신 버전을 삭제하고 v0.9.3으로 재설치
vagrant@kube-master1:~/test$ kubectl delete secret/memberlist  -n metallb-system
secret "memberlist" deleted

vagrant@kube-master1:~/test$ kubectl delete configmap/config -n metallb-system
configmap "config" deleted

vagrant@kube-master1:~/test$ kubectl delete -f  https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

vagrant@kube-master1:~/test$ kubectl delete -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
namespace "metallb-system" deleted

 

MetalLB v0.9.3 설치

  • false > true 수정
vagrant@kube-master1:~/kubespray$ kubectl edit configmap -n kube-system kube-proxy
configmap/kube-proxy edited

strictARP: true

 

  • MetalLB 네임스페이스 생성
vagrant@kube-master1:~/kubespray$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
namespace/metallb-system created

 

  • MetalLB Components 생성
vagrant@kube-master1:~/kubespray$ kubectl apply -f  https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml

 

 

  • Secret 생성
vagrant@kube-master1:~/kubespray$ kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
secret/memberlist created

 

  • 라우팅 처리를 위한 ConfigMap 생성
vagrant@kube-master1:~/kubespray$ cat << EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.56.200-192.168.56.229
> EOF
configmap/config created

 

  • 시스템 재부팅
vagrant@kube-master1:~/kubespray$ sudo shutdown -r now

 

  • metallb-system 네임스페이스 확인
vagrant@kube-master1:~$ kubectl get namespace

 

  • metallb-system 네임스페이스 정보 확인
  • 모든 오브젝트가 READY 상태인지 확인
vagrant@kube-master1:~$ kubectl get all -o wide -n metallb-system

 

  • 로드밸런서에 외부 IP가 부여된 것을 확인할 수 있음
vagrant@kube-master1:~$ kubectl get all -o wide

 

  • 웹 브라우저에서 192.168.56.200 으로 접속하여 확인

 

 

728x90
728x90

클러스터 연결 서비스


  • 쿠버네티스 클러스터에서 웹의 프론트엔드 서비스를 실행하는 파드의 경우 쿠버네티스 클러스터를 외부로 노출시켜 접근 가능하도록 구성
  • 클러스터 외부 서비스: NodePort, Ingress, 로드밸런서, MetalLB, HPA

 


 

NodePort 서비스

testapp-svc-np.yml

필드 속성 값
.spec.type 서비스 타입 (기본 값: ClusterIP)
.spec.ports.nodePort 30000-32767 포트, 포트를 지정하지 않으면 랜덤한 포트 지정
  • 레플리카셋 생성
vagrant@kube-master1:~/test$ cat testapp-rs-named-port.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: testapp-rs-named-port
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testapp-rs
  template:
    metadata:
      labels:
        app: testapp-rs
    spec:
      containers:
      - name: testapp
        image: c1t1d0s7/myweb
        ports:
        - name: testapp-http
          containerPort: 8080
        imagePullPolicy: Never
vagrant@kube-master1:~/test$ kubectl create -f testapp-rs-named-port.yml
replicaset.apps/testapp-rs-named-port created

 

  • 노드 포트 서비스 생성
  • 서비스 타입: NodePort
  • 노드에 노출할 포트 번호: 31000 (포트 번호는 30000-32767 내에서만 사용 가능)
vagrant@kube-master1:~/test$ cat testapp-svc-np.yml
apiVersion: v1
kind: Service
metadata:
  name: testapp-svc-np
spec:
  type: NodePort
  ports:
  - name: testapp-http
    port: 80
    targetPort: testapp-http
    nodePort: 31000
  selector:
    app: testapp-rs
vagrant@kube-master1:~/test$ kubectl create -f testapp-svc-np.yml
service/testapp-svc-np created

 

  • 노드의 IP 확인
vagrant@kube-master1:~/test$ kubectl get nodes -o wide
NAME           STATUS   ROLES    AGE    VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
kube-master1   Ready    master   4d3h   v1.18.10   192.168.56.11   <none>        Ubuntu 18.04.6 LTS   4.15.0-187-generic   docker://19.3.12
kube-node1     Ready    <none>   4d3h   v1.18.10   192.168.56.21   <none>        Ubuntu 18.04.6 LTS   4.15.0-187-generic   docker://19.3.12
kube-node2     Ready    <none>   4d3h   v1.18.10   192.168.56.22   <none>        Ubuntu 18.04.6 LTS   4.15.0-187-generic   docker://19.3.12
kube-node3     Ready    <none>   4d3h   v1.18.10   192.168.56.23   <none>        Ubuntu 18.04.6 LTS   4.15.0-187-generic   docker://19.3.12

 

  • 접속 확인
  • curl 노드 IP:31000
vagrant@kube-master1:~/test$ kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash
If you don't see a command prompt, try pressing enter.

bash-5.1# curl 192.168.56.11:31000

 

  • 외부에서 접속 확인
  • 외부에서 노드의 IP:31000으로 접속하면, 서비스 포트인 80번 포트로 리다이렉션되며, 이는 다시 내부 파드의 8080번 포트로 리다이렉션 되는 것을 확인할 수 있음

 

728x90
728x90

서비스


Service

서비스의 이해

  • 파드는 클러스터 외부의 요청이나 클러스터 내부의 다른 파드의 요청에 응답해야 하고 파드가 다른 파드에서 제공하는 애플리케이션에 접근하기 위해서는 파드를 찾을 수 있어야 함
  • 쿠버네티스가 아닌 기존의 시스템은 애플리케이션이 동작하는 시스템의 호스트 이름이나 정적 IP를 할당하여 해당 애플리케이션을 찾을 수 있지만, 쿠버네티스 환경에서는 그렇게 할 수 없음

 

쿠버네티스 환경에서 정적 IP 또는 시스템 호스트의 이름을 사용할 수 없는 이유

  • 파드는 일회성으로 동작하기 위해 설계되었으며, 언제든 제거될 수 있음
  • 특정 노드에 파드가 스케줄링되고 IP 주소가 동적으로 할당되며 클라이언트는 파드의 IP 주소를 미리 예측할 수 없음
  • 분산 아키텍처 및 스케일 아웃의 경우 여러 파드가 같은 애플리케이션을 제공하기 때문에 각 파드마다 IP가 존재하고, 스케일링이 될 때마다 클라이언트가 해당 IP를 알 수 없음

 

서비스란

  • 쿠버네티스 시스템에서 같은 애플리케이션을 실행하고 있는 컨트롤러의 파드 그룹에 단일 네트워크 진입 점을 제공하는 리소스
  • 서비스에 부여된 IP는 해당 서비스가 종료될 때까지 변경되지 않음
  • 클라이언트는 서비스가 제공하는 IP 및 Port를 통해 파드에 접근하게 되고 kube-dns( coredns )가 적용되어 있다면 서비스의 이름에 기반한 고유한 FQDN이 부여됨
  • 서비스는 레이블 셀렉터를 이용하여 서비스의 대상( 백엔드 ) 파드를 설정하는 데, 서비스에 선택된 파드의 목록은 엔드포인트( Endpoint ) 리소스로 관리
  • 서비스 리소스는 여러 파드가 연결되어 있을 때 라운드 로빈( Round Robin ) 방식의 부하 분산 제공

 

서비스의 종류

ClusterIP 클러스터 내부용 서비스
NodePort - NodePort + ClusterIP
- 모든 노드에 외부 접근용 포트 할당
- 노드의 포트를 사용하여 외부에서 접근 가능
- 노드의 포트로 접근하면 서비스에 의해 파드로 리다이렉션 함
- 파드를 실행하고 있지 않은 노드에도 포트가 할당되어 접근 가능
LoadBalancer - LoadBalancer + NodePort + ClusterIP
- NodePort의 확장
- 클러스터 외부의 로드밸런서를 사용하여 외부에서 접근 가능
- 외부 로드밸런서로 접근하면 서비스를 통해 파드로 리다이렉션 함
- 클라우드 공급업체(AWS, GCP 등)나 MetalLB에서 지원
ExternalName - 외부에서 접근하기 위한 종류가 아님
- 외부의 특정 FQDN에 대한 CNAME 매핑을 제공함
- 파드가 CNAME을 이용해 특정 FQDN과 통신하기 위함

 

Cluster IP

  • 서비스 및 엔드포인트는 쿠버네티스 아키텍처에서 살펴본 컨트롤 플레인의 API 서버( kube-apiserver )로 접근할 수 있는 서비스로 클러스터 내부의 파드가 API 서버에 접근하기 위해 해당 서비스를 통해 접근

 

  • 서비스 목록 확인
  • TYPE-Cluster IP( 서비스 타입 ): 쿠버네티스 클러스터 내에서만 접근할 수 있음
  • CLUSTER-IP 10.233.6.53:  서비스에 할당된 클러스터 IP
  • EXTERNAL-IP: 클러스터 외부에서 접근할 때 사용하며 로드밸런서 타입의 서비스를 선언할 경우 할당됨 
vagrant@kube-master1:~/test$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP   2d22h

 

 

  • 서비스 리소스와 동일한 이름의 엔드포인트 리소스도 확인
vagrant@kube-master1:~/test$ kubectl get endpoints
NAME         ENDPOINTS            AGE
kubernetes   192.168.56.11:6443   2d22h

 


 

Cluster IP


서비스 생성

testapp-svc.yml

.spec.ports.port 서비스 리소스의 포트
- 클라이언트가 접근할 서비스의 포트
.spec.ports.targetPort 파드(대상) 리소스의 포트
- 클라이언트가 포트로 접근하면 파드의 서비스 포트로 포워딩
.spec.selector 파드 레이블 셀렉터, 엔드포인트 리소스 생성
- 서비스에 연결할 파드를 레이블 셀렉터를 이용하여 매칭하게 되며 레이블 셀렉터가 있는 경우 서비스 리소스 이름과 똑같은 엔드포인트 리소스가 자동으로 생성됨
  • yml 파일 생성
vagrant@kube-master1:~/test$ cat testapp-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: testapp-svc
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: testapp-rs

 

  • 서비스 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-svc.yml
service/testapp-svc created

 

 

  • 파드 생성 및 엔드포인트 연결
vagrant@kube-master1:~/test$ kubectl create -f testapp-rs.yml
replicaset.apps/testapp-rs created
vagrant@kube-master1:~/test$ cat testapp-rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: testapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testapp-rs
  template:
    metadata:
      labels:
        app: testapp-rs
    spec:
      containers:
      - name: testapp
        image: c1t1d0s7/myweb
        ports:
        - containerPort: 8080
        imagePullPolicy: Never

 

 

  • 엔드포인트 목록과 파드의 IP 동일

 

  • 접속 확인
  • 접속 확인을 위해 nettool이라는 파드를 생성함
vagrant@kube-master1:~/test$ kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash
If you don't see a command prompt, try pressing enter.
bash-5.1#

 

  • 부하 분산을 통해 접속할 때마다 다른 파드로 연결되는 것을 확인할 수 있음
  • curl http://testapp-svc 서비스의 CLUSTER-IP

 


 

 

세션 어피니티 구성

testapp-svc-aff.yml

  • Session Affinity
  • 클라이언트 요청을 매번 같은 파드로 연결하고 싶은 경우 사용
  • 세션 유지가 필요한 경우 사용
필드 속성 값
.spec.sessionAffinity - None( 기본 값 ):  세션 어피니티가 없음
- ClientIP: 클라이언트의 IP를 확인하고 접속 시 마다 동일한 파드로 연결함
  • yml 파일 생성
vagrant@kube-master1:~/test$ cat testapp-svc-aff.yml
apiVersion: v1
kind: Service
metadata:
  name: testapp-svc-aff
spec:
  sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: testapp-rs

 

  • 서비스 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-svc-aff.yml
service/testapp-svc-aff created

 

  • 접속 확인
  • 여러 번 접속해도 동일한 파드로 연결되는 것을 확인할 수 있음
vagrant@kube-master1:~/test$ kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash
If you don't see a command prompt, try pressing enter.
bash-5.1#

 


 

포트 이름 참조

testapp-rs-named-port.yml / testapp-svc-named-port.yml

  • 다중 포트 설정 시 반드시 포트 이름을 부여해야 함
  • 파드나 파드를 생성하는 컨트롤러의 파드 템플릿의 컨테이너 포트에도 이름을 부여할 수 있음
  • 파드( 컨테이너 )의 포트 이름을 이용하여 서비스 생성 시 파드의 대상 포트( targetPort )에 이름을 이용하여 연결 가능
  • 이름으로 참조하기 때문에 파드의 포트 이름만 변경되지 않는다면, 실제 파드의 포트 번호가 변경되더라도, 스펙의 변경 없이 연결을 유지할 수 있음

 

  • 레플리카셋 생성 파일
  • .spec.ports.name: 포트 이름
  • 컨테이너 8080 포트에 testapp-http라는 이름 부여
  • 서비스 생성 시 이름 참조 
vagrant@kube-master1:~/test$ cat testapp-rs-named-port.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: testapp-rs-named-port
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testapp-rs
  template:
    metadata:
      labels:
        app: testapp-rs
    spec:
      containers:
      - name: testapp
        image: c1t1d0s7/myweb
        ports:
        - name: testapp-http
          containerPort: 8080
        imagePullPolicy: Never

 

  • 서비스 생성 파일
  • .spec.ports.targetPort: 대상 파드의 포트 이름 지정
  • testapp-http 포트 이름을 참조하는 서비스 구성
vagrant@kube-master1:~/test$ cat testapp-svc-named-port.yml
apiVersion: v1
kind: Service
metadata:
  name: testapp-svc-named-port
spec:
  ports:
  - name: testapp-http
    port: 80
    targetPort: testapp-http
  selector:
    app: testapp-rs

 

 

  • 레플리카셋 컨트롤러와 서비스 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-rs-named-port.yml
replicaset.apps/testapp-rs-named-port created

vagrant@kube-master1:~/test$ kubectl create -f testapp-svc-named-port.yml
service/testapp-svc-named-port created

 

  • 파드의 포트 변호 변경: 8080 > 8081
vagrant@kube-master1:~/test$ kubectl edit replicasets.apps testapp-rs-named-port

 

  • 파드 삭제 ( 레플리카셋 삭제 X )
  • 파드의 포트 번호가 8081로 변경되어 파드가 생성됨
  • endpoint 목록에 세 개의 파드 IP가 있으므로 연결이 유지되어 있는 것을 확인할 수 있음
vagrant@kube-master1:~/test$ kubectl delete pods --all

실행 중인 파드의 포트 번호: 8080
모든 파드 삭제 후 재실행 중인 파드의 포트 번호: 8081

 

728x90
728x90

컨트롤러


Job Controller

잡 컨트롤러란?

  • 파드(컨테이너)의 애플리케이션(잡) 실행이 완료/종료되는 것에 초점을 맞춘 컨트롤러
  • 애플리케이션이 실행되고 실행이 완료되면 파드의 할 일이 끝난 것으로 간주하고 파드를 종료함
  • 임시( Ad-hoc ) 작업 및 배치( Batch ) 작업에 유용하게 사용됨
  • 만약 애플리케이션이 실행되고 있는 중에 노드가 죽거나 파드의 실행이 완료되지 않았다면, 파드를 다시 스케줄링하여 재실하게 구성할 수 있음

 


 

잡 컨트롤러

잡 컨트롤러

  • 잡 오브젝트의 API는 batch 그룹의 v1 버전 사용
  • 오브젝트의 종류: Job
  • 잡 컨트롤러는 파드 오브젝트를 재실행하지 않음
  • ==> 재시작 정책을 OnFailure 또는 Never로 명시적 선언이 필요함 ( Always는 안 됨)
  • job.spec.template.spec.restartPolicy
Always (기본 값) 종료/실패 시 항상 재시작
OnFailure 실패 시 재시작
Never 종료 또는 오류 시 절대 재시작하지 않음

 

  • 파일 생성
vagrant@kube-master1:~/test$ cat testapp-job.yml
apiVersion: batch/v1
kind: Job
metadata:
  name: testapp-job1
spec:
  template:
    metadata:
      labels:
        app: testapp-job
    spec:
      restartPolicy: OnFailure
      containers:
      - name: testapp
        image: busybox
        command: ['sleep','10']

 

 

  • 데몬셋 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-job.yml
job.batch/testapp-job1 created

 

  • 실행 결과
  • 파드 상태 확인 (10초 실행 후 종료)
vagrant@kube-master1:~$ kubectl get pods --watch
NAME                 READY   STATUS      RESTARTS   AGE
testapp-job1-x8k8k   0/1     Pending       0          0s
testapp-job1-x8k8k   0/1     Pending       0          0s
testapp-job1-x8k8k   0/1     ContainerCreating   0          0s
testapp-job1-x8k8k   1/1     Running             0          6s
testapp-job1-x8k8k   0/1     Completed           0          16s

 

 

  • 잡 컨트롤러 상태 확인
  • 10초간 실행되고 종료
watch -n1 kubectl get jobs.batch
NAME               COMPLETIONS   DURATION   AGE
testapp-job1       1/1           16s        13m

 

  • 파드 오브젝트 상태 확인
NAME                     READY   STATUS      RESTARTS   AGE
testapp-job1-x8k8k       0/1     Completed   0          19m

 


 

 

다중 잡 컨트롤러

job.spec.completions: 작업의 완료 갯수 지정

  • job이 한 번으로 완료되지 않고 작업을 여러 번 순차적으로 실행됨
  • 하나의 파드가 생성되어 job이 실행되고 완료되면, 두 번째 파드가 생성되어 job이 완료되고, 마지막으로 세 번째 파드가 생성되고 job이 완료되어야 모든 job이 완료됨
vagrant@kube-master1:~/test$ cat testapp-job-comp.yml
apiVersion: batch/v1
kind: Job
metadata:
  name: testapp-job-comp
spec:
  completions: 3
  template:
    metadata:
      labels:
        app: testapp-job
    spec:
      restartPolicy: OnFailure

      containers:
      - name: testapp
        image: busybox
        command: ['sleep','10']

 

  • 다중 잡 컨트롤러 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-job-comp.yml
job.batch/testapp-job-comp created

 

  • 실행 결과
  • 하나의 파드가 생성되어 job이 실행되고 완료되면, 두 번째 파드가 생성되어 job이 실행됨
  • 두 번째 파드가 생성되어 job이 실행되고 완료되면, 세 번째 파드가 생성되어 job이 실행되고 완료됨
watch -n1 kubectl get pods

kubectl get jobs.batch


첫 번째 job 실행 완료

 


두 번째 job 실행 완료


세 번째 job 실행 완료


 


 

병렬 다중 잡 컨트롤러

job.spec.parallelism: 동시에 실행할 잡의 갯수 지정

  • 병렬로 동시에 실행할 job의 갯수를 지정할 수 있음
  • 총 3개의 job을 실행하며, 동시에 병렬로 세 개의 job을 실행함
vagrant@kube-master1:~/test$ cat testapp-job-para.yml
apiVersion: batch/v1
kind: Job
metadata:
  name: testapp-job-para
spec:
  completions: 3
  parallelism: 3
  template:
    metadata:
      labels:
        app: testapp-job-para
    spec:
      restartPolicy: OnFailure
      containers:
      - name: testapp
        image: busybox
        command: ["sleep","10"]

 

  • 실행 결과 모니터링
watch -n1 kubectl get jobs.batch

watch -n1 kubectl get pods

kubectl get pods --watch

 

 

 


 

크론잡 컨트롤러

CronJob Controller

  • 잡 컨트롤러는 job이 한 번만 실행되지만 크론잡 컨트롤러는 주기적으로 job을 반복 실행할 필요가 있을 때 사용하는 컨트롤러
  • 리눅스 시스템의 crontab 도구와 같은 기능

 

크론잡 컨트롤러 생성

  • 크론잡 컨트롤러는 아직 베타 기능이며 크론잡 API 역시 batch 그룹을 사용하며 버전은 v1beta1을 사용함
  • 오브젝트 종류: CronJob
  • cronjob.spec.schedule:스케줄 지정 > 주기적인 시간 구성

 

  • 파일 생성
  • 1분마다 파드 생성
vagrant@kube-master1:~/test$ cat testapp-cj.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: testapp-cj
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app:  testapp-cj
        spec:
          restartPolicy: OnFailure
          containers:
          - name: testapp
            image: busybox
            command: ['sleep', '20']

 

  • 실행 결과
  • 1분마다 cronjob이 실행되어 파드가 생성되고 종료되는 것을 확인할 수 있음 

728x90
728x90

컨트롤러


DaemonSet

데몬셋이란

  • 노드 레이블과 매칭이되는 모든 노드 또는 노드 레이블이 없다면 모든 노드에 파드를 하나씩 배치하는 컨트롤러
  • 노드 수와 관계 있음
  • 연결되어 있는 노드에 파드를 하나씩 생성
  • 레플리카셋과 비슷한 기능이지만, 복제본을 저장하지 않는다는 점에서 차이가 있음
  • 컨트롤러는 노드가 추가되면 자동으로 하나의 파드를 배치하고, 노드가 삭제되어도 다른 노드에 파드를 생성하지 않음 

 


 

 

데몬셋 생성: testapp-ds

  • 파일 생성
  • testapp-ds 라는 데몬셋 생성
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: testapp-ds
spec:
  selector:
    matchLabels:
      app: testapp-ds
  template:
    metadata:
      labels:
        app: testapp-ds
    spec:
      containers:
      - name: testapp
        image: ghcr.io/c1t1d0s7/go-myweb
        ports:
        - containerPort: 8080
        imagePullPolicy: Never

 

  • 버추얼박스에서 node-3 종료 후 데몬셋 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-ds.yml
daemonset.apps/testapp-ds created

 

  • 실행 결과 모니터링
  • node-1, node-2에 파드 생성
watch -n1 kubectl get pods -o wide --show-labels

 

  • node-3을 재시작하면 파드가 자동으로 새로 생성됨

 


 

데몬셋 생성: testapp-ds-node

  • 노드 셀렉터를 정의한 파일 생성
  • nodeSelector: node=dev 노드 레이블을 선택하도록 정의
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: testapp-ds-node
spec:
  selector:
    matchLabels:
      app: testapp-ds-node
  template:
    metadata:
      labels:
        app: testapp-ds-node
    spec:
      nodeSelector:
        node: dev
      containers:
      - name: testapp
        image: ghcr.io/c1t1d0s7/go-myweb
        ports:
        - containerPort: 8080
        imagePullPolicy: Never

 

  • 데몬셋 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-ds-node.yml
daemonset.apps/testapp-ds-node created

 

  • 실행 결과
  • 생성된 데몬셋과 노드 레이블 확인
vagrant@kube-master1:~/test$ kubectl get daemonsets.apps
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
testapp-ds-node   0         0         0       0            0           node=dev        52s

 

  • node=dev 노드 레이블과 매칭되는 레이블이 없기 때문에 파드가 생성되지 않음
vagrant@kube-master1:~/test$ kubectl get pods
No resources found in default namespace.

생성된 데몬셋
현재 노드들의 레이블 확인

 

  • kube-node1 노드에 node=dev 레이블 생성
vagrant@kube-master1:~/test$ kubectl label nodes kube-node1 node=dev
node/kube-node1 labeled

 

 

 

  • 레이블을 생성하자 kube-node1 노드에 파드가 생성됨

 

  • kube-node1 노드의 LABELS 필드에 추가된 node=dev 레이블 확인
vagrant@kube-master1:~/test$ kubectl get nodes --show-labels
NAME           STATUS   ROLES    AGE    VERSION    LABELS
kube-master1   Ready    master   3d1h   v1.18.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kube-master1,kubernetes.io/os=linux,node-role.kubernetes.io/master=
kube-node1     Ready    <none>   3d1h   v1.18.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kube-node1,kubernetes.io/os=linux,node=dev
kube-node2     Ready    <none>   3d1h   v1.18.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kube-node2,kubernetes.io/os=linux
kube-node3     Ready    <none>   3d1h   v1.18.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kube-node3,kubernetes.io/os=linux

 

  • 노드 레이블 키를 제거하자 삭제되는 파드 확인
vagrant@kube-master1:~/test$ kubectl label nodes kube-node1 node-
node/kube-node1 labeled

 

  • node=dev 가 제거된 것을 확인할 수 있음

 

  • 데몬셋 삭제
vagrant@kube-master1:~/test$ kubectl delete -f testapp-ds-node.yml
daemonset.apps "testapp-ds-node" deleted

vagrant@kube-master1:~/test$ kubectl get daemonsets.apps
No resources found in default namespace.

 

728x90
728x90

컨트롤러


Controller 개념

컨트롤러란

  • 쿠버네티스에서는 어플리케이션 구동을 위해 파드를 생성함
  • 실제 쿠버네티스를 통해서 서비스를 구축할 경우 개별 파드 오브젝트를 직접 컨트롤하는 방식은 사용하지 않음
  • 쿠버네티스는 컨테이너 가상화의 특징을 활용하여 유연하고 확장성 있는 서비스를 구성할 수 있도록 컨트롤러 오브젝트를 제공하고 있음
  • 컨트롤러는 'A 파드 5개 생성' 과 같은 동작 방식이 아닌 'A 파드가 5개인 상태 유지'와 같은 방식을 사용함

 

레플리카셋 컨트롤러란

  • 쿠버네티스의 컨트롤러는 파드를 올바르게 동작하기 위해 특정 상태를 보장하는 역할
  • 특정 상태는 컨트롤러에 따라 동작하는 방식 및 정의하는 상태가 조금씩 다름
  • 레플리카셋 컨트롤러는 파드가 특정 갯수만큼 복제되고 동작하는 것을 보장함
  • 노드에 문제가 발생하여 파드가 정상 작동하지 않을 경우 자동으로 스케줄러에 의해 새로운 노드 또는 기존 노드에 다시 새로운 파드를 생성하여 파드의 갯수를 유지하도록 복제함

 

정의한 갯수를 유지하지 않는 경우

  • 수동으로 동일한 형식의 파드를 생성하는 경우
  • 기존의 파드 유형을 변경하는 경우
  • 정의한 복제본의 갯수를 변경하는 경우

 

레플리카셋 컨트롤러의 구성 요소

  • 레이블 셀렉터: 파드 지정
  • 파드 템플릿: 새로운 파드의 복제본 생성
  • 복제본 수: 기본 값은 '1'

 

레플리카셋 컨트롤러가 제공하는 기능

  • 정의한 복제본의 수만큼 파드가 없는 경우 파드 템플릿을 이용해 파드 생성
  • 노드에 장애 발생 시 해당 노드에서 실행 중이던 파드를 다른 노드에 복제본 생성
  • 수동이나 자동으로 파드 스케일 아웃이 가능함

 


 

실습


 

레플리카셋 컨트롤러 실습 - 1

.spec.selector.matchLabels: 일치성 기준 레이블 셀렉터 지정

  • 복제본 수: 3
  • .spec.selector.matchLabels: 레이블 셀렉터의 레이블: app=testapp-rs
  • .spec.template.metadata.labels: 파드의 레이블: app=testapp-rs
  • 레이블 셀렉터의 레이블과 파드 템플릿의 레이블이 일치하지 않으면 파드는 생성되지 않음
vagrant@kube-master1:~/test$ vi testapp-rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: testapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testapp-rs
  template:
    metadata:
      labels:
        app: testapp-rs
    spec:
      containers:
      - name: testapp
        image: c1t1d0s7/myweb
        ports:
        - containerPort: 8080
          protocol: TCP
        imagePullPolicy: Never

 

  • 레플리카셋 컨트롤러 생성
vagrant@kube-master1:~/test$ vagrant@kube-master1:~/test$ kubectl create -f testapp-rs.yml
replicaset.apps/testapp-rs created

 

  • 생성된 파드 확인
vagrant@kube-master1:~/test$ kubectl get pods
NAME                READY   STATUS    RESTARTS   AGE
testapp-pod-label   1/1     Running   0          8m46s
testapp-rs-c5g4s    1/1     Running   0          29s
testapp-rs-wwptq    1/1     Running   0          29s

vagrant@kube-master1:~/test$ kubectl get pods --show-labels
NAME                READY   STATUS    RESTARTS   AGE    LABELS
testapp-pod-label   1/1     Running   0          11m    app=testapp-rs
testapp-rs-c5g4s    1/1     Running   0          3m8s   app=testapp-rs
testapp-rs-wwptq    1/1     Running   0          3m8s   app=testapp-rs

vagrant@kube-master1:~/test$ kubectl describe replicaset.apps testapp-rs | less

 

 

  • 파드의 레이블 변경
  • 실행 중인 파드의 레이블이 변경됨과 동시에 testapp-rs 레이블이 정의된 파드가 새로 생성됨
vagrant@kube-master1:~/test$ kubectl label pods testapp-rs-wwptq app=rs --overwrite
pod/testapp-rs-wwptq labeled

vagrant@kube-master1:~/test$ kubectl get pods --show-labels
NAME                READY   STATUS    RESTARTS   AGE     LABELS
testapp-pod-label   1/1     Running   0          13m     app=testapp-rs
testapp-rs-c5g4s    1/1     Running   0          5m20s   app=testapp-rs
testapp-rs-dvgs6    1/1     Running   0          4s      app=testapp-rs
testapp-rs-wwptq    1/1     Running   0          5m20s   app=rs

 

  • 변경한 레이블을 원래대로 설정함과 동시에 한 개의 파드가 삭제됨
  • yml 파일에서 정의한 복제본 수를 유지하기 위함 (3개)
vagrant@kube-master1:~/test$ kubectl label pods testapp-rs-wwptq app=testapp-rs --overwrite
pod/testapp-rs-wwptq labeled

vagrant@kube-master1:~/test$ kubectl get pods --show-labels
NAME                READY   STATUS        RESTARTS   AGE    LABELS
testapp-pod-label   1/1     Running       0          14m    app=testapp-rs
testapp-rs-c5g4s    1/1     Running       0          6m1s   app=testapp-rs
testapp-rs-dvgs6    1/1     Terminating   0          45s    app=testapp-rs
testapp-rs-wwptq    1/1     Running       0          6m1s   app=testapp-rs

 


 

레플리카셋 컨트롤러 실습 - 2

 

파드 스케일 아웃

  • kubectl scale: 명령을 통한 스케일링
vagrant@kube-master1:~/test$ kubectl scale replicaset testapp-rs --replicas=4
replicaset.apps/testapp-rs scaled

vagrant@kube-master1:~/test$ kubectl get all

NAME                    READY   STATUS    RESTARTS   AGE
pod/testapp-pod-label   1/1     Running   0          38m
pod/testapp-rs-c5g4s    1/1     Running   0          30m
pod/testapp-rs-drssp    1/1     Running   0          4s
pod/testapp-rs-wwptq    1/1     Running   0          30m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP   24h

NAME                         DESIRED   CURRENT   READY   AGE
replicaset.apps/testapp-rs   4         4         4       30m

 

  • kubectl edit: 온라인 상태의 YAML 파일 수정을 통해 스케일링
  • 변경한 내용이 문법 오류일 경우 저장이 되지 않고, 변경 사항이 반영되지 않음
  • 저장 후 출력 구문이 "~ edited" 라고 나오는지 반드시 확인
vagrant@kube-master1:~/test$ kubectl edit replicasets.apps testapp-rs
replicaset.apps/testapp-rs edited

 

  • kubectl replace: 오브젝트 파일 수정을 통한 스케일링
  • 기존 생성된 오브젝트의 구성과 YAML 파일의 구성 정보를 비교한 후 변경된 사항에 대해서만 반영됨
vagrant@kube-master1:~/test$ vi testapp-rs.yml

vagrant@kube-master1:~/test$ kubectl replace -f testapp-rs.yml
replicaset.apps/testapp-rs replaced

 


 

레플리카셋 컨트롤러 실습 - 3

.spec.selector.matchExpressions: 집합성 기준 레이블 셀렉터 지정

  • 레이블 매칭 확장 연산자
In 레이블의 키가 존재하며, 값이 대상 중 하나와 일치
NotIn 레이블의 키가 존재하며, 값이 대상 모두와 불일치
Exists 레이블의 키가 존재함 (값 무관)
DoesNotExist 레이블의 키가 존재하지 않아야 함
  • 실행 중인 모든 파드 삭제
vagrant@kube-master1:~/test$ kubectl delete replicasets.apps testapp-rs
replicaset.apps "testapp-rs" deleted

vagrant@kube-master1:~/test$ kubectl get all
NAME                    READY   STATUS        RESTARTS   AGE
pod/testapp-pod-label   1/1     Terminating   0          46m
pod/testapp-rs-7kjdt    1/1     Terminating   0          3m46s
pod/testapp-rs-kss92    1/1     Terminating   0          5m4s
pod/testapp-rs-wwptq    1/1     Terminating   0          37m
pod/testapp-rs-xghs5    1/1     Terminating   0          3m46s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP   24h

vagrant@kube-master1:~/test$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP   24h

 

  • app=testapp-rs-exp 레이블을 포함한 파드 생성
  • metadata.name: testapp-pod-1, 2 부분을 변경하여 파드 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-pod.yml
pod/testapp-pod-1 created

vagrant@kube-master1:~/test$ kubectl create -f testapp-pod.yml
pod/testapp-pod-2 created

vagrant@kube-master1:~/test$ kubectl get pods --show-labels
NAME            READY   STATUS    RESTARTS   AGE   LABELS
testapp-pod-1   1/1     Running   0          52s   app=testapp-rs-exp,env=dev
testapp-pod-2   1/1     Running   0          16s   app=testapp-rs-exp,env=admin
vagrant@kube-master1:~/test$ cat testapp-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: testapp-pod-2
  labels:
    app: testapp-rs-exp
    env: admin
spec:
  containers:
  - name: testapp
    image: c1t1d0s7/myweb
    ports:
    - containerPort: 8080
    imagePullPolicy: Never

 

  • app(key)의 값이 testapp-rs-exp 또는 testapp-rs와 일치하고 env(key)를 포함한 파드의 복제본 4개가 유지되도록 구성함
vagrant@kube-master1:~/test$ vi testapp-rs-exp.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: testapp-rs-exp
spec:
  replicas: 4
  selector:
    matchExpressions:
    - key: app
      operator: In
      values:
      - testapp-rs-exp
      - testapp-rs
    - key: env
      operator: Exists
  template:
    metadata:
      labels:
        app: testapp-rs
        env: op
    spec:
      containers:
      - name: testapp
        image: c1t1d0s7/myweb
        ports:
        - containerPort: 8080
        imagePullPolicy: Never

 

  • 레플리카셋 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-rs-exp.yml
replicaset.apps/testapp-rs-exp created

 

  • 레플리카셋 확인
  • 실행 중인 파드는 총 4개
vagrant@kube-master1:~/test$ kubectl get all --show-labels
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
pod/testapp-pod-1          1/1     Running   0          13m   app=testapp-rs-exp,env=dev
pod/testapp-pod-2          1/1     Running   0          12m   app=testapp-rs-exp,env=admin
pod/testapp-rs-exp-9mnjz   1/1     Running   0          11s   app=testapp-rs,env=op
pod/testapp-rs-exp-pmc29   1/1     Running   0          11s   app=testapp-rs,env=op

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   LABELSservice/kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP   25h   component=apiserver,provider=kubernetes

NAME                             DESIRED   CURRENT   READY   AGE   LABELS
replicaset.apps/testapp-rs-exp   4         4         4       11s   <none>

 

  • testapp-pod-1 파드의 레플리카셋 컨트롤러 확인
  • => testapp-rs-exp 파드들과 컨트롤러가 동일함
vagrant@kube-master1:~/test$ kubectl describe pods testapp-rs-exp-9mnjz | grep -i 'control'
Controlled By:  ReplicaSet/testapp-rs-exp

vagrant@kube-master1:~/test$ kubectl describe pods testapp-pod-1 | grep -i 'control'
Controlled By:  ReplicaSet/testapp-rs-exp

 

  • testapp-pod-1의 env 레이블 삭제
vagrant@kube-master1:~/test$ kubectl label pods testapp-pod-1 env- --overwrite
pod/testapp-pod-1 labeled

 

  • 파드 확인
  • app=testapp-rs, env=op 레이블을 포함한 파드가 생성됨
vagrant@kube-master1:~/test$ kubectl get all --show-labels
NAME                       READY   STATUS    RESTARTS   AGE    LABELS
pod/testapp-pod-1          1/1     Running   0          121m   app=testapp-rs-exp
pod/testapp-pod-2          1/1     Running   0          120m   app=testapp-rs-exp,env=admin
pod/testapp-rs-exp-9mnjz   1/1     Running   0          107m   app=testapp-rs,env=op
pod/testapp-rs-exp-gjnkk   1/1     Running   0          25s    app=testapp-rs,env=op
pod/testapp-rs-exp-pmc29   1/1     Running   0          107m   app=testapp-rs,env=op

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   LABELS
service/kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP   26h   component=apiserver,provider=kubernetes

NAME                             DESIRED   CURRENT   READY   AGE    LABELS
replicaset.apps/testapp-rs-exp   4         4         4       107m   <none>

 

  • testapp-pod-1 파드의 레플리카셋 컨트롤러 확인
  • => 컨트롤러가 사라짐
vagrant@kube-master1:~/test$ kubectl describe pods testapp-pod-1  | grep -i 'control'
vagrant@kube-master1:~/test$
728x90
728x90

파드의 생명 주기


파드의 생명 주기

오브젝트 상태 모니터링 (파드 생성)

vagrant@kube-master1:~$ kubectl get pods --watch

 

  • watch: 정해진 시간 뒤에 명령어를 실행함
vagrant@kube-master1:~$ watch -n1 kubectl get pods

 

kubelet

  • 쿠버네티스 노드의 구성 요소
  • 파드의 컨테이너 상태 추적
  • 오류 발생 시 정상 상태로 만들기 위한 조치로 컨테이너를 재시작할 수 있음

 

파드의 생명 주기

  • 파드는 정의된 순서대로 생명 주기를 가짐 (Pending > Running > Succeeded or Failed)
  • 파드는 임시로 사용하기 위한 워크로드 리소스 (영구적으로 사용 X)
  • 파드가 생성되면 파드를 식별하기 위한 고유의 UID가 할당되고, 종료될 때까지 특정 노드에서만 실행
  • 쿠버네티스는 파드를 일회용으로 간주하며, 상위 레벨의 추상화 리소스인 컨트롤러 리소스를 이용하여 파드 관리

 

파드의 단계

  • kubectl get pods 명령 결과 중 STATUS 필드에서 확인
Pending - 파드가 클러스터에서 승인되었지만, 실행되고 있지 않음
- 파드가 스케줄링되기 전
- 이미지 풀링
Running - 파드가 노드에 할당됨
- 하나 이상의 컨테이너가 실행 중
- 시작 또는 재시작 중
Succeeded - 모든 컨테이너가 정상적으로 종료
- 재시작되지 않음
Failed - 모든 컨테이너가 종료
- 하나 이상의 컨테이너가 실패로 종료
Unknown - 알 수 없음
- 일반적으로 노드와의 통신 오류

 


 

 

컨테이너 상태

컨테이너 상태

  • 스케줄러가 파드를 특정 노드에 할당하면, kubelet은 컨테이너 런타임을 이용하여 컨테이너를 생성하며, kubelet은 컨테이너의  상태를 주기적으로 모니터링
  • 컨테이너의 상태는 kubectl describe pod 명령의 결과 중 Containers 항목으로 확인 가능
Waiting - 컨테이너가 Running 또는 Terminated 상태가 아닌 상태
- 컨테이너 시작 전 필요한 작업 중(이미지 풀링, 스토리지 연결 등)
- Reason 필드에 이유가 표시됨
Running - 실행 중
- 해당 상태가 된 시각 표시
Terminated - 컨테이너 실행이 완료됨
- 실패
- Reason 필드에 이유가 표시됨
- 해당 상태가 된 시각 표시

 

컨테이너 재시작 정책

.spec.restartPolicy: 재시작 정책

  • 모든 컨테이너는 컨테이너의 오류 발생 시 재시작을 하기 위한 재시작 정책을 가지고 있음
  • 최대 300초로 제한된 지수 백오프 지연 시간을 순차적으로 가지며 재시작 (10초, 20초, 40초, 80초, ...)
  • 10동안 이상 없이 동작하면 지수 백오프 지연 시간 초기화
Always - 기본값
- 종료/실패 시 항상 재시작
Onfailure 실패 시 재시작 (정상 종료 시 재시작하지 않음)
Never 재시작 하지 않음

 

 


 

kubelet으로 컨테이너 진단


컨테이너 프로브

컨테이너 프로브는 kubelet이 컨테이너를 주기적으로 진단하는 프로브 핸들러를 호출함

  • 프로브 핸들러
  • 세 가지 메커니즘을 가지고 컨테이너의 상태 진단
HTTPGetAction - 특정 경로에 HTTP GET 요청
- HTTP 응답 코드가 2XX 또는 3XX 인지 확인함
TCPSocketAction - 특정 TCP 포트 연결
- 포트가 활성화되어 있는지 확인
ExecAction - 컨테이너 내의 지정된 바이너리 실행
- 명령의 종료 코드가 0인지 확인

 

  • 프로브 핸들러 상태
Success 진단 통과
Failure 진단 실패
Unknown 진단 자체가 실패

 

  • 프로브 종류
livenessProbe - 컨테이너가 동작 중인지 확인
- 진단에 실패하면 재시작 정책 적용
- livenessProbe를 선언하지 않으면, 기본 상태는 Success
readinessProbe - 컨테이너가 요청을 처리할 준비가 되었는지 확인
- 진단에 실패하면 엔드포인트 컨트롤러는 파드의 IP 주소를 엔드포인트에서 제거
- readinessProbe를 선언하지 않으면, 기본 상태는 Success
startupProbe - 컨테이너 내의 애플리케이션이 시작되었는지 확인
- startupProbe가 선언되었을 경우, 진단을 통과하기 전까지 다른 프로브를 활성화하지 않음

 

 

  • 프로브 정의
.spec.containers.*Probe 라이브니스 프로브 정의
.spec.containers.*Probe.httpGet HTTP GET 프로브 정의
.spec.containers.*Probe.tcpSocket TCP 소켓 프로브 정의
.spec.containers.*Probe.exec Exec 프로브 정의

 

 


 

livenessProbe

livenessProve란

  • 컨테이너가 실행되었는지 확인하고 진단이 실패하면 컨테이너를 종료시키고, 재시작 정책에 따라서 컨테이너를 재시작함
  • 컨테이너에 livenessProbe를 명시하지 않았다면 기본 상태 값 Success로 표시

 

정상 실행

  • testapp-pod-liveness.yaml 파일 생성
# testapp-pod-liveness.yaml

apiVersion: v1
kind: Pod
metadata:
  name: testapp-pod-liveness
spec:
  containers:
  - image: ghcr.io/c1t1d0s7/go-myweb
    name: testapp
    ports:
    - containerPort: 8080
      protocol: TCP
    livenessProbe:
      httpGet:
        path: /health
        port: 8080

 

  • 파드 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-pod-liveness.yml
pod/testapp-pod-liveness created

 

  • 실행 결과 확인
vagrant@kube-master1:~/test$ kubectl get pods --watch
NAME                READY   STATUS    RESTARTS   AGE
testapp-pod-liveness   0/1     Pending       0          0s
testapp-pod-liveness   0/1     Pending       0          0s
testapp-pod-liveness   0/1     ContainerCreating   0          0s
testapp-pod-liveness   1/1     Running             0          3s

 

비정상 실행: 404

  • liveness 작동을 확인하기 위해 에러가 발생하도록 설정
  • livenessProbe.httpGet.path 부분 수정
#testapp-pod-liveness-404.yaml

apiVersion: v1
kind: Pod
metadata:
  name: testapp-pod-liveness-404
spec:
  containers:
  - image: ghcr.io/c1t1d0s7/go-myweb
    name: testapp
    ports:
    - containerPort: 8080
      protocol: TCP
    livenessProbe:
      httpGet:
        path: /health?code=404
        port: 8080

 

  • 파드 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-pod-liveness-404.yml
pod/testapp-pod-liveness-404 created

 

  • 파드 상태 확인
  • 시간이 지나면 RESTART 필드가 0에서 양수로 변경됨
  • => livenessProbe에 의해 컨테이너가 건강한 상태가 아님을 감지하고 재시작을 시도했다는 의미
  • 시간이 더 지나면 CrashLoopBackOff 상태인 것을 확인할 수 있음
  • => 지수 백오프 지연을 나타냄
vagrant@kube-master1:~/test$ kubectl get pods --watch
NAME                READY   STATUS    RESTARTS   AGE
testapp-pod-liveness-404   0/1     Pending             0          0s
testapp-pod-liveness-404   0/1     Pending             0          0s
testapp-pod-liveness-404   0/1     ContainerCreating   0          0s
testapp-pod-liveness-404   1/1     Running             0          3s
testapp-pod-liveness-404   1/1     Running             1          33s
testapp-pod-liveness-404   1/1     Running             2          62s
testapp-pod-liveness-404   1/1     Running             3          92s
testapp-pod-liveness-404   1/1     Running             4          2m2s
testapp-pod-liveness-404   0/1     CrashLoopBackOff    4          2m31s

 

  • Containers.Liveness 필드 값 확인
  • livenessProbe의 경우 초기 지연 시간(initialDelaySeconds)을 설정하는 것이 중요한데, 파드(컨테이너)가 실행되고 난 이후 애플리케이션에 따라 애플리케이션이 정상 동작하는 데 시간이 걸릴 수 있기 때문임
  • 간혹 초기 지연 시간을 설정하지 않아 계속적인 재시작을 초래할 수 있음
  • livenessProbe가 동작하여 컨테이너를 종료하고 재시작하는 것을 확인할 수 있음
vagrant@kube-master1:~/test$ kubectl describe pods testapp-pod-liveness-404
~
 Liveness:       http-get http://:8080/health%3Fcode=404 delay=0s timeout=1s period=10s #success=1 #failure=3
~

delay - 프로브를 초기화 하기 전 지연
- 기본값: 0초
- .spec.contianers.*Probe.initialDelaySeconds
timeout - 프로브 타임아웃
- 기본값: 1초
- .spec.containers.*Probe.timeoutSeconds
period - 프로브 주기
- 기본값: 10초
- .spec.containers.*Probe.periodSeconds
success - 진단 성공 임계값
- 기본값: 1
- .spec.containers.*Probe.successThreshold
failure - 진단 실패 임계값
- 기본값: 3
- .spec.containers.*Probe.failureThreshold

 


 

startupProbe

startupProbe란

  • 컨테이너 내의 애플리케이션이 시작되었는지 확인
  • startupProbe가 선언되었을 경우, 진단을 통과하기 전까지 다른 프로브를 활성화하지 않음
  • startupProbe가 실패하면 kubelet은 컨테이너를 종료하고 컨테이너는 재시작 정책을 수행함

 

정상 실행

  • 파일 생성
vagrant@kube-master1:~/test$ cat testapp-pod-startup.yml

apiVersion: v1
kind: Pod
metadata:
  name: testapp-pod-startup
spec:
  containers:
  - name: testapp
    image: ghcr.io/c1t1d0s7/go-myweb
    ports:
    - containerPort: 8080
    startupProbe:
      httpGet:
        path: /health
        port: 8080
    livenessProbe:
      httpGet:
        path: /health
        port: 8080

 

  • 파드 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-pod-startup.yml
pod/testapp-pod-startup created

 

  • 실행 결과
  • 파드가 정상적으로 생성됨
vagrant@kube-master1:~$ kubectl get pods --watch

 

vagrant@kube-master1:~$ watch -n1 kubectl get pods

 

vagrant@kube-master1:~$ kubectl describe pod testapp-pod-startup

 

비정상 실행: 404

  • 파일 생성
  • 파드가 정상적으로 생성되지 않도록 파일 수정
  • startupProbe.httpGet.path 부분 수정
vagrant@kube-master1:~/test$ cat testapp-pod-startup-404.yml

apiVersion: v1
kind: Pod
metadata:
  name: testapp-pod-startup-404
spec:
  containers:
  - name: testapp
    image: ghcr.io/c1t1d0s7/go-myweb
    ports:
    - containerPort: 8080
    startupProbe:
      httpGet:
        path: /health?code=404
        port: 8080
    livenessProbe:
      httpGet:
        path: /health
        port: 8080

 

  • 파드 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-pod-startup-404.yml
pod/testapp-pod-startup-404 created

 

  • 실행 결과
  • 파드의 상태가 Running 상태이지만 준비(READY 0/1)가 되지 않고 있음
  • startupProbe에 실패한 것을 확인할 수 있음
  • startupProbe에 실패하면 livenessProbe는 활성화되지 않음
vagrant@kube-master1:~$ kubectl get pods --watch

 

vagrant@kube-master1:~$ watch -n1 kubectl get pods

 

vagrant@kube-master1:~$ kubectl describe pod testapp-pod-startup-404

728x90

+ Recent posts