This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

쿠버네티스 오브젝트로 작업하기

쿠버네티스 오브젝트는 쿠버네티스 시스템의 영구 엔티티이다. 쿠버네티스는 이러한 엔티티들을 사용하여 클러스터의 상태를 나타낸다. 쿠버네티스 오브젝트 모델과 쿠버네티스 오브젝트를 사용하는 방법에 대해 학습한다.

1 - 쿠버네티스 오브젝트 이해하기

이 페이지에서는 쿠버네티스 오브젝트가 쿠버네티스 API에서 어떻게 표현되고, 그 오브젝트를 어떻게 .yaml 형식으로 표현할 수 있는지에 대해 설명한다.

쿠버네티스 오브젝트 이해하기

쿠버네티스 오브젝트 는 쿠버네티스 시스템에서 영속성을 가지는 오브젝트이다. 쿠버네티스는 클러스터의 상태를 나타내기 위해 이 오브젝트를 이용한다. 구체적으로 말하자면, 다음같이 기술할 수 있다.

  • 어떤 컨테이너화된 애플리케이션이 동작 중인지 (그리고 어느 노드에서 동작 중인지)
  • 그 애플리케이션이 이용할 수 있는 리소스
  • 그 애플리케이션이 어떻게 재구동 정책, 업그레이드, 그리고 내고장성과 같은 것에 동작해야 하는지에 대한 정책

쿠버네티스 오브젝트는 하나의 "의도를 담은 레코드"이다. 오브젝트를 생성하게 되면, 쿠버네티스 시스템은 그 오브젝트 생성을 보장하기 위해 지속적으로 작동할 것이다. 오브젝트를 생성함으로써, 여러분이 클러스터의 워크로드를 어떤 형태로 보이고자 하는지에 대해 효과적으로 쿠버네티스 시스템에 전한다. 이것이 바로 여러분의 클러스터에 대해 의도한 상태 가 된다.

생성이든, 수정이든, 또는 삭제든 쿠버네티스 오브젝트를 동작시키려면, 쿠버네티스 API를 이용해야 한다. 예를 들어, kubectl 커맨드-라인 인터페이스를 이용할 때, CLI는 여러분 대신 필요한 쿠버네티스 API를 호출해 준다. 또한, 여러분은 클라이언트 라이브러리 중 하나를 이용하여 여러분만의 프로그램에서 쿠버네티스 API를 직접 이용할 수도 있다.

오브젝트 명세(spec)와 상태(status)

거의 모든 쿠버네티스 오브젝트는 오브젝트의 구성을 결정해주는 두 개의 중첩된 오브젝트 필드를 포함하는데 오브젝트 spec 과 오브젝트 status 이다. spec을 가진 오브젝트는 오브젝트를 생성할 때 리소스에 원하는 특징(의도한 상태)에 대한 설명을 제공해서 설정한다.

status 는 쿠버네티스 시스템과 컴포넌트에 의해 제공되고 업데이트된 오브젝트의 현재 상태 를 설명한다. 쿠버네티스 컨트롤 플레인은 모든 오브젝트의 실제 상태를 사용자가 의도한 상태와 일치시키기 위해 끊임없이 그리고 능동적으로 관리한다.

예를 들어, 쿠버네티스 디플로이먼트는 클러스터에서 동작하는 애플리케이션을 표현해줄 수 있는 오브젝트이다. 디플로이먼트를 생성할 때, 디플로이먼트 spec에 3개의 애플리케이션 레플리카가 동작되도록 설정할 수 있다. 쿠버네티스 시스템은 그 디플로이먼트 spec을 읽어 spec에 일치되도록 상태를 업데이트하여 3개의 의도한 애플리케이션 인스턴스를 구동시킨다. 만약, 그 인스턴스들 중 어느 하나가 어떤 문제로 인해 멈춘다면(상태 변화 발생), 쿠버네티스 시스템은 보정(이 경우에는 대체 인스턴스를 시작하여)을 통해 spec과 status간의 차이에 대응한다.

오브젝트 명세, 상태, 그리고 메타데이터에 대한 추가 정보는, Kubernetes API Conventions 를 참조한다.

쿠버네티스 오브젝트 기술하기

쿠버네티스에서 오브젝트를 생성할 때, (이름과 같은)오브젝트에 대한 기본적인 정보와 더불어, 의도한 상태를 기술한 오브젝트 spec을 제시해 줘야만 한다. 오브젝트를 생성하기 위해(직접이든 또는 kubectl을 통해서든) 쿠버네티스 API를 이용할 때, API 요청은 요청 내용 안에 JSON 형식으로 정보를 포함시켜 줘야만 한다. 대부분의 경우 정보를 .yaml 파일로 kubectl에 제공한다. kubectl은 API 요청이 이루어질 때, JSON 형식으로 정보를 변환시켜 준다.

