استقرار برنامه‌ها در چندین خوشه Kubernetes با Helm

نحوه استفاده Dailymotion از Kubernetes: Application Deployment

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

از کجا شروع شد

در اینجا نحوه استقرار برنامه های خود را در چندین خوشه Kubernetes در سراسر جهان پوشش خواهیم داد.

برای استقرار چندین شی Kubernetes در یک زمان، ما استفاده می کنیم سکان، و همه نمودارهای ما در یک مخزن git ذخیره می شوند. برای استقرار یک پشته کامل برنامه از چندین سرویس، از نمودار خلاصه استفاده می کنیم. در اصل، این نموداری است که وابستگی ها را اعلام می کند و به شما امکان می دهد API و خدمات آن را با یک دستور مقداردهی اولیه کنید.

ما همچنین یک اسکریپت کوچک پایتون در بالای Helm نوشتیم تا بررسی ها، ایجاد نمودارها، افزودن رازها و استقرار برنامه ها را انجام دهیم. همه این وظایف بر روی یک پلت فرم مرکزی CI با استفاده از یک تصویر داکر انجام می شود.

بریم سر اصل مطلب

توجه داشته باشید. با خواندن این مطلب، اولین نامزد انتشار Helm 3 قبلاً اعلام شده است. نسخه اصلی شامل مجموعه ای از پیشرفت ها برای رسیدگی به برخی از مشکلاتی است که در گذشته با آن مواجه شده ایم.

گردش کار توسعه نمودار

ما از شاخه‌بندی برای برنامه‌ها استفاده می‌کنیم و تصمیم گرفتیم همین رویکرد را برای نمودارها اعمال کنیم.

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

هر محیطی مخزن خصوصی خود را دارد که نمودارهای ما را ذخیره می کند و ما از آن استفاده می کنیم موزه چارت با API های بسیار مفید به این ترتیب ما از جداسازی دقیق بین محیط ها و آزمایش در دنیای واقعی نمودارها قبل از استفاده از آنها در تولید اطمینان حاصل می کنیم.

مخازن نمودار در محیط های مختلف

شایان ذکر است که وقتی توسعه‌دهندگان یک شاخه توسعه‌دهنده را فشار می‌دهند، نسخه‌ای از نمودار آن‌ها به‌طور خودکار به Dev Chartmuseum فرستاده می‌شود. بنابراین، همه توسعه‌دهندگان از یک مخزن برنامه‌نویس استفاده می‌کنند و شما باید نسخه نمودار خود را با دقت مشخص کنید تا تصادفاً از تغییرات شخص دیگری استفاده نکنید.

علاوه بر این، اسکریپت پایتون کوچک ما، اشیاء Kubernetes را در برابر مشخصات Kubernetes OpenAPI با استفاده از اعتبارسنجی می‌کند. کوبوال، قبل از انتشار آنها در Chartmusem.

شرح کلی گردش کار توسعه نمودار

  1. تنظیم وظایف خط لوله با توجه به مشخصات gazr.io برای کنترل کیفیت (لینت، تست واحد).
  2. فشار دادن یک تصویر داکر با ابزار پایتون که برنامه های ما را مستقر می کند.
  3. تنظیم محیط با نام شعبه
  4. اعتبار سنجی فایل های Kubernetes yaml با استفاده از Kubeval.
  5. به طور خودکار نسخه نمودار و نمودارهای اصلی آن را افزایش دهید (نمودارهایی که به تغییر نمودار بستگی دارند).
  6. ارائه نموداری به Chartmuseum که با محیط آن مطابقت دارد

مدیریت تفاوت ها در میان خوشه ها

فدراسیون خوشه ها

زمانی بود که استفاده می کردیم فدراسیون خوشه های Kubernetes، جایی که اشیاء Kubernetes را می توان از یک نقطه پایانی API اعلام کرد. اما مشکلاتی به وجود آمد. به عنوان مثال، برخی از اشیاء Kubernetes را نمی توان در نقطه پایانی فدراسیون ایجاد کرد، که حفظ اشیاء فدرال و سایر اشیاء را برای خوشه های جداگانه دشوار می کند.

برای حل این مشکل، شروع به مدیریت مستقل کلاسترها کردیم که این روند را بسیار ساده کرد (از نسخه اول فدراسیون استفاده کردیم؛ ممکن است چیزی در نسخه دوم تغییر کرده باشد).

پلت فرم جغرافیایی توزیع شده

پلت فرم ما در حال حاضر در 6 منطقه - 3 به صورت محلی و 3 در فضای ابری توزیع شده است.


استقرار توزیع شده

ارزش های گلوبال هلم

4 مقدار جهانی Helm به شما امکان می دهد تفاوت های بین خوشه ها را شناسایی کنید. همه نمودارهای ما دارای حداقل مقادیر پیش فرض هستند.

global:
  cloud: True
  env: staging
  region: us-central1
  clusterName: staging-us-central1

