فارسی

نگاهی عمیق به اپراتورهای کوبرنتیز، که توضیح می‌دهد چگونه مدیریت برنامه‌های پیچیده و منابع سفارشی را ساده و خودکار می‌کنند. بیاموزید چگونه اپراتورهای خود را بسازید و مستقر کنید.

اپراتورهای کوبرنتیز: خودکارسازی مدیریت منابع سفارشی

کوبرنتیز روش استقرار و مدیریت برنامه‌ها را متحول کرده است. با این حال، مدیریت برنامه‌های پیچیده و حالتمند (stateful) همچنان می‌تواند چالش‌برانگیز باشد. اینجاست که اپراتورهای کوبرنتیز وارد می‌شوند و راهی قدرتمند برای خودکارسازی مدیریت برنامه‌ها و گسترش قابلیت‌های کوبرنتیز ارائه می‌دهند.

اپراتورهای کوبرنتیز چه هستند؟

اپراتور کوبرنتیز یک کنترلر مخصوص برنامه است که API کوبرنتیز را برای مدیریت برنامه‌های پیچیده گسترش می‌دهد. آن را به عنوان یک مدیر سیستم خودکار در نظر بگیرید که به طور خاص برای یک برنامه مشخص طراحی شده است. اپراتورها دانش حوزه مربوط به اجرای یک برنامه خاص را در خود جای می‌دهند و به شما امکان می‌دهند آن را به روشی اعلانی، خودکار و تکرارپذیر مدیریت کنید.

برخلاف کنترلرهای سنتی کوبرنتیز که منابع اصلی مانند Podها و Serviceها را مدیریت می‌کنند، اپراتورها منابع سفارشی تعریف شده از طریق تعاریف منابع سفارشی (CRDها) را مدیریت می‌کنند. این به شما امکان می‌دهد منابع مخصوص برنامه خود را تعریف کرده و کوبرنتیز آنها را به طور خودکار مدیریت کند.

چرا از اپراتورهای کوبرنتیز استفاده کنیم؟

اپراتورها چندین مزیت کلیدی برای مدیریت برنامه‌های پیچیده ارائه می‌دهند:

درک تعاریف منابع سفارشی (CRDها)

تعاریف منابع سفارشی (CRDها) پایه و اساس اپراتورهای کوبرنتیز هستند. CRDها به شما اجازه می‌دهند تا با تعریف انواع منابع سفارشی خود، API کوبرنتیز را گسترش دهید. این منابع مانند هر منبع دیگر کوبرنتیز، مانند Podها یا Serviceها، در نظر گرفته می‌شوند و می‌توان آنها را با استفاده از `kubectl` و سایر ابزارهای کوبرنتیز مدیریت کرد.

نحوه کار CRDها به این صورت است:

  1. شما یک CRD تعریف می‌کنید که اسکما و قوانین اعتبارسنجی را برای منبع سفارشی شما مشخص می‌کند.
  2. شما CRD را در کلاستر کوبرنتیز خود مستقر می‌کنید.
  3. شما نمونه‌هایی از منبع سفارشی خود را ایجاد می‌کنید و پیکربندی مورد نظر را مشخص می‌کنید.
  4. اپراتور تغییرات این منابع سفارشی را مشاهده می‌کند و برای تطبیق وضعیت مطلوب با وضعیت واقعی اقدامات لازم را انجام می‌دهد.

برای مثال، فرض کنید می‌خواهید یک برنامه پایگاه داده را با استفاده از یک اپراتور مدیریت کنید. شما می‌توانید یک CRD به نام `Database` با فیلدهایی مانند `name`، `version`، `storageSize` و `replicas` تعریف کنید. سپس اپراتور تغییرات منابع `Database` را مشاهده کرده و بر اساس آن، نمونه‌های پایگاه داده زیربنایی را ایجاد یا به‌روزرسانی می‌کند.

اپراتورهای کوبرنتیز چگونه کار می‌کنند