여기 쿠버네티스 디플로이먼트를 위한 필수 필드와 오브젝트 spec을 보여주는 .yaml 파일 예시가 있다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

위 예시와 같이 .yaml 파일을 이용하여 디플로이먼트를 생성하기 위한 하나의 방식으로는 kubectl 커맨드-라인 인터페이스에 인자값으로 .yaml 파일을 건네 kubectl apply 커맨드를 이용하는 것이다. 다음 예시와 같다.

kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record

그 출력 내용은 다음과 유사하다.

deployment.apps/nginx-deployment created

요구되는 필드

생성하고자 하는 쿠버네티스 오브젝트에 대한 .yaml 파일 내, 다음 필드를 위한 값들을 설정해 줘야한다.

  • apiVersion - 이 오브젝트를 생성하기 위해 사용하고 있는 쿠버네티스 API 버전이 어떤 것인지
  • kind - 어떤 종류의 오브젝트를 생성하고자 하는지
  • metadata - 이름 문자열, UID, 그리고 선택적인 네임스페이스를 포함하여 오브젝트를 유일하게 구분지어 줄 데이터
  • spec - 오브젝트에 대해 어떤 상태를 의도하는지

오브젝트 spec에 대한 정확한 포맷은 모든 쿠버네티스 오브젝트마다 다르고, 그 오브젝트 특유의 중첩된 필드를 포함한다. Kubernetes API Reference 는 쿠버네티스를 이용하여 생성할 수 있는 오브젝트에 대한 모든 spec 포맷을 살펴볼 수 있도록 해준다. 예를 들어, 파드에 대한 spec 포맷은 PodSpec v1 Core 에서 확인할 수 있고, 디플로이먼트에 대한 spec 포맷은 DeploymentSpec v1 apps에서 확인할 수 있다.

다음 내용

  • 파드와 같이, 가장 중요하고 기본적인 쿠버네티스 오브젝트에 대해 배운다.
  • 쿠버네티스의 컨트롤러에 대해 배운다.
  • API 개념의 더 많은 설명은 쿠버네티스 API 사용을 본다.

2 - 쿠버네티스 오브젝트 관리

kubectl 커맨드라인 툴은 쿠버네티스 오브젝트를 생성하고 관리하기 위한 몇 가지 상이한 방법을 지원한다. 이 문서는 여러가지 접근법에 대한 개요을 제공한다. Kubectl로 오브젝트 관리하기에 대한 자세한 설명은 Kubectl 서적에서 확인한다.

관리 기법

경고: 쿠버네티스 오브젝트는 하나의 기법만 사용하여 관리해야 한다. 동일한 오브젝트에 대해 여러 기법을 혼용하는 것은 예상치 못한 동작을 초래하게 된다.
관리기법대상권장 환경지원하는 작업자 수학습 난이도
명령형 커맨드활성 오브젝트개발 환경1+낮음
명령형 오브젝트 구성개별 파일프로덕션 환경1보통
선언형 오브젝트 구성파일이 있는 디렉터리프로덕션 환경1+높음

명령형 커맨드

명령형 커맨드를 사용할 경우, 사용자는 클러스터 내 활성 오브젝트를 대상으로 직접 동작시킨다. 사용자는 실행할 작업을 인수 또는 플래그로 kubectl 커맨드에 지정한다.

이것은 클러스터에서 일회성 작업을 개시시키거나 동작시키기 위한 추천 방법이다. 이 기법은 활성 오브젝트를 대상으로 직접적인 영향을 미치기 때문에, 이전 구성에 대한 이력을 제공해 주지 않는다.

예시

디플로이먼트 오브젝트를 생성하여 nginx 컨테이너의 인스턴스를 구동시킨다.

kubectl create deployment nginx --image nginx

트레이드 오프

오브젝트 구성에 비해 장점은 다음과 같다.

  • 커맨드는 하나의 동작을 나타내는 단어로 표현된다.
  • 커맨드는 클러스터를 수정하기 위해 단 하나의 단계만을 필요로 한다.

오브젝트 구성에 비해 단점은 다음과 같다.

  • 커맨드는 변경 검토 프로세스와 통합되지 않는다.
  • 커맨드는 변경에 관한 감사 추적(audit trail)을 제공하지 않는다.
  • 커맨드는 활성 동작 중인 경우를 제외하고는 레코드의 소스를 제공하지 않는다.
  • 커맨드는 새로운 오브젝트 생성을 위한 템플릿을 제공하지 않는다.

명령형 오브젝트 구성

