Kubernetes를 사용하면서 자주 사용하는게 kubectl 명령어 이다. 그리고 그중에서 컨테이너를 생성할때 항상 kubectl create 명령어를 사용했다. 그런데 사용하다보니 어떤 글에는 create 를 사용하고 어디에서는 apply 를 사용하는 것을 보게 되었다. 그래서 이 차이점이 궁금해서 이렇게 정리하게 되었다.
아래 내용들은 kubernetes document 에서 요약한 내용들이다.
https://kubernetes.io/docs/concepts/overview/object-management-kubectl/overview/
Kubernetes 에서 Object Management 에는 3가지가 있다.
Management technique |
Operates on |
Recommended environment |
Supported writers |
Imperative commands |
Live objects |
Development |
1+ |
Imperative object configuration |
Individual files |
Production |
1 |
Declarative object configuration |
Directories of files |
Production |
1+ |
Imperative Commands
장점
- 클러스터에 특정 오브젝트를 한번에 실행하거나 시작할수 있는 가장 쉬운 방법이다. (실제 이미지 바로 실행 시킨다. )
단점
- 기존 설정에 대한 히스토리를 제공하지 않는다. (그래서 위에 권장 환경이 Development 인것 같다.)
- 변경사항이나 audit 내역, 템플릿등을 제공하지 않는다.
ex)
kubectl run nginx --image nginx
Imperative object configuration
- 최소한 1개 이상의 YAML 이나 JSON 포맷의 파일을 이용해서 Object 를 생성한다.
ex)
kubectl create -f nginx.yaml
Imperative object configuration vs Imperative Commands
장점
- 설정파일 내용을 Git 같은 곳에 저장이 가능하기 때문에 설정에 대한 변경 히스토리가 확인 가능하다.
- 새로운 Object를 생성하기 위한 템플릿을 제공한다.
단점
- YAML 파일 작성이 필요하며 템플릿 사용을 위해 Object schema 에 대해서 이해가 필요하다.
Imperative object configuration vs Declarative object configuration
단점
- 파일로 적용할때에만 동작한다. 디렉토리는 불가능.
- 실행중인 object 를 update 하기 위해서는 설정파일에 반영을 해야 한다.
Declarative object configuration
- 모든 설정 파일들은 디렉토리 안에 들어있고 오브젝트를 생성하거나 패치 한다.
ex)
kubectl apply -f configs/
Declarative object configuration vs Imperative object configuration
장점
- 실행중인 오브젝트 직접 적용한 변경사항을 설정파일에 merge 하지 않더라도 유지된다.(???)
단점
- 디버깅 하기 어렵고 예상한 결과가 아닐 경우 이해하기 어렵다.
- diffs 를 사용한 부분 업데이트는 복잡한 병합과 패치를 만들게 된다.
Imperative commands 나 Imperative object configuration 는 이해가 되는데 Declarative object configuration 은 약간 이해가 안된다.
https://kubernetes.io/docs/concepts/overview/object-management-kubectl/declarative-config/
여기 있는 샘플을 가지고 확인해보자.
sample_deployment.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx minReadySeconds: 5 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 | cs |
Create : kubectl apply -f sample_deployment.yaml
Live configuration : kubectl get -f sample_deployment.yaml -o yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | kind: Deployment metadata: annotations: # ... # This is the json representation of simple_deployment.yaml # It was written by kubectl apply when the object was created kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"apps/v1","kind":"Deployment", "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}}, "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx", "ports":[{"containerPort":80}]}]}}}} # ... spec: # ... minReadySeconds: 5 | cs |
kubectl.kubernetes.io/last-applied-configuration 어노테이션에 보면 sample_deployment.yaml 에 적용한 내용들이 나와있다.
다시 아래와 같이 명령어를 실행해보고 확인해보자.
kubectl scale deployment/nginx-deployment --replicas=2
Live configuration : kubectl get -f sample_deployment.yaml -o yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | apiVersion: apps/v1 kind: Deployment metadata: annotations: # ... # note that the annotation does not contain replicas # because it was not updated through apply kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"apps/v1","kind":"Deployment", "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}}, "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx", "ports":[{"containerPort":80}]}]}}}} # ... spec: replicas: 2 # written by scale # ... minReadySeconds: 5 | cs |
이 경우에는 apply를 하지 않았기 때문에 kubectl.kubernetes.io/last-applied-configuration 어노테이션에 포함되지 않았다.
sample_deployment.yaml 파일을 수정해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.11.9 # update the image ports: - containerPort: 80 | cs |
nginx image 버전이 1.7.9 에서 1.11.9 로 변경 되었다.
Create : kubectl apply -f sample_deployment.yaml
Live configuration : kubectl get -f sample_deployment.yaml -o yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | apiVersion: apps/v1 kind: Deployment metadata: annotations: # ... # The annotation contains the updated image to nginx 1.11.9, # but does not contain the updated replicas to 2 kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"apps/v1","kind":"Deployment", "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}}, "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx", "ports":[{"containerPort":80}]}]}}}} # ... spec: replicas: 2 # Set by `kubectl scale`. Ignored by `kubectl apply`. # minReadySeconds cleared by `kubectl apply` # ... selector: matchLabels: # ... app: nginx template: metadata: # ... labels: app: nginx spec: containers: - image: nginx:1.11.9 # Set by `kubectl apply` | cs |
확인을 해보면 apply 로 적용한 nginx 버전은 kubectl.kubernetes.io/last-applied-configuration 어노테이션에 포함 되어있다. 하지만 replicas 는 포함되지 않았다.
Warning: Mixing
kubectl apply
with the imperative object configuration commandscreate
andreplace
is not supported. This is becausecreate
andreplace
do not retain thekubectl.kubernetes.io/last-applied-configuration
thatkubectl apply
uses to compute updates
그리고 위와 같은 주의 사항도 있다. apply 는 create 나 replace 를 지원하지 않는다는 거다. 이유는 create 나 replace 는 kubectl.kubernetes.io/last-applied-configuration 어노테이션을 유지 하지 않기 때문이라고 한다.
apply 와 create 의 차이점을 찾아보다가 여기까지 오게 되었다. 결과적으로 가장 큰 차이점은 apply 를 할 경우에는 기존 설정에 대한 정보를 가지고 있다는 점인것 같다.
apply 이외에도 다른 명령어들이 있지만 우선은 이것만 이해하는걸로 하자.
'Development > Docker&Kubernetes' 카테고리의 다른 글
[K8S] Kubernetes Nginx Controller 에 TLS 설정하다 생긴일.... (0) | 2019.05.27 |
---|---|
[K8S] Replica Set vs Replication Controller 차이 (0) | 2019.05.08 |
[K8S] Kubernetes 기초 개념 정리 (0) | 2018.10.30 |
Docker 로 mysql 설치 및 접속 하기 (3) | 2018.09.18 |
Docker 사용시 sudo 없이 사용하기 (0) | 2018.09.10 |