본문 바로가기

Infrastructure/Kubernetes

[K8S] 오브젝트 - 2

쿠버네티스 공식문서를 확인하며 레이블, 셀렉터, 파이널라이저에 대해서 기억해야 하는 부분을 기록한다.


레이블과 셀렉터

  • 레이블은 파드와 같은 오브젝트에 첨부된 키와 값의 쌍이다.
  • 오브젝트의 특성을 식별하는 데 사용되어 사용자에게는 중요하지만, 코어 시스템에 직접적인 의미는 없다.
  • 레이블로 오브젝트의 하위 집합을 선택하고, 구성하는데 사용할 수 있다.
  • 오브젝트를 생성할 때에 붙이거나 생성 이후에도 언제든지 수정이 가능하다.
  • 오브젝트마다 미와 값으로 레이블을 정의할 수 있으며 키는 고유한 값이어야 한다.
  • 레이블은 UI와 CLI에서 효율적인 쿼리를 사용하고 검색에 사용하기 적합하며, 식별되지 않는 정보는 애너테이션으로 기록해야 한다.

사용 동기

  • 레이블을 사용하면 사용자가 느슨하게 결합한 방식으로 조직 구조와 시스템 오브젝트를 매핑할 수 있으며, 클라이언트에 매핑 정보를 저장할 필요가 없어진다.
  • 서비스 배포와 배치 프로세싱 파이프라인은 흔히 다차원의 엔티티이며, 관리에 크로스-커팅 작업이 필요한 경우가 많은데 이 작업은 사용자보다는 인프라에 의해 결정된 엄격한 계층 표현인 캡슐화를 깨트린다.
  • 아래의 예시는 일반적으로 사용하는 레이블이며, 사용자는 자신만의 규칙(convention)에 따라 자유롭게 개발할 수 있지만 오브젝트에 붙여진 레이블 키는 고유하다는 것을 기억해야 한다.
    • "release" : "stable", "release" : "canary"
    • "environment" : "dev", "environment" : "qa", "environment" : "production"
    • "tier" : "frontend", "tier" : "backend", "tier" : "cache"
    • "partition" : "customerA", "partition" : "customerB"
    • "track" : "daily", "track" : "weekly"

구문과 캐릭터 셋

  • 레이블은 키와 값의 쌍으로 유효한 레이블 키에는 슬래시(/)로 구분되는 선택한 접두사 이름이라는 2개의 세그먼트가 있다.
  • 이름 세그먼트는 63자 미만으로 시작과 끝은 영숫자([a-z0-9A-Z])이며, 대시(-), 밑줄(_), 점(.)과 함께 사용할 수 있다.
  • 접두사는 선택사항이며 접두사를 지정하는 경우 접두사는 DNS의 하위 도메인으로 해야하며, 점(.)과 전체 253자 이하, 슬래시(/)로 구분되는 DNS 레이블이다.
  • 접두사를 생략하면 키 레이블은 개인용으로 간주한다. 최종 사용자는 오브젝트에 자동화된 시스템 컴포넌트(예, kube-scheduler, kube-controller-manager, kube-apiserver, kubectl 또는 다른 타사의 자동화 구성 요소)의 접두사를 지정해야 한다.
  • kubernetes.io/k8s.io/ 접두사는 쿠버네티스의 핵심 컴포넌트로 예약되어 있다.
  • 유효한 레이블은 아래의 규칙을 지켜야 한다.
    • 63자를 넘길 수 없으며 공백일 수 있다.
    • 공백이 아니라면 시작과 끝은 영숫자로 구성되어야 한다.
    • 영숫자, 대시(-), 밑줄(_), 점(.)을 중간에 포함할 수 있다.
  • 아래의 예시는 파드에 environment: productionapp: nginx두 개의 레이블이 있는 구성 파일이다.
apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels:
    environment: production
    app: nginx

