
8 آوریل در کنفرانس ، به عنوان بخشی از بخش "DevOps و عملیات" ، گزارشی "گسترش و تکمیل Kubernetes" ارائه شد که در ایجاد آن سه کارمند شرکت Flant شرکت کردند. در آن، ما در مورد موقعیت های متعددی صحبت می کنیم که در آنها می خواستیم قابلیت های Kubernetes را گسترش دهیم و تکمیل کنیم، اما راه حل آماده و ساده ای برای آنها پیدا نکردیم. ما راهکارهای لازم را در قالب پروژه های متن باز داریم که این گفتار نیز به آنها اختصاص دارد.
طبق سنت، ما از ارائه خوشحالیم (50 دقیقه، بسیار آموزنده تر از مقاله) و خلاصه اصلی به صورت متنی. برو!
هسته و اضافات در K8s
Kubernetes در حال تغییر صنعت و رویکردهای مدیریتی است که مدتهاست ایجاد شده است:
- تشکر از او انتزاعات، ما دیگر با مفاهیمی مانند تنظیم یک پیکربندی یا اجرای یک فرمان (Chef, Ansible...) کار نمی کنیم، بلکه از گروه بندی کانتینرها، خدمات و غیره استفاده می کنیم.
- ما می توانیم بدون فکر کردن به تفاوت های ظریف برنامه های کاربردی را آماده کنیم سایت خاص، که روی آن راه اندازی خواهد شد: فلز لخت، ابر یکی از ارائه دهندگان و غیره.
- با K8s هرگز به این اندازه در دسترس نبوده اید بهترین شیوه ها در مورد سازماندهی زیرساخت ها: تکنیک های مقیاس بندی، خود ترمیمی، تحمل خطا و غیره.
با این حال، البته، همه چیز چندان هموار نیست: Kubernetes نیز چالش های جدید خود را به ارمغان آورد.
کوبرنیتس هیچ ترکیبی است که تمام مشکلات همه کاربران را حل می کند. هسته Kubernetes فقط مسئول مجموعه ای از حداقل توابع ضروری است که در آن وجود دارد هر یک خوشه:

هسته Kubernetes مجموعه ای از اصول اولیه را برای گروه بندی کانتینرها، مدیریت ترافیک و غیره تعریف می کند. در مورد آنها با جزئیات بیشتری صحبت کردیم .
از سوی دیگر، K8s فرصت های خوبی برای گسترش عملکردهای موجود ارائه می دهد که به بستن سایرین کمک می کند - خاص - نیازهای کاربر اضافه شدن به Kubernetes بر عهده مدیران خوشه است، که باید هر چیزی را که برای اینکه خوشه خود را "در شکل مناسب" قرار دهد [برای حل مشکلات خاص خود] نصب و پیکربندی کند. اینها چه نوع اضافاتی هستند؟ بیایید به چند نمونه نگاه کنیم.
نمونه هایی از افزونه ها
با نصب Kubernetes، ممکن است تعجب کنیم که شبکهای که برای تعامل پادها در داخل یک گره و بین گرهها بسیار ضروری است، به خودی خود کار نمیکند. هسته Kubernetes اتصالات لازم را تضمین نمی کند، در عوض، شبکه را تعیین می کند رابط () برای افزونه های شخص ثالث. ما باید یکی از این افزونه ها را نصب کنیم که مسئولیت پیکربندی شبکه را بر عهده خواهد داشت.

یک مثال نزدیک راه حل های ذخیره سازی داده ها (دیسک محلی، دستگاه بلوک شبکه، Ceph...) است. در ابتدا آنها در هسته بودند، اما با ظهور وضعیت به چیزی شبیه به آنچه قبلاً توضیح داده شده تغییر می کند: رابط در Kubernetes است و پیاده سازی آن در ماژول های شخص ثالث است.
نمونه های دیگر عبارتند از:
- ورود-کنترل کننده ها (نگاه کنید به بررسی آنها در ).
- :

- یک کلاس کامل از افزونه ها است (که شامل مدیر گواهی ذکر شده است)، آنها ابتدایی(ها) و کنترل کننده(ها) را تعریف می کنند. منطق کار آنها فقط با تخیل ما محدود می شود و به ما اجازه می دهد تا اجزای زیرساختی آماده (مثلاً یک DBMS) را به ابتدایی تبدیل کنیم که کار با آنها بسیار ساده تر است (نسبت به مجموعه ای از کانتینرها و تنظیمات آنها). تعداد زیادی از اپراتورها نوشته شده اند - حتی اگر بسیاری از آنها هنوز برای تولید آماده نباشند، فقط موضوع زمان است:

