backend/kubernetes docs

Kubernetes object - 쿠버네티스 오브젝트

seul chan 2020. 5. 16. 01:23

Kubernetes object

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

  • 쿠버네티스 오브젝트 는 쿠버네티스 시스템에서 영속성을 가지는 개체
  • 쿠버네티스 오브젝트는 하나의 “의도를 담은 레코드"이다. 오브젝트를 생성하게 되면, 쿠버네티스 시스템은 그 오브젝트 생성을 보장하기 위해 지속적으로 작동
  • 생성이든, 수정이든, 또는 삭제든 쿠버네티스 오브젝트를 동작시키려면, 쿠버네티스 API를 이용해야 한다. 예를 들어, kubectl 커맨드-라인 인터페이스를 이용할 때, CLI는 여러분 대신 필요한 쿠버네티스 API를 호출

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

  • spec을 가진 오브젝트는 오브젝트를 생성할 때 리소스에 원하는 특징(의도한 상태)에 대한 설명을 제공해서 설정한다.
  • status는 오브젝트의 현재 상태 를 기술하고, 쿠버네티스 컴포넌트에 의해 제공되고 업데이트

Writing kubernetes object

  • 쿠버네티스 오브젝트 생성시 기본 정보와 상태를 적은 spec이 필요함
  • API 요청 시 요청 내용 안에 JSON 정보 포함
  • 대부분의 경우 .yaml 파일로 kubectl에 제공

.yaml 파일에 필요한 정보들

  • apiVersion: 사용하는 쿠베 API 버전
  • kind: 어떤 종류의 오브젝트
  • metadata: 이름, UID, namespace 등 오브젝트를 유일하게 구분지어줄 데이터
  • spec: 오브젝트에 의도할 상태

쿠버네티스 오브젝트 관리

kubectl cmd 툴은 kubernetes 오브젝트를 생성하고 관리하기 위한 방법 제공

  • 명령형 커맨드 (Imperactive commands)
  • Imperactive object configuration (명령형 오브젝트 구성)
  • Declarative object configuration (선언형 오브젝트 구성)

다음 중 하나의 기법만 사용하여 관리하여아한다

Imperactive commands

  • 오브젝트를 대상으로 직접 동작시킴
  • 일회성 작업을 위한 가장 단순한 방법
kubectl run nginx --image nginx
kubectl create deployment nginx --image nginx

장점

  • 커맨드가 간단
  • 단 한 단계만으로 클러스터 수정 가능

단점

  • 변경 검토 프로세스와 통합 안됨
  • 변경 audit trail 제공안됨
  • 템플릿 제공 X

Imperactive object configuration

  • 명령형 오브젝트 구성에서 kubectl 커맨드는 작업(생성, 교체 등), 선택적 플래그, 그리고 최소 하나의 파일 이름을 정의
kubectl create -f nginx.yaml
kubectl delete -f nginx.yaml -f redis.yaml
kubectl replace -f nginx.yaml

장점

  • git 등 소스컨트롤시스템 사용 가능
  • 푸시, audit trail 전에 검토하는 등의 프로세스와 통합 가능
  • 새로운 오브젝트 생성을 위한 템플릿 제공
  • (Declarative object configuration에 비해) 간결하고 이해가 쉬움

단점

  • object scheme에 대한 이해 필요
  • yaml 기록하는 추가 과정
  • (Declarative object configuration에 비해) 디렉토리가 아니라 파일에만 효과가 좋음

Declarative object configurations

  • 사용자는 로컬에 보관된 오브젝트 구성 파일을 대상으로 작동시키지만, 사용자는 파일에서 수행 할 작업을 정의하지 않는다
  • 생성, 업데이트, 그리고 삭제 작업은 kubectl에 의해 오브젝트 마다 자동으로 감지

예시) configs 디렉토리 내 모든 object config 파일을 처리

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

장점

  • 직접 변경된 사항은 파일로 병합되지 않아도 유지된다.
  • 디렉토리의 작업 및 오브젝트별 작업 (생성, 패치, 삭제)의 자동 감지를 더 잘 지원

단점

  • 예상치 못한 결과를 디버깅하고 이해하기 어려움
  • diff를 사용한 부분 업데이트는 복잡한 패치 작업을 일으킴

실질적으로 helm을 사용한다면 위 기법들을 사용할 일은 딱히 없게 된다. 그래도 기본적으로 저런 방식을 알아두어야 helm - kubernetes 간의 연결고리를 더 명확하게 파악할 수 있을듯하다.

오브젝트 이름과 ID

  • 각 오브젝트는 해당 리소스에 대해 고유한 이름을 가지고 있다. (pod에서는 중복 이름 사용 불가, pod/deployment는 같은 이름 사용 가능)
  • 전체 클러스터에 걸쳐 고유 UID를 가지고 있다.
  • label, annotation은 unique하지 않아도 됨

이름

  • 동일한 물리 클러스터에서 다중 가상 클러스터를 지원하기 위해 사용하는 추상화
  • 리소스의 이름은 Namespance 내에서는 유일해야함
  • DNS subdomain, DNS label, 경로 세그멘트 이름이 필요하고 각각의 제약이 있다. 이 문서에서 확인 가능.

Namespace