명령형 오브젝트 구성에서는 kubectl 커맨드로 작업(생성, 교체 등), 선택적 플래그, 그리고 최소 하나의 파일 이름을 지정한다. 그 파일은 YAML 또는 JSON 형식으로 오브젝트의 완전한 정의를 포함해야만 한다.

오브젝트 정의에 대한 더 자세한 내용은 API 참조를 참고한다.

경고: 명령형 replace 커맨드는 기존 spec을 새로 제공된 spec으로 바꾸고 구성 파일에서 누락된 오브젝트의 모든 변경 사항을 삭제한다. 이 방법은 spec이 구성 파일과는 별개로 업데이트되는 리소스 유형에는 사용하지 말아야한다. 예를 들어 LoadBalancer 유형의 서비스는 클러스터의 구성과 별도로 externalIPs 필드가 업데이트된다.

예시

구성 파일에 정의된 오브젝트를 생성한다.

kubectl create -f nginx.yaml

두 개의 구성 파일에 정의된 오브젝트를 삭제한다.

kubectl delete -f nginx.yaml -f redis.yaml

활성 동작하는 구성을 덮어씀으로써 구성 파일에 정의된 오브젝트를 업데이트한다.

kubectl replace -f nginx.yaml

트레이드 오프

명령형 커맨드에 비해 장점은 다음과 같다.

  • 오브젝트 구성은 Git과 같은 소스 컨트롤 시스템에 보관할 수 있다.
  • 오브젝트 구성은 푸시와 감사 추적 전에 변경사항을 검토하는 것과 같은 프로세스들과 통합할 수 있다.
  • 오브젝트 구성은 새로운 오브젝트 생성을 위한 템플릿을 제공한다.

명령형 커맨드에 비해 단점은 다음과 같다.

  • 오브젝트 구성은 오브젝트 스키마에 대한 기본적인 이해를 필요로 한다.
  • 오브젝트 구성은 YAML 파일을 기록하는 추가적인 과정을 필요로 한다.

선언형 오브젝트 구성에 비해 장점은 다음과 같다.

  • 명령형 오브젝트 구성의 동작은 보다 간결하고 이해하기 쉽다.
  • 쿠버네티스 버전 1.5 부터는 더 성숙한 명령형 오브젝트 구성을 제공한다.

선언형 오브젝트 구성에 비해 단점은 다음과 같다.

  • 명령형 오브젝트 구성은 디렉터리가 아닌, 파일에 가장 적합하다.
  • 활성 오브젝트에 대한 업데이트는 구성 파일에 반영되어야 한다. 그렇지 않으면 다음 교체 중에 손실된다.

선언형 오브젝트 구성

선언형 오브젝트 구성을 사용할 경우, 사용자는 로컬에 보관된 오브젝트 구성 파일을 대상으로 작동시키지만, 사용자는 파일에서 수행 할 작업을 정의하지 않는다. 생성, 업데이트, 그리고 삭제 작업은 kubectl에 의해 오브젝트마다 자동으로 감지된다. 이를 통해 다른 오브젝트에 대해 다른 조작이 필요할 수 있는 디렉터리에서 작업할 수 있다.

참고: 선언형 오브젝트 구성은 변경 사항이 오브젝트 구성 파일에 다시 병합되지 않더라도 다른 작성자가 작성한 변경 사항을 유지한다. 이것은 전체 오브젝트 구성 변경을 위한 replace API를 사용하는 대신, patch API를 사용하여 인지되는 차이만 작성하기 때문에 가능하다.

예시

configs 디렉터리 내 모든 오브젝트 구성 파일을 처리하고 활성 오브젝트를 생성 또는 패치한다. 먼저 어떠한 변경이 이루어지게 될지 알아보기 위해 diff 하고 나서 적용할 수 있다.

kubectl diff -f configs/
kubectl apply -f configs/

재귀적으로 디렉터리를 처리한다.

kubectl diff -R -f configs/
kubectl apply -R -f configs/

트레이드 오프

명령형 오브젝트 구성에 비해 장점은 다음과 같다.

  • 활성 오브젝트에 직접 작성된 변경 사항은 구성 파일로 다시 병합되지 않더라도 유지된다.
  • 선언형 오브젝트 구성은 디렉터리에서의 작업 및 오브젝트 별 작업 유형(생성, 패치, 삭제)의 자동 감지에 더 나은 지원을 제공한다.

명령형 오브젝트 구성에 비해 단점은 다음과 같다.

  • 선언형 오브젝트 구성은 예상치 못한 결과를 디버깅하고 이해하기가 더 어렵다.
  • diff를 사용한 부분 업데이트는 복잡한 병합 및 패치 작업을 일으킨다.

다음 내용

