1. Application Update
- 클라이언트가 파드에 서비스를 통해 접근하며, 파드들은 ReplicaSet에 의해 관리된다.
- 파드에서 실행중인 애플리케이션의 버전을 바꾸고 싶을 때 기존 파드를 모두 삭제한 다음 새 파드를 시작하는 방식이 있다. 이는 간단해보이지만, 잠시동안 애플리케이션이 중단되는 문제가 있다.
- 혹은 새로운 파드를 모두 추가한 다음 한꺼번에 기존 파드를 삭제하는 방식도 있다. 리소스가 2배 더 소요되는 문제가 있다.
- 순차적으로 새로운 파드를 추가하고 기존 파드를 점진적으로 제거하는 방식도 있다. 이는 동시에 두가지 버전을 실행하기 때문에, 새로운 버전이 이전 버전을 손상시키는 케이스에선 사용하면 안된다.
2. 업데이트 종류
[1] 오래된 파드를 삭제하고 새 파드로 교체하는 '수동' 방식
- v1 pod set을 관리하는 'Replication Controller'가 있는 경우, v2를 참조하도록 pod template을 수정한 다음 이전 파드 인스턴스를(v1) 삭제해 쉽게 교체할 수 있다. 자연스럽게 RC는 v2를 참조하도록 변경했기 때문에 v2의 파드들을 생성한다.
- 이 방법은 이전 pod 가 삭제되고 새 pod 가 시작되는 동안 짧은 시간의 downtime 을 허용할 수 있어야 한다.
[2] Blue Green 배포
- 새 버전을 실행하는 파드를 불러오는 동안 서비스는 파드의 이전 버전에 연결된다. 새 파드가 모두 실행되면 서비스의 레이블 셀렉터를 변경하고, 서비스를 새 파드로 전화한다. 즉, 한 번에 이전 버전에서 새 버전으로 전환하는 방식이다.
- downtime 이 발생하지 않고 한번에 여러 version 의 application 이 실행되는 것을 지원하는 경우에 사용한다. 단, 잠시동안 두 배의 파드가 실행되므로 더 많은 리소스가 필요하다.
[3] Rolling 배포
- 이전 파드를 한번에 삭제하는 방법 대신 파드를 단계적으로 교체하는 롤링 업데이트를 수행할 수도 있다. 두 개의 레플리카셋을 이용해서 상태를 보면서 점진적으로 수행한다.
- downtime 이 발생하지 않고 한번에 여러 version 의 application 이 실행되는 것을 지원하는 경우에 사용한다.
쿠버네티스는 무중단 배포를 위해 'Deployment Resource'를 제공한다. (1) Label/ ReplicaSet을 관리할 필요가 없으며, (2)수동이 아닌 자동으로, (3) '명령형'이 '선언형'으로 처리할 수 있다.
3. Deployment Resource
- Deployment는 애플리케이션의 무중단 배포를 지원하는 리소스다.
- Deployment를 생성하면 ReplicaSet 리소스가 그 아래 생성된다.
- 무중단 배포를 위해 추가 ReplicaSet 및 Label을 관리해야하는데, 이를 Deployment가 알아서 처리한다. 우리는 '선언형' 형태로 Deployment 리소스를 정의하기만 하면 된다.
[1] Deployment 생성
- Deployment yaml파일은 레이블 셀렉터, 레플리카 수, 파드 템플릿으로 구성된다. 이때 업데이트 방식도 정의할 수 있다.
- 디플로이먼트는 파드 템플릿의 각 버전마다 하나씩 여러 개의 레플리카셋을 만든다.
- 파드 템플릿의 해시 값을 사용하면 디플로이먼트에서 지정된 버전의 파드 템플릿에 관해 항상 동일한 레플리카셋을 사용할 수 있다. 업데이트를 수행하더라도 ReplicaSet은 여전히 남아있다. 따라서 롤백시 RS를 재활용할 수 있다. RS에 revision 번호(버전)를 지정해 특정 버전으로 쉽게 롤백할 수 있다.
[2] Deployment 업데이트
- 디플로이먼트 리소스에 정의된 파드 템플릿을 수정하기만 하면 쿠버네티스가 실제 시스템 상태를 리소스에 정의된 상태로 만드는 데 필요한 모든 단계를 수행한다. ex) rc를 추가로 생성하고 업데이트 등
- 기본적으로 RollingUpdate 전략을 사용한다. 이 방식은 이전 버전과 새 버전을 동시에 실행할 수 있는 경우에만 사용해야 한다.
- 대안으로 존재하는 Recreate 전략은 한 번에 기존 모든 파드를 삭제한 뒤 새로운 파드를 만드는 전략이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v2
name: nodejs
[3] 롤링 업데이트 속도 제어
- 롤링 업데이트에서 두 가지 추가 속성을 통해 새 파드를 만들고 기존 파드를 삭제하는 과정에서 속도를 제어할 수 있다. 'maxSurge', 'maxUnavailable' 두 가지가 있는데, 이 속성들을 통해 한 번에 몇개의 파드를 교체하지를 결정된다.
- maxSurge : 의도하는 replica 수 보다 얼마나 많은 pod instance 를 허용하는지 결정한다.
- maxUnavailable : update 중 의도하는 replica 수를 기준으로 사용할 수 없는 pod instance 수를 결정한다
의도하는 replica 수가 3이고, 이러한 모든 속성이 default(25%) 라면 maxSurge 는 4까지 허용되고, maxUnavailable 은 사용할 수 없는 파드를 허용하지 않는다
위 예제에서 maxUnavailable만 1로 변해보면 어떻게 동작할까? maxUnavailable=1로 인해서 2개까지만 가용한 상태면 되기 때문에 결과적으로는 롤링 업데이트가 더 빠르게 수행될수 있다.
[4] minReadySeconds 속성
- minReadySeconds는 파드를 사용 가능한 것으로 취급하기 전에 새로 만든 파드를 준비할 시간을 지정하는 속성이다.
- 적절하게 구성된 레디니스 프로브와 적절한 minReadySeconds 설정으로 쿠버네티스는 버그가 있는 버전을 배포하지 못하게 할 수 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
minReadySeconds: 10
selector:
matchLabels:
app: kubia
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v3
name: nodejs
readinessProbe:
periodSeconds: 1
httpGet:
path: /
port: 8080
- 사용 가능한 것으로 간주되려면 10초 이상 준비돼 있어야 하기 때문에(초기에 이 값을 매우 늘려, 트래픽을 수용 가능한지 체크하기도 한다.) 해당 파드가 사용 가능할 때까지 새 파드를 만들지 않는다. 여기서 maxUnavailable 속성이 0으로 설정되었기 때문에 원래 파드도 제거되지 않는다.
- 만약 위 상황에서 minReadySeconds를 짧게 설정했더라면 레디니스 프로브의 첫 번째 호출이 성공한 후 즉시 새 파드가 사용 가능한것으로 간주해버릴 수도 있다.(트래픽, 오류 확인 없이) 그러면 잘못된 버전으로 롤아웃이 일어나기 때문에 이 값을 적절하게 잘 설정해야 한다.
- 만약 위 상황에서 minReadySeconds를 짧게 설정했더라면 레디니스 프로브의 결과값이 지속해서 실패할 수 있다.