Kubernetes는 물리 클러스터를 기반으로 여러 가상 클러스터를 제공하는데, 이를 "Namespace"라고 한다.

  • Namespace는 여러 팀, 프로젝트에 걸쳐 사용자가 많은 환경에서 사용하도록 만들어짐
  • 클러스터 자원을 여러 사용자 사이에서 나누는 방법

네임스페이스 다루기

$ kubectl get namespace
NAME              STATUS   AGE
default           Active   21d
kube-node-lease   Active   21d
kube-public       Active   21d
kube-system       Active   21d
  • default: 다른 네임스페이스가 없는 오브젝트를 위한 기본 네임스페이스
  • kube-system: 쿠버네티스 시스템에서 생성한 오브젝트를 위한 네임스페이스
  • kube-public: 이 네임스페이스는 자동으로 생성되며 모든 사용자(인증되지 않은 사용자 포함)가 읽기 권한으로 접근

현재 요청에 네임스페이스를 사용하려면 --namespace 플래그 사용

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

  • 대부분의 Kubernetes 리소스 (Pod, service, replicationController ...)는 네임스페이스에 속한다
  • 네임스페이스 자체는 속하지 않음. Node 등 low-level resource도 속하지 않음
# In namespace
kubectl api-resource --namespaced=true

# without namespace
kubectl api-resource --namespaced=false

레이블과 셀렉터

  • Label은 pod 등 object에 첨부된 key-value 쌍
  • 코어 시스템에 직접적인 의미는 없다. (사용자가 식별하기 위해서)
  • 언제든지 수정이 가능

사용 동기

  • label을 사용하면 사용자가 느슨한 방식으로 구조와 시스템 오브젝트를 매핑할 수 있다
  • 예시 (예시를 따를 필요 없이 자유롭게 개발 가능)
    • "release" : "stable", "release" : "canary"
    • "environment" : "dev", "environment" : "qa", "environment" : "production"

Label selector

  • 이름, UID와 다르게 Label은 unique하지 않음

  • label selector를 object 식별 가능

  • OR 연산자는 따로 없다. ,(쉼표)로 연결되면 AND의 의미

  • Equality-based requirement (일치성 기준 요건)

    • =, ==, != 연산자
      environment = production
      tier != frontend
    • 위의 내용을 선택하려면 environment=production,tier!=frontend로 쉼표를 통해 한 문장으로 사용하면 된다.
  • Set-based requirement (집합성 기준 요건)

    • in, notin, exists 연산자
      environment in (production, qa)
      tier notin (frontend, backend)
      partition
      !partition
    • 위 내용을 선택하려면 partition in (customerA, customerB),environment!=qa

API

  • List, Watch api 모두 label selector를 지정할 수 있다. (api를 직접 사용할 일은 없겠지만...)
  • kubectl에서는 아래와 같이 사용
kubectl get pods -l environment=production,tier=frontend
kubectl get pods -l 'environment in (production), tier in (frontend)'
kubectl get pods -l 'environment in (production, qa)'
kubectl get pods -l 'environment,environment notin (frontend)'

Annotation

kubernetes annotation을 사용하여 비식별된 메타데이터를 오브젝트에 첨부 가능하다.

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

  • 앞에 나온 label은 object를 선택하고 조건을 만족하는 object들을 선택할 수 있게 해주었다.
  • 반면 annotation은 object를 식별이나 선택하지 못한다.
  • 다양한 정보를 기록 가능
  • annotation 대신 외부 데이터베이스를 사용할 수도 있지만 더 복잡하고 어려움.

Field Selector (필드 셀렉터)

  • 필드 셀렉터는 resource field 값에 따라 resource를 선택하기 위해 사용

    • metadata.name=my-service
    • metadata.namespace!=default
    • status.phase=Pending
  • 아래와 같이 사용

kubectl get pods --field-selector status.phase=Running
  • 사용 가능한 필드는 리소스 종류마다 다르다. metadata.name, metadata.namespace 사용 가능

  • =, ==, != 연산자 사용 가능

kubectl get services --all-namespaces --field-selector metadata.namespace!=default
  • 다른 셀렉터처럼 ,(쉼표)로 chain 사용 가능
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
  • 여러 리소스 종류에 걸쳐서 사용 가능하다.
kubectl get statuefulsets,services --all-namespaces --field-selector metadata.namespace!=default

label 셀렉터도 마찬가지지만 많은 리소스를 사용하고 관리하는 게 아니라면 딱히 selector를 사용할 일이 있을까 싶은 생각이 든다.. 특히 kubernetes 관리자가 아니라 제한된 클러스터에 제한된 권한을 가진 사용자라면...

권장 레이블

  • 공통 레이블 셋은 kubectl, dashboard 등 모든 도구들이 이해할 수 있는 공통의 방식으로 오브젝트를 식별 가능하게 해준다.

  • 메타데이터는 application 개념을 중심으로 정리

    • Kubernetes는 Paas(Platform service)가 아니며 애플리케이션에 대해 공식적인 개념이 없음
    • 코어 도구에는 필요하지 않지만 application을 쉽게 관리하게 해줌
  • 공유 레이블/주석에는 공통 접두사인 app.kubernetes.io가 있음

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

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: wordpress-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

예시

simple stateless service

deployment, service 오브젝트를 통해 배포된 stateless 서비스의 경우

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

deployment, service가 같은 name, instance 라벨을 가짐

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

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 StatefulSet 과 Service 로 MySQL과 WordPress가 더 큰 범위의 애플리케이션에 포함되어 있는 것을 알게 된다