پرش به محتویات

آموزش کوبرنتیز؛ شب ششم: YAML اعلانی

در شب پایانی، وضعیت مطلوب را با Manifestهای قابل نگه‌داری در Git ایجاد، بررسی، مقایسه و به‌روزرسانی می‌کنیم.

ساختار یک Object

هر Object کوبرنتیز چهار بخش مهم در سطح بالا دارد:

apiVersion: apps/v1  # گروه و نسخهٔ API
kind: Deployment     # نوع منبع
metadata: {}         # هویت، Labelها و Annotationها
spec: {}             # وضعیت مطلوب

API Server و Controllerها بخش status را با وضعیت مشاهده‌شده پر می‌کنند. فیلدهای تولیدشده‌ای مانند status، resourceVersion، uid و managedFields را در Manifest دست‌نویس کپی نکنید.

Manifest برنامه

فایل app.yaml را بسازید:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: course-night-6
  labels:
    app.kubernetes.io/name: web
    app.kubernetes.io/part-of: night-school
  annotations:
    course.example/owner: student
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: web
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web
        app.kubernetes.io/part-of: night-school
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          ports:
            - name: http
              containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: course-night-6
  labels:
    app.kubernetes.io/name: web
    app.kubernetes.io/part-of: night-school
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: web
  ports:
    - name: http
      port: 80
      targetPort: http

اعتبارسنجی پیش از Apply

kubectl create namespace course-night-6
kubectl apply --dry-run=server -f app.yaml
kubectl diff -f app.yaml
kubectl apply -f app.yaml
kubectl rollout status deployment/web --namespace course-night-6

وقتی kubectl diff تفاوتی پیدا می‌کند، معمولاً با Exit Code برابر 1 خارج می‌شود. این نتیجه به‌تنهایی به معنی خرابی فرمان نیست.

فایل نوشته‌شده را با Object زنده مقایسه کنید:

kubectl get deployment web --namespace course-night-6 -o yaml
kubectl get deployment web --namespace course-night-6 \
  -o jsonpath='{.metadata.generation}{" desired; observed="}{.status.observedGeneration}{"\n"}'
kubectl get pods --namespace course-night-6 --show-labels

Label، Selector و Annotation

  • Label برای شناسایی و گروه‌بندی Objectهاست.
  • Selector کنترلرها و Serviceها را به Podها متصل می‌کند.
  • Annotation برای Metadataای است که نقش شناسایی ندارد.
  • Selector یک Deployment باید با Labelهای Pod Template هماهنگ باشد و پس از ایجاد عملاً تغییرناپذیر است.

Label و Annotation تعریف‌شده را Query کنید:

kubectl get all --namespace course-night-6 \
  -l app.kubernetes.io/name=web
kubectl get deployment web --namespace course-night-6 \
  -o jsonpath='{.metadata.annotations.course\\.example/owner}{"\n"}'

به‌روزرسانی Declarative و امن

در app.yaml تعداد Replica را از ۲ به ۳ تغییر دهید:

spec:
  replicas: 3

سپس تغییر را پیش‌نمایش، مقایسه و اعمال کنید:

kubectl apply --dry-run=server -f app.yaml
kubectl diff -f app.yaml
kubectl apply -f app.yaml
kubectl get deployment,pods --namespace course-night-6

اکنون Image را از nginx:alpine به nginx:1.27-alpine تغییر دهید:

kubectl diff -f app.yaml
kubectl apply -f app.yaml
kubectl rollout status deployment/web --namespace course-night-6
kubectl rollout history deployment/web --namespace course-night-6

تغییر Replica، Pod Template را تغییر نمی‌دهد؛ اما تغییر Image آن را عوض می‌کند و در نتیجه Revision تازه‌ای از ReplicaSet می‌سازد.

تمرین خطای Schema

یک کپی موقت از Manifest بگیرید:

cp app.yaml broken-app.yaml

تمام بلوک spec.selector مربوط به Deployment را از broken-app.yaml حذف و نسخهٔ خراب را فقط اعتبارسنجی کنید:

kubectl apply --dry-run=server -f broken-app.yaml

پیام اعتبارسنجی API را بخوانید، فایل را تعمیر و دوباره بررسی کنید. فایل خراب را روی کلاستر Apply نکنید.

چک‌لیست پایان

  • apiVersion، kind، metadata، spec و status را توضیح می‌دهم.
  • پیش از Apply از Dry-run سمت سرور و Diff استفاده کرده‌ام.
  • با Label جست‌وجو و یک Annotation را خوانده‌ام.
  • تعداد Replica و Image را به‌شکل Declarative تغییر داده‌ام.
  • خطای Schema ساخته و آن را رفع کرده‌ام.
  • فیلدهای تولیدشده یا اطلاعات محرمانه را Commit نکرده‌ام.

Objectهای کلاستر را پاک کنید، اما Manifest را به‌عنوان محتوای دوره نگه دارید:

kubectl delete -f app.yaml
kubectl delete namespace course-night-6