본문으로 건너뛰기

cf) kubectl apply 명령어의 원리


kubectl apply

개념

  • kubectl apply는 선언적 방식(declarative approach)으로 Kubernetes 객체를 관리하는 명령어이다.
  • 내부적으로 apply는 아래 3가지 구성 요소를 비교하여 변경사항을 결정한다.
  1. Local File - 사용자가 작성한 YAML 파일
  2. Live Object Configuration - 클러스터 내부에 존재하는 Object의 실시간 구성도
    • Local File과 유사한 구성이지만, status 필드와 같이 Kubernetes가 관리하는 runtime 필드들이 추가적으로 존재한다.
    • 해당 구성도는 ETCD에 존재한다.
  3. Last Applied Configuration - 마지막으로 apply를 적용했을 때의 스냅샷
    • Local File의 구성이 JSON 형식으로 변환된 형태
    • Live Object Configurationannotation으로 저장된다.
    • 오직 kubectl apply를 사용할 떄만 저장되며, kubectl create, 나 kubectl replace는 이 정보를 저장하지 않는다.

예시

Local File

# nginx.yaml
apiVersion: v1
kind: Pod

metadata:
name: myapp-pod
labels:
app: myapp
type: front-end-services
spec:
containers:
- name: nginx-container
image: nginx:1.18

Live Object Configuration (+ Last Applied Configuration)

apiVersion: v1
kind: Pod

metadata:
name: myapp-pod
labels:
app: myapp
type: front-end-services
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"name":"myapp-pod","labels":{"app":"myapp","type":"front-end-services"}},"spec":{"containers":[{"name":"nginx-container","image":"nginx:1.18"}]}}
spec:
containers:
- name: nginx-container
image: nginx:1.18
status:
conditions:
- lastProbeTime: null
status: "True"
type: Initialized

동작 원리

생성

  1. 오브젝트가 아직 존재하지 않는다면, kubectl apply는 오브젝트를 새로 생성한다.
  2. 생성될 때 Kubernetes 는 status를 포함한 Live Object Configuration을 만든다.
  3. 동시에, Local File을 JSON 형태로 변환하여 Last Applied Configuration 으로 오브젝트의 annotation에 저장한다.

수정

apply를 실행하면 아래 비교가 이루어진다.

  • 수정:

    • Local File에 수정된 필드가 있다면, Live Object Configuration에는 수정되지 않았을 것이다. 그렇다면 applyLive Object Configuration이 업데이트 될 것이다.
    • 이후 Last Applied Configuration도 업데이트 된다.
  • 삭제:

    • 만약 Local File의 삭제된 필드가 있다면, Last Applied Configuration에는 존재할 것이다. 그렇다면 applyLive Object Configuration에서 해당 필드가 삭제될 것이다.
    • 이후 Last Applied Configuration에서도 삭제된 것이 업데이트 된다.
정보

'삭제' 부분에서 잘 이해가 되지 않을 수 있다. (그냥 Local File에 없고 Live Object Configuration에 있는 필드는 삭제해버리면 되잖아 라는 의문이 들 수 있다)

하지만, 그렇게 되면 Kubernetes 입장에서는 그게 '사용자가 삭제한 필드인지', '시스템이 알아서 추가한 필드인지'를 구분할 수 없다.

예를들어 Live Object Configuration에는 status 필드나 metadata.creationTimestamp와 같은 필드도 존재한다. 이는 Kubernetes가 apply를 했을 때 자동으로 붙인 요소들이다.

만약 Last Applied Configuration이 없다면, 이러한 시스템이 관리하는 필드까지 삭제될 것이다.

이때문에, Kubernetes는 '사용자가 추가한 필드인지', '시스템이 추가한 필드인지'를 판단할 기준이 필요하고, 그 기준이 바로 Last Applied Configuration이다.


주의할 점

  • apply(declarative) 와 create/replace(imperative)를 혼용하면 관리가 꼬일 수 있다.
  • 즉, apply를 사용하기 시작했다면, 이후에도 계속 apply로 관리하는 것이 좋다.

예시

상황문제점
create로 만든 뒤 apply 실행apply는 비교 기준(Last Applied Configuration)이 없음 → “무엇이 변경됐는지” 몰라서 충돌/에러 가능
apply로 만든 뒤 replace 실행replace는 Live를 통째로 덮어써서, Last Applied Configuration가 삭제됨 → 이후 apply 시 diff 계산 불가
applyreplace를 번갈아 씀Last Applied Configuration 내용이 실제 YAML과 불일치 → 삭제/갱신 판단이 꼬임