쿠버네티스 컨트롤러 - ReplicaSet, Deployment, DaemonSet, Job/CronJob

yunyoung·2021년 1월 18일

쿠버네티스

목록 보기
5/12
post-thumbnail

1. Controller란?

쿠버네티스 컨트롤러는 서비스를 운영하고 관리하는 데에 도움을 준다. Pod를 관리하기 위한 컨트롤러로, 다음과 같은 기능들을 제공한다.

- Auto Healing

파드가 스케줄링되어 있는 노드가 다운되면 파드에서 돌아가는 서비스에 장애가 발생한다. 컨트롤러는 이를 즉각적으로 인지하고 파드를 다른 노드에 새로 만들어준다.

- Auto Scaling

파드의 리소스가 limit 상태가 되었을 때, 컨트롤러가 이 상태를 파악하고 파드를 하나 더 만들어줌으로써 부하를 분산시키고 파드가 죽지 않도록 해준다. 성능에 대한 장애 없이 안정적인 서비스를 운영할 수 있다.

- Software Update

여러 파드에 대해 버전을 업그레이드해야 할 경우 컨트롤러를 통해서 한 번에 쉽게 할 수 있고, 업그레이드에 문제가 생겼을 때도 쉽게 롤백할 수 있는 기능을 제공한다.

- Job

일시적인 작업을 해야 할 경우, 컨트롤러가 필요한 순간에만 파드를 만들어서 해당 작업을 수행하고 탑재한다. 그 순간에만 자원이 사용되고 작업 후에 반환되기 때문에 효율적인 작업이 가능하다.

2. Controller - Replication Controller, ReplicaSet

둘 다 비슷하지만 현재Replication Controller 오브젝트는 Deprecated된 오브젝트로, 대체로 사용하는 것이 ReplicaSet이다. 하지만 아직까지 Replication Controller도 많이 사용하기 때문에 같이 설명하겠다.

Template

컨트롤러와 파드는 labelselector로 연결된다. 템플릿으로 파드의 내용을 넣게 되며, 템플릿에 명시된 대로 파드가 생성된다. 만약 파드가 다운된다면 템플릿 안에 있는 파드의 내용으로 파드를 다시 만들어준다. 템플릿을 수정하게 되면, 파드가 죽었을 때 알아서 다시 새 내용으로 파드를 만들어준다.

Replicas

replicas 속성에 지정한 개수만큼 파드를 생성한다. replicas의 개수를 늘리면 파드가 늘어나는 Scale Out이 되는 것이고, 내리면 Scale In이다.

Selector

ReplicaSet에만 있는 기능!
셀렉터에는 두 가지 추가적인 속성이 있다.
matchLabels 는 키와 밸류가 모두 같아야 연결해주는 속성이다.
matchExpressions 는 키와 밸류를 좀 더 디테일하게 컨트롤할 수 있는 속성이다.

- key: ver
  operator: Exists 

이렇게 지정해주면 keyver인 파드들을 모두 선택하게 된다.

matchExpressionsoperator 속성에는 4가지 옵션이 있다.

  • Exists
    key값을 지정해주면, 그 key값과 같은 키를 가진 파드들을 연결해준다.
  • DoesNotExist
    key값을 지정해주면, 그 key값과 같지 않은 키를 가진 파드들을 연결해준다.
  • In
    key와 values를 지정할 수 있고, 같은 키를 가진 파드 중에 밸류도 맞는 파드를 선택한다.
  • NotIn
    key와 values를 지정할 수 있고, 같은 키를 가진 파드 중에 밸류가 다른 파드를 선택한다.

컨트롤러를 삭제할 때, 연결된 파드가 지워지지 않고 남아있도록 하려면 다음과 같은 명령어를 사용한다.
$ kubectl delete replicationcontrollers replication1 --cascade=false

3. Controller - Deployment

운영 중인 서비스를 업데이트 후 재배포해야 할 때 쓰는 컨트롤러이다. Deployment의 방식은 크게 4가지가 있다.

Recreate

deploymentv1의 파드들이 만들어진다. 업데이트를 하려고 할 때는 v1 파드들을 삭제한다. 이 때 서비스에 대한 downtime이 발생하여 잠시 서비스가 중단되며 자원 사용량이 없어진다. 그 후 v2 파드들을 생성해서 업데이트를 완료한다.

Rolling Update

v1인 파드들이 있고, 업데이트를 위해 v2 파드를 하나 만들어준다. 추가로 파드를 하나 더 생성했으므로 자원 사용량도 파드 하나만큼 늘어나게 된다. v1v2가 모두 서비스 중이며, 누군가는 v1에 접속되고 누군가는 v2에 접속되는 상태이다.

v2 파드를 하나 만든 대신 v1 파드를 하나 삭제하고, 마찬가지로 v2 파드를 하나 더 만들고 v1 파드 나머지 하나를 삭제함으로써 업데이트가 완료된다.
배포 중간에 추가적인 자원을 요구하지만 zero downtime 인 장점이 있다.

Blue/Green

deployment의 자체적인 기능은 아니며, ReplicaSet과 같은 컨트롤러를 이용해서 할 수 있는 방법이다.

컨트롤러를 이용해서 파드를 생성한 경우, 현재 파드들은 서비스의 셀렉터를 통해 서비스와 연결되어있는 상태이다.
이 때 컨트롤러를 하나 더 만들고, v2 파드들을 만들어준다.
v1 파드들의 개수만큼 똑같이 v2 파드들을 만들었기 때문에 자원 사용량은 두 배가 된다.

여기서 서비스에 있는 labelv2로 변경해주면 v2 파드들과 서비스가 바로 연결이 된다. 순간적으로 변경되기 때문에 다운타임은 발생하지 않는다. v2에 문제가 생기면 라벨만 v1으로 바꿔주면 되기 때문에 문제가 발생했을 때에도 롤백이 쉽다.