레이블 셀렉터

  • 이름과 UID와 다르게 레이블은 고유하지 않으며 일반적으로 우리는 많은 오브젝트들이 같은 레이블을 가질 것으로 예상한다.
  • 레이블 셀렉터를 통해 클라이언트와 사용자는 오브젝트를 식별할 수 있으며, 레이블 셀렉터는 쿠버네티스 코어 그룹의 기본이다.
  • API는 현재 “일치성 기준”과 “집합성 기준”이라는 두 종류의 셀렉터를 지원하고 레이블 셀렉터는 쉼표로 구분된 다양한 요구사항에 따라 만들 수 있다. 다양한 요구사항이 있는 경우 쉼표 기호가 AND(&&) 연산자로 구분되는 역할을 하도록 해야 한다.
  • 비어있거나 지정되지 않은 셀렉터는 상황에 따라 달라지기 때문에 셀렉터를 사용하는 API 유형은 유효성과 의미를 문서화 해야 한다.
  • 레플리카셋(ReplicaSet)과 같은 일부 API 유형에서 두 인스턴스의 레이블 셀렉터는 네임스페이스 내에서 겹치지 않아야 하며 그렇지 않은 경우 컨트롤러는 상충하는 명령으로 보고, 얼마나 많은 복제본이 필요한지 알 수 없다.
  • 일치성 기준과 집합성 기준 조건 모드에 대해 논리적인 OR(||)연산자가 없다. 필터 구문이 적절히 구성되어 있는지 확인해야 한다.

일치성 기준 요건

  • “일치성 기준” 또는 “불일치 기준”의 요구사항으로 레이블의 키와 값의 필터링을 허용한다.
  • 일치하는 오브젝트는 추가 레이블을 가질 수 있지만, 레이블의 명시된 제약 조건을 모두 만족해야 한다.
  • =, ==는 일치를 의미하며 !=는 불일치를 의미하며 세 개의 연산자면 허용되며 사용 예시는 아래와 같다.
environment = production
tier != frontend
  • 전자는 environment를 키로 가지는 것과 production을 값으로 가지는 모든 리소스를 선택한다.
  • 후자는 tier를 키로 가지며, 값을 공백으로 가지는 모든 리소스를 선택한다.
  • environment=production,tier!=frontend처럼 쉼표를 통해 한 문장으로 frontend를 제외한 production을 필터링할 수 있다.
  • “일치성 기준 레이블 요건”에 대한 하나의 이용 시나리오는 파드가 노드를 선택하는 기준을 지정하는 것이다. 아래의 샘플 파드는 accelerator=nvidia-tesla-p100 레이블을 가진 노드를 선택한다.
apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "k8s.gcr.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