3 - 오브젝트 이름과 ID

클러스터의 각 오브젝트는 해당 유형의 리소스에 대하여 고유한 이름 을 가지고 있다. 또한, 모든 쿠버네티스 오브젝트는 전체 클러스터에 걸쳐 고유한 UID 를 가지고 있다.

예를 들어, 이름이 myapp-1234인 파드는 동일한 네임스페이스 내에서 하나만 존재할 수 있지만, 이름이 myapp-1234인 파드와 디플로이먼트는 각각 존재할 수 있다.

유일하지 않은 사용자 제공 속성의 경우 쿠버네티스는 레이블어노테이션을 제공한다.

이름

/api/v1/pods/some-name과 같이, 리소스 URL에서 오브젝트를 가리키는 클라이언트 제공 문자열.

특정 시점에 같은 종류(kind) 내에서는 하나의 이름은 하나의 오브젝트에만 지정될 수 있다. 하지만, 오브젝트를 삭제한 경우, 삭제된 오브젝트와 같은 이름을 새로운 오브젝트에 지정 가능하다.

참고: 물리적 호스트를 나타내는 노드와 같이 오브젝트가 물리적 엔티티를 나타내는 경우, 노드를 삭제한 후 다시 생성하지 않은 채 동일한 이름으로 호스트를 다시 생성하면, 쿠버네티스는 새 호스트를 불일치로 이어질 수 있는 이전 호스트로 취급한다.

다음은 리소스에 일반적으로 사용되는 세 가지 유형의 이름 제한 조건이다.

DNS 서브도메인 이름

대부분의 리소스 유형에는 RFC 1123에 정의된 대로 DNS 서브도메인 이름으로 사용할 수 있는 이름이 필요하다. 이것은 이름이 다음을 충족해야 한다는 것을 의미한다.

  • 253자를 넘지 말아야 한다.
  • 소문자와 영숫자 - 또는 . 만 포함한다.
  • 영숫자로 시작한다.
  • 영숫자로 끝난다.

DNS 레이블 이름

일부 리소스 유형은 RFC 1123에 정의된 대로 DNS 레이블 표준을 따라야 한다. 이것은 이름이 다음을 충족해야 한다는 것을 의미한다.

  • 최대 63자이다.
  • 소문자와 영숫자 또는 - 만 포함한다.
  • 영숫자로 시작한다.
  • 영숫자로 끝난다.

경로 세그먼트 이름

일부 리소스 유형에서는 이름을 경로 세그먼트로 안전하게 인코딩 할 수 있어야 한다. 즉 이름이 "." 또는 ".."이 아닐 수 있으며 이름에는 "/" 또는 "%"가 포함될 수 없다.

아래는 파드의 이름이 nginx-demo라는 매니페스트 예시이다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
참고: 일부 리소스 유형은 이름에 추가적인 제약이 있다.

UID

오브젝트를 중복 없이 식별하기 위해 쿠버네티스 시스템이 생성하는 문자열.

쿠버네티스 클러스터가 구동되는 전체 시간에 걸쳐 생성되는 모든 오브젝트는 서로 구분되는 UID를 갖는다. 이는 기록상 유사한 오브젝트의 출현을 서로 구분하기 위함이다.

쿠버네티스 UID는 보편적으로 고유한 식별자이다(또는 UUID라고 한다). UUID는 ISO/IEC 9834-8 과 ITU-T X.667 로 표준화 되어 있다.

다음 내용

4 - 네임스페이스

쿠버네티스는 동일한 물리 클러스터를 기반으로 하는 여러 가상 클러스터를 지원한다. 이런 가상 클러스터를 네임스페이스라고 한다.

여러 개의 네임스페이스를 사용하는 경우

네임스페이스는 여러 개의 팀이나, 프로젝트에 걸쳐서 많은 사용자가 있는 환경에서 사용하도록 만들어졌다. 사용자가 거의 없거나, 수 십명 정도가 되는 경우에는 네임스페이스를 전혀 고려할 필요가 없다. 네임스페이스가 제공하는 기능이 필요할 때 사용하도록 하자.

네임스페이스는 이름의 범위를 제공한다. 리소스의 이름은 네임스페이스 내에서 유일해야하지만, 네임스페이스를 통틀어서 유일할 필요는 없다. 네임스페이스는 서로 중첩될 수 없으며, 각 쿠버네티스 리소스는 하나의 네임스페이스에만 있을 수 있다.

네임스페이스는 클러스터 자원을 (리소스 쿼터를 통해) 여러 사용자 사이에서 나누는 방법이다.

동일한 소프트웨어의 다른 버전과 같이 약간 다른 리소스를 분리하기 위해 여러 네임스페이스를 사용할 필요는 없다. 동일한 네임스페이스 내에서 리소스를 구별하기 위해 레이블을 사용한다.