문제가 없는 경우 최종적으로 v1 파드들을 삭제하면 된다. 안정적이지만 자원이 2배 필요하다.

Canary

실험체를 통해 위험을 검증하고 위험이 없다는 것이 확인되면 정식으로 배포하는 방식이다.
v1에 대한 파드가 있고, 각 파드에는 라벨이 붙어져 있다. 서비스와 파드를 연결할 때 ver:v1 라벨이 아닌 type:app과 같은 라벨로 서비스와 연결되어 있다.
이렇게 운영 중인 상태에서, 테스트용으로 컨트롤러를 만들 때 replicas를 1로 해서 type:app, ver:v2 를 붙인 파드를 만들어 서비스와 연결해준다.
그럼 서비스로 들어오는 트래픽의 일부는 v2 파드로 접근될 것이고 새 버전에 대한 테스트를 할 수 있다. 만약 테스트 중 문제가 생기면 컨트롤러의 replicas만 0으로 만들면 된다. 이 방법은 불특정 다수를 위한 테스팅 방법이다.

또는 ver:v1, ver:v2로 각각의 서비스를 만들고
Ingress Controller를 두고 서비스로 트래픽을 분산시켜줄 수 있다. Ingress Controller는 유입되는 트래픽을 url path에 따라서 서비스에 연결해주는 역할을 한다.

예를 들면, 미국에서 접근한 사람들에게만 테스팅을 하고 싶다면 미국에서 접속하는 경우 url/en/app으로 해줄 수 있다. 이렇게 특정 타겟을 정해놓고 테스트를 할 수 있으며, 테스팅 후 문제가 없다면 v1 파드들과 서비스를 삭제하고 테스팅 url/app으로 변경해주면 업데이트가 완료된다.

이 방식은 downtime이 없지만, 자원 사용량은 테스트에 사용할 파드의 수에 따라서 증가하게 된다.

Deployment를 롤백하는 방법은 다음과 같다.

# deployment-1의 revision 2로 롤백
$ kubectl rollout undo deployment deployment-1 --to-revision=2

# deployment의 revision 알아내기
$ kubectl rollout history deployment deployment-1

4. Controller - DaemonSet, Job, CronJob

DaemonSet

노드들이 있고 각각의 노드에 자원이 다르게 남아 있는 상태라고 가정한다. ReplicaSet을 이용한다면 자원이 많이 남은 노드에 파드를 많이 배치할 것이다.

DaemonSet은 자원량을 고려하지 않고 각각의 노드에 하나씩 파드를 설치한다. 이렇게 각각의 노드마다 설치해서 사용해야 하는 서비스는 성능 수집(프로메테우스) 모니터링, 로그수집, 스토리지와 같은 서비스가 있다.

셀렉터와 템플릿이 있어서 템플릿으로 파드를 만들고 셀렉터로 DaemonSet과 연결이 된다. DaemonSet은 노드에 하나를 초과해서 파드를 만들 수는 없지만, 안 만들수는 있다.

Job / CronJob

파드들이 Node1에서 돌아가는 상태에서 Node1이 다운되었을 경우 직접 만든 파드도 역시 다운된다.
컨트롤러에 의해서 만들어진 파드들은 장애가 감지되면 다른 노드에 재생성되서 서비스가 계속 유지된다.
그 중 ReplicaSet으로 만들어진 파드는 무슨 일이 있어도 서비스가 유지되어야 하는 경우에 쓴다.

Job으로 만든 파드는 파드가 일하지 않으면 종료한다. 삭제되는 것은 아니고 멈추는 것인데, 멈춘 파드 안에 들어가서 로그를 확인할 수도 있으며 정말 필요가 없어지면 파드를 삭제하면 된다.

spec:
  completions: 6
  parallelism: 2
  activeDeadlineSeconds: 30
  

6개의 파드를 순차적으로 실행시켜서, 모두 작업이 끝난 후 Job을 종료한다.(completions) 이 때 2개씩 파드를 생성해서 작업한다.(parallelism) 이 Job은 30초 후에 기능을 정지하고 모든 파드들을 삭제한다.(activeDeadlineSeconds)

CronJob은 이 Job들을 주기적으로 실행하는 목적으로 사용한다.
예를 들면 정기적으로 백업할 때, 주기적으로 업데이트를 확인할 때, 예약 메일과 같은 메시지를 발송할 때 사용한다.
Job Template이 있어서 이 내용대로 Job을 생성하고, Schedule에 적어준 주기에 맞게 Job을 만든다.

CronJob에는 concurrencyPolicy라는 기능이 있는데, 3가지의 옵션이 있다.

  • allow
    따로 설정하지 않았을 때의 디폴트 옵션이다. 스케줄이 1분 간격이라고 가정했을 때, 첫 번째 Job이 어떤 상태이든 상관없이 2분에 두 번째 Job을 만든다.
  • forbid
    1분에 Job이 생성되지만, 2분까지도 첫 번째 Job이 계속 실행중이면 2분 Job은 스킵한다. 첫 번째 Job이 종료되면 다음 스케줄 Job이 바로 만들어진다.
  • replace
    1분 Job이 2분 째에도 계속 실행 중이면 새로운 파드를 만들어 1분 Job의 파드를 교체해준다. 2분 째에 Job이 만들어지진 않지만 새로운 파드가 만들어진다.
spec:
  schedule: "*/1 * * * *"
  concurencyPolicy: Allow

CronJob에 설정된 Job을 수동으로 생성하는 명령어는 다음과 같다.

$ kubectl create job --from=cronjob/cron-job cron-job-manual-001
profile
🌈TIL과 개발 노트

0개의 댓글