Post

Part 6/26: Label, Selector, Annotation

Part 6/26: Label, Selector, Annotation

1. Label 개념

1.1 Label이란?

Label은 키-값 쌍으로 Kubernetes 리소스에 부착되는 메타데이터다. 리소스를 분류하고 선택하는 데 사용되며, Kubernetes의 주요 조직화 메커니즘이다.

1
2
3
4
5
6
7
metadata:
  labels:
    app: nginx           # 애플리케이션 이름
    version: v1.21       # 버전
    environment: prod    # 환경
    tier: frontend       # 계층
    team: platform       # 담당 팀

Label의 역할:

  • Pod, Service, Deployment 등 모든 Kubernetes 리소스에 적용 가능
  • ReplicaSet이 관리할 Pod 선택
  • Service가 트래픽을 보낼 Pod 선택
  • 리소스 쿼리 및 필터링
  • 느슨한 결합(Loosely Coupled) 구현

1.2 Label 명명 규칙

1
[prefix/]name: value

이름(name) 규칙:

  • 63자 이내
  • 알파벳, 숫자, -, _, . 사용
  • 시작과 끝은 알파벳 또는 숫자

접두사(prefix) 규칙:

  • 선택적
  • DNS 서브도메인 형식 (253자 이내)
  • kubernetes.io/, k8s.io/는 Kubernetes 코어 컴포넌트 예약

값(value) 규칙:

  • 63자 이내
  • 비어있을 수 있음
  • 시작과 끝은 알파벳 또는 숫자 (비어있지 않다면)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 유효한 Label 예시
metadata:
  labels:
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: "1.21"
    app.kubernetes.io/component: webserver
    team: platform-infra
    cost-center: "12345"

# 잘못된 Label 예시
metadata:
  labels:
    App: nginx          # 대문자는 허용되지만 권장하지 않음
    -invalid: value     # 하이픈으로 시작 불가
    too-long-value: " 값은 63자를 초과하면 안됩니다..."

1.3 권장 Label

Kubernetes는 표준화된 Label 집합을 권장한다:

Label설명예시
app.kubernetes.io/name앱 이름nginx
app.kubernetes.io/instance앱 인스턴스 식별자nginx-prod
app.kubernetes.io/version앱 버전1.21.0
app.kubernetes.io/component컴포넌트webserver
app.kubernetes.io/part-of상위 애플리케이션wordpress
app.kubernetes.io/managed-by관리 도구helm
1
2
3
4
5
6
7
8
metadata:
  labels:
    app.kubernetes.io/name: nginx
    app.kubernetes.io/instance: nginx-prod
    app.kubernetes.io/version: "1.21"
    app.kubernetes.io/component: frontend
    app.kubernetes.io/part-of: myapp
    app.kubernetes.io/managed-by: helm

2. Selector

Selector는 Label을 기반으로 리소스를 선택하는 메커니즘이다.

2.1 Equality-based Selector (등식 기반)

키와 값이 정확히 일치하는지 확인한다.

연산자의미예시
=같음app=nginx
==같음 (= 와 동일)app==nginx
!=다름app!=nginx
1
2
3
4
# kubectl에서 사용
kubectl get pods -l app=nginx
kubectl get pods -l "app=nginx,version=v1"   # AND 조건
kubectl get pods -l app!=apache
1
2
3
4
5
6
7
8
9
10
# Service에서 사용
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx        # Equality-based (암묵적으로 =)
  ports:
  - port: 80

2.2 Set-based Selector (집합 기반)

집합 연산을 사용한 더 복잡한 선택이 가능하다.

연산자의미예시
in값이 집합에 포함version in (v1, v2)
notin값이 집합에 미포함version notin (v3, v4)
exists키가 존재app (값 없이 키만)
!exists키가 존재하지 않음!app
1
2
3
4
5
6
7
8
# kubectl에서 사용
kubectl get pods -l "version in (v1, v2)"
kubectl get pods -l "version notin (v3, v4)"
kubectl get pods -l "tier"              # tier 키가 있는 Pod
kubectl get pods -l "!tier"             # tier 키가 없는 Pod

# 복합 조건
kubectl get pods -l "app=nginx,version in (v1, v2)"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Deployment에서 사용 (matchLabels + matchExpressions)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx                    # Equality-based
    matchExpressions:
    - key: version
      operator: In
      values:
      - v1
      - v2
    - key: environment
      operator: NotIn
      values:
      - dev
    - key: tier
      operator: Exists

2.3 리소스별 Selector 지원