네임스페이스 다루기

네임스페이스의 생성과 삭제는 네임스페이스 관리자 가이드 문서에 기술되어 있다.

참고: kube- 접두사로 시작하는 네임스페이스는 쿠버네티스 시스템용으로 예약되어 있으므로, 사용자는 이러한 네임스페이스를 생성하지 않는다.

네임스페이스 조회

사용 중인 클러스터의 현재 네임스페이스를 나열할 수 있다.

kubectl get namespace
NAME              STATUS   AGE
default           Active   1d
kube-node-lease   Active   1d
kube-public       Active   1d
kube-system       Active   1d

쿠버네티스는 처음에 네 개의 초기 네임스페이스를 갖는다.

  • default 다른 네임스페이스가 없는 오브젝트를 위한 기본 네임스페이스
  • kube-system 쿠버네티스 시스템에서 생성한 오브젝트를 위한 네임스페이스
  • kube-public 이 네임스페이스는 자동으로 생성되며 모든 사용자(인증되지 않은 사용자 포함)가 읽기 권한으로 접근할 수 있다. 이 네임스페이스는 주로 전체 클러스터 중에 공개적으로 드러나서 읽을 수 있는 리소스를 위해 예약되어 있다. 이 네임스페이스의 공개적인 성격은 단지 관례이지 요구 사항은 아니다.
  • kube-node-lease 클러스터가 스케일링될 때 노드 하트비트의 성능을 향상시키는 각 노드와 관련된 리스(lease) 오브젝트에 대한 네임스페이스

요청에 네임스페이스 설정하기

현재 요청에 대한 네임스페이스를 설정하기 위해서 --namespace 플래그를 사용한다.

예를 들면,

kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>

선호하는 네임스페이스 설정하기

이후 모든 kubectl 명령에서 사용하는 네임스페이스를 컨텍스트에 영구적으로 저장할 수 있다.

kubectl config set-context --current --namespace=<insert-namespace-name-here>
# 확인하기
kubectl config view --minify | grep namespace:

네임스페이스와 DNS

서비스를 생성하면 해당 DNS 엔트리가 생성된다. 이 엔트리는 <서비스-이름>.<네임스페이스-이름>.svc.cluster.local의 형식을 갖는데, 이는 컨테이너가 <서비스-이름>만 사용하는 경우, 네임스페이스 내에 국한된 서비스로 연결된다. 개발, 스테이징, 운영과 같이 여러 네임스페이스 내에서 동일한 설정을 사용하는 경우에 유용하다. 네임스페이스를 넘어서 접근하기 위해서는, 전체 주소 도메인 이름(FQDN)을 사용해야 한다.

모든 오브젝트가 네임스페이스에 속하지는 않음

대부분의 쿠버네티스 리소스(예를 들어, 파드, 서비스, 레플리케이션 컨트롤러 외)는 네임스페이스에 속한다. 하지만 네임스페이스 리소스 자체는 네임스페이스에 속하지 않는다. 그리고 노드나 퍼시스턴트 볼륨과 같은 저수준 리소스는 어느 네임스페이스에도 속하지 않는다.

다음은 네임스페이스에 속하지 않는 쿠버네티스 리소스를 조회하는 방법이다.

# 네임스페이스에 속하는 리소스
kubectl api-resources --namespaced=true

# 네임스페이스에 속하지 않는 리소스
kubectl api-resources --namespaced=false

자동 레이블링

FEATURE STATE: Kubernetes 1.21 [beta]

쿠버네티스 컨트롤 플레인은 NamespaceDefaultLabelName 기능 게이트가 활성화된 경우 모든 네임스페이스에 변경할 수 없는(immutable) 레이블 kubernetes.io / metadata.name 을 설정한다. 레이블 값은 네임스페이스 이름이다.

다음 내용

5 - 레이블과 셀렉터

레이블 은 파드와 같은 오브젝트에 첨부된 키와 값의 쌍이다. 레이블은 오브젝트의 특성을 식별하는 데 사용되어 사용자에게 중요하지만, 코어 시스템에 직접적인 의미는 없다. 레이블로 오브젝트의 하위 집합을 선택하고, 구성하는데 사용할 수 있다. 레이블은 오브젝트를 생성할 때에 붙이거나 생성 이후에 붙이거나 언제든지 수정이 가능하다. 오브젝트마다 키와 값으로 레이블을 정의할 수 있다. 오브젝트의 키는 고유한 값이어야 한다.

"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

레이블은 UI와 CLI에서 효율적인 쿼리를 사용하고 검색에 사용하기에 적합하다. 식별되지 않는 정보는 어노테이션으로 기록해야 한다.

