[kubernetes] kubernetes label

2해승·2024년 11월 12일

쿠버네티스?!

목록 보기
11/16

오늘은 쿠버네티스를 사용한다면 필수라고 할 수 있는 label에 대해 알아보는 시간을 가져보겠다.

Kubernetes Lable

레이블은 쿠버네티스 클러스터 내부에 사용자가 객체를 생성할때 그 객체를 구분하기 위해서 임의로 원하는 값을 지정해서 사용한다.

  • Node를 포함하여 Pod, Deployment 등 모든 리소스에 할당이 가능함
  • 리소스의 특성을 분류하고 Selector를 이용하여 선택
  • key-value 한 쌍으로 적용

이처럼 오브젝트마다 Key-Value로 레이블을 정의할 수 있으며 만일 수십개 이상의 오브젝트가 존재한다면 레이블 없이 관리하기 어려울 것이다.

다음의 예시는 파드에 name: mainui, rel: stable 2개의 레이블이 있는 구성 파일이다.

apiVersion: v1
kind: Pod
metadata:
  name: label-pod-demo
  labels:
    name: mainui
    rel: stable
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

Pod 레이블 확인

기본적인 Nginx 파드와 레이블을 정의한 파드를 생성하여 레이블을 확인해보자.

  • --show-labels : 파드에 정의된 레이블을 조회할 수 있다.
  • -l : 레이블을 지정해 조회할 수 있다.
  • --selector : -l 옵션과 동일한 기능을 한다.
$ kubectl get pod --show-labels
NAME             READY   STATUS    RESTARTS   AGE     LABELS
label-pod-demo   1/1     Running   0          38s     name=mainui,rel=stable
pod-demo         1/1     Running   0          38s     <none>

$ kubectl get pod -l name=mainui
NAME             READY   STATUS    RESTARTS   AGE
label-pod-demo   1/1     Running   0          3m23s

$ kubectl get pod --selector name=mainui
NAME             READY   STATUS    RESTARTS   AGE
label-pod-demo   1/1     Running   0          3m57s

커맨드 라인으로 레이블을 적용시켜 보자

아무런 레이블이 적용되어 있지 않은 pod-demo 파드에 name=test 라는 레이블을 적용 시켜보았다.

$ kubectl label pod pod-demo name=test
pod/pod-demo labeled

$ kubectl get pod --show-labels
NAME             READY   STATUS    RESTARTS   AGE     LABELS
label-pod-demo   1/1     Running   0          5m28s   name=mainui,rel=stable
pod-demo         1/1     Running   0          5m28s   name=test

이미 레이블이 존재하고 있을 경우 덮어쓰기를 할 수 있는 옵션이 별도로 존재한다.
pod-demo 파드에 name=login 라는 레이블을 덮어씌워보자.

$ kubectl label pod pod-demo name=login --overwrite
$ kubectl get pod --show-labels                    
NAME             READY   STATUS    RESTARTS   AGE     LABELS
label-pod-demo   1/1     Running   0          6m56s   name=mainui,rel=stable
pod-demo         1/1     Running   0          6m56s   name=login

레이블 삭제하기

$ kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE     LABELS
testpod          1/1     Running   0          10m     run=testpod 

$ kubectl label pod testpod run-
pod/testpod unlabeled

$ kubectl get pod --show-labels 
NAME             READY   STATUS    RESTARTS   AGE     LABELS
testpod          1/1     Running   0          11m     <none>

워커 노드에 레이블 설정하기

워커 노드의 특성을 레이블로 설정해보자.

kubectl label node <노드 이름> <레이블 >-<레이블 >

워커 노드에 레이블을 설정하는 이유는 보통 노드를 선택해서 파드를 배치하기 위함이다.

$ kubectl get nodes
NAME                                    STATUS   ROLES           AGE   VERSION
kind-test-today-cluster-control-plane   Ready    control-plane   15d   v1.30.0
kind-test-today-cluster-worker          Ready    <none>          15d   v1.30.0
kind-test-today-cluster-worker2         Ready    <none>          15d   v1.30.0
kind-test-today-cluster-worker3         Ready    <none>          15d   v1.30.0

위와 같이 노드가 존재한다고 할 때 세개의 워커노드에 그림과 같이 레이블을 설정하는 실습을 진행해보겠다.

커맨드 라인을 통해 간편히 적용 후 조회해보자.

$ kubectl label nodes kind-test-today-cluster-worker gpu=true disk=ssd
$ kubectl label nodes kind-test-today-cluster-worker2 gpu=true
$ kubectl label nodes kind-test-today-cluster-worker3 disk=ssd

처음 노드를 생성할 때 함께 정의된 레이블 사이에 새로 설정한 레이블이 확인된다.

$ kubectl get nodes -L disk,gpu
NAME                                    STATUS   ROLES           AGE   VERSION   DISK   GPU
kind-test-today-cluster-control-plane   Ready    control-plane   15d   v1.30.0          
kind-test-today-cluster-worker          Ready    <none>          15d   v1.30.0   ssd    true
kind-test-today-cluster-worker2         Ready    <none>          15d   v1.30.0          true
kind-test-today-cluster-worker3         Ready    <none>          15d   v1.30.0   ssd

노드를 지정해서 파드 실행하기

