تقریباً هر فایل YAML کوبرنتیز با دو خط شروع میشود:
apiVersion: apps/v1
kind: Deploymentاین apiVersion نسخهٔ image اپ شما نیست، نسخهٔ chart هم نیست، و لزوماً برابر نسخهٔ cluster (1.29، 1.31، …) هم نیست. این فیلد میگوید: با کدام قرارداد API سرور این نوع شیء را بشناس و validate کن.
طبق API Overview رسمی: کل Kubernetes روی REST API بنا شده؛ هر چیزی که kubectl یا کنترلر لمس میکند یک API object است.
این مقاله deep dive است: معنی apiVersion، انواع سطح پایداری، گروههای API، تفاوت رفتار نسخهها، deprecate/حذف، و نسخهبندی CRDها.
سهگانه هویت: Group · Version · Kind (GVK)
هر شیء با GVK شناخته میشود:
| جزء | مثال | نقش |
|---|---|---|
| Group | apps، batch، networking.k8s.io، (خالی = core) | خانواده API |
| Version | v1، v1beta1، v1alpha1 | سطح پایداری + شکل schema |
| Kind | Deployment، Job، Ingress | نوع منبع |
در YAML:
# Core group — Group در رشته نیست
apiVersion: v1
kind: Pod
# Named group — Group/Version
apiVersion: apps/v1
kind: Deployment
apiVersion: networking.k8s.io/v1
kind: Ingressمسیر REST متناظر:
| apiVersion | مسیر تقریبی |
|---|---|
v1 | /api/v1/... |
batch/v1 | /apis/batch/v1/... |
networking.k8s.io/v1 | /apis/networking.k8s.io/v1/... |
علاوه بر GVK، GVR (Group / Version / Resource) برای URL جمعها مهم است: deployments، pods، ingresses. Kind مفرد است؛ resource معمولاً جمع.
kubectl api-resources
kubectl api-versions
kubectl explain deployment --api-version=apps/v1Core group در برابر Named groups
| Core (legacy) | Named groups | |
|---|---|---|
| apiVersion | فقط v1 | GROUP/VERSION |
| نمونهها | Pod، Service، ConfigMap، Secret، Namespace، PersistentVolumeClaim، … | Deployment (apps)، Job (batch)، Ingress (networking.k8s.io)، … |
| چرا جدا؟ | تاریخچه اولیه Kubernetes | گسترشپذیری؛ جلوگیری از شلوغی یک namespace عظیم |
بسیاری منابع امروز در named groupsاند چون از core/extensions مهاجرت کردهاند (مثلاً Ingress از extensions/v1beta1 به networking.k8s.io/v1).
سه سطح پایداری: Alpha · Beta · Stable
نام version خودش سیگنال پایداری است. رفتار عملیاتیشان عملاً فرق دارد.
جدول مقایسه رفتار
| موضوع | Alpha (v1alpha1) | Beta (v1beta1, v2beta3) | Stable / GA (v1, v2) |
|---|---|---|---|
| نام | شامل alpha | شامل beta | فقط vX عددی |
| پیشفرض روی apiserver | معمولاً غیرفعال | معمولاً غیرفعال (بهجز betaهای قدیمی قبل از ~۱.۲۲) | فعال |
| فعالسازی | --runtime-config=... | --runtime-config=... | پیشفرض |
| باگ / ناپایداری | محتمل | کمتر؛ هنوز schema ممکن است عوض شود | production-ready |
| تغییر ناسازگار | بدون اخطار طولانی | ممکن در beta/stable بعدی + راهنمای مهاجرت | در major فعلی حذف نمیشود |
| عمر تا deprecate/حذف | ممکن است هر زمان حذف شود | سقف تقریبی: ۹ ماه یا ۳ minor تا deprecate، سپس همانقدر تا حذف | پایدار در سراسر major فعلی |
| توصیه | فقط cluster آزمایشی کوتاهعمر | آزمایش / بازخورد؛ production با احتیاط | پیشفرض production |
منبع قواعد: Kubernetes API Overview.
مثال نامگذاری
v1alpha1 → اولین آزمایش feature
v1alpha2 → تکرار alpha (شکست schema ممکن)
v1beta1 → ورود به beta
v1beta2 → اصلاحات ناسازگار در beta
v1 → فارغالتحصیلی به stable
v2alpha1 → نسل بعدی feature بزرگ (موازی با v1)نکته مهم: v2 لزوماً «بهتر از v1 برای همان Kind» نیست — گاهی نسل API جدید برای مدل متفاوت است؛ v1 ممکن است هنوز preferred باشد.
نسخههای رایج که در YAML میبینید
| apiVersion | Kindهای نمونه | یادداشت |
|---|---|---|
v1 | Pod، Service، ConfigMap، Secret، ServiceAccount، Namespace، PVC، … | core |
apps/v1 | Deployment، StatefulSet، DaemonSet، ReplicaSet | پایدار |
batch/v1 | Job، CronJob | CronJob قبلاً batch/v1beta1 بود (حذف در مسیر ارتقا) |
networking.k8s.io/v1 | Ingress، NetworkPolicy، IngressClass | جایگزین extensions قدیمی |
rbac.authorization.k8s.io/v1 | Role، ClusterRole، RoleBinding، … | |
storage.k8s.io/v1 | StorageClass، CSIDriver، … | |
apiextensions.k8s.io/v1 | CustomResourceDefinition | v1beta1 CRD حذف شده |
policy/v1 | PodDisruptionBudget | قبلاً policy/v1beta1 |
autoscaling/v2 | HorizontalPodAutoscaler | نسل متریک چندگانه |
gateway.networking.k8s.io/v1 | Gateway، HTTPRoute، … | Gateway API |
cert-manager.io/v1 | Certificate، Issuer | نمونه CRD محبوب — مقاله cert-manager |
helm.toolkit.fluxcd.io/v2 | HelmRelease | نمونه GitOps — Flux / Helm |
لیست کامل روی هر cluster:
kubectl api-resources -o wideیک شیء، چند نسخه — چطور «متفاوت عمل میکنند»؟
فرض کنید Kind واحد CronJob زمانی هم batch/v1beta1 و هم batch/v1 را serve میکرد.
| جنبه | رفتار |
|---|---|
| Schema روی سیم | فیلدها، نامها، validation ممکن است فرق کند |
| ذخیره در etcd | معمولاً یک storage version — نه دو کپی کامل |
| درخواست با نسخه قدیمی | apiserver تبدیل (conversion) به/از storage میکند |
| درخواست با نسخه جدید | ممکن است فیلدهای تازهای ببینید که در نسخه قدیمی وجود نداشتند |
| نوشتن با نسخه قدیمی پس از deprecate | warning در response header؛ بعداً ۴۰۴ / عدم serve |
پس «تفاوت عمل» یعنی:
- Validation متفاوت — چیزی که در alpha قبول میشود در stable رد میشود (یا برعکس بعد از تغییر schema)
- Defaulting متفاوت — مقادیر پیشفرض ممکن است عوض شوند
- فیلدهای موجود/غایب — feature جدید فقط روی نسخه جدید
- Conversion lossy — خواندن با نسخه قدیمی ممکن است فیلد جدید را drop کند؛ نوشتن دوباره = از دست رفتن داده
- دسترسی — اگر نسخه روی apiserver disable باشد، YAML با آن
apiVersionاصلاً apply نمیشود
مثال مفهومی تفاوت schema
# نسل قدیمی (ساده شده — تاریخی)
apiVersion: extensions/v1beta1
kind: Ingress
spec:
rules: [...]
# برخی فیلدها و annotation-محور بودن متفاوت بود
# نسل پایدار
apiVersion: networking.k8s.io/v1
kind: Ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix # اجباریتر / صریحتر
backend:
service:
name: web
port:
number: 80همین «Ingress» است، اما قرارداد فیلدها و گروه API عوض شده — کلاینت قدیمی و جدید رفتار متفاوت میبینند.
Preferred, Served, Storage
روی منابع built-in و CRDها سه مفهوم جداست:
| مفهوم | معنی |
|---|---|
| Served | این نسخه روی API در دسترس است؟ |
| Storage | کدام نسخه در etcd نوشته میشود؟ (معمولاً فقط یکی) |
| Preferred | kubectl / discovery کدام را ترجیح میدهد؟ |
برای CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
spec:
group: example.com
names:
kind: Widget
plural: widgets
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
# ...
- name: v1
served: true
storage: true # تنها storage
schema:
openAPIV3Schema:
type: object
# ...اولویت نامگذاری برای preferred تقریباً: GA > Beta > Alpha، سپس شماره بالاتر.
Conversion: None در برابر Webhook
وقتی چند نسخه served هستند:
| استراتژی | کی | رفتار |
|---|---|---|
| None | همه نسخهها شکل سیم یکسان (فقط فیلد اختیاری اضافه) | بدون تبدیل واقعی؛ برچسب version عوض میشود |
| Webhook | rename، split، merge، تو در تو شدن فیلدها | apiserver webhook را صدا میزند تا بین نسخهها reshape کند |
الگوی رایج در کنترلرها: hub-and-spoke — یک نسخه hub (معمولاً storage)، بقیه به hub تبدیل میشوند.
خطر: conversion یکطرفه یا lossy → کاربر با kubectl get widget.v1alpha1 میخواند، فیلد v1-only حذف میشود، بعد apply میکند و داده از بین میرود.
مهاجرت storage کامل نیست تا objectهای قدیمی در etcd rewrite شوند (StorageVersionMigration / ابزارهای migrator). فقط عوض کردن storage: true ردیفهای قدیمی را بازنویسی نمیکند.
Deprecation و حذف — تقویم واقعی دردسر
سیاست تقریبی Kubernetes:
معرفی → (عمر) → deprecate (warning) → (عمر) → دیگر serve نمیشود- Alpha: ممکن است بدون مسیر طولانی حذف شود
- Beta: حداقل حدود ۹ ماه یا ۳ minor تا deprecate، و همانقدر تا توقف serve
- Stable: در major فعلی حذف نمیشود (ممکن است deprecate شود ولی بماند)
مهاجرتهای معروفی که YAMLها را شکستند
| از | به | یادداشت |
|---|---|---|
extensions/v1beta1 Ingress/Deployment | networking.k8s.io/v1 / apps/v1 | |
batch/v1beta1 CronJob | batch/v1 | حذف در مسیر ۱.۲۵ |
policy/v1beta1 PDB | policy/v1 | |
apiextensions.k8s.io/v1beta1 CRD | apiextensions.k8s.io/v1 | schema اجباریتر |
autoscaling/v2beta2 HPA | autoscaling/v2 |
قبل از ارتقا cluster:
# هشدارهای deprecate در audit / kubectl
kubectl get --raw /metrics | head # یا بررسی logs apiserver
# ابزارهای رایج جامعه
# pluto, kube-no-trouble (kubent), kubepug — مانیفست/Helm را اسکن میکنندHelm charts قدیمی اغلب آخرین جایی هستند که apiVersion مرده را نگه میدارند — قبل از upgrade، chart را بهروز کنید.
apiVersion ≠ اینها
| مفهوم | چیست | اشتباه رایج |
|---|---|---|
نسخه Kubernetes (Server Version: v1.31) | نسخه باینری/cluster | فکر کردن apiVersion: v1 یعنی K8s v1 |
| appVersion در Chart.yaml | نسخه نرمافزار داخل بسته | ربط مستقیم به GVK ندارد |
| version در Chart.yaml | نسخه بسته Helm | |
| image tag | نسخه کانتینر | |
| Feature gate | روشن/خاموش کردن رفتار در کامپوننتها | بعضی featureها قبل از API جداگانه با gate میآیند |
CRD spec.versions[].name | نسخههای منبع سفارشی | باید با apiVersion: group/version در اشیاء CR جور باشد |
# درست برای یک CR
apiVersion: example.com/v1
kind: Widgetاگر فقط v1alpha1 served باشد و شما example.com/v1 بفرستید → خطا.
فعال/غیرفعال کردن روی API Server
# مثال مفهومی روی kube-apiserver
--runtime-config=batch/v1=false
--runtime-config=batch/v2alpha1=true
--runtime-config=storage.k8s.io/v1beta1/csistoragecapacities=trueبعد از تغییر معمولاً restart apiserver (و گاه controller-manager) لازم است. روی سرویسهای managed (EKS/GKE/AKS) این سطح کنترل محدودتر است — نسخه alpha/beta ممکن است اصلاً در دسترس نباشد.
کشف و دیباگ روزمره
# چه versionهایی زندهاند؟
kubectl api-versions | sort
# برای یک resource کدام نسخه؟
kubectl api-resources | grep -i ingress
# توضیح فیلدها روی نسخه مشخص
kubectl explain ingress.spec --api-version=networking.k8s.io/v1
# شیء ذخیرهشده را با version صریح بخوانید
kubectl get ingress.v1.networking.k8s.io my-ing -o yaml
# تبدیل مانیفست (ابزارها/نسخههای مختلف kubectl)
kubectl convert -f old.yaml --output-version networking.k8s.io/v1در GitOps (Flux / Argo) شکست reconcile اغلب از no matches for kind ... in version ... است = apiVersion روی آن cluster دیگر serve نمیشود.
تفاوت رفتار در عمل — سناریوها
۱. Apply با نسخه حذفشده
error: unable to recognize "ingress.yaml":
no matches for kind "Ingress" in version "extensions/v1beta1"رفع: بهروز کردن apiVersion و فیلدهای اجباری جدید (pathType، ingressClassName، …).
۲. Beta روی production بدون enable
YAML معتبر است؛ cluster آن version را advertise نمیکند → همان خطای بالا یا dry-run شکست.
۳. دو کلاینت، دو نسخه
Controller با v1 فیلد جدید مینویسد؛ انسان با v1beta1 get/edit میکند → فیلد گم میشود (lossy).
۴. CRD فقط storage را عوض کردید
Objectهای قدیمی هنوز با version قبلی در etcdاند تا migrate شوند؛ ابزارهای فرضکننده «همه v1 هستند» گیج میشوند.
۵. HPA v1 در برابر v2
autoscaling/v1 عمدتاً CPU؛ autoscaling/v2 متریکهای چندگانه و رفتار غنیتر — Kind یکسان نیست از نظر قابلیت، هرچند هر دو «HPA»اند.
ارتباط با stack شما
YAML / Helm / Kustomize
apiVersion + kind → GVK
│
▼
kube-apiserver (served versions, conversion)
│
▼
etcd (storage version) ← مقاله etcd
│
▼
Controllers, Flux, Operators, cert-manager CRDs, Istio CRDs, ...روی K3s همان مدل GVK برقرار است؛ فقط مجموعه APIهای enableشده را با kubectl api-versions چک کنید.
Best practices
- در مانیفستهای production فقط stable بنویسید مگر feature مجبورتان کند
- قبل از upgrade cluster، مانیفستها و Helm charts را با ابزار deprecate اسکن کنید
- در CI:
kubeconform/kubevalبا version هدف cluster - برای CRD: همیشه OpenAPI schema؛ migration با conversion تستشده
- از
kubectl explainنسخه صریح استفاده کنید — نه حافظه از آموزش قدیمی - در مستندات تیم جدول «apiVersion ممنوع / اجباری» بگذارید
- Image/chart version را با apiVersion قاطی نکنید
- بعد از تغییر storage CRD، migration etcd را تمام کنید قبل از حذف version قدیمی
- Warningهای deprecate در CI و audit را جدی بگیرید — نه بعد از شکست upgrade
- برای Gateway / mesh / cert-manager نسخه CRD را با نسخه کنترلر همتراز نگه دارید
جمعبندی
| مفهوم | یک جمله |
|---|---|
| apiVersion | Group+Version قراردادی که schema و endpoint را تعیین میکند |
| GVK | هویت نوع شیء |
| Alpha/Beta/Stable | قواعد enable، پشتیبانی و حذف متفاوت |
| Served vs Storage | چه چیزی دیده میشود در برابر چه چیزی در etcd میماند |
| Conversion | پل بین نسخهها؛ ممکن است lossy باشد |
| Deprecate | فرصت مهاجرت قبل از حذف از apiserver |
apiVersion کوچک بهنظر میرسد، اما مرز بین «YAML دیروز» و «cluster امروز» است. فهم تفاوت alpha/beta/stable و served/storage همان چیزی است که upgradeهای Kubernetes را قابل پیشبینی یا کابوس میکند.
قدم بعدی
- روی cluster خود:
kubectl api-versionsوkubectl api-resources - یک Ingress/CronJob قدیمی را عمداً با apiVersion منسوخ dry-run کنید و خطا را ببینید
- مانیفستهای Git را برای
extensions/وv1beta1جستجو کنید - یک CRD چندنسخهای (مثلاً از cert-manager) را با
kubectl get crd -o yamlنگاه کنید:served/storage - قبل از ارتقا minor بعدی، Deprecation Guide نسخه هدف را بخوانید
منابع
- API Overview — Kubernetes
- Deprecation Guide
- CRD versioning
- API changes documentation
- etcd (مقاله P30Light)
- Helm (مقاله P30Light)
- Flux (مقاله P30Light)
منتشر شده در P30Light — بخش زیرساخت و سرور.