- معیارهای - تصویر دیگری از نحوه جداسازی Kubernetes رابط (API Metrics) از پیاده سازی (افزونه های شخص ثالث مانند آداپتور Prometheus، عامل خوشه Datadog...).
- برای نظارت و آمار، جایی که در عمل نه تنها مورد نیاز است ، اما همچنین kube-state-metrics، node-exporter و غیره.
و این لیست کاملی از موارد اضافه نیست... به عنوان مثال، در شرکت فلانت که ما در حال حاضر نصب می کنیم 29 اضافه شده (همه آنها در مجموع 249 شی Kubernetes ایجاد می کنند). به بیان ساده، ما نمی توانیم زندگی یک خوشه را بدون اضافات ببینیم.
اتوماسیون
اپراتورها به گونه ای طراحی شده اند که عملیات معمولی را که هر روز با آن مواجه می شویم، خودکار کنند. در اینجا نمونه های واقعی وجود دارد که نوشتن یک اپراتور راه حلی عالی برای آنها خواهد بود:
- یک رجیستری خصوصی (یعنی نیاز به ورود به سیستم) با تصاویر برای برنامه وجود دارد. فرض بر این است که به هر پاد راز خاصی اختصاص داده شده است که امکان احراز هویت در رجیستری را فراهم می کند. وظیفه ما اطمینان از یافتن این راز در فضای نام است تا پادها بتوانند تصاویر را دانلود کنند. برنامه های زیادی می تواند وجود داشته باشد (که هر کدام به یک راز نیاز دارند) و مفید است که خود اسرار را به طور مرتب به روز کنید ، بنابراین گزینه تنظیم اسرار با دست حذف می شود. اینجاست که اپراتور به کمک می آید: ما یک کنترلر ایجاد می کنیم که منتظر ظاهر شدن فضای نام می ماند و بر اساس این رویداد، یک راز به فضای نام اضافه می کند.
- اجازه دهید به طور پیش فرض دسترسی از پادها به اینترنت ممنوع است. اما گاهی اوقات ممکن است لازم باشد: منطقی است که مکانیسم مجوز دسترسی به سادگی کار کند، بدون نیاز به مهارت های خاص، به عنوان مثال، با وجود یک برچسب خاص در فضای نام. اپراتور چگونه می تواند در اینجا به ما کمک کند؟ یک کنترلر ایجاد می شود که منتظر می ماند تا برچسب در فضای نام ظاهر شود و خط مشی مناسب برای دسترسی به اینترنت را اضافه می کند.
- یک وضعیت مشابه: فرض کنید ما نیاز به اضافه کردن یک معین داشتیم ، اگر برچسب مشابهی داشته باشد (با نوعی پیشوند). اقدامات با اپراتور واضح است ...
در هر خوشه، وظایف روتین باید حل شوند، و به درستی این را می توان با استفاده از عملگرها انجام داد.
با جمع بندی تمام داستان های شرح داده شده، به این نتیجه رسیدیم که برای کار راحت در Kubernetes شما نیاز دارید: آ) افزونه ها را نصب کنید، ب) توسعه اپراتورها (برای حل وظایف روزمره ادمین).
چگونه برای Kubernetes بیانیه بنویسیم؟
به طور کلی، این طرح ساده است:

... اما بعد معلوم می شود که:
- Kubernetes API یک چیز نسبتاً بیاهمیت است که برای تسلط بر آن زمان زیادی میطلبد.
- برنامه نویسی نیز برای همه نیست (زبان Go به عنوان زبان ترجیحی انتخاب شد زیرا چارچوب خاصی برای آن وجود دارد - );
- وضعیت در مورد خود چارچوب نیز مشابه است.
خط پایین: برای نوشتن یک کنترلر (اپراتور) مجبور است منابع قابل توجهی را صرف کنند برای مطالعه مواد این برای اپراتورهای "بزرگ" قابل توجیه است - مثلاً برای MySQL DBMS. اما اگر مثالهایی را که در بالا توضیح داده شد (افشای اسرار، دسترسی به غلافها به اینترنت...) به خاطر بسپاریم، که ما نیز میخواهیم آن را به درستی انجام دهیم، میفهمیم که تلاش صرف شده بیشتر از نتیجهای است که اکنون نیاز داریم:

به طور کلی، یک معضل پیش میآید: منابع زیادی را صرف کنید و ابزار مناسب برای نوشتن بیانیهها را پیدا کنید، یا این کار را به روش قدیمی (اما سریع) انجام دهید. برای حل آن - برای یافتن مصالحه بین این افراط - ما پروژه خود را ایجاد کردیم: (همچنین نگاه کنید به او در هاب).
اپراتور پوسته
او چگونه کار می کند؟ این خوشه دارای یک غلاف حاوی یک باینری Go با یک عملگر پوسته است. در کنار آن مجموعه ای از قلاب ها (جزئیات بیشتر در مورد آنها - زیر را ببینید). خود اپراتور پوسته اشتراک خاصی دارد تحولات در Kubernetes API، به محض وقوع آن، قلاب های مربوطه را راه اندازی می کند.
چگونه اپراتور پوسته میداند که کدام قلابها را روی کدام رویدادها فراخوانی کند؟ این اطلاعات توسط خود هوک ها به اپراتور پوسته منتقل می شود و آنها این کار را بسیار ساده انجام می دهند.
هوک یک اسکریپت Bash یا هر فایل اجرایی دیگری است که یک آرگومان واحد را می پذیرد --config و با JSON پاسخ می دهد. دومی تعیین می کند که کدام اشیاء مورد علاقه آن هستند و به کدام رویدادها (برای این اشیا) باید پاسخ داده شود:

من پیادهسازی را بر روی اپراتور پوسته یکی از نمونههایمان - تجزیه اسرار برای دسترسی به یک رجیستری خصوصی با تصاویر برنامه، نشان خواهم داد. از دو مرحله تشکیل شده است.
تمرین: 1. یک قلاب بنویسید
اول از همه، در قلاب ما پردازش خواهیم کرد --config، نشان می دهد که ما به فضاهای نام و به طور خاص، لحظه ایجاد آنها علاقه مندیم:
[[ $1 == "--config" ]] ; then
cat << EOF
{
"onKubernetesEvent": [
{
"kind": "namespace",
"event": ["add"]
}
]
}
EOF
…منطق چگونه خواهد بود؟ همچنین بسیار ساده:
…
else
createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
kubectl create -n ${createdNamespace} -f - << EOF
Kind: Secret
...
EOF
fi اولین قدم این است که بفهمید کدام فضای نام ایجاد شده است و مرحله دوم این است که آن را با استفاده از آن ایجاد کنید kubectl راز برای این فضای نام
تمرین: 2. مونتاژ تصویر
تنها چیزی که باقی می ماند این است که قلاب ایجاد شده را به اپراتور پوسته منتقل کنید - چگونه این کار را انجام دهیم؟ خود اپراتور پوسته به عنوان یک تصویر Docker ارائه می شود، بنابراین وظیفه ما این است که قلاب را به یک فهرست خاص در این تصویر اضافه کنیم:
FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooksتنها چیزی که باقی می ماند این است که آن را جمع کنید و فشار دهید:
$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1آخرین لمس این است که تصویر را در خوشه مستقر کنید. برای انجام این کار، بیایید بنویسیم گسترش:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-operator
spec:
template:
spec:
containers:
- name: my-operator
image: registry.example.com/my-operator:v1 # 1
serviceAccountName: my-operator # 2دو نکته قابل توجه است:
- نشان دادن تصویر تازه ایجاد شده؛
- این یک جزء سیستمی است که (حداقل) به حقوقی برای اشتراک در رویدادهای Kubernetes و اختصاص اسرار به فضاهای نام نیاز دارد، بنابراین ما یک ServiceAccount (و مجموعه ای از قوانین) برای قلاب ایجاد می کنیم.
نتیجه - ما مشکل خود را حل کردیم بستگان برای Kubernetes به گونه ای که عملگر را برای تجزیه اسرار ایجاد می کند.
سایر ویژگی های اپراتور پوسته
برای محدود کردن اشیا از نوع انتخابی خود که قلاب با آنها کار می کند، آنها می توانند فیلتر شوند، انتخاب با توجه به برچسب های خاص (یا استفاده از matchExpressions):
"onKubernetesEvent": [
{
"selector": {
"matchLabels": {
"foo": "bar",
},
"matchExpressions": [
{
"key": "allow",
"operation": "In",
"values": ["wan", "warehouse"],
},
],
}
…
}
]ارائه شده است مکانیسم تکراری سازی، که - با استفاده از یک فیلتر jq - به شما امکان می دهد اشیاء JSON بزرگ را به موارد کوچک تبدیل کنید، جایی که فقط آن پارامترهایی باقی می مانند که می خواهیم برای تغییرات نظارت کنیم.
هنگامی که یک قلاب فراخوانی می شود، اپراتور پوسته آن را عبور می دهد داده های شی، که برای هر نیازی قابل استفاده است.
رویدادهایی که قلاب ها را راه اندازی می کنند به رویدادهای Kubernetes محدود نمی شوند: اپراتور پوسته از آنها پشتیبانی می کند فراخوانی قلاب ها بر حسب زمان (مشابه crontab در زمانبندی سنتی)، و همچنین یک رویداد خاص در آغاز. همه این رویدادها را می توان ترکیب کرد و به یک قلاب اختصاص داد.
و دو ویژگی دیگر از shell-operator:
- کار می کند به صورت ناهمزمان. از آنجایی که یک رویداد Kubernetes (مانند یک شی در حال ایجاد) دریافت شده است، رویدادهای دیگر (مانند همان شی که حذف می شود) ممکن است در خوشه رخ داده باشد، و هوک ها باید این را توضیح دهند. اگر قلاب با خطا اجرا شده باشد، به طور پیش فرض چنین خواهد بود به خاطر آوردن تا تکمیل موفقیت آمیز (این رفتار قابل تغییر است).
- صادر می کند معیارهای برای Prometheus، که با آن می توانید بفهمید که آیا اپراتور پوسته کار می کند یا خیر، تعداد خطاهای هر هوک و اندازه صف فعلی را بیابید.
خلاصه این قسمت از گزارش:

