1. 개요

apiVersion은 쿠버네티스 매니페스트의 첫 줄에 오는 필드로, 이 리소스가 어느 API 그룹에 속하며 어느 버전의 스키마를 따르는지를 선언한다. API 서버는 이 값을 보고 요청을 어느 핸들러로 넘길지, 어떤 필드를 허용할지 결정한다.

apiVersion: apps/v1
kind: Deployment
매니페스트apiVersion: apps/v1API 서버그룹으로핸들러 선택버전으로스키마 검증apps · batchrbac · networking …v1 · v2v1beta1 · v1alpha1etcdapply저장그룹이 어디로 갈지를, 버전이 어떤 필드를 허용할지를 정한다

2. 구조

apps/v1
└┬─┘ └┬
 │    └── 버전 — 얼마나 안정적인가
 └─────── 그룹 — 어느 묶음 소속인가

슬래시가 없으면 코어 그룹이다. 그룹명이 없는 게 아니라 생략된 것으로, 쿠버네티스 초기부터 있던 리소스들이 그룹 체계가 도입되기 전에 자리를 잡았다.

형태예해당 리소스
코어 (그룹 생략)v1Pod, Service, ConfigMap, Secret, Namespace, ServiceAccount
그룹 + 버전apps/v1Deployment, StatefulSet, DaemonSet
batch/v1Job, CronJob
networking.k8s.io/v1NetworkPolicy, Ingress
rbac.authorization.k8s.io/v1Role, RoleBinding

3. 버전

3.1. 안정도 단계

버전뜻실무
v1alpha1실험 단계. 예고 없이 바뀌거나 사라지며 기본 비활성인 경우가 많다프로덕션 금지
v1beta1대체로 동작하지만 필드가 바뀔 수 있다조건부. 업그레이드 시 확인
v1, v2안정. 하위 호환이 보장된다안심하고 사용

숫자가 올라가는 것(v1 → v2)은 안정 버전 안에서의 세대 교체다. autoscaling/v2가 그 예로, HPA가 여러 지표를 다루게 되면서 스펙이 크게 바뀌었다.

3.2. 명명 규칙의 예외

버전이 v1이어도 내장이 아닐 수 있다.

apiVersion: serving.knative.dev/v1     # Knative — 설치해야 함
kind: Service

v1은 그 프로젝트 안에서 안정적이라는 뜻이지 쿠버네티스에 내장이라는 뜻이 아니다.

도메인이 k8s.io여도 내장이 아닐 수 있다.

apiVersion: autoscaling.k8s.io/v1      # VPA — 쿠버네티스 프로젝트 산하지만 별도 설치
kind: VerticalPodAutoscaler

k8s.io는 “쿠버네티스 프로젝트가 관리한다"는 표시일 뿐이다. 반대로 HPA(autoscaling/v2)는 도메인이 없는데도 내장이다.

4. 확인 명령

첫 줄만으로는 내장 여부를 확정할 수 없다. 클러스터에 직접 묻는 것이 정확하다.

kubectl api-resources                      # 이 클러스터가 아는 리소스 전부
kubectl api-resources --api-group=apps     # 그룹으로 좁혀서
kubectl api-versions | grep autoscaling    # 살아 있는 버전 확인

kubectl explain hpa                        # 이 리소스가 무엇인지, 어느 버전인지
kubectl explain hpa.spec.metrics           # 필드 단위로

목록에 없으면 설치되지 않은 것이다. error: the server doesn't have a resource type "..." 가 그 신호다.

5. 그룹당 단일 등록

하나의 API 그룹에는 하나의 구현만 등록할 수 있다. 확장 API를 등록하는 APIService 리소스의 이름이 <버전>.<그룹> 형태로 고정되기 때문이다.

kubectl get apiservice | grep metrics
# v1beta1.metrics.k8s.io           kube-system/metrics-server            True
# v1beta1.custom.metrics.k8s.io    monitoring/prometheus-adapter         True
# v1beta1.external.metrics.k8s.io  keda/keda-operator-metrics-apiserver  True

metrics.k8s.io는 metrics-server가, external.metrics.k8s.io는 KEDA 같은 어댑터가 차지한다. 같은 자리에 다른 어댑터를 등록하면 에러가 아니라 덮어써지고, 먼저 있던 연결이 조용히 끊긴다. 한 클러스터에서 외부 지표 어댑터를 둘 이상 쓰기 어려운 이유다.

6. 사례 목록

이 블로그 K8sPatterns 시리즈에 실제로 등장한 것들.

apiVersionkind내장비고
v1Pod, Service, ConfigMap, Secret✅코어 그룹
apps/v1Deployment, StatefulSet✅
batch/v1Job, CronJob✅
autoscaling/v2HorizontalPodAutoscaler✅도메인 없는 내장 그룹
networking.k8s.io/v1NetworkPolicy✅규격만 내장, 집행은 CNI 몫
rbac.authorization.k8s.io/v1Role, RoleBinding✅
apiregistration.k8s.io/v1APIService✅확장 등록용
scheduling.k8s.io/v1PriorityClass✅
policy/v1PodDisruptionBudget✅
autoscaling.k8s.io/v1VerticalPodAutoscaler❌k8s.io 인데 설치 대상
serving.knative.dev/v1Service❌v1 인데 서드파티
keda.sh/v1alpha1ScaledObject❌
bitnami.com/v1alpha1SealedSecret❌
external-secrets.io/v1beta1ExternalSecret, SecretStore❌
security.istio.io/v1beta1AuthorizationPolicy❌Istio
secrets-store.csi.x-k8s.io/v1SecretProviderClass❌x- 는 SIG 산하 확장

serving.knative.dev/v1의 kind: Service는 코어 v1의 Service와 이름만 같은 다른 리소스다. 그룹이 다르면 남남이라 같은 이름을 써도 충돌하지 않는다. 그룹이 존재하는 이유가 이것이다.

7. 관련 문서

  • CRD — 새 리소스 종류를 정의하는 방법
  • Admission Webhook — admissionregistration.k8s.io 그룹의 리소스
  • API Aggregation — 확장 API 를 등록하는 APIService (예정)

8. 출처