0. 선언형(Declarative) 접근법 vs 명령형(Imperative) 접근법
0.1. 선언형 접근법
선언형 접근법은, 원하는 상태 그 자체를 선언하는 방식이다. 쿠버네티스에서는 YAML 파일을 통해 원하는 구성 요소의 원하는 상태를 기술한 뒤, kubectl apply -f <파일명.yaml> 형태의 명령어로 이를 적용하는 방식이 해당된다.
이렇게 선언된 상태를 실제로 적용하기 위해 필요한 작업은 쿠버네티스 시스템이 알아서 판단하고 수행한다.
이 접근법은 결국 "요구되는 환경이 무엇인가(what)"에 초점을 둔다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
위의 파일을 통해 nginx 파드를 배포했는데, 이 파드에 쓰이고 있는 이미지를 특정 버전으로 수정하여 재배포를 해보자.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:1.20.2
이렇게 수정된 내역을 기존의 파드에 적용하고 싶다면, 다음의 명령어를 실행하면 된다.
kubectl apply -f nginx.yaml
여기서 수행하는 kubectl apply 명령이 바로 쿠버네티스의 선언적 접근법에 해당하는 부분이다. 관리자가 선언한 특정한 상태를 시스템이 스스로 파악하여 반영하는 프로세스가 바로 쿠버네티스에서의 선언형 접근법이다.
0.2. 명령형 접근법
명령형 접근법은, 원하는 상태를 만들기 위해 필요한 동작을 지시하는 방식이다. 쿠버네티스에서는 아래와 같이 CLI 환경에서 kubectl을 통한 구성 요소 생성/수정/삭제 명령어를 수행하는 방식이 이에 해당한다.
이러한 접근법은 결국 "요구되는 환경을 어떻게(how) 만들 것인가"에 초점을 두고 있다.
kubectl run nginx --image=nginx
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80
kubectl edit deployment nginx
kubectl scale deployment nginx --replicas=5
kubectl set image deployment nginx nginx=nginx:1.18
kubectl <create|replace|delete> -f nginx.yaml
YAML 파일을 통해 '구성 요소의 상태'를 정의해 놓은 경우라도, create나 replace에 해당하는 작업을 실행한다면 이는 명령형 접근법에 속한다. 패당 파일의 내용을 토대로 어떤 작업을 수행할 것인지(생성/대체/삭제 등)를 명시적으로 지시하는 방식이기 때문이다.
예를 들어 nginx 파드가 이미 구동중인 상태에서 같은 이름의 파드가 정의된 YAML 파일로 create 명령을 실행하면 중복 오류가 발생한다. 반대로 nginx 파드가 존재하지 않는데 같은 파일로 replace 명령을 실행한다면 마찬가지로 오류가 발생한다.
정리하자면, 명령형 접근법은 아래와 같은 한계점을 가진다.
- 명령어만으로 수행 가능한 작업이 제한적이다. 특히 멀티 컨테이너 파드처럼 복잡도가 있는 쿠버네티스의 구송 요소를 명령어 만으로 하나하나 설정하기는 어렵다.
- 작업 내역을 추적하기 어렵다. 여러 사람이 함께 하는 협업 환경에서는 누군가 명령어로 단순 생성시킨 특정 요소의 히스토리를 파악하기 힘들다.
- 현재 작업 환경의 설정사항을 직접 파악해야 한다. 앞서 YAML 파일로 create, replace 실행 시 오류가 발생하는 경우들을 살펴봤다. 이런 오류의 가능성으로 인해, 명령 수행 전에 현재 작업 환경을 수동으로 체크해야 하는 과정이 추가로 요구된다.
다만 필요한 요소를 명령어 한 줄로 즉시 생성하여 다룰 수 있게 해주는 것은 명확한 장점이므로, 빠르고 간격한 작업 수행이 요구되는 환경에서 명령형 접근법은 여전히 유용할 수 있다.
1. kubectl apply (선언형)
kubectl apply 명령을 사용하여 구성 변경 사항을 클러스터에 push할 수 있다. push시 전달되는 구성을 이전 버전과 비교한 뒤 적용한다.
kubectl에서 제공하는 create, edit, scale 같은 명령을 kubectl apply와 절대 혼용해서는 안된다. 만약 혼용할 경우, 이미 생성된 요소들의 추후 업데이트 과정에서 의도하지 않은 결과가 나오거나 업데이트 이력에 대한 추적 관리가 여려워진다.
이 문제를 이해하려면, 우선 활성 객체 설정(Live Object Configuration) 이라는 개념과 이에 연관된 kubectl apply의 동작 방식을 이해해야 한다.
1.1. 활성 객체 설정(Live Object Configuration) 이란?
yaml 형식의 구성 파일로 만든 객체라면, "활성 객체 설정(live object configuration)"에 한가지 내용이 더 추가된다. 앞서 쓰인 YAML 파일의 내용이 JSON 포맷으로 변환되어 어노테이션(metadata.annotation)안에 kubectl.kubernetes.io/last-applied-configuration 항목으로 함께 삽입된다.
여기에는 kubectl apply가 실행된 가장 최근의 시점을 기준으로 원본 객체 구성 파일(Object Configuration File)에 있던 내용이 그대로 반영되어 있다. 이것을 최신 적용 설정(last-applied-configuration)이라 부른다.
즉, 쿠버네티스의 선언형 관리 환경에서는 kubectl apply 명령으로 현재 활성 상태인 요소에 변화를 줄 때 다음의 3가지 항목이 함께 활용된다.
- YAML 포맷의 원복 객체 구성 파일
- 1번의 내용이 JSON 포맷으로 변환된 최신 적용 설정 (last-applied-configuration)
- 2번의 내용을 어노테이션으로 포함하고 있는 활성 객체 설정(Live Object Configuration) - 클러스터 메모리에 있는 정보
1.2. kubectl apply의 동작 방식
kubectl apply는 원본 객체 구성 파일(1번)의 내용을 최신 적용 설정(2번)으로 옮겨 업데이트 시키는 명령이다. 이때 활성 객체 설정(3번)이 업데이트 되는 과정은 경우에 따라 약간의 차이가 있다.
1.2.1. 항목(필드)이 추가되거나 수정될 경우
- 쿠버네티스는 활성 객체 설정(3번)을 원본 객체 구성 파일(1번)과 대조시킨다.
- 만약 서로 일치하지 않는 항목이 있다면 해당 항목이 새로 추가되거나 수정된 것으로 간주하고, 이를 원본 객체 구성 파일(1번) 기준으로 업데이트 시킨다.
- 최신 적용 설정(2번)은 원본 객체 구성 파일(1번) 내용을 따라 업데이트 된다.
1.2.2. 항목(필드)을 삭제할 경우
- 쿠버네티스는 최신 적용 설정(2번)에는 있지만 원본 객체 구성 파일(1번)에는 없는 항목을 탐색한다.
- 이렇게 발견된 항목은 삭제 대상으로 간주하고, 해당 항목을 활성 객체 설정(3번)에서 제거시킨다.
- 최신 적용 설정(2번)은 원본 객체 구성 파일(1번) 내용을 따라 업데이트 된다.
그렇다면 왜 최신 적용 설정(2번)과 활성 객체 설정(3번)을 굳이 별개로 구분하여 생각해야 하는가?
만약 객체를 수정할 때 kubectl apply 대신 '명령형 접근법(create, edit, scale 등)'을 이용할 경우, 최신 적용 설정(2번)은 업데이트 되지 않고 활성 객체 설정(3번) 부분만 바뀌게 된다. 선언형 관리 환경에서 명령형 커맨드를 잘못 혼용할 경우 원본 객체 구성 파일(1번)과 최신 적용 설정(2번)엔 누락되어 있는 내용이 활성 객체 설정(3번)에는 버젓이 포함된 채로 들어갈 수도 있는 것이다.
1.3. 예시로 살펴보는 kubectl apply의 동작 방식
아래는 nginx-deployment 디플로이먼트의 원본 구성 파일(1번)이다.
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.14.2
ports:
- containerPort: 80
snchoi@snchoi:~/test$ kubectl apply -f deployment.yaml
위의 디플로이먼트가 배포되었을 때 쿠버네티스 시스템 안에 생성되는 활성 객체 설정(3번)은 아래와 같다. metadata.annotations 아래에 최신 적용 설정(2번)이 JSON 포맷으로 함께 삽입되었다.
snchoi@snchoi:~/test$ kubectl get -f deployment.yaml -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"nginx-deployment","namespace":"argocd"},"spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2023-08-18T02:08:23Z"
generation: 1
managedFields:
- ...
spec:
minReadySeconds: 5
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2023-08-18T02:08:35Z"
lastUpdateTime: "2023-08-18T02:08:35Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2023-08-18T02:08:23Z"
lastUpdateTime: "2023-08-18T02:08:35Z"
message: ReplicaSet "nginx-deployment-66b6c48dd5" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
이 상태에서 아래와 같은 작업을 수행해보자.
- kubectl scale deployment/nginx-deployment --replicas=2 명령으로 레플리카 설정을 직접 추가한다.
- 원본 구성 파일(1번)에 다음의 수정 사항을 반영하여 kubectl apply를 실행한다.
- spec.containers에 포함된 image 버전을 nginx:1.20.2로 변경.
- spec.minReadySeconds 항목을 삭제
- 1번에서 적용한 replicas 항목은 파일에 추가하지 않음
두 가지 변경 사항을 모두 적용한 뒤 쿠버네티스 메모리 상에 적용된 활성 객체 설정(3번)의 내용은 다음과 같다.
snchoi@snchoi:~/test$ kubectl get -f deployment.yaml -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "2"
# 2-1, 2-2 항목이 아래의 JSON 내용에도 반영되었음을 알 수 있다.
# 반면 kubectl scale로 추가시킨 replicas 설정은 누락되어 있다.
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"nginx-deployment","namespace":"argocd"},"spec":{"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.20.2","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2023-08-18T02:08:23Z"
generation: 3
managedFields:
- ...
spec:
# minReadySeconds 항목 삭제됨(2-2)
progressDeadlineSeconds: 600
replicas: 2 # kubectl scale로 추가된 부분(1)
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.20.2 # nginx 이미지 버전 변경(2-1)
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2023-08-18T02:18:02Z"
lastUpdateTime: "2023-08-18T02:18:02Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2023-08-18T02:08:23Z"
lastUpdateTime: "2023-08-18T02:19:04Z"
message: ReplicaSet "nginx-deployment-cc4b758d6" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 3
readyReplicas: 2
replicas: 2
updatedReplicas: 2
1.4. 결론
- YAML 파일로 객체를 관리할 때에는 create나 replce 대신 apply를 사용한다.
- kubectl 에서 create, edit 또는 scale 같은 명령을 apply와 절대 혼용하지 않는다.
- 쿠버네티스는 "원하는 상태를 선언한다"는 선언적 구성을 설계 사상으로 가지고 있다. 클러스터 구성 요소들의 변경 이력 추적 등에 문제의 소지를 만드는 일이 없도록 유의하자!
2. kubectl edit (명령형)
쿠버네티스 공식문서에서는 텍스트 편집기로 내용을 수정한 뒤 다시 apply하는 것과 같다고 설명되어있다. 그러나 어떤 블로그에서는 apply와 replace중 선택해서 사용된다고 되어있어서, 정확한 방법을 알고 싶어 코드를 분석해보았다.
결론부터 말하자면 정확히 apply로 수정이 이루어지는 것이 아니라, strategy merge patch 방법을 이용하여 patch가 이루어졌다.
(23년 8월 18일 기준 master 브랜치 코드)
func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor resource.Visitor, results *editResults) error {
err := patchVisitor.Visit(func(info *resource.Info, incomingErr error) error {
editObjUID, err := meta.NewAccessor().UID(info.Object)
if err != nil {
return err
}
var originalInfo *resource.Info
for _, i := range originalInfos {
originalObjUID, err := meta.NewAccessor().UID(i.Object)
if err != nil {
return err
}
if editObjUID == originalObjUID {
originalInfo = i
break
}
}
if originalInfo == nil {
return fmt.Errorf("no original object found for %#v", info.Object)
}
originalJS, err := encodeToJSON(originalInfo.Object.(runtime.Unstructured))
if err != nil {
return err
}
editedJS, err := encodeToJSON(info.Object.(runtime.Unstructured))
if err != nil {
return err
}
if reflect.DeepEqual(originalJS, editedJS) {
// no edit, so just skip it.
printer, err := o.ToPrinter("skipped")
if err != nil {
return err
}
return printer.PrintObj(info.Object, o.Out)
}
preconditions := []mergepatch.PreconditionFunc{
mergepatch.RequireKeyUnchanged("apiVersion"),
mergepatch.RequireKeyUnchanged("kind"),
mergepatch.RequireMetadataKeyUnchanged("name"),
mergepatch.RequireKeyUnchanged("managedFields"),
}
// Create the versioned struct from the type defined in the mapping
// (which is the API version we'll be submitting the patch to)
versionedObject, err := scheme.Scheme.New(info.Mapping.GroupVersionKind)
var patchType types.PatchType
var patch []byte
switch {
case runtime.IsNotRegisteredError(err):
// fall back to generic JSON merge patch
patchType = types.MergePatchType
patch, err = jsonpatch.CreateMergePatch(originalJS, editedJS)
if err != nil {
klog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
return err
}
var patchMap map[string]interface{}
err = json.Unmarshal(patch, &patchMap)
if err != nil {
klog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
return err
}
for _, precondition := range preconditions {
if !precondition(patchMap) {
klog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
return fmt.Errorf("%s", "At least one of apiVersion, kind and name was changed")
}
}
case err != nil:
return err
default:
patchType = types.StrategicMergePatchType
patch, err = strategicpatch.CreateTwoWayMergePatch(originalJS, editedJS, versionedObject, preconditions...)
if err != nil {
klog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
if mergepatch.IsPreconditionFailed(err) {
return fmt.Errorf("%s", "At least one of apiVersion, kind and name was changed")
}
return err
}
}
if o.OutputPatch {
fmt.Fprintf(o.Out, "Patch: %s\n", string(patch))
}
patched, err := resource.NewHelper(info.Client, info.Mapping).
WithFieldManager(o.FieldManager).
WithFieldValidation(o.ValidationDirective).
WithSubresource(o.Subresource).
Patch(info.Namespace, info.Name, patchType, patch, nil)
if err != nil {
fmt.Fprintln(o.ErrOut, results.addError(err, info))
return nil
}
info.Refresh(patched, true)
printer, err := o.ToPrinter("edited")
if err != nil {
return err
}
return printer.PrintObj(info.Object, o.Out)
})
return err
}
분석결과 결론은 visitToPatch 라는 함수를 호출하게 되는데, CreateTwoWayMergePatch 함수를 이용해 원본 문서와 수정된 문서에서 StrategicMergePatch로 전달할 수 있는 패치를 생성하며, 이렇게 생성된 패치를 통해 strategy merge patch를 이용해 업데이트 하게 된다.
3. kubectl patch (명령형)
kubectl patch 명령어는 JSON patch, JSON merge pach, 그리고 strategic merge patch를 지원한다. 기본 값은 strategic 이다.
3.1. strategic merge patch
다음은 2개의 replicas가 있는 Deployment에 대한 구성 파일이다. 각 replica는 하나의 컨테이너가 있는 파드이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: patch-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: patch-demo-ctr
image: nginx
tolerations:
- effect: NoSchedule
key: dedicated
value: test-team
NAME READY STATUS RESTARTS AGE
patch-demo-28633765-670qr 1/1 Running 0 23s
patch-demo-28633765-j5qs3 1/1 Running 0 23s
Deployment의 각 파드는 nginx 이미지를 실행하는 하나의 컨테이너가 있다.
여기에 redis 이미지를 실행하는 하나의 컨테이너를 더 띄우고 싶다.
# patch-file.yaml
spec:
template:
spec:
containers:
- name: patch-demo-ctr-2
image: redis
kubectl patch deployment patch-demo --patch-file patch-file.yaml
위의 명령을 사용하여 patch하고 나면, 컨테이너가 2개가 된 것을 볼 수 있다.
containers:
- image: redis
imagePullPolicy: Always
name: patch-demo-ctr-2
...
- image: nginx
imagePullPolicy: Always
name: patch-demo-ctr
...
지금까지 수행한 patch를 strategic merge patch라고 한다. patch는 containers 목록을 대체하지 않고 새 컨테이너를 추가했다. 즉, patch의 목록이 기존 목록과 병합되었다.
이것은 strategic merge patch를 사용할 때 항상 발생하는 일은 아니다. 경우에 따라 목록이 병합(merge)되지 않고 교체(replace)된다.
merge patch 전략에 따라 목록이 병합되거나 대체된다. patch 전략은 kubernetes 소스코드의 필드 태그에 있는 patchStrategy 키 값으로 지정된다. 예를 들어 PodSpec 구조체의 Containers 필드에는 merge의 patchStrategy가 있다.
type PodSpec struct {
...
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`
...
}
OpenApi 에서 patch strategy를 확인할 수 있다.
"io.k8s.api.core.v1.PodSpec": {
...,
"containers": {
"description": "List of containers belonging to the pod. ...."
},
"x-kubernetes-patch-merge-key": "name",
"x-kubernetes-patch-strategy": "merge"
}
다음 yaml을 patch 시켜보면
# patch-file-tolerations.yaml
spec:
template:
spec:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
kubectl patch deployment patch-demo --patch-file patch-file-tolerations.yaml
위의 컨테이너 예시와는 다르게 PodSpec에 단 하나의 Toleration만 있는 것을 확인할 수 있다.
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
PodSpec의 tolerations 목록이 병합(merge)되지 않고 교체(replace)된 것이다.
그 이유는 PodSpec의 Tolerations 필드의 필드 태그에 patchStrategy 키가 없기 때문이다. 따라서 strategic merge patch는 기본으로 replace 패치 전략을 사용한다.
type PodSpec struct {
...
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
...
}
3.2. JSON patch
- op, path, value 3개의 항목으로 구성되어 있다.
- op: 작업 유형 (add, remove, replace, move, copy or test 등)
- path: 변경할 데이터 경로
- value: 변경할 값
//변경전 기존데이터
{
"users": [
{ "id": 1, "name" : "Alice", "email" : "alice@example.org" },
{ "id": 2, "name" : "Bob", "email" : "bob@example.org" }
]
}
//PATCH 메소드를 이용한 변경요청
PATCH /users/2
[
{
"op": "replace",
"path": "/name",
"value": "kildong"
},
{
"op": "replace",
"path": "/email",
"value": "kildong@test.com"
}
]
//변경 후 데이터
{
"users": [
{ "id": 1, "name" : "Alice", "email" : "alice@example.org" },
{ "id": 2, "name" : "kildong", "email" : "kildong@test.com" }
]
}
3.3. JSON merge patch
- JSON patch보다 단순하고 간단하다.
- 변경하려는 데이터를 json 형식으로 작성하여 던지면, 해당되는 데이터들이 merge되는 방식이다.
- 키를 null로 변경하는 것은 삭제를 의미한다.
//변경 전 기존데이터
{
"a": "b",
"c": {
"d": "e",
"f": "g"
}
}
//PATCH 메소드를 이용한 변경요청
{
"a": "z",
"c": {
"f": null
}
}
//변경 후 데이터
{
"a": "z",
"c": {
"d": "e"
}
}
JSON merge patch를 사용하여 목록을 업데이트 하려면, 새 목록 전체를 지정해야한다. 그리고 새로운 목록은 기존 목록을 완전히 대체한다.
위에서 실행했던 예제의 동일한 Deployment에서 JSON merge patch를 수행하면
# patch-file-2.yaml
spec:
template:
spec:
containers:
- name: patch-demo-ctr-3
image: gcr.io/google-samples/node-hello:1.0
kubectl patch deployment patch-demo --type merge --patch-file patch-file-2.yaml
컨테이너 목록에는 컨테이너 하나만 있다. 하나의 컨테이너 목록이 기존 컨테이너 목록을 대체한 것이다.
spec:
containers:
- image: gcr.io/google-samples/node-hello:1.0
...
name: patch-demo-ctr-3
NAME READY STATUS RESTARTS AGE
patch-demo-1307768864-69308 1/1 Running 0 1m
patch-demo-1307768864-c86dc 1/1 Running 0 1m
4. kubectl replace (명령형)
한번 초기화되면 수정할 수 없는 필드들을 수정해야할 때가 있다. 이런 필드들을 수정하기 위해 replace --force 명령어를 쓴다. 이 명령어를 사용하면 리소스를 삭제한 뒤에 재생성한다.
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
--force 옵션을 사용하면, 리소스 삭제후 재생성하지만, 아무 옵션도 주지 않을경우 PUT을 이용해 업데이트를 진행한다.
5. 참고 문서
https://seongjin.me/kubernetes-imparative-vs-declarative/
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment
'클라우드 > Kubernetes(쿠버네티스)' 카테고리의 다른 글
[Kubernetes] ArgoCD (0) | 2024.07.30 |
---|---|
[쿠버네티스] 클러스터 구축 (0) | 2024.06.08 |
[kubernetes] pod lifecycle (0) | 2023.08.10 |
[kubernetes] kube-proxy (0) | 2023.08.03 |
[kubernetes] Kubernetes Networking Model (0) | 2023.08.03 |