ارزش های جهانی

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

  • "ابر": ما یک پلت فرم ترکیبی Kubernetes داریم. به عنوان مثال، API ما در مناطق GCP و در مراکز داده ما مستقر است.
  • "env": برخی از مقادیر ممکن است برای محیط های غیر تولیدی تغییر کنند. به عنوان مثال، تعاریف منابع و تنظیمات مقیاس خودکار.
  • "region": این اطلاعات به تعیین مکان خوشه کمک می کند و می تواند برای تعیین نقاط پایانی نزدیک برای خدمات خارجی استفاده شود.
  • "clusterName": اگر و زمانی که بخواهیم برای یک خوشه منفرد مقداری تعریف کنیم.

در اینجا یک مثال خاص آورده شده است:

{{/* Returns Horizontal Pod Autoscaler replicas for GraphQL*/}}
{{- define "graphql.hpaReplicas" -}}
{{- if eq .Values.global.env "prod" }}
{{- if eq .Values.global.region "europe-west1" }}
minReplicas: 40
{{- else }}
minReplicas: 150
{{- end }}
maxReplicas: 1400
{{- else }}
minReplicas: 4
maxReplicas: 20
{{- end }}
{{- end -}}

نمونه قالب هلم

این منطق در یک الگوی کمکی برای جلوگیری از بهم ریختگی Kubernetes YAML تعریف شده است.

اطلاعیه درخواست

ابزارهای استقرار ما بر اساس چندین فایل YAML هستند. در زیر مثالی از نحوه اعلان یک سرویس و توپولوژی مقیاس آن (تعداد replicas) در یک خوشه آورده شده است.

releases:
  - foo.world

foo.world:                # Release name
  services:               # List of dailymotion's apps/projects
    foobar:
      chart_name: foo-foobar
      repo: [email protected]:dailymotion/foobar
      contexts:
        prod-europe-west1:
          deployments:
            - name: foo-bar-baz
              replicas: 18
            - name: another-deployment
              replicas: 3

تعریف خدمات

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


مراحل استقرار جنکینز

در مورد اسرار چطور؟

با توجه به امنیت، ما تمام اسرار را از مکان های مختلف دنبال می کنیم و آنها را در یک خزانه منحصر به فرد ذخیره می کنیم طاق در پاریس.

ابزارهای استقرار ما مقادیر مخفی را از Vault استخراج می کنند و وقتی زمان استقرار فرا رسید، آنها را در Helm قرار می دهند.

برای انجام این کار، ما یک نقشه بین رازهای موجود در Vault و رازهایی که برنامه های ما به آن نیاز دارند، تعریف کردیم:

secrets:                                                                                                                                                                                                        
     - secret_id: "stack1-app1-password"                                                                                                                                                                                  
       contexts:                                                                                                                                                                                                   
         - name: "default"                                                                                                                                                                                         
           vaultPath: "/kv/dev/stack1/app1/test"                                                                                                                                                               
           vaultKey: "password"                                                                                                                                                                                    
         - name: "cluster1"                                                                                                                                                                           
           vaultPath: "/kv/dev/stack1/app1/test"                                                                                                                                                               
           vaultKey: "password"

  • ما قوانین کلی را تعریف کرده ایم که هنگام ضبط اسرار در Vault باید رعایت شود.
  • اگر راز صدق کند به یک زمینه یا خوشه خاص، باید یک ورودی خاص اضافه کنید. (در اینجا Context cluster1 مقدار خاص خود را برای مخفی stack-app1-password دارد).
  • در غیر این صورت از مقدار استفاده می شود به طور پیش فرض.
  • برای هر مورد در این لیست در راز Kubernetes یک جفت کلید-مقدار درج شده است. بنابراین، الگوی مخفی در نمودارهای ما بسیار ساده است.

apiVersion: v1
data:
{{- range $key,$value := .Values.secrets }}
  {{ $key }}: {{ $value | b64enc | quote }}
{{ end }}
kind: Secret
metadata:
  name: "{{ .Chart.Name }}"
  labels:
    chartVersion: "{{ .Chart.Version }}"
    tillerVersion: "{{ .Capabilities.TillerVersion.SemVer }}"
type: Opaque

مشکلات و محدودیت ها

کار با چندین مخزن

اکنون توسعه نمودارها و برنامه ها را از هم جدا می کنیم. این بدان معنی است که توسعه دهندگان باید در دو مخزن git کار کنند: یکی برای برنامه و دیگری برای تعریف استقرار آن در Kubernetes. 2 مخزن git به معنای 2 گردش کار است و برای یک تازه کار آسان است که گیج شود.

مدیریت نمودارهای تعمیم یافته یک دردسر است

همانطور که قبلاً گفتیم، نمودارهای عمومی برای شناسایی وابستگی ها و استقرار سریع برنامه های کاربردی بسیار مفید هستند. اما ما استفاده می کنیم --reuse-valuesبرای جلوگیری از عبور همه مقادیر هر بار که برنامه‌ای را که بخشی از این نمودار تعمیم‌یافته است اجرا می‌کنیم.