사용 동기

레이블을 이용하면 사용자가 느슨하게 결합한 방식으로 조직 구조와 시스템 오브젝트를 매핑할 수 있으며, 클라이언트에 매핑 정보를 저장할 필요가 없다.

서비스 배포와 배치 프로세싱 파이프라인은 흔히 다차원의 엔티티들이다(예: 다중 파티션 또는 배포, 다중 릴리스 트랙, 다중 계층, 계층 속 여러 마이크로 서비스들). 관리에는 크로스-커팅 작업이 필요한 경우가 많은데 이 작업은 사용자보다는 인프라에 의해 결정된 엄격한 계층 표현인 캡슐화를 깨트린다.

레이블 예시:

  • "release" : "stable", "release" : "canary"
  • "environment" : "dev", "environment" : "qa", "environment" : "production"
  • "tier" : "frontend", "tier" : "backend", "tier" : "cache"
  • "partition" : "customerA", "partition" : "customerB"
  • "track" : "daily", "track" : "weekly"

이 예시는 일반적으로 사용하는 레이블이며, 사용자는 자신만의 규칙(convention)에 따라 자유롭게 개발할 수 있다. 오브젝트에 붙여진 레이블 키는 고유해야 한다는 것을 기억해야 한다.

구문과 캐릭터 셋

레이블 은 키와 값의 쌍이다. 유효한 레이블 키에는 슬래시(/)로 구분되는 선택한 접두사와 이름이라는 2개의 세그먼트가 있다. 이름 세그먼트는 63자 미만으로 시작과 끝은 알파벳과 숫자([a-z0-9A-Z])이며, 대시(-), 밑줄(_), 점(.)과 함께 사용할 수 있다. 접두사는 선택이다. 만약 접두사를 지정한 경우 접두사는 DNS의 하위 도메인으로 해야 하며, 점(.)과 전체 253자 이하, 슬래시(/)로 구분되는 DNS 레이블이다.

접두사를 생략하면 키 레이블은 개인용으로 간주한다. 최종 사용자의 오브젝트에 자동화된 시스템 컴포넌트(예: kube-scheduler, kube-controller-manager, kube-apiserver, kubectl 또는 다른 타사의 자동화 구성 요소)의 접두사를 지정해야 한다.

kubernetes.io/k8s.io/ 접두사는 쿠버네티스의 핵심 컴포넌트로 예약되어있다.

유효한 레이블 값은 다음과 같다.

  • 63 자 이하여야 하고 (공백일 수도 있음),
  • (공백이 아니라면) 시작과 끝은 알파벳과 숫자([a-z0-9A-Z])이며,
  • 알파벳과 숫자, 대시(-), 밑줄(_), 점(.)을 중간에 포함할 수 있다.

유효한 레이블 값은 63자 미만 또는 공백이며 시작과 끝은 알파벳과 숫자([a-z0-9A-Z])이며, 대시(-), 밑줄(_), 점(.)과 함께 사용할 수 있다.

다음의 예시는 파드에 environment: productionapp: nginx 2개의 레이블이 있는 구성 파일이다.


apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels:
    environment: production
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

레이블 셀렉터

이름과 UID와 다르게 레이블은 고유하지 않다. 일반적으로 우리는 많은 오브젝트에 같은 레이블을 가질 것으로 예상한다.

레이블 셀렉터를 통해 클라이언트와 사용자는 오브젝트를 식별할 수 있다. 레이블 셀렉터는 쿠버네티스 코어 그룹의 기본이다.

API는 현재 일치성 기준집합성 기준 이라는 두 종류의 셀렉터를 지원한다. 레이블 셀렉터는 쉼표로 구분된 다양한 요구사항 에 따라 만들 수 있다. 다양한 요구사항이 있는 경우 쉼표 기호가 AND(&&) 연산자로 구분되는 역할을 하도록 해야 한다.

비어있거나 지정되지 않은 셀렉터는 상황에 따라 달라진다. 셀렉터를 사용하는 API 유형은 유효성과 의미를 문서화해야 한다.

참고: 레플리카셋(ReplicaSet)과 같은 일부 API 유형에서 두 인스턴스의 레이블 셀렉터는 네임스페이스 내에서 겹치지 않아야 한다. 그렇지 않으면 컨트롤러는 상충하는 명령으로 보고, 얼마나 많은 복제본이 필요한지 알 수 없다.
주의: 일치성 기준과 집합성 기준 조건 모두에 대해 논리적인 OR (||) 연산자가 없다. 필터 구문이 적절히 구성되어있는지 확인해야 한다.

일치성 기준 요건

