Pythonдогу Kubernetes оператору алкаксыз жана SDKсыз
Go учурда адамдар Kubernetes үчүн билдирүү жазууну тандаган программалоо тилдеринде монополияга ээ. Мунун объективдүү себептери бар, мисалы:
Go операторлорун өнүктүрүү үчүн күчтүү негиз бар - Оператор SDK.
Docker жана Kubernetes сыяктуу оюнду өзгөртүүчү колдонмолор Go'до жазылган. Go'до операторуңузду жазуу экосистема менен бир тилде сүйлөөнү билдирет.
Go тиркемелеринин жогорку өндүрүмдүүлүгү жана кутудан тышкары параллелдүүлүк менен иштөө үчүн жөнөкөй куралдар.
NB: Баса, Go өз арызын кантип жазуу керек, биз мурунтан эле сүрөттөлгөн чет элдик авторлордун котормолору-буздун биринде.
Бирок убакыттын жетишсиздигинен же жөн эле айтканда, мотивациядан улам барып үйрөнүүгө тоскоол болсочу? Макалада дээрлик ар бир DevOps инженери билген эң популярдуу тилдердин бирин колдонуп кантип жакшы билдирүү жазууга болорун мисал келтирет - Python.
Таанышуу: Көчүрүүчү - көчүрүү оператору!
Мисал катары, жаңы аттар мейкиндиги пайда болгондо же эки объекттин бири өзгөргөндө ConfigMapты көчүрүү үчүн арналган жөнөкөй билдирүүнү иштеп чыгууну карап көрөлү: ConfigMap жана Secret. Практикалык көз караштан алганда, оператор тиркемелердин конфигурацияларын жапырт жаңыртуу үчүн (ConfigMapты жаңыртуу менен) же жашыруун маалыматтарды жаңыртуу үчүн пайдалуу болушу мүмкүн - мисалы, Докер реестри менен иштөө үчүн ачкычтар (ат мейкиндигине Сырды кошууда).
Оператор конфигурацияланышы мүмкүн. Бул үчүн, биз буйрук сабынын желектерин жана чөйрө өзгөрмөлөрүн колдонобуз.
Docker контейнеринин жана Helm диаграммасынын түзүлүшү колдонуучулар операторду Kubernetes кластерине оңой (түз мааниде бир буйрук менен) орното алышы үчүн иштелип чыккан.
CRD
Оператор кандай ресурстарды жана кайда издөө керектигин билиши үчүн, биз ага эреже коюшубуз керек. Ар бир эреже бир CRD объектиси катары көрсөтүлөт. Бул CRD кандай талааларга ээ болушу керек?
Ресурстун түрү, биз издей турган (ConfigMap же Secret).
Ат мейкиндиктеринин тизмеси, анда ресурстарды жайгаштыруу керек.
Селектор, анын жардамы менен биз аттар мейкиндигинде ресурстарды издейбиз.
Даяр! Эми кандайдыр бир жол менен биздин эреже тууралуу маалымат алышыбыз керек. Мага дароо ээлеп коюуга уруксат этиңиз, биз кластердик API серверине өзүбүздөн сурам жазбайбыз. Бул үчүн биз даяр Python китепканасын колдонобуз kubernetes-кардар:
import kubernetes
from contextlib import suppress
CRD_GROUP = 'flant.com'
CRD_VERSION = 'v1'
CRD_PLURAL = 'copyrators'
def load_crd(namespace, name):
client = kubernetes.client.ApiClient()
custom_api = kubernetes.client.CustomObjectsApi(client)
with suppress(kubernetes.client.api_client.ApiException):
crd = custom_api.get_namespaced_custom_object(
CRD_GROUP,
CRD_VERSION,
namespace,
CRD_PLURAL,
name,
)
return {x: crd[x] for x in ('ruleType', 'selector', 'namespace')}
Бул кодду иштетүүнүн натыйжасында биз төмөнкүлөрдү алабыз:
Мыкты: биз оператор үчүн эреже алууга жетиштик. Эң негизгиси, биз Kubernetes жолу деп аталган нерсени жасадык.
Айлана-чөйрөнүн өзгөрмөлөрү же желектерби? Биз баарын алабыз!
Келгиле, оператордун негизги конфигурациясына өтөбүз. Тиркемелерди конфигурациялоонун эки негизги ыкмасы бар:
буйрук сабынын параметрлерин колдонуу;
чөйрө өзгөрмөлөрүн колдонуу.
Буйрук сабынын параметрлери маалымат түрүн колдоо жана текшерүү менен орнотууларды ийкемдүү окууга мүмкүндүк берет. Python стандарттык китепканасында модулу бар argparser, биз колдонобуз. Анын мүмкүнчүлүктөрүнүн майда-чүйдөсүнө чейин жана мисалдар бар расмий документтер.
Биздин учурда, окуу буйрук сабынын желектерин орнотуунун мисалы ушундай болот:
Башка жагынан алганда, Kubernetes'теги чөйрө өзгөрмөлөрүн колдонуу менен, сиз контейнердин ичиндеги подкаст жөнүндө кызматтык маалыматты оңой өткөрүп бере аласыз. Мисалы, биз подкаст төмөнкү конструкция менен иштеп жаткан аттар мейкиндиги жөнүндө маалымат ала алабыз:
ConfigMap жана Secret менен иштөө ыкмаларын кантип бөлүүнү түшүнүү үчүн биз атайын карталарды колдонобуз. Андан кийин объектти түзүү үчүн кандай ыкмалар керек экенин түшүнө алабыз:
Андан кийин, сиз API серверинен окуяларды алышыңыз керек. Аны төмөнкүдөй ишке ашыралы:
def handle(specs):
kubernetes.config.load_incluster_config()
v1 = kubernetes.client.CoreV1Api()
# Получаем метод для слежения за объектами
method = getattr(v1, LIST_TYPES_MAP[specs['ruleType']])
func = partial(method, specs['namespace'])
w = kubernetes.watch.Watch()
for event in w.stream(func, _request_timeout=60):
handle_event(v1, specs, event)
Окуяны алгандан кийин, биз аны иштетүүнүн негизги логикасына өтөбүз:
# Типы событий, на которые будем реагировать
ALLOWED_EVENT_TYPES = {'ADDED', 'UPDATED'}
def handle_event(v1, specs, event):
if event['type'] not in ALLOWED_EVENT_TYPES:
return
object_ = event['object']
labels = object_['metadata'].get('labels', {})
# Ищем совпадения по selector'у
for key, value in specs['selector'].items():
if labels.get(key) != value:
return
# Получаем активные namespace'ы
namespaces = map(
lambda x: x.metadata.name,
filter(
lambda x: x.status.phase == 'Active',
v1.list_namespace().items
)
)
for namespace in namespaces:
# Очищаем метаданные, устанавливаем namespace
object_['metadata'] = {
'labels': object_['metadata']['labels'],
'namespace': namespace,
'name': object_['metadata']['name'],
}
# Вызываем метод создания/обновления объекта
methodcaller(
CREATE_TYPES_MAP[specs['ruleType']],
namespace,
object_
)(v1)
Негизги логика даяр! Эми мунун баарын бир Python пакетине топтошубуз керек. Файлды даярдайбыз setup.py, ал жерде долбоор жөнүндө мета маалымат жаз:
from sys import version_info
from setuptools import find_packages, setup
if version_info[:2] < (3, 5):
raise RuntimeError(
'Unsupported python version %s.' % '.'.join(version_info)
)
_NAME = 'copyrator'
setup(
name=_NAME,
version='0.0.1',
packages=find_packages(),
classifiers=[
'Development Status :: 3 - Alpha',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
author='Flant',
author_email='[email protected]',
include_package_data=True,
install_requires=[
'kubernetes==9.0.0',
],
entry_points={
'console_scripts': [
'{0} = {0}.cli:main'.format(_NAME),
]
}
)
NB: Python үчүн kubernetes кардарынын өзүнүн версиясы бар. Кардар версиялары менен Kubernetes версияларынын ортосундагы шайкештик жөнүндө көбүрөөк маалымат бул жерден тапса болот шайкештик матрицалары.
Эми биздин долбоор мындай көрүнөт:
copyrator
├── copyrator
│ ├── cli.py # Логика работы с командной строкой
│ ├── constant.py # Константы, которые мы приводили выше
│ ├── load_crd.py # Логика загрузки CRD
│ └── operator.py # Основная логика работы оператора
└── setup.py # Оформление пакета
Докер жана Хелм
Dockerfile укмуштуудай жөнөкөй болот: базалык питон-альп сүрөтүн алып, биздин пакетти орнотуңуз. Келгиле, аны оптималдаштырууну жакшыраак убакытка жылдыралы:
FROM python:3.7.3-alpine3.9
ADD . /app
RUN pip3 install /app
ENTRYPOINT ["copyrator"]
Ошентип, коркпой, жемелебестен же Go үйрөнбөй туруп, биз Pythonдо Кубернетес үчүн өз операторубузду түзө алдык. Албетте, анын дагы деле өсө турган жери бар: келечекте ал бир нече эрежелерди иштетип, бир нече жипте иштей алат, CRDдеги өзгөрүүлөрдү өз алдынча көзөмөлдөй алат...
Кодду жакшыраак көрүү үчүн, биз аны киргиздик коомдук репозиторий. Эгер сиз Python аркылуу ишке ашырылган олуттуураак операторлордун мисалдарын кааласаңыз, анда mongodb (дипломатиясы) үчүн эки операторго көңүл бурсаңыз болот.первый и экинчи).
PS Эгерде сиз Kubernetes окуялары менен күрөшүүгө жалкоо болсоңуз же сиз жөн гана Bashты колдонууга көнүп калган болсоңуз, анда биздин кесиптештер формада даяр чечим даярдашкан. шел-оператор (Биз жарыялады апрелде).