본 포스팅은 Kubernetes Official Documents를 기반으로 한다.
# 소유자와 종속 항목 - Owners and Dependents
쿠버네티스에서, 일부 Object는 다른 Object들에 대한 소유자이다. 예를 들어 ReplicaSet은 Pod 집합의 소유자이다(파드는 레플리카셋에 속한다).
이러한 소유된 Object들은 소유자에 대해 종속된다.
소유권은 리소스가 사용하는 Labels 및 Selector 동작 방식에 따라서 다르다. EndPointSlice Object를 생성하는 Service를 예로 들 수 있다.
서비스는 레이블을 사용하여 컨트롤 플레인이 해당 서비스에 사용되는 `EndPointSlice`를 결정할 수 있게 한다. 레이블에 더해서, Service Object를 대신하여 관리되는 각 `EndpointSlice`에는 소유자 참조를 갖는다.
# 객체 명세의 소유자 참조 - Owner references in object specifications
종속 객체는 그들의 소유자 객체를 참조하는 `metadata.ownerReferences` 필드를 갖는다.
유효한 소유자 참조는 종속된 객체와 동일한 네임스페이스에 속하는 객체의 이름과 UID로 구성된다.
쿠버네티스는 ReplicaSets, DaemonSets, Deployments, Jobs and CronJobs, ReplicationControllers과 같이 다른 객체에 종속성을 갖는 객체에 대해서 이 필드 값을 자동으로 구성한다.
직접 해당 필드 값을 수정함으로써 수동적으로 이러한 관계를 설정할 수도 있다.
하지만, 일반적으로 쿠버네티스가 자동적으로 이러한 관계를 관리하는 것이 좋다.
종속 객체들은 또한 불리언(Boolean) 값을 갖는 `ownerReferences.blockOwnerDeletion` 필드를 갖는다.
이 필드는 해당 객체의 소유자가 삭제될 때 GC를 수행할지 말지를 지정하기 위해 사용된다.
쿠버네티스는 Conroller가 metadata.ownerReferenes 필드 값을 지정하면, 자동적으로 해당 필드 값을 true로 지정한다.
해당 값 또한 마찬가지로, 수동적으로 설정을 변경할 수 있다.
Kubernetes Admission Controller는 소유자에 대한 권한을 제거함으로서 종속 자원에 대한 해당 필드를 변경하기 위한 사용자의 접근을 제어할 수 있다.
이를 통해 권한 없는 사용자가 Owner Object의 삭제를 지연시키는 것을 예방한다.
참고:
네임스페이스 간의 소유자 참조는 허용되지 않도록 설계했다. 네임스페이스 종속 항목은 클러스터 범위 또는 네임스페이스 소유자를 지정할 수 있다.
네임스페이스를 갖는 소유자는 종속 항목과 반드시 동일한 네임스페이스에 존재해야한다.
만약 다르다면, 소유관 참조는 존재하지 않는 것으로 간주되고, 소유자가 존재하지 않는다고 판단된 종속 항목은 삭제된다.
클러스터 범위의 종속 항목들은 오직 클러스터 범위의 소유자를 특정할 수 있다.
1.20 버전 이상부터, 클러스터 범위의 종속 항목들을 소유자로써 클러스터 타입을 지정하는 경우, 이는 해석할 수 없는 소유자 참조를 갖는다고 간주하여 GC되지 않는다.
1.20 버전부터, 만약 GC가 허용되지 않는 네임스페이스 간의 ownerRefernce 값을 확인하거나 클러스터 범위의 종속 항목이 네임스페이스 종류를 참조하고 있다면, `OwnerRefInvalidNamespace` 라는 이유와 잘못된 종속항목에 대한 `involvedObject`가 포함된 경고 이벤트가 발생된다.
`kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace`를 실행함으로써 해당 이벤트에 대해서 확인하는 것이 가능하다.
# 소유권과 파이널라이저 - Onwership and Finalizers
만약, 쿠버네티스가 특정 리소스를 삭제하게 한다면, API Server는 관리용 컨트롤러가 해당 리소스에 대한 finalizer rules에 따라 처리하도록 한다.
Finalizers는 해당 클러스터에서 동작하는데 여전히 필요로 하는 리소스들을 삭제하는 사고를 예방한다.
예를 들어서, 파드가 여전히 사용중인 PV를 삭제하려고 한다면, PV는 `kubernetes.io/pv-protection` 파이널라이저를 갖기 때문에 삭제가 일어나지 않는다.
대신 해당 볼륨은 쿠버네티스가 파이널라이저를 제거할때 까지 Terminating 상태로 유지되고, PV가 더 이상 파드에 묶여있지 않을 때 삭제된다.
쿠버네티스는 foreground 또는 orphan cascading deletion을 사용할 때 소유자 리소스에 파이널라이저를 추가한다.
Foreground Deletion에서는,컨트롤러가 소유자를 삭제하기 전에 `ownerReferences.blockOwnerDeletion=true` 갖을 갖는 종속 항목에 대해서 무조건 삭제하기 위해 foreground 파이널라이저를 추가한다.
만약, orphan deletion policy를 지정한다면, 쿠버네티스는 컨트롤러가 소유자 객체를 삭제한 후 종속 리소스들을 무시하도록 하기 위해서 orphan 파이널라이저를 추가한다.
# 권장 레이블 - Recommended Labels
kubectl과 대시보드와 같은 많은 도구들로 쿠버네티스 오브젝트를 시각화 하고 관리할 수 있다.
공통 레이블 셋은 모든 도구들이 이해할 수 있는 공통의 방식으로 오브젝트를 식별하고 도구들이 상호 운용적으로 작동할 수 있도록 한다.
권장 레이블은 지원 도구 외에도 쿼리 방식으로 애플리케이션을 식별하게 한다.
메타 데이터는 애플리케이션의 개념을 중심으로 정리된다. 쿠버네티스는 플랫폼 서비스가 아니며 애플리케이션에 대해 공식적인 개념이 없거나 이를 강요하지 않는다.
대신 애플리케이션은 비공식적이며 메타데이터로 설명된다. 따라서, 애플리케이션에 포함된 정의는 유연하다.
참고:
메타 데이터들은 권장하는 레이블(필수가 아님)이다. 애플리케이션을 보다 쉽게 관리할 수 있지만, 코어 도구(구성요소)에는 필요하지 않다.
공유 레이블과 주석에는 공통 접두사인 `app.kubernets.io`가 있다. 접두사가 없는 레이블은 사용자가 개인적으로 사용할 수 있다. 공유 접두사를 통해 공유 레이블이 사용자 정의 레이블을 방해하지 않도록 한다.
# Labels
레이블을 최대한 활용하려면 모든 리소스 오브젝트에 적용해야한다.
키 | 설명 | 예시 | 타입 |
app.kubernetes.io/name | 애플리케이션 이름 | mysql | 문자열 |
app.kubernetes.io/instance | 애플리케이션의 인스턴스를 식별하는 고유한 이름 | mysql-abcxzy | 문자열 |
app.kubernetes.io/version | 애플리케이션의 현재 버전 | 5.7.21 | 문자열 |
app.kubernetes.io/component | 아키텍처 내 구성 요소 | database | 문자열 |
app.kubernetes.io/part-of | 이 애플리케이션이 속한 전체 App 이름 | wordpress | 문자열 |
app.kubernetes.io/managed-by | 애플리케이션의 작동을 관리하는데 사용되는 도구 | helm | 문자열 |
위 레이블의 실제 예시는 다음 StatefulSet Object를 고려한다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instacne: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/managed-by: helm
# Applications & Application Instances
애플리케이션은 동일한 쿠버네티스 클러스터에, 심지어는 동일한 네임스페이스에도 한번 또는 그 이상 설치될 수 있다.
예를 들어, 하나의 쿠버네티스 클러스터에 WordPress가 여러 번 설치되어 각각 서로 다른 웹사이트를 서비스할 수 있다.
애플리케이션의 이름과 애플리케이션 인스턴스 이름은 별도로 기록된다.
예를 들어 WordPress는 애플리케이션 이름으로, `app.kubernetes.io/name`이라는 레이블에 wordpress-abcxzy 라는 값을 가진다.
이를 통해 애플리케이션과 애플리케이션 인스턴스를 식별할 수 있다. 따라서, 모든 애플리케이션 인스턴스는 고유한 이름을 가져야 한다.
예시
# 단순한 Stateless 서비스
Deployment와 Service 오브젝트를 통해 배포된 단순한 스테이트리스 서비스의 경우를 확인해보자. 다음 두 식별자는 레이블을 가장 간단한 형태로 사용하는 방법을 나타낸다.
Deployment는 애플리케이션을 실행하는 파드를 감시하는 데 사용한다.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
Service는 애플리케이션을 노출하기 위해 사용한다.
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
데이터베이스가 존재하는 Web Application
Helm을 이용해서 데이터베이스(MySQL)을 이용하는 웹 애플리케이션을 설치한 것과 같이 더 복잡한 구조의 애플리케이션을 고려할 수 있다.
다음 식별자는 이 애플리케이션을 배포하는 데 사용하는 오브젝트의 시작을 보여준다.
아래는 WordPress를 배포하기 위한 매니페스트 구성요소이다. Deployment로 시작한다.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
`Service` 는 애플리케이션을 노출하기 위해 사용한다.
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
MySQL은 StatefulSet에 MySQL의 소속과 상위 애플리케이션에 대한 메타 데이터가 포함되어 노출된다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
Service는 WordPress의 일부로 MySQL을 노출하는 데 이용한다.
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
# 첨언
두 가지 측면에 대해서 추가적인 정보를 얻을 수 있었다.
- 쿠버네티스 실습을 하면서 PV가 붙어있는 파드가 존재할 때, PV 재배포가 이루어지지 않거나 하는 상황을 맞이했었다.
쿠버네티스 자체적으로 이러한 소유권과 지난번 확인했던 파이널라이저를 바탕으로 이러한 실행 순서 또는 클러스터 전체의 안정성을 확보하기 위해 사용한 매커니즘을 알 수 있었다.
추가적으로, 이를 소유자 참조가 일어나고, 이를 바탕으로 삭제가 일어나게 만들거나 종속항목에 대해 삭제가 일어나지 않게 만드는 파이널라이저 등을 확인할 수 있었다. - AWS LB Controller 또는 다른 일부 관리형 서비스를 사용할 때, 어노테이션 혹은 labels가 접두사를 바탕으로 길게 사용되는 경우가 많았다.
그냥, 이를 통해서 관리하는 것일 거다~ 라고 여겼던 부분을, 실제로 사용하는 이유에 대해서 알 수 있었다. 앞으로의 프로젝트에서 쿠버네티스에 애플리케이션을 배포할 때, 레이블을 빡세게 관리해서 모니터링이나 관리의 이점을 얻어봐야겠다.
Deployment라는 Object를 공부할 때, 일반적으로 Pod는 여러 개의 컨테이너로 이루어져있고, Pod를 레이블 셀렉터를 통해서 replicas에서 정의한 개수를 유지하고, Deployment를 통해서 버전을 무중단 업데이트하는 RollingUpdate를 지원하기 위한 객체이다.
즉, Deployment > ReplicaSet > Pod > CTN의 구조를 갖는데, 사실 Pod만 하나 삭제해도 Deployment 소유자가 남아 있으니, 지속적으로 종속 항목인 파드가 생성되고 하는 구조를 파악할 수 있었다.
# 실습: Pod - ReplicaSet - Deployment 관계 확인하기
아래는 해당 Object들의 관계이다. 이를 직접 동작하고 있는 Deployment에 대하여 Pod와 ReplicaSet의 상세 정보를 확인하고자 한다.
실제로, Pod의 Onwer(ReplicaSet)의 name과 uid가 확인되고 blockOwnerDeletion 필드로 추가되어 있음을 확인할 수 있었다.
마찬가지로, ReplicaSet은 Deployment에 속하게 되는데, 해당 정보를 동일하게 확인할 수 있었다.
이를 통해서 이론적으로 알고 있었던, Pod - ReplicaSet - Deployment의 관계와 실제 종속성을 갖고 이를 표현하는 부분을 확인할 수 있었다.
'Infra > Kubernetes' 카테고리의 다른 글
쿠버네티스 클러스터 구축하기 - 1 / 가상머신 세팅 - Vagrant & VMware Workstation 사용 (157) | 2023.12.03 |
---|---|
노드 - Node (2) | 2023.11.22 |
Field Selector & Finalizers (2) | 2023.10.28 |
Namespace & Annotation (2) | 2023.10.26 |
오브젝트 이름과 ID & 레이블과 셀렉터 (4) | 2023.10.23 |