리소스Selector 필드지원 방식
Servicespec.selectorEquality-based만
ReplicaSetspec.selector.matchLabels/matchExpressions둘 다 지원
Deploymentspec.selector.matchLabels/matchExpressions둘 다 지원
Jobspec.selector.matchLabels/matchExpressions둘 다 지원
NetworkPolicyspec.podSelector둘 다 지원
PersistentVolumeClaimspec.selector둘 다 지원

중요: Service는 Equality-based만 지원한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Service - Equality-based만
apiVersion: v1
kind: Service
spec:
  selector:
    app: nginx
    version: v1

# Deployment - 둘 다 지원
apiVersion: apps/v1
kind: Deployment
spec:
  selector:
    matchLabels:
      app: nginx
    matchExpressions:
    - key: tier
      operator: In
      values: [frontend, backend]

3. Label 사용 패턴

3.1 Service와 Pod 연결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Pod
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx        # Service가 이 Label로 선택
    version: v1
spec:
  containers:
  - name: nginx
    image: nginx

---
# Service
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx        # app=nginx인 Pod 선택
  ports:
  - port: 80

3.2 Deployment와 ReplicaSet 연결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx              # 관리할 Pod 선택 기준
  template:
    metadata:
      labels:
        app: nginx            # 생성될 Pod의 Label (selector와 일치해야 함)
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx

주의: spec.selectorspec.template.metadata.labels는 최소한 일치해야 한다.

3.3 환경별 리소스 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
# Production Pod
metadata:
  labels:
    app: myapp
    environment: production
    tier: backend

# Staging Pod
metadata:
  labels:
    app: myapp
    environment: staging
    tier: backend
1
2
3
4
5
6
# 환경별 조회
kubectl get pods -l environment=production
kubectl get pods -l environment=staging

# 특정 환경 제외
kubectl get pods -l "environment notin (dev, test)"

3.4 Blue-Green Deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Blue 버전 (현재 라이브)
metadata:
  labels:
    app: myapp
    version: blue

# Green 버전 (새 버전)
metadata:
  labels:
    app: myapp
    version: green

# Service - 버전 전환
spec:
  selector:
    app: myapp
    version: blue    # green으로 변경하면 트래픽 전환

4. Annotation

4.1 Annotation이란?

Annotation은 비식별 메타데이터로, 리소스에 추가 정보를 저장한다. Label과 달리 Selector로 선택하는 데 사용되지 않는다.

1
2
3
4
5
6
metadata:
  annotations:
    description: "This is the main web server"
    owner: "team-platform@example.com"
    build.date: "2024-12-28"
    git.commit: "abc123def456"

4.2 Label vs Annotation

특성LabelAnnotation
용도리소스 선택/그룹화추가 정보 저장
Selector 사용가능불가
값 크기최대 63자제한 없음 (256KB까지 권장)
사용처쿼리, 필터링, 조직화도구 설정, 빌드 정보, 설명

4.3 Annotation 사용 사례

1. 도구/라이브러리 설정:

1
2
3
4
5
6
7
8
9
10
11
12
13
metadata:
  annotations:
    # Prometheus 스크래핑 설정
    prometheus.io/scrape: "true"
    prometheus.io/port: "8080"
    prometheus.io/path: "/metrics"

    # Ingress Controller 설정
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"

    # Istio 설정
    sidecar.istio.io/inject: "true"

2. 빌드/배포 정보:

1
2
3
4
5
6
7
8
metadata:
  annotations:
    build.number: "1234"
    build.date: "2024-12-28T10:00:00Z"
    git.repository: "https://github.com/example/app"
    git.commit: "abc123def456"
    git.branch: "main"
    deployed.by: "jenkins"

3. 운영 정보:

1
2
3
4
5
6
metadata:
  annotations:
    description: "Production web server for customer-facing API"
    owner: "team-platform@example.com"
    oncall: "pagerduty://team-platform"
    documentation: "https://wiki.example.com/myapp"

4. 리소스 정책:

1
2
3
4
5
6
7
8
metadata:
  annotations:
    # 변경 원인 기록 (kubectl에서 자동 추가)
    kubernetes.io/change-cause: "Update to version 1.22"

    # 마지막 적용된 설정 (kubectl apply에서 자동 추가)
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment"...}

4.4 kubectl에서 Annotation 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
# Annotation 추가
kubectl annotate pod nginx description="web server"

# Annotation 수정
kubectl annotate pod nginx description="main web server" --overwrite

# Annotation 삭제
kubectl annotate pod nginx description-

# 여러 Annotation 동시 추가
kubectl annotate pod nginx \
  owner="team@example.com" \
  build.date="2024-12-28"

5. kubectl에서 Label 관리

5.1 Label 조회

1
2
3
4
5
6
7
8
9
10
# Label 포함하여 Pod 조회
kubectl get pods --show-labels

