매니페스트만으로는 안 된다. Deployment·StatefulSet·DaemonSet 의 metadata.namespace 는 고정 문자열만 받는다. 셀렉터를 넣는 자리가 아니다.
metadata:
namespace: <string> # 라벨 셀렉터를 쓸 수 없다
kubectl apply 도 대상 네임스페이스를 명시하거나 컨텍스트의 기본값을 따를 뿐, 라벨로 찾아 주지 않는다.
namespaceSelector 를 쓰는 자리는 따로 있다라벨로 네임스페이스를 고르는 필드는 존재하지만, 워크로드를 배치하는 쪽이 아니라 정책을 적용하는 쪽에 있다.
| 대상 | namespaceSelector 의 의미 |
|---|---|
NetworkPolicy |
어느 네임스페이스에서 오는 트래픽을 허용할지 |
ValidatingWebhookConfiguration · MutatingWebhookConfiguration |
어느 네임스페이스의 요청을 웹훅에 넘길지 |
PodAffinity · PodAntiAffinity |
어느 네임스페이스의 파드를 기준으로 붙이거나 떼어 놓을지 |
| Kyverno · Gatekeeper 정책 | 어느 네임스페이스에 규칙을 적용할지 |
Kyverno 정책의 예다. 이것은 "environment=prod 라벨이 붙은 네임스페이스에 규칙을 건다" 는 뜻이지, 그곳으로 배포해 준다는 뜻이 아니다.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: prod-namespace-rule
spec:
rules:
- name: match-ns-label
match:
any:
- resources:
kinds:
- Pod
namespaceSelector:
matchLabels:
environment: prod
배포 시점에 라벨로 네임스페이스를 찾아 인자로 넘긴다. 이 일은 매니페스트가 아니라 배포 도구나 파이프라인이 한다.
kubectl label namespace my-prod environment=prod
TARGET_NS=$(kubectl get ns -l environment=prod -o jsonpath='{.items[0].metadata.name}')
test -n "$TARGET_NS" || { echo "라벨에 맞는 네임스페이스가 없다"; exit 1; }
helm upgrade --install app ./chart -n "$TARGET_NS"
TARGET_NS=$(kubectl get ns -l team=dev -o jsonpath='{.items[0].metadata.name}')
kustomize build overlays/dev | kubectl apply -n "$TARGET_NS" -f -
jsonpath 로 첫 항목만 꺼내는 방식은 라벨에 맞는 네임스페이스가 둘 이상일 때 조용히 하나만 고른다. 개수를 먼저 확인하거나, 여러 개면 반복해서 적용한다.
for ns in $(kubectl get ns -l environment=prod -o name | cut -d/ -f2); do
kustomize build overlays/prod | kubectl apply -n "$ns" -f -
done
Argo CD 의 ApplicationSet 은 클러스터·네임스페이스 생성기로 대상을 훑어 Application 을 만들어 낸다. 사람이 셸에서 찾아 넘기는 대신 선언으로 남는다는 점이 다르다. 대상이 늘고 줄 때마다 파이프라인을 고치지 않아도 되므로, 네임스페이스가 여러 개인 구성에서는 이쪽이 관리하기 낫다.