이제 Selector를 이용해 노드를 지정해서 파드를 실행해보도록 하자.

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeselector
spec:
  nodeSelector:
    gpu: "true"
    disk: ssd
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

아까의 실습에서gpu:truedisk:ssd 레이블을 다 가지고 있는 노드는 kind-test-today-cluster-worker 임을 우리는 알고 있다.

nodeselector.yaml 파일에 위와같이 선언하고 파드를 실행하면 관련 노드로 파드가 실행될 것이다.

$ kubectl get pods -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP           NODE                              NOMINATED NODE   READINESS GATES
pod-nodeselector   1/1     Running   0          5s    10.244.2.6   kind-test-today-cluster-worker    <none>           <none>

Label과 Anotation

어노테이션은 레이블과 동일하게 key-vaule를 통해 리소스의 특성을 기록하는데, 쿠버네티스에게 특정 정보를 전달하는 용도로 사용되거나 관리를 위해 필요한 정보를 기록할 용도로 사용된다.

예를 들어 deployment에 롤링 업데이트 정보를 기억시킬 수가 있다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-annotation
  annotations:
    builder: "test lee"
    buildDate: "20241107"
    imageRegistry: https://hub.docker.com/
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

yaml 파일에 어노테이션을 설정하고 생성된 파드를 상세 조회하면 설정된 값을 확인할 수 있다.


레이블을 이용한 카나리 업데이트

카나리 배포?

기존 버전을 유지한 채로 일부 버전만 신규 버전으로 업데이트하여 신규 버전에 버그나 이상이 없는지 확인하는 배포 방식이다.

예를 들어 기존의 블루 버전의 deployment가 2개 있고 신규인 그린 버전의 deployment 1개가 존재한다고 할때 한번에 묶어 사용자들에게 서비스하는 방식이다.

이후 그린 버전의 deployment가 하나 더 추가되면 서비스가 확장되도록 할 수 있다.

예시를 실습을 통해 진행해보자

카나리 업데이트 실습

우선 version: stable 레이블을 가진 블루 버전의 deployment 2개를 실행하는 스크립트를 실행시켜 실습 환경을 만들어 둔다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mainui-stable
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mainui
      version: stable
  template:
    metadata:
      labels:
        app: mainui
        version: stable
    spec:
      containers:
      - name: mainui
        image: nginx:1.14
        ports:
        - containerPort: 80
$ Kubectl create -f mainui-stable.yaml

$ kubectl get pods --show-labels      
NAME                            READY   STATUS    RESTARTS   AGE   LABELS
mainui-stable-cc7bdcfbb-ddz2c   1/1     Running   0          18s   app=mainui,pod-template-hash=cc7bdcfbb,version=stable
mainui-stable-cc7bdcfbb-lccsm   1/1     Running   0          18s   app=mainui,pod-template-hash=cc7bdcfbb,version=stable

생성된 파드를 서비스로 묶어주는 작업까지하면 블루 버전의 서비스가 돌아가는 환경이 된다.

apiVersion: v1
kind: Service
metadata:
  name: mainui-svc
spec:
  selector:
    app: mainui
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080

app: mainui 레이블을 기준으로 두개의 파드를 묶어주는 서비스 스크립트를 실행

$ kubectl create -f mainui-svc.yaml

$ kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
mainui-svc   ClusterIP   10.96.27.73   <none>        8080/TCP   9s

두 파드를 하나의 단일 진입점으로 묶어주었다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mainui-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mainui
      version: canary
  template:
    metadata:
      labels:
        app: mainui
        version: canary
    spec:
      containers:
      - name: mainui
        image: nginx:1.14
        ports:
        - containerPort: 80

이제 신규 버전인 version:canary 레이블을 가진 파드를 mainui-svc에 추가하는 작업을 진행해보겠다.

$ kubectl create -f mainui-canary.yaml 

$ kubectl get pod
NAME                             READY   STATUS    RESTARTS   AGE
mainui-canary-6f49855785-k4ddt   1/1     Running   0          6s
mainui-stable-cc7bdcfbb-ddz2c    1/1     Running   0          8m24s
mainui-stable-cc7bdcfbb-lccsm    1/1     Running   0          8m24s

$ kubectl describe svc mainui-svc
Name:              mainui-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=mainui
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.96.27.73
IPs:               10.96.27.73
Port:              <unset>  8080/TCP
TargetPort:        8080/TCP
Endpoints:         10.244.1.6:8080,10.244.2.7:8080,10.244.3.9:8080
Session Affinity:  None
Events:            <none>

Endpoints 에 카나리 버전의 파드가 추가된 것을 확인할 수 있다.

이렇게 새로운 버전의 배포가 완료되면 버그와 동작 여부를 확인하면서 업데이트를 진행하면 된다.

점점 카나리 버전을 하나 더 늘리고 스테이블 버전을 하나 줄이는 식으로 진행되다가 마지막엔 스테이블 버전이 전부 삭제되고 신규 버전으로 교체되는 형태가 될 것이다.


[참고자료]
https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/labels/
https://anggeum.tistory.com/entry/Kubernetes-%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EB%A0%88%EC%9D%B4%EB%B8%94-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-Label-Annotation-Deep-Dive

profile
주니어 데브옵스 엔지니어

0개의 댓글