# 특정 Label 컬럼으로 표시
kubectl get pods -L app,version

# Label로 필터링
kubectl get pods -l app=nginx
kubectl get pods -l "app in (nginx, apache)"
kubectl get pods -l app=nginx,version=v1

5.2 Label 추가/수정/삭제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Label 추가
kubectl label pod nginx env=production

# Label 수정 (--overwrite 필요)
kubectl label pod nginx env=staging --overwrite

# Label 삭제 (키 뒤에 - 붙임)
kubectl label pod nginx env-

# 여러 리소스에 동시 적용
kubectl label pods -l app=nginx tier=frontend

# 모든 Pod에 적용
kubectl label pods --all env=production

5.3 Node Label 관리

1
2
3
4
5
6
7
8
9
# Node Label 추가 (스케줄링에 사용)
kubectl label node worker-1 disktype=ssd
kubectl label node worker-2 disktype=hdd

# Node Label 확인
kubectl get nodes --show-labels

# Node Label로 Pod 스케줄링
# (Pod의 nodeSelector에서 사용)

6. 면접 빈출 질문

Q1. Label과 Annotation의 차이는?

Label:

  • 리소스를 식별하고 선택하는 데 사용
  • Selector로 쿼리 가능
  • 값 크기 제한 (63자)
  • 예: app=nginx, env=prod

Annotation:

  • 추가 정보를 저장하는 메타데이터
  • Selector로 선택 불가
  • 더 큰 데이터 저장 가능
  • 예: 빌드 정보, 도구 설정, 설명

Q2. Service는 왜 Set-based Selector를 지원하지 않는가?

Service는 Endpoint를 통해 Pod과 연결되는데, 이 연결은 간단한 키-값 매칭으로 충분하다. Set-based Selector는 ReplicaSet, Deployment 같은 복잡한 워크로드 관리에 더 필요하다.

또한 Service의 Selector는 단순성을 유지하여 성능과 예측 가능성을 보장한다.

Q3. matchLabels와 matchExpressions는 언제 사용하는가?

matchLabels:

  • 간단한 등식 매칭 (키=값)
  • 대부분의 경우 충분
  • Service에서도 사용 가능한 방식

matchExpressions:

  • 복잡한 조건이 필요할 때
  • In, NotIn, Exists, DoesNotExist 연산
  • 여러 값 중 하나를 선택해야 할 때
  • 특정 Label이 없는 리소스를 선택해야 할 때
1
2
3
4
5
6
7
8
9
# 둘 다 사용하면 AND 조건
selector:
  matchLabels:
    app: nginx
  matchExpressions:
  - key: tier
    operator: In
    values: [frontend, backend]
# app=nginx AND tier in (frontend, backend)

Q4. Label 변경 시 주의할 점은?

  1. Selector와의 일치: Deployment의 Pod Template Label을 변경하면 새 ReplicaSet이 생성됨
  2. Service 연결: Label 변경으로 Service와 연결이 끊어질 수 있음
  3. 불변 Selector: 일부 리소스(Deployment, ReplicaSet)의 spec.selector는 생성 후 변경 불가
  4. Immutability: Job의 selector는 변경 불가

7. 실습

7.1 Label을 이용한 Pod 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Pod 생성
kubectl run nginx1 --image=nginx --labels="app=nginx,version=v1,env=prod"
kubectl run nginx2 --image=nginx --labels="app=nginx,version=v2,env=prod"
kubectl run apache --image=httpd --labels="app=apache,version=v1,env=dev"

# Label 조회
kubectl get pods --show-labels
kubectl get pods -L app,version

# Selector로 필터링
kubectl get pods -l app=nginx
kubectl get pods -l "version in (v1, v2)"
kubectl get pods -l "env!=dev"
kubectl get pods -l "app,version"   # app과 version 키가 있는 것

# Label 수정
kubectl label pod nginx1 version=v1.1 --overwrite

# Label 삭제
kubectl label pod nginx1 env-

7.2 Deployment와 Service 연결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  selector:
    app: web
  ports:
  - port: 80
1
2
3
4
5
6
7
kubectl apply -f deployment.yaml

# Endpoint 확인 (Label 매칭 결과)
kubectl get endpoints web-svc

# Service의 Label 선택 확인
kubectl describe svc web-svc

정리

주요 개념 체크리스트

  • Label의 명명 규칙과 권장 Label
  • Equality-based vs Set-based Selector
  • Label과 Annotation의 차이
  • Service, Deployment에서의 Selector 사용
  • kubectl로 Label 관리하기

다음 포스트

Part 7: Namespace와 ResourceQuota에서는 멀티테넌시와 리소스 격리를 다룬다.


참고 자료

This post is licensed under CC BY 4.0 by the author.