집합성 기준 요건

  • “집합성 기준 레이블 요건”에 따라 값 집합을 키로 필터링할 수 있으며 in, notin, exists 세 개의 연산자를 지원한다. 사용법은 아래와 같다.
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
  • 1라인: 키가 environment이며 값이 production 또는 qa인 모든 리소스를 선택한다.
  • 2라인: 키가 tier이고 값이 frontendbackend를 가지는 리소스를 제외한 모든 리소스를 선택한다. 추가로 키로 tier를 가지고 값을 공백으로 가지는 모든 리소스를 선택한다.
  • 3라인: 레이블의 값에 상관없이 키가 partition을 포함하는 모든 리소스를 선택한다.
  • 4라인: 레이블의 값에 상관없이 키가 partition을 포함하지 않는 모든 리소스를 선택한다.
  • 쉼표(,)는 AND 연산자로 작동하기 때문에 partition,environment notin (qa)와 같이 사용하면 값과 상관없이 키가 partition또는 environment이고 값이 qa와 다른 리소스를 필터링할 수 있다.
  • “집합성 기준 레이블 셀렉터”는 일반적으로 environment=productionenvironment in (production)을 동일한 것으로 보고 !=notin을 같은 것으로 본다.
  • “집합성 기준 요건”은 “일치성 기준 요건”과 조합하여 사용할 수 있다. (`partition in (customerA,customerB),environment!=qa)

API

LIST와 WATCH 필터링

  • LIST와 WATCH 작업은 쿼리 파라미터를 사용해서 반환되는 오브젝트 집합을 필터링하기 위해 레이블 셀렉터를 지정할 수 있으며 아래와 같은 요건 모두 허용된다.
    • 일치성 기준 요건: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
    • 집합성 기준 요건: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%frontend%29
  • 두 가지 레이블 셀렉터 스타일은 모두 REST 클라이언트를 통해 선택된 리소스를 확인하거나 목록을 볼 수 있으며 아래처럼 kubectlapiserver를 대상으로 “일치성 기준”과 “집합성 기준” 셀렉터를 이용할 수 있다.
# 일치성 기준
kubectl get pods -l environment=production,tier=frontend
# 집합성 기준
kubectl get pods -l 'environment in (production),tier in (frontend)'
# OR 연산자
kubectl get pods -l 'environment in (production, qa)'
# exists 연산자
kubectl get pods -l 'environment,environment notin (frontend)'

API 오브젝트에서 참조 설정

  • servicesreplicationcontrollers와 같은 일부 쿠버네티스 오브젝트는 레이블 셀렉터를 사용해서 파드와 같은 다른 리소스 집합을 선택한다.

서비스와 레플리케이션 컨트롤러

  • services에서 지정하는 파드 집합은 레이블 셀렉터로 정의한다. 마찬가지로 replicationcontrollers가 관리하는 파드의 오브젝트 그룹도 레이블 셀렉터로 정의한다.
  • 서비스와 레플리케이션 컨트롤러의 레이블 셀렉터는 json 또는 yaml 파일에 매핑된 일치성 기준 요구사항의 셀렉터만 지원한다. 아래의 두 방식은 같은 결과를 가져온다.
"selector": {
    "component" : "redis",
}
or
selector:
    component: redis

세트-기반 요건을 지원하는 리소스

  • Job, Deployment, ReplicaSet 그리고 DaemonSet 같은 새로운 리소스들은 “집합성 기준”의 요건도 지원한다.
selector:
  matchLabels:
    component: redis
  matchExpressions:
    - {key: tier, operator: In, values: [cache]}
    - {key: environment, operator: NotIn, values: [dev]}
  • matchLabels{key,value}의 쌍과 매칭된다.
  • matchLabels에 매칭된 단일 {key,value}matchExpressions의 요소와 같으며 key 필드는 “key”로, operator는 “In” 그리고 values에는 “value”만 나열되어 있다.
  • matchExpressions는 파드 셀렉터의 요건 목록이며 유효한 연산자에는 In, NotIn, Exists, DoNotExist가 있고 In, NotIn은 설정된 값이 있어야 한다.
  • matchLabelsmatchExpressions 모두 AND로 되어 있어 일치하기 위해서는 모든 요건을 만족해야 한다.

노드 셋 선택

  • 레이블을 통해 선택하는 사용 사례 중 하나는 파드를 스케줄 할 수 있는 노드 셋을 제한하는 것이다.

애너테이션

  • 쿠버네티스 애너테이션을 사용하여 임의의 비-식별 메타데이터를 오브젝트에 첨부할 수 있다. 도구 및 라이브러리와 같은 클라이언트는 이 메타데이터를 검색할 수 있다.

오브젝트에 메타데이터 첨부

  • 레이블이나 애너테이션을 사용하여 쿠버네티스 오브젝트에 메타데이터를 첨부할 수 있다.
  • 레이블을 사용하여 오브젝트를 선택하고, 특정 조건을 만족하는 오브젝트 컬렉션을 찾을 수 있다.
  • 애너테이션은 오브젝트를 식별하고 선택하는데 사용되지 않는다.
  • 애너테이션의 메타데이터는 작거나 크고, 구조적이거나 구조적이지 않을 수 있으며, 레이블에서 허용되지 않는 문자를 포함할 수 있다.
  • 애너테이션은 아래처럼 레이블과 같은 형식의 키-값 매핑이다.
"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}
  • 맵의 키와 값은 문자열이어야 하며 숫자, 불리언, 리스트 등의 다른 형식을 키나 값에 사용할 수 없다.
  • 아래는 애너테이션에 기록할 수 있는 정보의 예시이다.
    • 필드는 선언적 구성 계층에 의해 관리된다. 이러한 필드를 애너테이션으로 첨부하는 것은 클라이언트 또는 서버가 설정한 기본 값, 자동 생성된 필드, 그리고 오토사이징 또는 오토스케일링 시스템에 의해 설정된 필드와 구분된다.
    • 빌드, 릴리즈, 또는 타임 스탬프, 릴리즈 ID, git 브랜치, PR 번호, 이미지 해시 및 레지스트리 주소와 같은 이미지 정보.
    • 로깅, 모니터링, 분석 또는 감사 리포지토리에 대한 포인터.
    • 디버깅 목적으로 사용될 수 있는 클라이언트 라이브러리 또는 도구 정보. (이름, 버전, 빌드 정보 등)
    • 다른 생태계 구성 요소의 관련 오브젝트 URL과 같은 사용자 또는 도구/시스템 출처 정보.
    • 경량 롤아웃 도구 메타데이터. (구성, 체크포인트 등)
    • 책임자의 전화번호 또는 호출기 번호, 또는 팀 웹 사이트 같은 해당 정보를 찾을 수 있는 디렉터리 진입점.
    • 행동을 수정하거나 비표준 기능을 수행하기 위한 최종 사용자의 지시 사항.
  • 애너테이션을 사용하는 대신, 이 유형의 정보를 외부 데이터베이스 또는 디렉터리에 저장할 수 있지만, 이는 배포, 관리, 인트로스펙션(introspection)등을 위한 공유 클라이언트 라이브러리와 도구 생성을 훨씬 더 어렵게 만들 수 있다.

문법과 캐릭터 셋

  • 애너테이션은 키/값 쌍이다.
  • 유효한 애너테이션 키에는 두 개의 세그먼트가 있으며 두 개의 세그먼트는 선택적인 접두사와 이름이며, 슬래시(/)로 구분된다.
  • 이름 세그먼트는 필수이며, 시작과 끝은 영숫자([a-z0-9A-Z])여야 하며 63자 이내로 작성되어야 한다. 이름에는 -, _, . 3개의 특수문자가 사용될 수 있다.
  • 접두사는 선택 사항이며, 접두사가 지정되는 경우에는 DNS의 서브도메인이어야 한다.
  • 점(.)으로 구분된 일련의 DNS 레이블은 총 253자 이내로 작성되어야 하며, 뒤에 슬래시(/)가 붙는다.
  • 접두사가 생략되면, 애너테이션 키는 사용자에게 비공개로 간주된다.
  • 최종 사용자 오브젝트에 애너테이션을 추가하는 자동화된 시스템 구성 요소(kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, 다른 써드파티 자동화)는 접두사를 지정해야 한다.
  • 아래는 imageregistry: https://hub.docker.com/ 애너테이션이 있는 파드의 구성 파일 예시다.
apiVersion: v1
kind: Pod
metadata:
  name: annotations-demo
  annotations:
    imageregistry: "https://hub.docker.com/"
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

소유자 및 종속 개체(Owners and Dependents)

  • 쿠버네티스에서 일부 개체는 다른 개체를 소유한다.
  • 레플리카세트는 파드 집합의 소유자이며 종속 객체는 소유자에게 종속된다.
  • 소유권은 일부 리소스에서도 사용되는 레이블 과 셀렉터 메커니즘과는 다르다.
  • 서비스는 레이블을 사용하여 컨트롤 플레인이 EndpointSlice 해당 서비스를 사용하게 되는 개체를 결정하게 할 수 있다.
  • 레이블 외에도 EndpointSlice를 대신하여 관리되는 각 레이블에는 “소유자 참조”가 존재하며 “소유자 참조”는 쿠버네티스의 다른 부분이 제어하지 않는 개체를 방해하는 것을 방지하는데 도움된다.

개체 명세의 소유자 참조

  • 종속 개체에는 metadata.ownerReferences와 같은 형태의 소유자 개체를 참조하기 위한 필드가 존재한다.
  • 유효한 소유자 참조는 종속 개체와 동일한 네임스페이스 내의 개체 이름과 UID로 구성된다.
  • ReplicaSets, DaemonSets, Deployments, Jobs 및 CronJobs, ReplicationController와 같은 다른 개체에 종속되는 개체는 metadata.ownerReferences 필드의 값이 자동으로 설정된다. 사용자는 이 값을 수동으로 변경할 수 있지만 일반적으로 쿠버네티스에게 권한을 허용하고 자동으로 설정되도록 한다.
  • 종속 개체에는 ownderReferences.blockOwnerDeletion 불리언 값을 사용하고 특정 종속 항목이 소유자 개체를 삭제하지 못하도록 가비지 수집을 차단을 제어하는 필드가 있다.
  • 쿠버네티스는 자동으로 이 값을 true로 설정하고 제어 장치 metadata.ownerReferences 필드의 값을 설정한다.
  • admission controller는 소유자의 삭제 권한에 따라 종속 리소스에 대해 이 필드를 변경하기 위한 사용자 액세스를 제어한다. 이 제어는 권한이 없는 사용자가 소유자 개체 삭제를 지연하는 것을 방지한다.
  • 상호 네임스페이스 소유자 참조는 설계상 허용되지 않는다. 네임스페이스에 종속 항목은 클러스터 범위 또는 네임스페이스 소유자를 지정할 수 있다.
  • 네임스페이스 소유자는 종속 개체와 동일한 네임스페이스에 위치해야 하며, 그렇지 않은 경우 소유자 참조는 부재로 처리되어 모든 소유자가 부재인 것으로 확인되어 종속 개체는 삭제될 수 있다.
  • 클러스터 범위의 종속 개체은 클러스터 범위 소유자만 지정할 수 있다. v1.20 이상 버전에서 클러스터 범위 종속 개체인 네임스페이스 종류를 소유자로 지정하면 확인할 수 없는 소유자 참조가 있는 것으로 처리되고 가비지 수집이 불가능해진다.
  • v1.20 이상 버전에서 가비지 수집기가 유효하지 않은 교차 네임스페이스 ownerReference 또는 네임스페이스 종류를 참조하는 클러스터 범위 종속을 감지하면 유효하지 않은 종속이 ownerReference에 있다는 경고 이벤트가 보고된다.

소유권(Ownership)과 파이널라이저(Finalizers)

  • 쿠버네티스에게 리소스를 삭제하도록 지시하면 API 서버에서 관리 컨트롤러가 리소스에 대한 파이널라이저(finalizer) 규칙을 처리할 수 있다. 종료자 클러스터가 올바르게 작동하는 데 필요할 수 있는 리소스가 실수로 삭제되는 것을 방지한다.
  • 파드에서 아직 사용 중인 PersistentVolume을 삭제하려고 하면 파이널라이저가 있기 때문에 바로 종료되지 않는다. 쿠버네티스는 볼륨이 더 이상 파드에 바인딩되지 않은 상황이 될 때 해당 볼륨을 삭제한다.
  • 쿠버네티스는 소유자 개체가 삭제될 때 종속 개체까지 삭제하기 위해서 소유자 리소스에 파이널라이저 추가한다.
  • 포그라운드 삭제에서는 컨트롤러가 소유자를 삭제하기 전에 forground 종속 리소스도 삭제되도록 파이널라이저를 추가한다.
  • ownerReferences.blockOwnerDeletion=true와 같이 설정하는 경우 쿠버네티스는 orphan 컨트롤러가 소유자 개체를 삭제한 후 종속 리소스를 무시하도록 파이널라이저를 추가하게 된다.

파이널라이저

  • 파이널라이저는 쿠버네티스가 오브젝트를 완전히 학제하기 이전, 삭제 표시를 위해 특정 조건이 만족될 때까지 대기하도록 알려주기 위한 네임스페이스에 속한 키(namespaced key)다.
  • 파이널라이저는 삭제 완료된 오브젝트가 소유한 리소스를 정리하기 위해 컨트롤러에게 알린다.
  • 파이널라이저를 가진 특정한 오브젝트를 쿠버네티스가 삭제하도록 지시할 때, 쿠버네티스 API는 .metadata.delationTimestamp을 덧붙여 삭제하도록 오브젝트에 표시하며, 202 상태코드(HTTP, Acceptesd)
  • 대상 오브젝트가 terminating 상태를 유지하는 동안 컨트롤 플레인 또는 다른 컴포넌트는 하나의 파이널라이저에서 정의한 작업을 수행한다.
  • 정의된 작업이 완료 후에, 그 컨트롤러는 대상 오브젝트로부터 연관된 파이널라이저를 삭제한다, metadata.finalizers 필드가 비어 있을 때 쿠버네티스는 삭제가 완료된 것으로 간주하고 오브젝트를 삭제한다.
  • 파이널라이저가 리소스들의 가비지 컬렉션을 제어하도록 할 수 있다. 하나의 파이널라이저를 컨트롤러가 대상 리소스를 삭제하기 전에 연관된 리소스들 또는 인프라를 정리하도록 정의 할 수 있다.
  • 파이널라이저를 사용하면 리소스를 삭제하기 전 특정 정리 작업을 수행하도록 컨트롤러에 경고하여 리소스의 가비지 수집을 제어할 수 있다.
  • 파이널라이저는 보통 실행할 코드를 지원하지 않는다. 대신 파이널라이저는 일반적으로 애너테이션과 비슷하게 특정 리소스에 대한 키들의 목록으로 일부 파이널라이저는 쿠버네티스가 자동으로 지정하지만 사용자가 직접 지정할 수도 있다.

파이널라이저의 작동 방식

  • 매니페스트 파일을 사용해 리소스를 생성하면 metadata.finalizers 필드에 파이널라이저를 명시할 수 있다. 리소스를 삭제하려 할 때는 삭제 요청을 처리하는 API 서버가 finalizers 필드의 값을 인식하고 아래의 작업을 수행한다.
    • 삭제를 시작한 시각과 함께 metadata.deletionTimestamp 필드를 추가하도록 오브젝트를 수정한다.
    • 오브젝트의 metadata.finalizers 필드가 비워질 때까지 오브젝트가 제거되지 않도록 한다.
    • 202 상태 코드를 리턴한다(Accepted)
  • 파이널라이저를 관리하는 컨트롤러는 metadata.deletionTimestamp를 설정하는 오브젝트가 업데이트 되었음을 인지하여 오브젝트의 삭제가 요청되었음을 나타낸다.
  • 컨트롤러는 해당 리소스에 지정된 파이널라이저의 요구사항을 충족하려 시도한다.
  • 컨트롤러는 파이널라이저 조건이 충족될 때 마다 리소스의 finalizers 필드에서 해당 키(key)를 제거한다.
  • finalizers 필드가 비워지면 deletionTimestamp 필드가 설정된 오브젝트는 자동으로 삭제되며 파이널라이저를 사용하여 관리되지 않는 리소스가 삭제되지 않도록 할 수 있다.
  • 파이널라이저의 일반적인 예시로 퍼시스턴트 볼륨(Persistent Volume) 오브젝트가 실수로 삭제되는 것을 방지하는 kubernetes.io/pv-protection가 있다.
  • 파드가 퍼시스턴트 볼륨 오브젝트를 사용 중일 때 쿠버네티스는 pv-protection 파이널라이저를 추가한다.
  • 퍼시스턴트 볼륨을 삭제하려 하면 Terminating 상태가 되지만 파이널라이저가 존재하기 때문에 삭제할 수 없다.
  • 파드가 퍼시스턴트 볼륨의 사용을 중지하면 쿠버네티스가 pv-protection 파이널라이저를 해제하고 컨트롤러는 볼륨을 삭제한다.

소유자 참조, 레이블, 파이널라이저

  • 레이블(Label)과 마찬가지로 쿠버네티스에서 소유자 참조(Owner reference)는 오브젝트 간의 관계를 설명하지만 다른 목적으로 사용된다.
  • 컨트롤러가 파드와 같은 오브젝트를 관리할 때 레이블을 사용하여 관련 오브젝트의 그룹에 대한 변경 사항을 추적한다. 예를 들어 잡(Job)이 하나 이상의 파드를 생성하면 잡 컨트롤러는 해당 파드에 레이블을 적용하고 클러스터 내 동일한 레이블을 갖는 파드에 대한 변경 사항을 추적한다.
  • 잡 컨트롤러는 이러한 파드에 “소유자 참조”도 추가하여 파드를 생성한 잡을 가리킨다.
  • 이 파드가 실행될 때 잡을 삭제하면 쿠버네티스는 “사용자 참조(레이블 대신)”를 사용하여 클러스터 내 어떤 파드가 정리되어야 하는지 결정한다.
  • 쿠버네티스는 또한 삭제 대상 리소스에 대한 소유자 참조를 식별할 때 파이널라이저를 처리한다.
  • 경우에 따라 파이널라이저는 종속 오브젝트의 삭제를 차단할 수 있으며 이로 인해 대상 소유자 오브젝트가 완전히 삭제되지 않고 예상보다 오래 유지될 수 있다.
  • 삭제가 차단된 경우 대상 소유자 및 종속 객체에 대한 파이널라이저와 소유자 참조를 확인해 원인을 해결해야 한다.
  • 오브젝트가 삭제 상태에 있는 경우, 삭제를 계속하기위해 파이널라이저를 수동으로 제거하면 안된다.
  • 일반적으로 파이널라이저는 특정한 목적을 가지고 리소스에 추가되기 때문에, 강제로 제거하면 클러스터에 문제가 발생할 수 있다.
  • 파이널라이저의 목적을 이해하고 “일부 종속 객체를 수동으로 정리하는 것과 같은 방법으로 수행될 때”만 삭제를 수행해야 한다.

필드 셀렉터

  • 필드 셀렉터는 한 개 이상의 리소스 필드 값에 따라 쿠버네티스 리소스를 선택하기 위해 사용된다. 필드 셀렉터 쿼리는 아래와 같은 형태를 가진다.
    • metadata.name=my-service
    • metadata.namespace!=default
    • status.phase=Pending
  • 아래의 kubectl 커맨드는 status.phase 필드의 값이 Running인 모든 파드를 선택한다.
kubectl get pods --field-selector status.phase=Running
  • 필드 셀렉터는 본질적으로 리소스 필터이며 기본적으로 적용되는 셀렉터나 필드는 없고 이것은 명시된 종류의 모든 리소스가 선택된다는 것을 의미한다. 아래 두 개의 쿼리는 같은 결과를 출력하게 된다.
kubectl get pods
kubectl get pods --field-selector ""

사용 가능한 필드

  • 사용 가능한 필드는 쿠버네티스의 리소스 종류에 따라서 다르다.
  • 모든 종류의 리소스는 metadata.namemetadata.namespace필드 셀렉터를 사용할 수 있으며 사용할 수 없는 필드 셀렉터를 사용하면 아래와 같은 에러를 출력한다.
Error from server (BadRequest): Unable to find "ingresses" that match label selector "

사용 가능한 연산자

  • 필드 셀렉터에서는 =, ==, != 연산자를 사용할 수 있으며 ===는 동일한 의미로 사용된다. 아래의 커맨드는 default 네임스페이스에 속해있지 않은 모든 쿠버네티스 서비스를 선택한다.
kubectl get services --all-namespaces --field-selector metadata.namespace!=default

연계되는 셀렉터

  • 레이블을 비롯한 다른 셀렉터처럼, 쉼표로 구분되는 목록을 통해 셀렉터를 연계해서 사용할 수 있다. 아래의 커맨드는 status.phase 필드가 Running이 아니고, spec.restartPolicy 필드가 Always인 모든 파드를 선택한다.
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always

여러 개의 리소스 종류

  • 필드 셀렉터를 여러 개의 리소스 종류에 걸쳐 사용할 수 있다. 아래의 커맨드는 default 네임스페이스에 속해있지 않은 모든 스테이트풀셋(StatefulSet)과 서비스를 선택한다.
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default

권장 레이블

  • kubectl과 대시보드와 같은 많은 도구들로 쿠버네티스 오브젝트를 시각화 하고 관리할 수 있다.
  • 공통 레이블 셋은 모든 도구들이 이해할 수 있는 공통의 방식으로 오브젝트를 식별하고 도구들이 상호 운용적으로 작동할 수 있도록 한다.
  • 권장 레이블은 지원 도구 외에도 쿼리한느 방식으로 애플리케이션을 식별하게 한다.
  • 메타데이터는 “애플리케이션”의 개념을 중심으로 정리되며 쿠버네티스는 플랫폼 서비스(PaaS)가 아니며 애플리케이션에 대해 공식적인 개념이 없거나 강요하지 않는다.
  • 애플리케이션은 비공식적이며 메타데이터로 설명되고 애플리케이션에 포함된 정의는 유연하다.
  • 메타데이터들은 권장하는 레이블이다. 애플리케이션을 보다 쉽게 관리할 수 있지만 코어 도구에는 필요하지 않다.
  • 메타데이터들은 권장하는 레이블이며 애플리케이션을 보다 쉽게 관리할 수 있지만 코어 도구에는 필요하지 않다.
  • 공유 레이블과 주석에는 공통 접두사인 app.kubernetes.io가 있다.
  • 접두사가 없는 레이블은 사용자가 개인적으로 사용할 수 있다. 공유 접두사는 공유 레이블이 사용자 정의 레이블을 방해하지 않도록 한다.

레이블

  • 레이블을 최대한 활용하려면 모든 리소스 오브젝트에 적용해야 한다.
설명 예시 타입
app.kubernetes.io/name 애플리케이션 이름 mysql 문자열
app.kubernetes.io/instance 애플리케이션의 인스턴스를 식별하는 고유한 이름 myslq-abcxzy 문자열
app.kubernetes.io/version 애플리케이션의 현재 버전(예: a semantic version, revision hash 등.) 5.7.21 문자열
app.kubernetes.io/component 아키텍처 내 구성요소 database 문자열
app.kubernetes.io/part-of 이 애플리케이션의 전체 이름 wordpress 문자열
app.kubernetes.io/managed-by 애플리케이션의 작동을 관리하는 데 사용되는 도구 helm 문자열
app.kubernetes.io/created-by 이 리소스를 만든 컨트롤러/사용자 controller-manager 문자열
- 아래는 위의 레이블을 사용한 스테이트풀셋 오브젝트이다.
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/component: database
    app.kubernetes.io/part-of: wordpress
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/created-by: controller-manager

애플리케이션과 애플리케이션 인스턴스

  • 애플리케이션은 동일한 쿠버네티스 클러스터에, 심지어 동일한 네임스페이스에도 한번 이상 설치될 수 있다.
    예를 들어, 하나의 쿠버네티스 클러스터에 WordPress가 여러 번 설치되어 각각 서로 다른 웹사이트를 서비스할 수 있다.
  • 애플리케이션의 이름과 애플리케이션 인스턴스 이름은 별도로 기록된다. 예를 들어, WordPress는 애플리케이션 이름으로 app/kubernetes.io/name이라는 레이블에 wordpress라는 값을 가지며, 애플리케이션 인스턴스 이름으로는 app.kubernetes.io/instance라는 레이블에 wordpress-abcxzy라는 값을 가진다.
  • 이름과 인스턴스의 이름을 통해 정확한 식별이 가능하며, 모든 애플리케이션 인스턴스는 고유한 이름을 가져야 한다.

단순한 스테이트리스 서비스

  • DeploymentService오브젝트를 통해 배포된 단순한 스테이트리스 서비스의 경우를 살펴본다. 다음 두 식별자는 레이블을 가장 간단한 형태로 사용하는 방법을 나타낸다.
  • 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
...

데이터베이스가 있는 웹 애플리케이션

  • Helm을 티용해서 데이터베이스(MySQL)을 이용하는 웹 애플리케이션(WordPress)을 설치한 것과 같이 좀 더 복잡한 애플리케이션을 고려할 수 있다.
  • 아래의 식별자는 이 애플리케이션을 배포하는 데 사용하는 오브젝트의 시작을 보여준다.
  • 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
...
  • MySQL StatefulSetService로 MySQL과 WordPress가 더 큰 범위의 애플리케이션에 포함되어 있는 것을 알게 된다.

참고 자료

'Infrastructure > Kubernetes' 카테고리의 다른 글

[클러스터 아키텍처] 컨트롤 플레인-노드 간 통신  (0) 2022.10.13
[클러스터 아키텍처] 노드  (0) 2022.10.13
[K8S] 오브젝트 - 1  (0) 2022.10.12
[K8S] 쿠버네티스란  (0) 2022.10.12
[K8S] 모범 사례  (0) 2022.10.12