- Deployment 명세를 작성 및 이해 한다.
- 롤링업데이트를 진행할 수 있어야 한다.
- 롤백을 진행할 수 있어야 한다.
모든 진행은 쿠버네티스 공식문서를 통해 진행했습니다.
먼저 kind에 대해 알 필요가 있다. Kubenertes에서 kind는 리소스의 타입을 명시한다고 생각하면 된다. 내가 만드려는 것이 어떤 리소스의 타입인지를 정확히 알고 명세를 작성할 수 있어야 한다.
내가 만드려는 것은 하나의 파드가 아니라 그 파드에 대한 선언적 컨트롤러를 만들기를 원하기 때문에 Deployment를 작성했다.
▶ Deployment 명세에 반드시 들어가야 하는 항목은 총 4가지이다.
1. apiVersion
2. kind
3. metadata
4. spec
먼저 내가 만들려고 하는 것을 확실하게 알았다면 kind에 대한 고민은 필요가 없다.
그리고 apiVersion의 경우에도 kind에 맞는 설정이 필요하기 때문에 고민이 필요한 부분은 아니다.
apiVersion은 kubectl api-resources
명령어를 통해 확인할 수 있다.
다음 가장 먼저 신경쓸 부분이 metadata의 필드이다.
metadata는 쉽게 설명하자면 해당 Deployment를 나타내는 정보라고 생각해도 좋다.
가장 먼저 metadata에 포함되어야 할 요소들을 파악했다.
내가 생성할 리소스 타입의 이름을 설정해야 하기에 name:
을 포함해 주어야 한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cozserver
metadata field까지 작성한 Deployment-v1.yaml의 내용이다.
spec 필드는 내가 생성할 Deployment의 작동을 정의하고 Deployment가 관리할 pod에 대한 정의가 포함되어야 한다.
내가 작성한 spec field의 포함내용은 아래와 같다.
replicas:
Deployment를 통해 생성하고 관리할 pod의 수를 나타낸다.
replicas: 4
는 4개의 pod를 생성 및 관리하겠다는 의도이다.selector:
Deployment를 통해 관리할 pod의 집합을 명세한다.
matchLabels:
는 해당 레이블로 정의된 pod들을 Deployment로 관리하겠다는 의도이다. template:
Deployment를 통해 생성 및 관리할 pod의 정의이다.
labels:
를 붙여 각 pod들을 Deployment가 레이블로 관리 될 수 있도록 정의해줬다.Deployment에서 가장 중요하게 생각할 부분이 바로 labels:
이다.
오늘 작성하게 될 명세에서는 labels:
가 여러번 등장하게 되는데 이를 분별적으로 이해할 수 있어야 한다.
이 후 부분은 pod에 대한 정의이다. 컨테이너의 이름과 이미지, 포트를 설정해줬다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cozserver
<#↓ 생성 및 관리할 pod의 수를 정의한다.>
spec:
replicas: 4
<#↓ deployment를 통해 관리할 label을 정의한다.>
selector:
matchLabels:
app: cozserver
<#↓ 생성 및 관리할 pod의 정의이다.>
template:
<#↓ pod를 label화 해준다. → Deployment의 관리하에 두기 위해>
metadata:
labels:
app: cozserver
spec:
containers:
- name: cozserver
image: sebcontents/cozserver:1.0
<#↓ 리소스 설정은 아래 값이 Default값이다 고로 따로 설정해주지 않아도 괜찮다.>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
이후 kubectl apply -f Deployment-v1.yaml 을 통해 Deployment를 생성해줬다.
기본적으로 pod는 외부 IP를 가지지 않기 때문에 서비스를 외부로 노출시킬 수 없다. 이때 포트 포워딩을 해서 외부에 서비스를 노출시킬수도 있지만
레플리카가 4개이기 때문에 엔드포인트가 나누어진다는 단점이 있다.
이러한 문제를 상쇄하기 위해 로드밸런서를 적용하기로 했다.
apiVersion: v1
kind: Service
metadata:
name: cozserver
namespace: default
spec:
<#↓ 로드밸런서를 통해 관리할 label을 정의한다.>
selector:
app: cozserver
<#↓ 서비스 타입을 정의한다.>
type: LoadBalancer
ports:
- name: cozserver
protocol: TCP
port: 80
targetPort: 8080
로드밸런서가 성공적으로 생성되었다면 클러스터 IP 및 노드 포트가 자동으로 생성 되며 kubectl describe svc <loadbalancer name>
명령어를 통해 확인해보면 로드밸런서가 pod들의 ip:port로 된 엔드포인트들을 하위 구성으로 가지고 있는 것을 확인할 수 있다.
또한 생성된 외부 IP를 통해 접근이 가능해진다.
Deployment의 버전 업데이트를 진행해야 하는 상황이라면 아마도 컨테이너를 구성하는 이미지가 변경된 상황일것이다.
명령어를 통해 업데이트를 진행할 수도 있지만 보다 많은 IaC 작성 습관을 들이기 위해 Deployment-v2.yaml을 작성해봤다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cozserver
<#↓ 생성 및 관리할 pod의 수를 정의한다.>
spec:
replicas: 4
<#↓ deployment를 통해 관리할 label을 정의한다.>
selector:
matchLabels:
app: cozserver
<#↓ 생성 및 관리할 pod의 정의이다.>
template:
<#↓ pod를 label화 해준다. → Deployment의 관리하에 두기 위해>
metadata:
labels:
app: cozserver
spec:
containers:
- name: cozserver
image: sebcontents/cozserver:2.0
<#↓ 리소스 설정은 아래 값이 Default값이다 고로 따로 설정해주지 않아도 괜찮다.>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
이걸 바로 kubectl apply -f Deployment-v2.yaml
을 통해 롤링 업데이트를 진행할 수도 있다.
kubenetes의 배포 전략에서 Default 설정은 롤링 업데이트이고 그 구성은
maxSurge: 25% maxUnavaliable: 25%로 설정되어 있다.
maxSurge와 maxUnavaliable을 통해 내가 구성할 서비스에 맞게 배포의 속도를 조정할 수 있다.
만약 직접 확인해 보고 싶다면 kubectl describe deployment <deployment name>
명령어를 통해 확인해 보길 바란다.
나는 이걸 직접 설정해보고 싶었다. 하지만 공식 문서에 활용 사례가 나오질 않았고 엔지니어님께 여쭤 봄으로써 확인 사례를 알 수 있었다.
spec field에 아래 내용을 추가했다.
strategy: RollingUpdate
rollingupdate:
maxSurge: 1
maxUnavaliable: 1
전체 갯수를 내가 의도한 pod 수인 4개의 +1개를 넘지 않도록 설정했고 업데이트 중 발생할 수 있는 최대로 불가능한 pod의 수를 1개로 지정하여 전체적인 배포 속도가 천천히 안정적으로 진행될 수 있도록 설정했다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cozserver
spec:
<#↓ 업데이트 전략 설정.>
strategy: RollingUpdate
rollingupdate:
maxSurge: 1
maxUnavaliable: 1
<#↓ 생성 및 관리할 pod의 수를 정의한다.>
replicas: 4
<#↓ deployment를 통해 관리할 label을 정의한다.>
selector:
matchLabels:
app: cozserver
<#↓ 생성 및 관리할 pod의 정의이다.>
template:
<#↓ pod를 label화 해준다. → Deployment의 관리하에 두기 위해>
metadata:
labels:
app: cozserver
spec:
containers:
- name: cozserver
image: sebcontents/cozserver:2.0
<#↓ 리소스 설정은 아래 값이 Default값이다 고로 따로 설정해주지 않아도 괜찮다.>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
이제 kubectl apply -f Deployment-v2.yaml
명령어를 통해 롤링 업데이트를 진행했다. 각 apply 진행시 --record
옵션을 통해 rollout history를 남겨주었다.
서비스 장애 발생시 쿠버네티스를 통해 rollback하는 실습을 진행해 보기 위해 장애가 발생하는 Deployment-v3.yaml을 작성했다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cozserver
spec:
<#↓ 업데이트 전략 설정.>
strategy: RollingUpdate
rollingupdate:
maxSurge: 1
maxUnavaliable: 1
<#↓ 생성 및 관리할 pod의 수를 정의한다.>
replicas: 4
<#↓ deployment를 통해 관리할 label을 정의한다.>
selector:
matchLabels:
app: cozserver
<#↓ 생성 및 관리할 pod의 정의이다.>
template:
<#↓ pod를 label화 해준다. → Deployment의 관리하에 두기 위해>
metadata:
labels:
app: cozserver
spec:
containers:
- name: cozserver
image: sebcontents/cozserver:3.0
<#↓ 리소스 설정은 아래 값이 Default값이다 고로 따로 설정해주지 않아도 괜찮다.>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
kubectl apply -f Deployment-v3.yaml
을 통해 롤링 업데이트를 진행하고 이를 롤백하기 위해 알아봐야 할 것들이 있다.
먼저 --record
옵션이다. 지금까지 apply 적용시 --record 옵션을 통해 rollout history를 남겼다고 위에 적어놨는데.
이를 kubectl rollout history deployment <deployment name>
을 통해 확인할 수 있다.
REVISION CHANGE-CAUSE
1 kubectl apply --filename=deployment-v1.yaml --record=true
2 kubectl apply --filename=deployment-v2.yaml --record=true
3 kubectl apply --filename=deployment-v3.yaml --record=true
현재 적용된 버전이 v3이고 이전 버전으로 롤백하고 싶다면 공식문서에 나와있는 롤백을 위한 kubectl 명령어를 사용 하면된다.
kubectl rollout undo deployment <deployment name> --to-revision=2
나는 해당 명령어를 통해 revision 2에 기록된 v2로 롤백을 시도하도록 적용했다.
그 후 다시 rollout history를 확인해 보면 아래와 같이 변경되어 있을 것이다.
REVISION CHANGE-CAUSE
1 kubectl apply --filename=deployment-v1.yaml --record=true
3 kubectl apply --filename=deployment-v3.yaml --record=true
4 kubectl apply --filename=deployment-v2.yaml --record=true
이렇게 오늘의 실습을 마쳤다. yaml파일을 많이 만지면서 라인을 잘 설정해야 한다는 걸 다시 한번 느꼈고 IaC를 통해 관리되는 쿠버네티스의 편리함을 다시 한번 느낀것 같다.