Controller는 kubernetes의 object를 모니터링하고 원하는 state로의 동작을 진행한다.
node에 하나의 pod가 다운되는 것은 당연하다고 생각하면 된다. 그렇기 때문에 여러 개의 pod를 배포하고 자동 복구할 수 있도록 해야하는데, 이를 가능하게 해주는 것이 바로 Replication Controller
이다.
----------------Node---------------------
| |
| ------Replication Controller----- |
| | ---pod--- ---pod---- | |
| | | | | | | |
| | --------- ---------- | |
| --------------------------------- |
| |
-----------------------------------------
이렇게 Replication Controller는 user를 위해서 pod의 갯수를 설정한만큼 유지하는데, 이 갯수를 Replicas
라고 한다. 이렇게 pod 갯수를 여러 개 두어서 유지하면 user는 하나의 pod가 없어져도 지속적으로 접근이 가능하게되어 높은 고가용성을 제공해줄 수 있는 것이다.
replication controller가 필요한 또 다른 이유로는 load balancing
과 scaling
에 있다. user의 수요가 늘어나면, replication controller는 여러 node에 pod들을 추가적으로 더 생성할 수 있다. 이렇게 하면 하나의 node만으로 pod를 배포하지 않아서 자원을 효율적으로 사용할 수 있고, 더 많은 pod들을 배포할 수 있어 사용자 경험에 있어 아주 좋다.
----------------Node1--------------------
| |
| ------Replication Controller----- |
| | ---pod--- ---pod---- | |
| | | | | | | |
| | --------- ---------- | |
| | | |
| | | |
----| |---|
| |
----------------Node2--------------------
| | | |
| | | |
| | ---pod--- ---pod---- | |
| | | | | | | |
| | --------- ---------- | |
| --------------------------------- |
| |
-----------------------------------------
다음과 같이 서로 다른 node간에 하나의 replication controller
가 가로질러있어 pod들을 배포할 수 있고, user의 요청이 많아지면 pod의 수를 늘릴 수 있다. 반대로 user의 요청이 적어지면 pod의 수를 줄 일 수도 있다.
용어적으로 조심해야할 것이 있는데, Replication Controller
와 Replica Set
이다. 둘 다 용도는 같지만 다르다. Replication Controller
는 구버전이고 ReplicaSet
이 새로운 기술이다. 이들은 작동 방식이 약간 다르지만, 위에서 설명한 방식은 동일하다.
apiVersion: v1
kind: ReplicationController
metadata:
name: myapp-rc
labels:
app: myapp
type: front-end
spec:
template:
{pod-template}
ReplicationController
는 pod의 replica를 생성하기 때문에 어떤 pod를 생성하는 지 알려주어야 한다. 이 부분들이 바로 pod-template
이다. pod의 metadata
, spec
부분을 그대로 넣어주어한다.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
다음의 pod 정의에서 metadata
와 spec
부분을 가져와 template
에 넣어주면 된다.
apiVersion: v1
kind: ReplicationController
metadata:
name: myapp-rc
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
이 다음 해당 pod의 복제본(Replica)를 몇 개나 유지할 지를 적어주어야 한다.
apiVersion: v1
kind: ReplicationController
metadata:
name: myapp-rc
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
이제 myapp-pod
를 3개 만들어줄 것이다.
kubectl create -f ./rc-definition.yaml
kubectl get replicationcontroller
kubectl get rc
이제 ReplicaSet
을 보도록 하자. 거의 다 ReplicationController
와 동일하다. 단, 주의할 것은 apiVersion
이 ReplicationController
처럼 v1
이 아니라 apps/v1
이라는 것이다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-replicaset
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
selector:
matchLabels:
type: front-end
만약 apiVersion
을 apps/v1
이 아니라 v1
으로 치면 다음의 error가 발생한다.
error: resource mapping not found for name: "replicaset-1" namespace: "" from "/root/replicaset-definition-1.yaml": no matches for kind "ReplicaSet" in version "v1"
ensure CRDs are installed first
나머지 부분은 거의 동일하다는 사실을 알도록 하자. 단, 한가지 추가되는 부분이 있는데 replicas
아래에 selector
를 추가해야한다. pod를 식별해주는 기능인데, 왜 template가 있어서 pod를 만들어주는데, selector
가 필요할까?
이는 ReplicaSet
의 기능인데 selector
의 label과 일치하는 pod가 이미 기존에 있었다면, ReplicaSet
은 복사본 pod의 갯수에 해당 pod를 포함한다. 가령, Replicas
가 3개 일때, 기존에 pod가 이미 하나있다면 두 개만 더 만드는 것이다.
따라서, ReplicaSet
은 자신의 template에서 정의된 pod뿐만 아니라, label selctor로 설정된 다른 pod까지 모두 동일하게 관리를 한다는 것이다.
한 가지 명심할 것은 selector
와 template
에 정의한 label
이 일치해야한다. 위의 경우 type: front-end
가 아니라, type: back-end
라고 쓰면 error가 발생한다.
kubectl create -f ./replicaset-definition.yaml
kubectl get replicaset
kubectl get rs
kubectl get pods
사실 ReplicaSet
은 자신의 관할에 있는 pod를 관리하고 모니터링하는 것이 기능의 전부이다. 그렇다면 자신의 관할에 있는 pod라는 것을 어떻게 설정할까?? 그것이 바로 selctor
와 label
이라는 것이다.
만약, replica의 수를 변경하여 스케일링하고 싶다면 yaml
파일 정의를 바꾸고 replace
를 해주면 된다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-replicaset
labels:
app: myapp
type: front-end
spec:
...
replicas: 6
selector:
matchLabels:
type: front-end
이 다음 replicaset-definition.yaml
에 replace
명령어를 실행시켜주면 된다.
kubectl replace -f ./replicaset-definition.yaml
두번째 방법은 kubectl scale
명령어를 사용하면 된다.
kubectl scale --replicas=6 -f ./replicaset-definition.yaml
또는
kubectl scale --replicaset=6 replicaset myapp-replicaset
단, 이 경우는 원본 file은 아무것도 변경되지 않는다는 것을 명심하자.
deployment를 말하기 전에 application을 배포해서 사용자에게 제공하는 production 상황을 생각해보도록 하자. 우리는 한 번에 pod들을 업데이트하기 보다는 각각의 rolling update
하고 싶을 것이다.
----- ------------------
|pod|<--v1-->| |
----- | |
| |
----- | |
|pod|<--v1-->| |
----- | |
| |
----- | |
|pod|<--v1-->| docker registry|
----- | |
| |
----- | |
|pod|<--v2-->| |
----- | |
| |
----- | |
|pod|<--v2-->| |
----- ------------------
왜 하나씩 업데이트 하는 지 생각해보면 간단한데, 모두 새로운 버전으로 업데이트했다가는 error가 발생할 경우 사용자에게 좋지 않은 경험을 줄 수 있기 때문이다. 따라서 하나씩 업데이트하는데, 만약 error가 발생하면 다시 이전 버전으로 돌아가는 rolling out
이 발생한다.
이러한 rolling update
, rolling out
기능을 Deployment
로 가능하게 한다. Deployment
는 ReplicaSet
의 상위 개념으로 ReplicaSet
처럼 Replica
들을 유지하는 것을 제공해주며 rolling update
, rolling out
가지 제공해주는 것이다.
따라서, Deployment
는 내부에 ReplicaSet
있고, 추가적인 rolling기능을 넣은 것 뿐이다.
정의 역시도 ReplicaSet
과 거의 일치한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
selector:
matchLabels:
type: front-end
ReplicaSet
에서 kind
부분만 다른데,Deployment
로만 바꾸면 된다. 참고로 deployment
라고 하면 에러가 발생하니 조심하자.
kubectl create -f ./deployment-definition.yaml
kubectl get deploytments
심지어 replicaset
으로도 확인이 가능하다.
kubectl get replicaset
kubectl get pods
추가적으로 생성된 모든 object들을 보고 싶다면 kubectl get all
을 사용하면 된다.
pod와 deployment를 사용해서 pod를 배포할 때는 yaml파일을 사용해서 배포하기 보다는 kubectl run
을 사용하는 것이 더 편할 때가 많다. kubectl run
은 --image
로 pod의 image를 결정하고 입력 파라미터로 pod-name
을 받는다. 다음 정리를 보도록 하자.
kubectl run nginx --image=nginx
kubectl run nginx --image=nginx --dry-run=client -o yaml
kubectl create deployment --image=nginx nginx
kubectl create deployment --image=nginx nginx --dry-run=client -o yaml
kubectl create deployment --image=nginx nginx --dry-run=client -o yaml > nginx-deployment.yaml
replicas
가 설정 가능하다.kubectl create deployment --image nginx nginx --replicas=4 --dry-run=client -o yaml > nginx-deployment.yaml