نصب افزونه ها
برای کار راحت با Kubernetes، نیاز به نصب افزونه ها نیز ذکر شد. من در مورد آن با استفاده از مثالی از مسیر شرکت ما به شما می گویم که چگونه آن را در حال حاضر انجام می دهیم.
ما کار با Kubernetes را با چندین کلاستر شروع کردیم که تنها مورد اضافه شده Ingress بود. لازم بود در هر خوشه به طور متفاوتی نصب شود، و ما چندین پیکربندی YAML را برای محیط های مختلف ایجاد کردیم: فلز لخت، AWS...
همانطور که خوشه های بیشتری وجود داشت، تنظیمات بیشتری وجود داشت. علاوه بر این، ما خود این پیکربندی ها را بهبود دادیم که در نتیجه کاملاً ناهمگن شدند:

برای اینکه همه چیز را مرتب کنیم، با یک اسکریپت شروع کردیم (install-ingress.sh) که نوع خوشه ای را که در آن مستقر خواهیم کرد به عنوان آرگومان در نظر گرفت، پیکربندی YAML لازم را ایجاد کرد و آن را به Kubernetes ارائه کرد.
به طور خلاصه، مسیر بعدی ما و استدلال مرتبط با آن به شرح زیر بود:
- برای کار با پیکربندی های YAML، یک موتور قالب مورد نیاز است (در مراحل اول این sed ساده است).
- با افزایش تعداد خوشه ها، نیاز به به روز رسانی خودکار ایجاد شد (اولین راه حل قرار دادن اسکریپت در Git، به روز رسانی آن با استفاده از cron و اجرای آن بود).
- یک فیلمنامه مشابه برای پرومتئوس مورد نیاز بود (
install-prometheus.shبا این حال، به دلیل این واقعیت قابل توجه است که به داده های ورودی بسیار بیشتری و همچنین ذخیره سازی آنها (به روشی خوب - متمرکز و در یک خوشه) نیاز دارد و برخی از داده ها (رمزهای عبور) می توانند به طور خودکار تولید شوند:
- خطر انتشار اشتباهی برای تعداد فزاینده ای از خوشه ها دائما در حال افزایش بود، بنابراین ما متوجه شدیم که نصب کنندگان (یعنی دو فیلمنامه: برای Ingress و Prometheus) مرحله بندی مورد نیاز بود (چندین شاخه در Git، چندین کرون برای به روز رسانی آنها در مربوطه: خوشه های پایدار یا آزمایشی).
- с
kubectl applyکار با آن دشوار شده است زیرا اظهاری نیست و فقط می تواند اشیاء ایجاد کند، اما درباره وضعیت آنها تصمیم گیری نمی کند / آنها را حذف می کند. - ما برخی از توابع را که در آن زمان اصلاً اجرا نکرده بودیم گم کرده بودیم:
- کنترل کامل بر نتیجه به روز رسانی خوشه،
- تعیین خودکار برخی از پارامترها (ورودی برای اسکریپت های نصب) بر اساس داده هایی که می توان از خوشه به دست آورد (کشف)،
- توسعه منطقی آن در قالب کشف مستمر.
ما تمام این تجربه انباشته شده را در چارچوب پروژه دیگر خود اجرا کردیم - .
اپراتور افزونه
این بر اساس اپراتور پوسته ذکر شده است. کل سیستم به شکل زیر است:
موارد زیر به قلاب های اپراتور پوسته اضافه می شود:
- ذخیره سازی ارزش ها,
- نمودار هلم,
- جزء که ذخیره مقادیر را نظارت می کند و - در صورت هر گونه تغییر - از هلم می خواهد که نمودار را دوباره رول کند.

بنابراین، ما میتوانیم به یک رویداد در Kubernetes واکنش نشان دهیم، یک قلاب راهاندازی کنیم، و از این قلاب میتوانیم تغییراتی در فضای ذخیرهسازی ایجاد کنیم، پس از آن نمودار دوباره دانلود میشود. در نمودار به دست آمده مجموعه قلاب ها و نمودار را به یک جزء جدا می کنیم که به آن می گوییم ماژول:

ماژولهای زیادی میتوانند وجود داشته باشند، و به آنها قلابهای جهانی، یک فروشگاه مقادیر جهانی و یک مؤلفه که این فروشگاه جهانی را نظارت میکند، اضافه میکنیم.
اکنون، وقتی چیزی در Kubernetes اتفاق می افتد، می توانیم با استفاده از یک هوک جهانی به آن واکنش نشان دهیم و چیزی را در فروشگاه جهانی تغییر دهیم. این تغییر متوجه میشود و باعث میشود که همه ماژولها در خوشه منتشر شوند:

این طرح تمام الزامات نصب افزونه هایی را که در بالا بیان شد برآورده می کند:
- Helm مسئول قالب بندی و بیانی بودن است.
- مشکل بهروزرسانی خودکار با استفاده از یک هوک جهانی حل شد، که طبق یک برنامه زمانی به رجیستری میرود و اگر یک تصویر سیستم جدید را در آنجا ببیند، آن را منتشر میکند (یعنی «خود»).
- تنظیمات ذخیره سازی در خوشه با استفاده از پیاده سازی انجام می شود ConfigMap، که حاوی داده های اولیه برای ذخیره سازی ها است (در هنگام راه اندازی آنها در حافظه ها بارگذاری می شوند).
- مشکلات مربوط به تولید رمز عبور، کشف و کشف مداوم با استفاده از هوک حل شد.
- مرحلهبندی به لطف تگهایی که داکر خارج از جعبه از آنها پشتیبانی میکند، به دست میآید.
- نتیجه با استفاده از معیارهایی که ما می توانیم وضعیت را درک کنیم، نظارت می شود.
کل این سیستم به صورت یک باینری در Go پیاده سازی می شود که به آن addon-operator می گویند. این باعث می شود نمودار ساده تر به نظر برسد:

جزء اصلی در این نمودار مجموعه ای از ماژول ها است (در زیر با رنگ خاکستری مشخص شده است). حالا می توانیم با کمی تلاش یک ماژول برای افزونه مورد نیاز بنویسیم و مطمئن باشیم که در هر خوشه نصب می شود، به روز می شود و به رویدادهای مورد نیاز آن در کلاستر پاسخ می دهد.
"فلانت" استفاده می کند در بیش از 70 خوشه Kubernetes. وضعیت فعلی - نسخه آلفا. اکنون ما در حال آماده سازی اسناد برای انتشار نسخه بتا هستیم، اما در حال حاضر در مخزن ، بر اساس آن می توانید افزونه خود را ایجاد کنید.
ماژول های اپراتور افزونه را از کجا می توانم دریافت کنم؟ انتشار کتابخانه ما مرحله بعدی برای ما است؛ ما قصد داریم این کار را در تابستان انجام دهیم.
فیلم ها و اسلایدها
ویدئویی از اجرا (50 دقیقه):

ارائه گزارش:
PS
گزارش های دیگر در وبلاگ ما:
- «"؛ (دیمیتری استولیاروف؛ 8 نوامبر 2018 در HighLoad++);
- «"؛ (دیمیتری استولیاروف؛ 28 مه 2018 در RootConf);
- «"؛ (دیمیتری استولیاروف؛ 7 نوامبر 2017 در HighLoad++);
- «"؛ (دیمیتری استولیاروف؛ 6 ژوئن 2017 در RootConf).
همچنین ممکن است به انتشارات زیر علاقه مند باشید:
- «'.
منبع: www.habr.com