اپراتورهای کوبرنتیز با ترکیب تعاریف منابع سفارشی (CRDها) و کنترلرهای سفارشی کار می‌کنند. کنترلر تغییرات منابع سفارشی را مشاهده می‌کند و برای تطبیق وضعیت مطلوب با وضعیت واقعی اقداماتی را انجام می‌دهد. این فرآیند معمولاً شامل مراحل زیر است:

  1. مشاهده رویدادها: اپراتور رویدادهای مربوط به منابع سفارشی مانند ایجاد، حذف یا به‌روزرسانی را مشاهده می‌کند.
  2. تطبیق وضعیت (Reconciling State): هنگامی که یک رویداد رخ می‌دهد، اپراتور وضعیت برنامه را تطبیق می‌دهد. این شامل مقایسه وضعیت مطلوب (تعریف شده در منبع سفارشی) با وضعیت واقعی و انجام اقدامات برای هماهنگ کردن آنهاست.
  3. مدیریت منابع: اپراتور منابع کوبرنتیز (Podها، Serviceها، Deploymentها و غیره) را برای رسیدن به وضعیت مطلوب ایجاد، به‌روزرسانی یا حذف می‌کند.
  4. مدیریت خطاها: اپراتور خطاها را مدیریت کرده و عملیات ناموفق را دوباره تلاش می‌کند تا اطمینان حاصل شود که برنامه در وضعیت پایداری باقی می‌ماند.
  5. ارائه بازخورد: اپراتور بازخوردهایی در مورد وضعیت برنامه، مانند بررسی‌های سلامتی و استفاده از منابع، ارائه می‌دهد.

حلقه تطبیق (reconcile loop) هسته منطق اپراتور است. این حلقه به طور مداوم وضعیت برنامه را نظارت می‌کند و برای حفظ وضعیت مطلوب اقداماتی را انجام می‌دهد. این حلقه معمولاً با استفاده از یک تابع تطبیق (reconciliation function) پیاده‌سازی می‌شود که عملیات لازم را انجام می‌دهد.

ساخت اپراتور کوبرنتیز خودتان

چندین ابزار و فریم‌ورک می‌توانند به شما در ساخت اپراتورهای کوبرنتیز کمک کنند:

در اینجا یک نمای کلی ساده از مراحل ساخت یک اپراتور با استفاده از Operator Framework آمده است:

  1. تعریف یک تعریف منبع سفارشی (CRD): یک CRD ایجاد کنید که وضعیت مطلوب برنامه شما را توصیف کند. این اسکما و قوانین اعتبارسنجی را برای منبع سفارشی شما تعریف می‌کند.
  2. تولید کد اپراتور: از Operator SDK برای تولید کد اولیه اپراتور بر اساس CRD خود استفاده کنید. این کار کنترلرها و تعاریف منابع لازم را ایجاد می‌کند.
  3. پیاده‌سازی منطق تطبیق (Reconcile Logic): منطق تطبیق را پیاده‌سازی کنید که وضعیت مطلوب (تعریف شده در منبع سفارشی) را با وضعیت واقعی مقایسه کرده و برای هماهنگ کردن آنها اقداماتی را انجام می‌دهد. این هسته عملکرد اپراتور شماست.
  4. ساخت و استقرار اپراتور: ایمیج اپراتور را بسازید و آن را در کلاستر کوبرنتیز خود مستقر کنید.
  5. آزمایش و تکرار: اپراتور خود را به طور کامل آزمایش کنید و برای بهبود عملکرد و قابلیت اطمینان آن، کد را تکرار و اصلاح کنید.

بیایید با یک مثال ساده با استفاده از Operator Framework این موضوع را نشان دهیم. فرض کنید می‌خواهید یک اپراتور ایجاد کنید که یک استقرار ساده `Memcached` را مدیریت کند.

۱. تعریف CRD:

یک فایل `memcached.yaml` با تعریف CRD زیر ایجاد کنید:


apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: memcacheds.cache.example.com
spec:
  group: cache.example.com
  versions:
    - name: v1alpha1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                size:
                  type: integer
                  description: Size is the number of Memcached instances
              required: ["size"]
  scope: Namespaced
  names:
    plural: memcacheds
    singular: memcached
    kind: Memcached
    shortNames: ["mc"]

این CRD یک منبع `Memcached` را با یک فیلد `size` تعریف می‌کند که تعداد نمونه‌های Memcached را برای اجرا مشخص می‌کند.

۲. تولید کد اپراتور:

از Operator SDK برای تولید کد اولیه اپراتور استفاده کنید:


operator-sdk init --domain=example.com --repo=github.com/example/memcached-operator
operator-sdk create api --group=cache --version=v1alpha1 --kind=Memcached --resource --controller

این دستور فایل‌ها و دایرکتوری‌های لازم برای اپراتور شما را تولید می‌کند، از جمله کد کنترلر و تعاریف منابع.

۳. پیاده‌سازی منطق Reconcile:

فایل `controllers/memcached_controller.go` را ویرایش کنید تا منطق reconcile را پیاده‌سازی کنید. این تابع، استقرارهای Memcached را بر اساس وضعیت مطلوب تعریف شده در منبع `Memcached` ایجاد، به‌روزرسانی یا حذف می‌کند.


func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	log := r.Log.WithValues("memcached", req.NamespacedName)

	// واکشی نمونه Memcached
	memcached := &cachev1alpha1.Memcached{}
	err := r.Get(ctx, req.NamespacedName, memcached)
	if err != nil {
		if errors.IsNotFound(err) {
			// شیء درخواست یافت نشد، ممکن است پس از درخواست reconcile حذف شده باشد.
			// اشیاء تحت مالکیت به طور خودکار زباله‌روبی می‌شوند. برای منطق پاکسازی اضافی از finalizerها استفاده کنید.
			// بازگشت و عدم قرار دادن مجدد در صف
			log.Info("Memcached resource not found. Ignoring since object must be deleted")
			return ctrl.Result{}, nil
		}
		// خطا در خواندن شیء - درخواست را مجدداً در صف قرار دهید.
		log.Error(err, "Failed to get Memcached")
		return ctrl.Result{}, err
	}

	// تعریف یک شیء Deployment جدید
	deployment := &appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      memcached.Name,
			Namespace: memcached.Namespace,
		},
		Spec: appsv1.DeploymentSpec{
			Replicas: &memcached.Spec.Size,
			Selector: &metav1.LabelSelector{
				MatchLabels: map[string]string{
					"app": memcached.Name,
				},
			},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{
						"app": memcached.Name,
					},
				},
				Spec: corev1.PodSpec{
					Containers: []corev1.Container{
						{
							Name:  "memcached",
							Image: "memcached:1.6.17-alpine",
							Ports: []corev1.ContainerPort{
								{
									ContainerPort: 11211,
								},
							},
						},
					},
				},
			},
		},
	}

	// تنظیم نمونه Memcached به عنوان مالک و کنترلر
	if err := ctrl.SetControllerReference(memcached, deployment, r.Scheme);
		err != nil {
			log.Error(err, "Failed to set controller reference")
			return ctrl.Result{}, err
	}

	// بررسی اینکه آیا این Deployment از قبل وجود دارد یا خیر
	found := &appsv1.Deployment{}
	err = r.Get(ctx, types.NamespacedName{
		Name:      deployment.Name,
		Namespace: deployment.Namespace,
	}, found)
	if err != nil && errors.IsNotFound(err) {
		log.Info("Creating a new Deployment", "Deployment.Namespace", deployment.Namespace, "Deployment.Name", deployment.Name)
		err = r.Create(ctx, deployment)
		if err != nil {
			log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", deployment.Namespace, "Deployment.Name", deployment.Name)
			return ctrl.Result{}, err
		}

		// Deployment با موفقیت ایجاد شد - بازگشت و قرار دادن مجدد در صف
		return ctrl.Result{Requeue: true}, nil
	} else if err != nil {
		log.Error(err, "Failed to get Deployment")
		return ctrl.Result{}, err
	}

	// اطمینان از اینکه اندازه deployment با مشخصات spec یکسان است
	size := memcached.Spec.Size
	if *found.Spec.Replicas != size {
		log.Info("Updating Deployment", "Deployment.Namespace", deployment.Namespace, "Deployment.Name", deployment.Name)
		found.Spec.Replicas = &size
		err = r.Update(ctx, found)
		if err != nil {
			log.Error(err, "Failed to update Deployment", "Deployment.Namespace", deployment.Namespace, "Deployment.Name", deployment.Name)
			return ctrl.Result{}, err
		}
		// Spec به‌روزرسانی شد - بازگشت و قرار دادن مجدد در صف
		return ctrl.Result{Requeue: true}, nil
	}

	// Deployment از قبل وجود دارد - در صف قرار ندهید
	log.Info("Skip reconcile: Deployment already exists", "Deployment.Namespace", deployment.Namespace, "Deployment.Name", deployment.Name)
	return ctrl.Result{}, nil
}

این مثال یک نسخه بسیار ساده‌شده از منطق reconcile است. یک اپراتور آماده برای محیط پروداکشن به مدیریت خطای قوی‌تر، لاگ‌برداری و گزینه‌های پیکربندی بیشتری نیاز دارد.

۴. ساخت و استقرار اپراتور:

ایمیج اپراتور را بسازید و آن را در کلاستر کوبرنتیز خود با استفاده از `make deploy` مستقر کنید.

۵. ایجاد یک منبع Memcached:

یک فایل `memcached-instance.yaml` با محتوای زیر ایجاد کنید:


apiVersion: cache.example.com/v1alpha1
kind: Memcached
metadata:
  name: memcached-sample
spec:
  size: 3

این فایل را با استفاده از `kubectl apply -f memcached-instance.yaml` در کلاستر خود اعمال کنید.

اکنون اپراتور یک Deployment با ۳ نمونه Memcached ایجاد خواهد کرد.

بهترین شیوه‌ها برای توسعه اپراتورهای کوبرنتیز

توسعه اپراتورهای مؤثر کوبرنتیز نیازمند برنامه‌ریزی و اجرای دقیق است. در اینجا برخی از بهترین شیوه‌ها برای به خاطر سپردن آورده شده است:

نمونه‌های واقعی از اپراتورهای کوبرنتیز

بسیاری از سازمان‌ها از اپراتورهای کوبرنتیز برای مدیریت برنامه‌های پیچیده در محیط تولید استفاده می‌کنند. در اینجا چند نمونه آورده شده است:

اینها تنها چند نمونه از اپراتورهای کوبرنتیز موجود هستند. با ادامه رشد پذیرش کوبرنتیز، می‌توان انتظار داشت که اپراتورهای بیشتری ظهور کنند و مدیریت طیف وسیع‌تری از برنامه‌ها را ساده‌تر کنند.

ملاحظات امنیتی برای اپراتورهای کوبرنتیز

اپراتورهای کوبرنتیز، مانند هر برنامه‌ای که در یک کلاستر کوبرنتیز اجرا می‌شود، نیازمند ملاحظات امنیتی دقیق هستند. از آنجا که اپراتورها اغلب دارای امتیازات بالایی برای مدیریت منابع کلاستر هستند، پیاده‌سازی اقدامات امنیتی مناسب برای جلوگیری از دسترسی غیرمجاز و فعالیت‌های مخرب بسیار مهم است.

در اینجا برخی از ملاحظات کلیدی امنیتی برای اپراتورهای کوبرنتیز آورده شده است:

با پیاده‌سازی این اقدامات امنیتی، می‌توانید خطر رخنه‌های امنیتی را به میزان قابل توجهی کاهش داده و اپراتورهای کوبرنتیز خود را از فعالیت‌های مخرب محافظت کنید.

آینده اپراتورهای کوبرنتیز

اپراتورهای کوبرنتیز به سرعت در حال تکامل هستند و به بخش مهمی از اکوسیستم کوبرنتیز تبدیل شده‌اند. با ادامه رشد پذیرش کوبرنتیز، می‌توانیم انتظار نوآوری‌های بیشتری را در فضای اپراتورها داشته باشیم.

در اینجا برخی از روندهایی که آینده اپراتورهای کوبرنتیز را شکل می‌دهند آورده شده است:

نتیجه‌گیری

اپراتورهای کوبرنتیز راهی قدرتمند برای خودکارسازی مدیریت برنامه‌های پیچیده و گسترش قابلیت‌های کوبرنتیز ارائه می‌دهند. با تعریف منابع سفارشی و پیاده‌سازی کنترلرهای سفارشی، اپراتورها به شما امکان می‌دهند برنامه‌ها را به روشی اعلانی، خودکار و تکرارپذیر مدیریت کنید. با ادامه رشد پذیرش کوبرنتیز، اپراتورها به بخش مهمی از چشم‌انداز ابر-بومی تبدیل خواهند شد.

با پذیرش اپراتورهای کوبرنتیز، سازمان‌ها می‌توانند مدیریت برنامه‌ها را ساده‌تر کرده، سربار عملیاتی را کاهش دهند و قابلیت اطمینان و مقیاس‌پذیری کلی برنامه‌های خود را بهبود بخشند. چه در حال مدیریت پایگاه‌های داده، سیستم‌های مانیتورینگ یا سایر برنامه‌های پیچیده باشید، اپراتورهای کوبرنتیز می‌توانند به شما در ساده‌سازی عملیات و آزادسازی پتانسیل کامل کوبرنتیز کمک کنند.

این یک حوزه در حال تحول است، بنابراین به‌روز ماندن با آخرین تحولات و بهترین شیوه‌ها برای استفاده مؤثر از اپراتورهای کوبرنتیز در سازمان شما بسیار مهم است. جامعه پیرامون اپراتورها پرجنب‌وجوش و حمایتگر است و انبوهی از منابع و تخصص را برای کمک به موفقیت شما ارائه می‌دهد.