일치성 기준 또는 불일치 기준 의 요구사항으로 레이블의 키와 값의 필터링을 허용한다. 일치하는 오브젝트는 추가 레이블을 가질 수 있지만, 레이블의 명시된 제약 조건을 모두 만족해야 한다. =,==,!= 이 세 가지 연산자만 허용한다. 처음 두 개의 연산자의 일치성(그리고 동의어), 나머지는 불일치 를 의미한다. 예를 들면,

environment = production
tier != frontend

전자는 environment를 키로 가지는 것과 production을 값으로 가지는 모든 리소스를 선택한다. 후자는 tier를 키로 가지고, 값을 frontend를 가지는 리소스를 제외한 모든 리소스를 선택하고, 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,notinexists(키 식별자만 해당)의 3개의 연산자를 지원한다. 예를 들면,

environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
  • 첫 번째 예시에서 키가 environment이고 값이 production 또는 qa인 모든 리소스를 선택한다.
  • 두 번째 예시에서 키가 tier이고 값이 frontendbackend를 가지는 리소스를 제외한 모든 리소스와 키로 tier를 가지고 값을 공백으로 가지는 모든 리소스를 선택한다.
  • 세 번째 예시에서 레이블의 값에 상관없이 키가 partition을 포함하는 모든 리소스를 선택한다.
  • 네 번째 예시에서 레이블의 값에 상관없이 키가 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 작업은 쿼리 파라미터를 사용해서 반환되는 오브젝트 집합을 필터링하기 위해 레이블 셀렉터를 지정할 수 있다. 다음의 두 가지 요건 모두 허용된다(URL 쿼리 문자열을 그대로 표기함).

  • 일치성 기준 요건: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
  • 집합성 기준 요건: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%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

