Run The Bridge
kubectl apply, create, patch, replace 비교 본문
0. 들어가기에 앞서
kubernetes에는 yaml 파일로 pod을 생성할 때 다양한 명령어들이 존재하는데 apply, create를 많이 사용하고 있다.
또한 그렇게 생성된 pod에 편집을 할 때는 patch, replcae와 같은 명령어들을 사용하여 편집을 한다.
이번에는 각 명령어들의 차이점을 알아보고 정리한다.
1. Pod 생성
명령어의 간단한 테스트를 위해 kubernets docs에 있는 nginx pod를 이용한다.
이름은 nginx-apply로 주고 apply 명령어로 생성한다.
apiVersion: v1
kind: Pod
metadata:
name: nginx-apply
spec:
containers:
- name: nginx-apply
image: nginx:1.14.2
ports:
- containerPort: 80
그리고 비교를 위해 nginx-create로 하나 더 생성한다.
apiVersion: v1
kind: Pod
metadata:
name: nginx-create
spec:
containers:
- name: nginx-create
image: nginx:1.14.2
ports:
- containerPort: 80
2. Create와 apply
kubernets 문서에 create와 apply의 정의는 다음과 같다.
Create: 파일 또는 표준 입력으로 리소스를 생성한다. (JSON 및 YAML 형식이 허용된다.)
Apply: 파일 이름 또는 표준 입력으로 리소스에 구성을 적용한다. 만약 리소스가 존재하지 않으면 생성한다. (JSON 및 YAML 형식이 허용된다)
문서에는 크게 차이점이 보이지 않는다.
문서는 아래 링크에서 볼 수 있다.
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create
Kubectl Reference Docs
kubernetes.io
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply
Kubectl Reference Docs
kubernetes.io
일단은 apply, create 명령으로 생성하고 edit으로 수정했을 때 변화를 본다.
# kubectl create -f nginx-create.yaml
pod/nginx-create created
# kubectl apply -f nginx-apply.yaml
pod/nginx-apply created
이제 'kubectl get pod' 명령으로 잘 올라왔는지 확인한다.
# k get pod
NAME READY STATUS RESTARTS AGE
nginx-apply 1/1 Running 0 32s
nginx-create 1/1 Running 0 36s
이제 yaml 파일에 형식을 변경한다. 둘 다 포트를 80으로 쓰고 있는데 8080으로 바꾸고 apply, create 명령을 사용한다.
sed -i 's/80/8080/g' *
이제 변화를 적용한다.
- create 명령어는 이미 존재한다고 오류가 난다.
# k create -f nginx-create.yaml
Error from server (AlreadyExists): error when creating "nginx-create.yaml": pods "nginx-create" already exists
- apply 명령어도 마찬가지로 오류가 발생한다.
k apply -f nginx-apply.yaml
The Pod "nginx-apply" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
core.PodSpec{
Volumes: {{Name: "kube-api-access-tb8x8", VolumeSource: {Projected: &{Sources: {{ServiceAccountToken: &{ExpirationSeconds: 3607, Path: "token"}}, {ConfigMap: &{LocalObjectReference: {Name: "kube-root-ca.crt"}, Items: {{Key: "ca.crt", Path: "ca.crt"}}}}, {DownwardAPI: &{Items: {{Path: "namespace", FieldRef: &{APIVersion: "v1", FieldPath: "metadata.namespace"}}}}}}, DefaultMode: &420}}}},
InitContainers: nil,
Containers: []core.Container{
{
... // 3 identical fields
Args: nil,
WorkingDir: "",
Ports: []core.ContainerPort{
{
Name: "",
HostPort: 0,
- ContainerPort: 8080,
+ ContainerPort: 80,
Protocol: "TCP",
HostIP: "",
},
},
EnvFrom: nil,
Env: nil,
... // 14 identical fields
},
},
EphemeralContainers: nil,
RestartPolicy: "Always",
... // 25 identical fields
}
apply 명령어는 Forbidden이 발생하는데 오류 문구를 읽어보니 pod에 변경은 `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` 만 변경할 수 있다고 한다.
그러면 image만 latest로 변경한다.
image: nginx:latest
# k get pod
NAME READY STATUS RESTARTS AGE
nginx-apply 1/1 Running 0 13m
nginx-create 1/1 Running 0 13m
# k describe pod nginx-apply | grep -i image
Image: nginx:latest
Image ID: docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
Normal Pulling 13m kubelet Pulling image "nginx:1.14.2"
Normal Pulled 13m kubelet Successfully pulled image "nginx:1.14.2" in 22.306749421s
Normal Pulling 18s kubelet Pulling image "nginx:latest"
Normal Pulled 3s kubelet Successfully pulled image "nginx:latest" in 14.742542965s
여기까지 정리를 해보자면...
- Create는 최초로 Pod를 생성할 때만 사용할 수 있다. 말 그대로 생성할 때만 사용한다.
- Apply는 생성된 Pod에 편집을 하고 싶을 때, image나 설정된 값에 대해서만 변경 후 적용할 수 있다.
(deployment에선 다를 수 있음)
2. replace와 patch
replace와 patch의 문서는 아래 사이트에서 확인이 가능하다.
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#replace
Kubectl Reference Docs
kubernetes.io
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#patch
Kubectl Reference Docs
kubernetes.io
조금 더 정확하게 하기 위해서 pod를 deployment로 변경한다.
- Apply를 적용할 Pod를 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-apply
labels:
app: nginx-apply
spec:
replicas: 1
selector:
matchLabels:
app: nginx-apply
template:
metadata:
labels:
app: nginx-apply
spec:
containers:
- name: nginx-apply
image: nginx:1.14.2
ports:
- containerPort: 80
- Create를 적용할 Pod를 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-create
namespace: iskim
labels:
app: nginx-create
spec:
replicas: 1
selector:
matchLabels:
app: nginx-create
template:
metadata:
labels:
app: nginx-create
spec:
containers:
- name: nginx-create
image: nginx:1.14.2
ports:
- containerPort: 80
테스트 방법은 각 명령어로 image를 변경해본다. 먼저 Create로 생성한 yaml에 image를 latest로 바꾸고 replace 한다.
# k replace -f nginx-create-deploy.yaml
deployment.apps/nginx-create replaced
이제 Apply로 생성한 yaml에 image를 latest로 바꾸고 replace 한다. replace 명령어는 크게 차이가 없다고 볼 수 있다.
# k replace -f nginx-apply-deploy.yaml
deployment.apps/nginx-apply replaced
이제 patch명령으로도 동일하게 바꾸어 본다.
patch 명령은 pod에다가 사용할 수 있다. nginx:1.14.2을 latest로 변경하였다.
# kubectl patch pod nginx-apply-6847845f59-l7cxp -p '{"spec":{"containers":[{"name":"nginx-apply","image":"nginx:latest"}]}}'
이제 Create로 생성한 Pod에도 동일하게 적용한다.
# kubectl patch pod nginx-create-79cbcb8bd9-wvmm2 -p '{"spec":{"containers":[{"name":"nginx-create","image":"nginx:latest"}]}}'
둘 다 문제없이 잘 적용된다.
내 생각에는 replace는 yaml에 직접적인 변경을 주고 그 변경 값을 적용할 때 사용하는 걸로 보인다.
patch는 그에 반해 명령어 줄에서 특정 value을 변경시키고 싶을 때 사용하는 것으로 보인다.
정리하자면 yaml 파일을 수정해서 적용하냐 와 CLI에서 바로 적용하냐의 차이점으로 보인다.
근데 전체적으로 차이가 많이 없어서.. 최초 생성할 때 create를 쓰고 변경 값은 apply 나 replace를 써도 상관없어 보인다.
3. 참고자료
https://kubernetes.io/docs/concepts/overview/working-with-objects/object-management/
Kubernetes Object Management
The kubectl command-line tool supports several different ways to create and manage Kubernetes objects. This document provides an overview of the different approaches. Read the Kubectl book for details of managing objects by Kubectl. Management techniques W
kubernetes.io
What is the difference between kubectl apply and kubectl replace
I am learning Kubernetes recently, and I am not very clear about the difference between "kubectl apply" and "kubectl replace". Is there any situation that we can only use one of them?
stackoverflow.com
감사합니다.
'Cloud > k8s' 카테고리의 다른 글
네임스페이스에 배포할 때, 특정 노드에만 배포하는 방법 (0) | 2022.12.26 |
---|---|
Calico CNI를 이용하여 Pod 고정 IP 할당하는 방법 (0) | 2022.08.02 |
사이드카 컨테이너 restart 테스트 (0) | 2022.03.13 |
kubens을 통한 multi-cluster 컨트롤하기 (0) | 2022.01.17 |
kubernetes install guide(v1.18.6) (0) | 2021.12.12 |