Run The Bridge

kubectl apply, create, patch, replace 비교 본문

Cloud/k8s

kubectl apply, create, patch, replace 비교

anfrhrl5555 2022. 3. 20. 19:10
728x90
반응형

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

https://stackoverflow.com/questions/47241626/what-is-the-difference-between-kubectl-apply-and-kubectl-replace#:~:text=The%20difference%20between%20apply%20and,use%20replace%20to%20update%20it.

 

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

 


감사합니다.

728x90
반응형
Comments