json 또는 yaml 서식에서 셀렉터는 component=redis 또는 component in (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로 되어있어 일치하기 위해서는 모든 요건을 만족해야 한다.

노드 셋 선택

레이블을 통해 선택하는 사용 사례 중 하나는 파드를 스케줄 할 수 있는 노드 셋을 제한하는 것이다. 자세한 내용은 노드 선택 문서를 참조한다.

6 - 어노테이션

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

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

레이블이나 어노테이션을 사용하여 쿠버네티스 오브젝트에 메타데이터를 첨부할 수 있다. 레이블을 사용하여 오브젝트를 선택하고, 특정 조건을 만족하는 오브젝트 컬렉션을 찾을 수 있다. 반면에, 어노테이션은 오브젝트를 식별하고 선택하는데 사용되지 않는다. 어노테이션의 메타데이터는 작거나 크고, 구조적이거나 구조적이지 않을 수 있으며, 레이블에서 허용되지 않는 문자를 포함할 수 있다.

어노테이션은 레이블과 같이 키/값 맵이다.

"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

다음은 어노테이션에 기록할 수 있는 정보의 예제이다.

  • 필드는 선언적 구성 계층에 의해 관리된다. 이러한 필드를 어노테이션으로 첨부하는 것은 클라이언트 또는 서버가 설정한 기본 값, 자동 생성된 필드, 그리고 오토사이징 또는 오토스케일링 시스템에 의해 설정된 필드와 구분된다.

  • 빌드, 릴리스, 또는 타임 스탬프, 릴리스 ID, git 브랜치, PR 번호, 이미지 해시 및 레지스트리 주소와 같은 이미지 정보.

  • 로깅, 모니터링, 분석 또는 감사 리포지터리에 대한 포인터.

  • 디버깅 목적으로 사용될 수 있는 클라이언트 라이브러리 또는 도구 정보: 예를 들면, 이름, 버전, 그리고 빌드 정보.

  • 다른 생태계 구성 요소의 관련 오브젝트 URL과 같은 사용자 또는 도구/시스템 출처 정보.

  • 경량 롤아웃 도구 메타데이터. 예: 구성 또는 체크포인트

  • 책임자의 전화번호 또는 호출기 번호, 또는 팀 웹 사이트 같은 해당 정보를 찾을 수 있는 디렉터리 진입점.

  • 행동을 수정하거나 비표준 기능을 수행하기 위한 최종 사용자의 지시 사항.

어노테이션을 사용하는 대신, 이 유형의 정보를 외부 데이터베이스 또는 디렉터리에 저장할 수 있지만, 이는 배포, 관리, 인트로스펙션(introspection) 등을 위한 공유 클라이언트 라이브러리와 도구 생성을 훨씬 더 어렵게 만들 수 있다.

문법과 캐릭터 셋

어노테이션 은 키/값 쌍이다. 유효한 어노테이션 키에는 두 개의 세그먼트가 있다. 두 개의 세그먼트는 선택적인 접두사와 이름(name)이며, 슬래시(/)로 구분된다. 이름 세그먼트는 필수이며, 영문 숫자([a-z0-9A-Z])로 시작하고 끝나는 63자 이하이어야 하고, 사이에 대시(-), 밑줄(_), 점(.)이 들어갈 수 있다. 접두사는 선택적이다. 지정된 경우, 접두사는 DNS 서브도메인이어야 한다. 점(.)으로 구분된 일련의 DNS 레이블은 총 253자를 넘지 않고, 뒤에 슬래시(/)가 붙는다.

접두사가 생략되면, 어노테이션 키는 사용자에게 비공개로 간주된다. 최종 사용자 오브젝트에 어노테이션을 추가하는 자동화된 시스템 구성 요소(예 :kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, 또는 다른 써드파티 자동화)는 접두사를 지정해야 한다.

kubernetes.io/k8s.io/ 접두사는 쿠버네티스 핵심 구성 요소를 위해 예약되어 있다.

다음은 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

다음 내용

레이블과 셀렉터에 대해 알아본다.

7 - 필드 셀렉터

필드 셀렉터 는 한 개 이상의 리소스 필드 값에 따라 쿠버네티스 리소스를 선택하기 위해 사용된다. 필드 셀렉터 쿼리의 예시는 다음과 같다.

  • metadata.name=my-service
  • metadata.namespace!=default
  • status.phase=Pending

다음의 kubectl 커맨드는 status.phase 필드의 값이 Running 인 모든 파드를 선택한다.

kubectl get pods --field-selector status.phase=Running
참고: 필드 셀렉터는 본질적으로 리소스 필터 이다. 기본적으로 적용되는 셀렉터나 필드는 없으며, 이는 명시된 종류의 모든 리소스가 선택된다는 것을 의미한다. 여기에 따라오는 kubectl 쿼리인 kubectl get podskubectl get pods --field-selector "" 는 동일하다.

사용 가능한 필드

사용 가능한 필드는 쿠버네티스의 리소스 종류에 따라서 다르다. 모든 리소스 종류는 metadata.namemetadata.namespace 필드 셀렉터를 사용할 수 있다. 사용할 수 없는 필드 셀렉터를 사용하면 다음과 같이 에러를 출력한다.

kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"

사용 가능한 연산자

필드 셀렉터에서 =, ==, != 연산자를 사용할 수 있다 (===는 동일한 의미이다). 예를 들면, 다음의 kubectl 커맨드는 default 네임스페이스에 속해있지 않은 모든 쿠버네티스 서비스를 선택한다.

kubectl get services  --all-namespaces --field-selector metadata.namespace!=default

연계되는 셀렉터

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

kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always

여러 개의 리소스 종류

필드 셀렉터를 여러 개의 리소스 종류에 걸쳐 사용할 수 있다. 다음의 kubectl 커맨드는 default 네임스페이스에 속해있지 않은 모든 스테이트풀셋(StatefulSet)과 서비스를 선택한다.

kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default

8 - 권장 레이블

kubectl과 대시보드와 같은 많은 도구들로 쿠버네티스 오브젝트를 시각화 하고 관리할 수 있다. 공통 레이블 셋은 모든 도구들이 이해할 수 있는 공통의 방식으로 오브젝트를 식별하고 도구들이 상호 운용적으로 작동할 수 있도록 한다.

권장 레이블은 지원 도구 외에도 쿼리하는 방식으로 애플리케이션을 식별하게 한다.

메타데이터는 애플리케이션 의 개념을 중심으로 정리된다. 쿠버네티스는 플랫폼 서비스(PaaS)가 아니며 애플리케이션에 대해 공식적인 개념이 없거나 강요하지 않는다. 대신 애플리케이션은 비공식적이며 메타데이터로 설명된다. 애플리케이션에 포함된 정의는 유연하다.

참고: 메타데이터들은 권장하는 레이블이다. 애플리케이션을 보다 쉽게 관리할 수 있지만 코어 도구에는 필요하지 않다.

공유 레이블과 주석에는 공통 접두사인 app.kubernetes.io 가 있다. 접두사가 없는 레이블은 사용자가 개인적으로 사용할 수 있다. 공유 접두사는 공유 레이블이 사용자 정의 레이블을 방해하지 않도록 한다.

레이블

레이블을 최대한 활용하려면 모든 리소스 오브젝트에 적용해야 한다.

설명예시타입
app.kubernetes.io/name애플리케이션 이름mysql문자열
app.kubernetes.io/instance애플리케이션의 인스턴스를 식별하는 고유한 이름mysql-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가 더 큰 범위의 애플리케이션에 포함되어 있는 것을 알게 된다.