k8s - ReplicaSet, Deployment!
리플리카셋 (ReplicaSet)
파드가 자동으로 상태검사, 정상화(재시작) 하며 상태를 복구하는 것이라면 리플리카셋은 파드의 수를 유지, 자동으로 새로운 파드를 시작한다.
매니페스트
매니페스트 기본 구성은 파드와 같다.
spec
부분만 다른부분이 있는데 알아보자.
필드 | 타입 | 설명 |
---|---|---|
replicaset.spec.replicas |
Integer |
클러스터 안에서 가동시킬 파드의 수 (기본값 1) |
replicaset.spec.selector |
LabelSelector |
어떤 파드를 가동할지 정의, 파드의 template.metadata.label 에 설정된 값과 일치해야함 |
replicaset.spec.template |
PodTemplateSpec |
실제 클러스터 내부 파드 수가 replicas 에 설정된 수보다 적을때 새로작성되는 파드의 템플릿 |
replicaset.spec.template.metadata |
Object |
템플릿의 이름, Label 과 같은 메타데이터 |
replicaset.spec.template.spec |
PodSpec |
파드의 상세정보를 설정 |
즉 리플리카셋을 사용하려면 리플리카셋의 spec
과 파드의 spec
을 모두 정의해야한다.
리플리카셋 CRUD
# ReplicaSet/replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: photoview-rs
spec:
replicas: 5
selector:
matchLabels:
app: photoview
template:
metadata:
labels:
app: photoview
env: prod
spec:
containers:
- image: mydomain:5000/photo-view:v1.0
name: photoview-container
ports:
- containerPort: 80
kubectl create -f ReplicaSet/replicaset.yaml
kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
photoview-rs-466w6 1/1 Running 0 3h35m app=photoview,env=prod
photoview-rs-fwv2f 1/1 Running 0 3h35m app=photoview,env=prod
photoview-rs-j46rr 1/1 Running 0 3h40m app=photoview,env=prod
photoview-rs-n64z2 1/1 Running 0 3h35m app=photoview,env=prod
photoview-rs-zk4bz 1/1 Running 0 3h35m app=photoview,env=prod
# 파일을 수정 후 apply 하면 기존 리플리카셋의 설정이 자동 수정/적용 된다.
kubectl apply -f ReplicaSet/replicaset.yaml
kubectl delete -f ReplicaSet/replicaset.yaml
리플리카셋은 철저히 spec.template.metadata.labels.app
을 통해서 관리된다.
먼저 라벨명이 photo-view
인 파드 를 하나 생성
kubectl apply -f ReplicaSet/pod-nginx.yaml
pod/nginx-pod created
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 27s
그리고 리플리카셋으로 photo-view
라벨을 가진 파드 5개를 생성하도록한다.
kubectl apply -f ReplicaSet/replicaset-nginx.yaml
replicaset.apps/nginx-replicaset created
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 79s
nginx-replicaset-cg8l7 0/1 ContainerCreating 0 2s
nginx-replicaset-hgkkd 0/1 ContainerCreating 0 2s
nginx-replicaset-kg5ks 0/1 ContainerCreating 0 2s
nginx-replicaset-p2w5f 0/1 ContainerCreating 0 2s
기존에 파드 매니페스트로 생성했던 nginx-pod
파드와 함께 4개의 추가 파드가 생성된다.
디플로이먼트 (Deployment)
Deployment: 전개, 배치
https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/
쿠버네티스에선 어플리케이션의 유연한 CI/CD
를 위해 Deployment
를 제공한다.
Deployment
는 ReplicaSet
의 상위개념이다.
똑같이 여러개의 파드를 생성하고 관리면서 업데이트 관련 기능을 추가 제공한다.
기본적으로 무중단 배포를 위해 Rolling Update
를 지원한다.
매니페스트
# 기본항목
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
# 디플로이먼트 스팩
spec:
replicas: 10
revisionHistoryLimit: 2 # replicaset version 을 2개까지만 유지, default 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 50%
maxSurge: 50%
selector:
matchLabels:
app: nginx-pod # 템플릿 검색조건
# 파드 템플릿
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.14 # 컨테이너 이미지
ports:
- containerPort: 80
Deployment
의 매니페스트 또한 spec
속성이 좀 다를뿐 나머지는 비슷하다.
-
strategy
업데이트 방식 결정 가능,Recreate
,RollingUpdate
사용 가능, 기본값은RollingUpdate
Recreate
는 오래된 파드를 정지시키고 새로운 파드를 다시 작성하는 방식, 가장 심플하고 빠르지만 서버가 모두 내려가 버리기에 다운타임이 발생한다. -
rollingUpdate.maxUnavailable
spec.replicas 수 기준 unavailable 상태인 Pod 의 최대 개수를 설정. 기본값은 25% -
rollingUpdate.maxSurge
spec.replicas 수 기준 최대 새로 추가되는 파드 수, 기본값은 25%.
100% 설정시 신버전의 파드수가 리플리카수만큼 실행되어 한번에 20개의 파드가 동작하게 된다.
리소스 상황에 따라 특이사항이 발생할 수 있음으로maxSurge
는 작성하는 것을 권장한다.
디플로이먼트 CRUD
도커 허브에서 바로 이미지를 가져와 디플로이먼트 CRUD
# 생성
kubectl create deployment --image=nginx nginx-app
deployment.apps/nginx-app created
# 스케일 업
kubectl scale deploy nginx-app --replicas=2
deployment.apps/nginx-app scaled
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app-d6ff45774-m6frx 1/1 Running 0 113s
nginx-app-d6ff45774-q7r5v 1/1 Running 0 26s
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-app 2/2 2 2 2m17s
# 서비스 생성
kubectl expose deployment nginx-app --type=NodePort --port=80
service/nginx-app exposed
kubectl get service nginx-app # localhost:30403 접속
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-app NodePort 10.104.196.2 <none> 80:30403/TCP 6s
# 상세 조회
kubectl describe service nginx-app
Name: nginx-app
Namespace: default
Labels: app=nginx-app
Annotations: <none>
Selector: app=nginx-app
Type: NodePort
IP Families: <none>
IP: 10.104.196.2
IPs: <none>
LoadBalancer Ingress: localhost
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30403/TCP
Endpoints: 10.1.0.11:80,10.1.0.12:80 # 중요
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
# 삭제
kubectl delete deployment nginx-app
deployment.apps "nginx-app" deleted
매니페스트를 생성후 Deployment
리플리카셋과 파드가 생성되는지 확인
# 기본항목
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
# 디플로이먼트 스팩
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod # 템플릿 검색조건
# 파드 템플릿
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.15 # 컨테이너 이미지
ports:
- containerPort: 80
kubectl apply -f Deployment/nginx-deployment.yaml
deployment.apps/nginx-deployment created
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 24s
kubectl get replicaset,pod
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-5bff7844cb 3 3 3 5m11s
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-5bff7844cb-6n2xh 1/1 Running 0 5m11s
pod/nginx-deployment-5bff7844cb-9jmvt 1/1 Running 0 5m11s
pod/nginx-deployment-5bff7844cb-kc7ph 1/1 Running 0 5m11s
디플로이먼트는 내부에서 리플리카셋, 파드 이력을 갖고 있다. kubectl get replicaset
명령에도 조회가 가능하다.
리소스의 네이밍 규칙이 있다.
Deployment
- nginx-deployment
ReplicaSet
- nginx-deployment-5bff7844cb
Pod
- nginx-deployment-5bff7844cb-kc7ph
뒤에 특정 해시값이 라벨로도 붙어있으며 이를 사용해 Deployment
가 리소스를 관리한다.
기존의 nginx:1.14
버전의 이미지를 nginx:1.15
로 변경해보자.
kubectl apply -f Deployment/nginx-deployment.yaml
deployment.apps/nginx-deployment configured
kubectl describe deploy nginx-deployment
Name: nginx-deployment
Namespace: default
...
...
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-f75fb748c (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 28m deployment-controller Scaled up replica set nginx-deployment-5bff7844cb to 3
Normal ScalingReplicaSet 18s deployment-controller Scaled up replica set nginx-deployment-f75fb748c to 1
Normal ScalingReplicaSet 4s deployment-controller Scaled down replica set nginx-deployment-5bff7844cb to 2
Normal ScalingReplicaSet 4s deployment-controller Scaled up replica set nginx-deployment-f75fb748c to 2
Normal ScalingReplicaSet 3s deployment-controller Scaled down replica set nginx-deployment-5bff7844cb to 1
Normal ScalingReplicaSet 3s deployment-controller Scaled up replica set nginx-deployment-f75fb748c to 3
Normal ScalingReplicaSet 2s deployment-controller Scaled down replica set nginx-deployment-5bff7844cb to 0
nginx-deployment-5bff7844cb
이름의 리플리카셋의 파드를 하나씩 줄이며
nginx-deployment-f75fb748c
이름의 새로운 리플리카셋의 파드를 하나씩 생성한다.
디플로이먼트 이력(history)을 확인하려면 rollout history
옵션을 사용한다.
kubectl rollout history deploy rollout-deployment --revision=3
deployment.apps/rollout-deployment with revision #3
Pod Template:
Labels: app=photo-view pod-template-hash=d8bf6cb58
Containers:
photoview-container:
Image: mydomain:5000/photo-view:v1.0
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
kubectl rollout history deploy rollout-deployment --revision=4
deployment.apps/rollout-deployment with revision #4
Pod Template:
Labels: app=photo-view pod-template-hash=6b5ddcb6b7
Containers:
photoview-container:
Image: mydomain:5000/photo-view:v2.0
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Roll out, Roll back
디플로이먼트를 업데이트하고 문제가 생기면 다시 이전버전으로 돌릴 수 있는 기능(롤백) 을 사용해보자.
먼저 아래와 같은 디플로이먼트를 생성 후 실제 서비스까지 동작하는지 확인
apiVersion: apps/v1
kind: Deployment
metadata:
name: rollout-deployment
spec:
replicas: 3
selector:
matchLabels:
app: photo-view
template:
metadata:
labels:
app: photo-view
spec:
containers:
- image: mydomain:5000/photo-view:v1.0
name: photoview-container
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: rollout
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: photo-view
kubectl apply -f Deployment/rollout-depoyment.yaml
# deployment.apps/rollout-deployment created
# service/rollout created
현재 사용중인 이미지 photo-view:v1.0
를 photo-view:v2.0
으로 수정 후 다시 적용(Roll out
)
kubectl apply -f Deployment/rollout-depoyment.yaml
# deployment.apps/rollout-deployment configured
# service/rollout unchanged
describe
명령으로 출력된 Annotations
속성으로 revision
값 확인
해당 디플로이먼트가 몇번 업데이트 되었는지 확이 가능하다.
kubectl describe deploy rollout-deployment
# Name: rollout-deployment
# Namespace: default
# ...
# Annotations: deployment.kubernetes.io/revision: 2
# ...
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Normal ScalingReplicaSet 41s deployment-controller Scaled up replica set rollout-deployment-d8bf6cb58 to 3
# Normal ScalingReplicaSet 27s deployment-controller Scaled up replica set rollout-deployment-6b5ddcb6b7 to 1
d8bf6cb58 -> 6b5ddcb6b7
해시의 변경값이다.
photo-view:v2.0
에 문제가 있단 가정 하에, 업데이트된 디플로이먼트를 다시 이전버전으로 rollback
해보자.
첫번째 방법으로 탬플릿 이미지를 photo-view:v1.0
로 다시 적용해보자.
kubectl apply -f Deployment/rollout-depoyment.yaml
# deployment.apps/rollout-deployment configured
# service/rollout unchanged
kubectl describe deploy rollout-deployment
# ...
# Annotations: deployment.kubernetes.io/revision: 3
# ...
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# rollout-deployment-d8bf6cb58-9nwh5 1/1 Running 0 33s
# rollout-deployment-d8bf6cb58-t2f4l 1/1 Running 0 34s
# rollout-deployment-d8bf6cb58-tgg57 1/1 Running 0 31s
revision
값은 3이 되었고 해시값이 새롭게 변하지 않고 다시 d8bf6cb58
로 돌아갔다.
[Deployment, Replicaset, Pod]
모두 매니페스트 이력을 가지고 롤아웃/롤백을 진행하고 있기 때문.
이 외에도 현재 사용중인 매니페스트 수정하거나 kubectl rollout
명령을 사용해 롤백이 가능하다.
kubectl edit deploy rollout-deployment
kubectl rollout undo deployment rollout-deployment --to-revision=2
구성관리가 유지되지 않음으로 매니페스트 파일의 갱신(선언적 관리)으로 롤아웃/롤백 하는것을 권장한다.
블루/그린 디플로이먼트
블루/그린 이라고 별다른 기법이 있는건 아니다.
서로 다른 버전의 2개의 디플로이먼트를 각각 생성하고 이에 접근하는 Service
리소스를 변경하는 것이다.
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: blue-deployment
spec:
replicas: 3
selector:
matchLabels:
app: photo-view
template:
metadata:
labels:
app: photo-view
ver: v1.0
spec:
containers:
- image: mydomain:5000/photo-view:v1.0
name: photoview-container
ports:
- containerPort: 80
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: green-deployment
spec:
replicas: 3
selector:
matchLabels:
app: photo-view
template:
metadata:
labels:
app: photo-view
ver: v2.0
spec:
containers:
- image: mydomain:5000/photo-view:v2.0
name: photoview-container
ports:
- containerPort: 80
kubectl apply -f Deployment/blue-deployment.yaml
# deployment.apps/blue-deployment created
kubectl apply -f Deployment/green-deployment.yaml
# deployment.apps/green-deployment created
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# blue-deployment-58d5d4869b-kmn88 1/1 Running 0 19s
# blue-deployment-58d5d4869b-vlx2c 1/1 Running 0 19s
# blue-deployment-58d5d4869b-w4729 1/1 Running 0 19s
# green-deployment-5466fc4568-7hxqp 1/1 Running 0 15s
# green-deployment-5466fc4568-mvs2w 1/1 Running 0 15s
# green-deployment-5466fc4568-t8hp2 1/1 Running 0 15s
그리고 이 Deployment
에 접근하는 서비스를 작성하고 실행한다.
apiVersion: v1
kind: Service
metadata:
name: webserver
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
protocol: TCP
selector: # 접근할 파드 수정
app: photo-view
ver: v1.0
kubectl apply -f Deployment/service.yaml
# service/webserver created
이제 service.yml
매니페스트 파일만 수정해서 두 버전의 디플로이먼트에 접근할 수 있도록 설정하면 된다.
오토스케일링
순간적으로 많은양의 요청이 들어올 경우 시스템 처리능력을 높이는 방법
시스템 처리능력을 높이는 방법은 2가지가 있다.
- 스케일 아웃(수평 스케일): 시스템 구성 서버 대수를 늘림으로 처리능력 향상, 로드밸런서를 추가해야 하며 시스템의 가용성이 높아진다.
- 스케일 업(수직 스케일): 서버의 리소스(CPU, Memory) 를 증가 시켜 처리능령 향상시킨다.
처리량의 증가정도에 따라 파드를 스케일할지 노드를 스케일할지 결정한다.
가장 쉽게 스케일 아웃하는 방법은 kubectl scale
명령으로 수동으로 진행하는 것이다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: photo-view
template:
metadata:
labels:
app: photo-view
spec:
containers:
- image: nginx
name: photoview-container
nginx
파드를 3개 생성하고 kubectl scale
명령으로 replicas
개수를 8개 까지 스케일 아웃
kubectl apply -f HPA/pod-scale.yaml
replicaset.apps/nginx-replicaset created
kubectl scale --replicas=8 rs/nginx-replicaset
replicaset.apps/nginx-replicaset scaled
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-replicaset-4bv5g 1/1 Running 0 19s
nginx-replicaset-4cjjq 1/1 Running 0 19s
nginx-replicaset-5z9qk 1/1 Running 0 19s
nginx-replicaset-bt98h 1/1 Running 0 19s
nginx-replicaset-c5fkk 1/1 Running 0 2m29s
nginx-replicaset-hnv8w 1/1 Running 0 2m29s
nginx-replicaset-nxtcn 1/1 Running 0 19s
nginx-replicaset-zbsd6 1/1 Running 0 2m29s
HPA(Horizontal Pod Autoscaler)
HPA(Horizontal Pod Autoscaler)
를 사용하면 CPU 사용률에 따라 사용해 자동으로 스케일 아웃 가능하다.
k8s 의 마스터 컴포넌트인 컨트롤러 매니저가 주기적으로 파드들의 CPU 를 감시하며 HPA 설정대로 스케일 아웃한다.
스케일 아웃 조건은 아래와 같다.
목표 파드 개수 = (현재 파드의 CPU 사용률을 모두 더한 값 / 목표 CPU 사용률) 올림값
목표 CPU 사용률이 60 이고 파드 2개 CPU 사용률이 각각 50, 80 일 때
위 수식값은 130/60=2.17, 올림하면 3 이다.
목표 파드개수는 3개가 된다.
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: kubernetes-simple-app-hpa
namespace: default
spec:
minReplicas: 1 # 최소 설정개수
maxReplicas: 10 # 최대 설정개수
scaleTargetRef: # 오토스케일링 대상
apiVersion: extensions/v1beta1
kind: Deployment
name: kubernetes-simple-app
targetCPUUtilizationPercentage: 30 # CPU 사용률
Deployment
,Relication Controller
,StatefuleSet
등의 리소스에서 오토스케일링 가능
kubectl autoscale
명령으로도 설정 가능하다.
kubectl autoscale \
deployment kubernetes-simple-app \
--cpu-percent=30 \
--min=1 --max=10
autoscaling/v2
부턴 metrics
설정을 통해 CPU 외에 다른 메트릭 데이터를 통해 오토스케일링 가능하다.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: kubernetes-simple-app-hpa
namespace: default
spec:
minReplicas: 1 # 최소 설정개수
maxReplicas: 10 # 최대 설정개수
scaleTargetRef: # 오토스케일링 대상
apiVersion: extensions/v1beta1
kind: Deployment
name: kubernetes-simple-app
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 30 # CPU 가 30% 되도록 조정
한번 스케일 아웃 HPA 가 발동하면 다음번 HPA 는 3분뒤에 다시 발동가능하다.
(줄어드는건 5분)
아래 k8s 컨트롤 매니저 설정파일에서 조절 가능하다.
/etc/kubernetes/manifests/kube-controller-manager.yaml
--horizontal-pod-autoscaler-upscale-delay=3m0s
--horizontal-pod-autoscaler-downscale-delay=5m0s