개인적으로 공부한 내용을 작성한 게시글입니다. 잘못된 내용이 있을 수 있습니다.
틀린 부분을 알려주시면 바로 고치겠습니다.감사합니다.
쿠버네티스 리소스의 Manifest 파일들을 작성하다보면 많은 labels, matchLabels, selectors 필드들을 볼 수 있다.
이번 포스팅을 통해 이들을 정리해보려고 한다.
Selector
Deployment
우선 Deployment의 Manifest 파일을 살펴보자
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
labels:
app: hello
spec:
selector:
matchLabels:
app: hello
track: stable
matchExpressions:
- {key: tier, operator: In, values: [backend, backend2, backend3]}
replicas: 3
template:
metadata:
labels:
app: hello
tier: backend
track: stable
spec:
containers:
- name: hello
image: "gcr.io/google-samples/hello-go-gke:1.0"
ports:
- name: http
containerPort: 80
- `metadata`필드의 `labels`필드는 Deployment자체의 label 정보를 의미한다.
- `selector`필드의 `matchLabels`와 `matchExpressions`필드는 배포할 Pod의 labels를 가리킨다.
- `matchLabels`와 `matchExpressions`는 각각의 필드에 AND(&&) 연산자가 사용되고, `matchLabels`와 `matchExpressions` 끼리도 AND(&&) 연산자가 사용된다.
- `template`필드부터는 사실 Pod의 metadata라고 생각하면 된다. 그래서 `template`필드의 `labels`필드는 Deployment의 label 정보가 아닌 Pod의 자체의 label 정보이다.
- 그래서 꼭 `selector.matchLabels`와 `template.metadata.labels`는 일치해야 한다!
- 라벨을 지정하면 다음 커맨드로 해당 라벨이 존재하는 리소스들을 조회할 수 있다. `$ kubectl get <resource> -l <label>`
Service
이제 Service의 Manifest 파일을 살펴보자
apiVersion: v1
kind: Service
metadata:
name: hello
labels:
app: hello
spec:
selector: # matchLabels가 존재하지 않는다.
app: hello
tier: backend
ports:
- protocol: TCP
port: 80
targetPort: http
- `metadata`필드의 `labels`필드는 Service의 label 정보를 의미한다.
- `selector`필드는 해당 값의 label을 가진 Pod들을 Service 대상으로 지정한다.
- `matchLabels`필드와 `matchExpressions`필드가 존재하지 않는다.
위에서 확인할 수 있듯이 `matchLabels`, `matchExpresisons` 필드가 Service에는 존재하지 않는다. 대신 `selector`필드만으로도 `matchLabels`처럼 동작한다.
사실 Deployment뿐만 아니라 Job, ReplicaSet, 그리고 DaemonSet에서도 `matchLabels`, `matchExpressions`필드가 있다.
그렇다면 왜 Service만 matchLabels, matchExpressions 필드가 없을까?
내 개인적인 생각은 Job, Deployment, ReplicaSet, DaemonSet은 다양한 Pod들을 생성하거나 직접적으로 제어해야 하기 때문에 `matchExpressions`를 사용한다고 생각한다.
반면에, Service는 네트워크 요청을 기존에 존재하고, 동일한 역할을 수행하는 Pod들에 라우팅 하는 것이기 때문에, 라벨을 명확하게 정하는 것이 좀 더 안정적일 것이다.
그래서 `matchExpressions`를 삭제하고, `selector` 만으로 `matchLabels` 역할을 하도록 한 것이 아닐까 생각한다. (괜히 matchLabels가 존재하면, matchExpressions 기능도 있을 것이라 생각하여 작성할 수 있으므로)
ETC
Equality-based, Set-based Requirement
사실 위의 `matchLabels`는 Equality-based requirement(동등 기반 요구)방식, `matchExpression`는 Set-based Requirement(집합 기만 요구)이다.
API는 현재 Equality-based, Set-based이라는 두 가지 유형의 selector를 지원한다. label selector는 쉼표로 여러 label을 선택할 수 있는데, 이때 쉼표는 AND(&&) 연산자 역할을 한다. OR(||) 연산자는 존재하지 않는다.
Equality-based requirement
Equality-based 또는 InEquality-based requirements를 통해 label의 keys와 values로 필터링할 수 있다. `=, ==, !=` 연산자를 이용하여 필터링할 수 있다. `=`, `==` 은 둘 다 동등함을 의미한다.
Set-based requirement
Set-based label requirements는 values 집합에 따라 keys를 필터링할 수 있다. in, notin 그리고 exists (키 식별자만) 연산자를 이용하여 필터링할 수 있다.
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
partition,environment notin (qa)
- 첫 번째는 key가 `environment`일 경우, value가 `production` 또는 `qa`인 label을 필터링한다.
- 두 번째는 key가 `tier`일 경우, value가 `frontend`, `backend`가 아닌 label을 필터링한다
- 세 번째는 value를 체크하지 않는다. 오직 `partition`인 key가 있는 label을 필터링한다.
- 네 번째도 value를 체크하지 않는다. 오직 `partition`가 아닌 key가 있는 label을 필터링한다.
- 다섯 번째는 key가 `partition` 또는 `environment`일 때 value가 `qa`가 아닌 key가 있는 label을 필터링한다.
따라서, Service 리소스는 Equality-based selector를 사용하는 반면, 나머지 리소스들은 Equality-based selector와 Set-based selector 모두 사용한다는 것을 알 수 있다.
labels 작성 예시
- release : "stable", "canary"
- environment : "dev", "qa", "production"
- tier : "frontend", "backend", "cache"
- partition : "customerA", "customerB"
- track : "daily", "weekly"
REFERENCES
Assigning Pods to Nodes - https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
Labels and Selectors - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/