در یک گردش کار تحویل پیوسته، ما فقط دو مقدار داریم که به طور منظم تغییر می کنند: تعداد کپی ها و تگ تصویر (نسخه). سایر مقادیر پایدارتر به صورت دستی تغییر می کنند و این بسیار دشوار است. علاوه بر این، همانطور که از تجربه خودمان دیدیم، یک اشتباه در به کارگیری یک نمودار کلی می تواند منجر به شکست های جدی شود.

به روز رسانی چندین فایل پیکربندی

هنگامی که یک توسعه دهنده یک برنامه جدید اضافه می کند، باید چندین فایل را تغییر دهد: اعلامیه برنامه، لیست اسرار، اضافه کردن برنامه به عنوان یک وابستگی در صورتی که در نمودار کلی گنجانده شود.

مجوزهای جنکینز در Vault بسیار گسترش یافته است

حالا یکی داریم AppRole، که تمام اسرار را از خرک می خواند.

فرآیند بازگشت خودکار نیست

برای بازگشت، باید دستور را روی چندین خوشه اجرا کنید، و این مملو از خطا است. ما این عملیات را به صورت دستی انجام می دهیم تا مطمئن شویم که شناسه نسخه صحیح مشخص شده است.

ما به سمت GitOps حرکت می کنیم

هدف ما

ما می خواهیم نمودار را به مخزن برنامه ای که مستقر می کند برگردانیم.

گردش کار مانند توسعه خواهد بود. به عنوان مثال، هنگامی که یک شاخه به Master فشار داده می شود، استقرار به طور خودکار فعال می شود. تفاوت اصلی بین این رویکرد و گردش کار فعلی در این خواهد بود همه چیز در git مدیریت خواهد شد (خود برنامه و نحوه استقرار آن در Kubernetes).

چندین مزیت وجود دارد:

  • خیلی واضح تر برای توسعه دهنده یادگیری نحوه اعمال تغییرات در نمودار محلی آسان تر است.
  • تعریف استقرار سرویس را می توان مشخص کرد همان مکان کد سرویس.
  • مدیریت حذف نمودارهای تعمیم یافته. این سرویس نسخه Helm خود را خواهد داشت. این به شما امکان می دهد چرخه عمر برنامه (بازگشت، ارتقا) را در کوچکترین سطح مدیریت کنید تا بر سایر خدمات تأثیر نگذارد.
  • مزایای git برای مدیریت نمودار: لغو تغییرات، گزارش حسابرسی و غیره. اگر نیاز به لغو تغییر در نمودار دارید، می توانید این کار را با استفاده از git انجام دهید. استقرار به طور خودکار شروع می شود.
  • ممکن است در نظر داشته باشید که گردش کار توسعه خود را با ابزارهایی مانند بهبود ببخشید داربست، که با آن توسعه دهندگان می توانند تغییرات را در زمینه ای نزدیک به تولید آزمایش کنند.

مهاجرت دو مرحله ای

توسعه دهندگان ما اکنون 2 سال است که از این گردش کار استفاده می کنند، بنابراین ما می خواهیم مهاجرت تا حد امکان بدون دردسر باشد. بنابراین تصمیم گرفتیم یک گام میانی در راه رسیدن به هدف اضافه کنیم.
مرحله اول ساده است:

  • ما ساختار مشابهی را برای راه اندازی استقرار برنامه نگه می داریم، اما در یک شی واحد به نام DailymotionRelease.

apiVersion: "v1"
kind: "DailymotionRelease"
metadata:
  name: "app1.ns1"
  environment: "dev"
  branch: "mybranch"
spec:
  slack_channel: "#admin"
  chart_name: "app1"
  scaling:
    - context: "dev-us-central1-0"
      replicas:
        - name: "hermes"
          count: 2
    - context: "dev-europe-west1-0"
      replicas:
        - name: "app1-deploy"
          count: 2
  secrets:
    - secret_id: "app1"
      contexts:
        - name: "default"
          vaultPath: "/kv/dev/ns1/app1/test"
          vaultKey: "password"
        - name: "dev-europe-west1-0"
          vaultPath: "/kv/dev/ns1/app1/test"
          vaultKey: "password"

  • 1 نسخه در هر برنامه (بدون نمودارهای کلی).
  • نمودارها در مخزن git برنامه.

ما با همه توسعه دهندگان صحبت کرده ایم، بنابراین روند مهاجرت از قبل آغاز شده است. مرحله اول همچنان با استفاده از پلت فرم CI کنترل می شود. من به زودی یک پست دیگر در مورد فاز دوم خواهم نوشت: چگونه به یک گردش کاری GitOps منتقل شدیم شار. من به شما خواهم گفت که چگونه همه چیز را تنظیم کردیم و با چه مشکلاتی مواجه شدیم (مخزن های متعدد، اسرار و غیره). اخبار را دنبال کنید.

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

منبع: www.habr.com

اضافه کردن نظر