반응형

 

  • 쿠버네티스 크론잡(cronjob) 이란? 

크론잡은 매일 오후 6시에 특정 파드를 실행시키는 등 지정한 일정에 따라 잡을 실행 시킬 수 있습니다.

잡을 모를 경우 이전에 업로드한 글을 참고 해주세요. (https://nirsa.tistory.com/142)

 

  • 크론잡 생성 및 확인

아래 코드는 크론잡과 병렬 잡을 같이 사용하는 코드 입니다..

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: pi
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      completions: 3
      parallelism: 3
      template:
        spec:
          containers:
          - name: pi
            image: perl
            command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(100)"]
          restartPolicy: Never
      backoffLimit: 4
  • apiVersion apps/v1beta1 → 쿠버네티스의 apps/v1beta1 API를 사용 합니다.
  • kind: CronJob → CronJob의 작업으로 명시 합니다.
  • spec.schedule → 코드 내 설정은 1분마다 잡을 실행하도록 설정 합니다. (순서에 따라 "분 시 일 월 요일" 입니다. )
  • spec.jobTemplate → 실행될 잡의 설정 내용 입니다.

yaml 파일을 설정할 때 혹시나 잡 이름이 52자 이하인지 확인해야 합니다. 크론잡은 잡 이름에 11자를 자동으로 추가하고, 잡 이름의 최대 길이는 63자리이므로 혹시나 너무 긴 이름을 사용하였을 경우 이를 생각하고 재지정해야 합니다.

실행 후 몇분 뒤 확인해보면 아래 이미지처럼 매분 잡과 3개의 파드가 실행되고 있다는걸 확인할 수 있습니다.

 

크론잡의 확인은 kubectl get cronjob 으로 가능하고, kubectl delete cronjobs [크론잡 이름] 으로 크론잡을 삭제하면 연관된 모든 잡과 파드가 삭제 됩니다.

 

  • 크론잡 설정

크론잡을 좀 더 안전하게 사용하기 위해서는 필드값을 몇개 추가해주어야 합니다. 여러가지의 잡이 실행되거나 등 예약한 작업이 누락될 가능성이 있기 때문 입니다.

크론잡 컨트롤러는 마지막 잡부터 지금까지 얼마나 많은 잡이 누락되었는지 확인하게 되는데, 만약 100회 이상 누락이 발생할 경우 에러를 떨구며 잡을 실행하지 않게 됩니다.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: test
spec:
  schedule: "*/1 * * * *"
  startingDeadlineSeconds: 200
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      completions: 3
      parallelism: 3
      template:
        spec:
          containers:
          - name: test
            image: test
          restartPolicy: Never
      backoffLimit: 4
  • spec.startingDaelineSeconds: 200 → 여기서 지정된 시간동안 위에서 설명했던 잡 누락 횟수를 카운팅 합니다. 200초 동안 100개 이상 발생 시 에러를 떨구며 잡을 실행하지 않습니다.
  • spec.concurrencyPolicy: Forbid → 정상 종료되지 않고 실행 상태인 잡이 있을 경우 다음 잡을 실행해야될 시간이 오더라도 잡을 실행하지 않습니다.
  • spec.jobTemplate.spec.template.spec.containers.image → concurrencyPolicy를 확인해보기 위해 존재하지 않는 이미지 파일을 입력 하였습니다. 

 

concurrencyPolicy의 기본 값은 Allow 입니다. 이 값은 크로잡이 여러개의 잡을 동시에 실행할 수 있도록 해주고, Forbid는 정상 종료되지 않고 실행 상태인 잡이 있을 경우 다음 잡을 실행해야될 시간이 오더라도 잡을 실행하지 않습니다.

또한 Replace 는 정상 종료되지 않고 실행 상태인 잡이 있을 경우 실행중인 상태의 잡을 종료하고, 다음 실행해야할 잡을 실행 시킵니다.

 

위의 코드에서 존재하지 않는 이미지 파일을 지정하여 파드가 정상 종료되지 않도록 설정 하였고, 현재 concurrencyPolicy의 값은 Forbid 이므로 정상 종료되지 않은 잡이 작업을 계속하며 다음 잡을 실행시킬 시간이 되어도 기존 잡이 계속 유지 됩니다.

매분 실행되도록 설정하였고 크론탭이 실행된지 3분 이상 지낫지만, 잡은 첫 실행 후 다음 잡이 실행되지 않고 있습니다.

 

아래는 ConcurrencyPolicy의 값이 Replace 입니다. 잡이 정상 종료되지 않아도 매 분마다 기존에 있던 잡을 종료하고 새로운 잡이 실행중임을 알 수 있습니다.

 

마지막으로 기본값인 Allow 입니다. 기존 잡과 새로운 잡이 동시에 실행중임을 알 수 있습니다.

 

반응형
반응형

 

  • 쿠버네티스 잡(job) 이란?

잡은 하나 이상의 파드를 지정하고 지정된 수의 파드를 성공적으로 실행하도록 하는 설정 입니다. 노드의 H/W 장애나 재부팅 등으로 인해 파드가 정상 실행이 되지 않았을 경우 job은 새로운 파드를 시작하도록 할 수 있습니다.

즉, 백업이나 특정 배치 파일들처럼 한번 실행하고 종료되는 성격의 작업에 사용될 수 있습니다.

 

  • 잡 생성 및 확인

아래 코드는 원주율은 2000 자리까지 계산 후 출력해주는 코드 입니다.

저는 경로를 "/root/kubespray/inventory/test/job/"에 test-job.yaml 로 저장 하였습니다.

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4
  • apiVersion batch/v1 → 쿠버네티스의 batch/v1 API를 사용 합니다.
  • kind: Job → Job의 작업으로 명시 합니다.
  • metadata.name → Job 이름을 설정 합니다.
  • spec.template.spec.containers → 실행할 컨테이너의 t설정을 저장 합니다.
  • spec.template.spec.containers.restartPolicy → 파드의 재시작 정책을 설정 합니다. Never는 재시작을 하지 않는 설정 입니다.

 

kubectl apply -f test-job.yaml 을 실행 후 kubectl get job 으로 잡 이름을 확인 후 kubectl describe job [잡 이름] 을 입력하면 아래와 같이 성공적으로 실행 했으며 약 11초가 걸렸다는 내용을 확인할 수 있습니다.

 

추가적으로 해당 실행 값을 확인할 땐 kubectl get pods 로 파드의 이름을 확인한 뒤 kubectl logs [파드 이름] 을 입력하면 아래와 같이 실행 값을 확인할 수 있습니다.

 

  • restartPolicy, backoffLimit 필드 옵션

 restartPolicy 필드 옵션에는 아래와 같이 3가지가 있으며 상황에 따른 재시작 유무는 쿠버네티스 docs 문서에서 확인할 수 있습니다. 아래 docs 문서 링크에서 Ctrl+F로 Example states 를 검색하면 확인 가능 합니다.

  • Always → 항상 재시작 합니다.
  • OnFailure → 비정상 종료 발생 시 컨테이너를 재시작 합니다.
  • Never → 재시작을 하지 않습니다.

restartPolicy 필드 상황별 재시작 유무 : https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/

 

backoffLimit 은 백오프 정책이라고 하며 잡에 실패할 경우 다시 실행시킬 재시도 횟수를 지정 합니다. 기본적으로 6이 설정 되어 있으며 재시작 실패 후 10초, 20초, 40초와 같이 실행을 재시도 합니다. 

 

  • 여러개의 컨테이너 처리

아래 코드와 같이 하나의 파드에 여러개의 컨테이너를 처리할수도 있습니다. pi 라는 파드 이름을 가진 작업에 pi1, pi2 컨테이너를 생성하고 pi1은 원주율의 100자리 계산 후 출력, pi2는 원주율의 200자리 계산 후 출력 입니다.

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi1
        image: perl
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(100)"]
      - name: pi2
        image: perl
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(200)"]
      restartPolicy: Never
  backoffLimit: 4

 

kubectl apply -f [yaml파일명] 이후 파드 이름으로 logs를 출력하려고 하면 입력했던 2개의 컨테이름(pi1, pi2)이 출력되면서 하나를 선택하라고 합니다.

kubectl logs [파드명] pi1 과 같이 입력하면 각각의 컨테이너 출력값을 확인할 수 있습니다.

 

  • 병렬 잡 (Parallel Jobs)

바로 위에서는 하나의 잡과 하나의 파드에 컨테이너를 여러개 실행 시켰다면, 병렬 잡은 하나의 잡에 여러개의 파드를 실행시켜 작업하는것을 말합니다. 이 작업을 할땐 비정렬 작업, 완료 횟수가 고정되어있는 병렬 작업, 작업간 대기열이 존재하는 병렬 작업이 대표적인 예 입니다.

위의 3가지 상황에 따른 옵션 선택은 아래 링크에서 Ctrl + F로 Parallel Jobs 를 검색하면 찾을 수 있습니다.

3가지 상황에 따른 옵션 선택 : https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/

 

아래 코드는 3개의 파드를 실행 시키며 파드가 3개 이상 정상 종료 될 경우 잡을 성공 처리 하는 코드 입니다. completions과 parallelism은 둘 다 기본값은 1 입니다.

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  completions: 3
  parallelism: 3
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(100)"]
      restartPolicy: Never
  backoffLimit: 4
  • spec.completions: 3 → 파드가 3개 이상 정상 종료 될 경우 잡을 성공 처리 합니다.
  • spec.parallelism: 3 → 한번에 3개의 파드를 실행 합니다.

 

위의 코드를 실행하면 아래와 같이 3개의 파드가 실행 된것을 확인할 수 있습니다.

 

반응형
반응형

 

  • 데몬셋(Daemonset) 이란?

데몬셋은 디플로이먼트와 유사하게 파드를 생성하고 관리 합니다. 디플로이먼트는 롤링 업데이트나 배포 일시 중지, 재개 등 배포 작업을 좀 더 세분화하여 조작하였다면, 데몬셋은 특정 노드 또는 모든 노드에 항상 실행되어야 할 특정 파드를 관리 합니다.

하나의 예를 들자면 모니터링 시스템 구축을 위해 모든 노드에 특정 파드(로그 수집용)를 관리해야 할 때 사용할 수 있습니다. 모니터링 시스템을 원활히 사용하기 위해선 모든 노드에 항상 로그 수집할 무언가가 필요하기 때문 입니다. 특정 노드를 지정하여 사용할수도 있습니다.

 

  • 데몬셋 생성 및 확인

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: test-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: test-logging
spec:
  selector:
    matchLabels:
      name: test-elasticsearch
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: test-elasticsearch
    spec:
      containers:
      - name: container-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
      terminationGracePeriodSeconds: 30
  • apiVersion apps/v1 → 쿠버네티스의 apps/v1 API를 사용 합니다.
  • kind: DaemonSet → DaemonSet의 작업으로 명시 합니다.
  • metadata.name → DaemonSet의 이름을 설정 합니다.
  • metadata.namespace → 네임스페이스를 지정 합니다. kube-system은 쿠버네티스 시스템에서 직접 관리하며 보통 설정 또는 관리용 파드를 설정합니다.
  • metadata.labels → DaemonSet를 식별할 수 있는 레이블을 지정 합니다.
  • spec.selector.matchLabels → 어떤 레이블의 파드를 선택하여 관리할 지 설정 합니다.
  • spec.updateStrategy.type → 업데이트 방식을 설정 합니다. 이 코드에서는 롤링 업데이트로 설정 돼었으며 OnDelete 등의 방식으로 변경이 가능 합니다. 롤링 업데이트는 설정 변경하면 이전 파드를 삭제하고 새로운 파드를 생성 합니다.
  • spec.template.metadata.labels.name → 생성할 파드의 레이블을 파드명: "" 으로 지정 합니다.
  • spec.template.spec.containers → 하위 옵션들은 컨테이너의 이름, 이미지, 메모리와 CPU의 자원 할당을 합니다.
  • terminationGracePeriodSeconds 30  → 기본적으로 kubelet에서 파드에 SIGTERM을 보낸 후 일정 시간동안 graceful shutdown이 되지 않는다면 SIGKILL을 보내서 파드를 강제 종료 하게 됩니다. 이 옵션은 그레이스풀 셧다운 대기 시간을 30초로 지정하여 30초 동안 정상적으로 종료되지 않을 경우 SIGKILL을 보내서 강제 종료 시킵니다.

 

네임스페이스를 따로 지정 했으므로 kubectl get daemonset,pods -n kube-system 으로 조회할 수 있습니다. n 옵션은 네임스페이스를 따로 지정 합니다.

위와같이 실제로 kube-system이란 네임스페이스에 데몬셋이 실행 되었으며 test-elasticsearch라는 파드가 2개 생성된것을 확인 했습니다. (현재 저의 테스트환경이 마스터 3대, 노드 2대이므로 노드 개수에 맞춰 파드가 생성 됩니다.)

위에서는 모든 노드에 하도록 했지만 .spec.template.spec.nodeSelector 또는 .spec.template.spec.affinity 를 명시하여 특정 노드를 정해줄 수 있습니다. 두 옵션의 차이는 노드 셀렉터 / 노트 어피니티의 차이이며 자세한 내용은 쿠버네티스의 docs 문서를 참고 해주세요.

노드 셀렉터(.spec.template.spec.nodeSelector) : https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector

노드 어피니티(.spec.template.spec.affinity) : https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity

 

  • 파드가 어떤 노드에서 사용중인지 확인

우선 생성한 마스터 서버에서 kubectl get pods -n kube-system 으로 어떤 노드에서 동작중인지 확인하고 싶은 파드의 이름을 확인 후 kubectl edit pods [파드 이름] -n kube-system 을 입력해서 vi 편집기로 진입 합니다.

아래에 표시한것처럼 현재 동작중인 노드의 이름(호스트명)을 확인할 수 있습니다.

 

  • 데몬셋 업데이트

데몬셋의 내용을 변경하고 싶다면 kubectl get daemonset -n kube-system 을 입력하여 데몬셋 이름을 확인하고 kubectl edit daemonset [데몬셋 이름] -n kube-system 입력 후 vi 편집기로 진입 합니다.

이후 spec.template.spec.container.env에 아래와 같이 환경 변수의 이름과 값을 작성해 주세요.

 

현재 롤링 업데이트 방식이므로 바로 적용이 되며 기존 파드를 삭제하고 새로운 파드를 생성해냅니다. kubectl  kubectl describe daemonset [데몬셋 이름] -n kube-system 을 입력하여 보면 환경 변수의 값에 입력했던 환경변수 키 - 값이 재대로 적용 되었고, kubectl get daemonset,pods -n kube-system 으로 새로운 파드가 생성중임을 알 수 있습니다.

 

반응형
반응형

 

  • 디플로이먼트(Deployment) 란?

디플로이먼트는 레플리카셋의 상위 개념으로 볼 수도 있습니다. 레플리카셋을 생성하는 디플로이먼트를 정의할 수 있고, 배포 작업을 좀 더 세분화(롤링 업데이트 등) 하여 조작할 수 있는 기능을 가지고 있습니다.

이러한 이유로 레플리카셋만 사용하는것 보다는 디플로이먼트를 사용하는 추세라고 합니다.

 

  • 디플로이먼트 생성 및 확인

우선 기본적인 디플로이먼트를 생성 하겠습니다. 아래 코드를 저장해주시고 저는 경로 "/root/kubespray/inventory/test/deployment" 에 test-deployment.yaml 로 저장 하였습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
  labels:
    app: test-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test-deployment
  template:
    metadata:
      labels:
        app: test-deployment
    spec:
      containers:
      - name: test-deployment
        image: nginx:1.7.9
        ports:
        - containerPort: 80
  • apiVersion apps/v1 → 쿠버네티스의 apps/v1 API를 사용 합니다.
  • kind: Deployment → Deployment의 작업으로 명시 합니다.
  • metadata.name → Deployment의 이름을 설정 합니다.
  • metadata.labels.app → Deployment의 레이블을 설정 합니다.
  • spec.replicas → 파드의 개수를 몇개 유지할 것 인지 설정 합니다. 기본값은 1 입니다.
  • spec.selector → 어떤 레이블의 파드를 선택하여 관리할지에 대한 설정 입니다. 앱 컨테이너의 test-deployment 레이블을 식별하여 해당되는 파드들을 관리하며, 이 필드가 없을 경우 spec.template.metadata.labels에 설정된 내용들을 기본값으로 사용 합니다.
  • spec.template.metadata → 어떤 파드를 실행할지에 대한 정보를 하위에 설정 합니다.
  • spec.template.metadata.name → 생성될 파드의 이름을 지정 합니다.
  • spec.template.metadata.labels.app:test-deployment → 식별하는 레이블이 앱 컨테이너이며 test-deployment 으로 식별 합니다.
  • spec.spec → 이 하위의 옵션들은 컨테이너에 대한 설정을 합니다. 위 코드에선 컨테이너 명, 이미지, 포트를 지정 했습니다.

 

마찬가지로 kubectl apply -f [파일명] 으로 생성 후 kubectl get deployment,replicaset,pods 를 입력하여 조회를 해보겠습니다.

디플로이먼트를 생성했더니 레플리카셋 한개와 3개의 파드가 생성 되었습니다. 디플로이먼트는 레플리카셋을 좀 더 효율적으로 배포하기 위해 사용되므로 기본적으로 디플로이먼트 생성하면 레플리카셋도 같이 생성 되기 때문에 파드 개수유지를 보증 합니다.

기본적인 코드긴 하지만 사실 레플리카셋과 디플로이먼트 yaml 파일을 비교해봐도 kind와 replicas, selector가 spec 하위 옵션으로 들어갓다는거 말고는 거의 차이가 없습니다.

 

  • 디플로이먼트 업데이트

디플로이먼트를 사용하여 이미지의 버전을 업데이트하거나 할 수 있습니다. 명령 사용 방법은 아래와 같습니다.

  • kubectl set image deployment/[디플로이먼트이름] [컨테이너이름]=[이미지]:[버전]

 

가장 처음 사용했던 코드에서 해당되는 부분은 아래와 같으며 빨간색은 디플로이먼트 이름, 파란색은 컨테이너와 이미지,버전 입니다. 이제 확인되었으면 명령어를 입력하여 실제로 업데이트가 되는지 확인 해보면 됩니다.

저는 kubectl set image deployment/test-deployment test-deployment=nginx:1.9.1 을 사용하여 기존에 있던 nginx 1.7.9 버전을 ngixn 1.9.1 버전으로 업데이트 하였습니다.

 

이미지와 같이 새로운 레플리카셋, 파드가 생성되며 기존의 레플리카셋(96bc7dbd9)은 0/0/0 상태가 되어 비활성화로 변경 됩니다. 좀 더 자세히 확인하고 싶다면 kubectl describe deployments 를 입력해보면 아래와 같이 확인해볼 수 있습니다.

 

  • 디플로이먼트 롤백 및 롤아웃 기록 조회

디플로이먼트를 이용하여 이전 작업으로 되돌아가거나, 작업했던 기록을 살펴볼 수 있습니다. 롤아웃 기록은 기본적으로 10까지 저장하며 더 많은 기록을 저장하기 위해서는 따로 설정이 필요 합니다. 롤아웃 기록 조회 명령은 아래와 같습니다.

  • kubectl rollout history deployment [디플로이먼트 이름]

그럼 위와 같은 메세지가 출력 되는데 현재 CHANGE-CAUSE는 따로 입력한적이 없으므로 none 으로 표시되고 가장 최근에한 작업이 2번(REVISION)이라는것을 알 수 있습니다.

 

롤백할때는 아래 명령어를 입력하시면 되며, 저는 최근에 한 작업이 2번이니 그보다 전인 1번으로 되돌아 가겠습니다.

  • kubectl rollout undo deployment [디플로이먼트 이름] --to-revision=[숫자]

롤백한 후 파드 하나는 종료중이며 새로운 파드 3개가 생성 및 이미지 버전을 1.9.1로 업그레이드 후 비활성화 되었던 레플리카셋(96bc7dbd9)이 다시 활성화 상태로 변경된걸 확인할 수 있습니다. kubectl describe deployments 를 입력해서 자세한 내용을 확인하면 다시 이미지 버전이 1.7.9로 변경된것을 확인할 수 있습니다.

 

  • 디플로이먼트 롤아웃 기록에 CHANGE-CAUSE를 남겨서 버전 기록하기

kubectl edit deployment [디플로이먼트 이름] 을 입력하여 vi 편집기로 진입 합니다. 이후 가장 상단에 있는 metadata.annotations에 kubernetes.io/change-cause: [기록할 단어] 를 입력한 후 :wq 로 저장하고 나오면 끝 입니다.

이제 롤백을 진행하면 아래와 같이 CHANGE-CAUSE에 기록이 남는걸 보실 수 있고, 아래 이미지의 경우 테스트하는 과정에서 히스토리가 남아 생긴겁니다. 이와 같이 버전을 남겨서 기록을 관리할 수 있습니다.

 

  • 디플로이먼트 일시 중지, 시작, 재시작

쿠버네티스의 디플로이먼트는 배포 작업을 잠시 일시 중지 시켰다가 시작할수도, 아예 재시작 할수도 있습니다.

  • 배포 일시 중지 : kubectl rollout pause deployment/[디플로이먼트 이름]
  • 배포 시작 : kubectl rollout resume deployment/[디플로이먼트 이름]

아래와 같이 디플로이먼트의 배포 작업을 일시중지 후 이미지 버전을 1.8.9 버전으로 업데이트를 해보고나서 히스토리 기록을 봣을 땐 남아있지 않습니다. resum 으로 배포를 다시 시작하면 히스토리 기록에 생기는것을 볼 수 있습니다. (CHANGE-CAUSE는 따로 변경해주지 않았으므로 version 1.9.1 로 남았습니다)

위에선 일부로 아무 버전이나 입력하였는데, 존재하지 않는 버전을 입력할 경우 파드에 ImagePullBackOFF 상태가 발생하여 정상적으로 실행되지 않으니 참고 해주세요.

 

또한 아예 전체 파드 재시작이 필요한 경우 아래 명령어를 입력하면 됩니다.

  • kubectl rollout restart deployment/[디플로이먼트 이름]

위의 사진은 재시작 후 파드들이 생성/삭제되는 과정 입니다. 디플로이먼트 재시작 시 아래와 같은 과정을 거치는것을 확인할 수 있습니다.

  1. 새로운 레플리카셋 생성
  2. 새로운 파드 생성
  3. 기존 파드 종료
  4. 기존 레플리카셋 비활성화

 

반응형

+ Recent posts