Go нь одоогоор Kubernetes-д зориулж мэдэгдэл бичихээр сонгосон програмчлалын хэл дээр монополь эрхтэй. Үүний объектив шалтгаанууд байдаг, тухайлбал:
- Go-д операторуудыг хөгжүүлэх хүчирхэг тогтолцоо бий.
SDK оператор . - Docker, Kubernetes гэх мэт тоглоомыг өөрчилдөг программуудыг Go дээр бичсэн. Go-д оператороо бичнэ гэдэг нь экосистемтэй нэг хэлээр ярьдаг гэсэн үг.
- Go програмуудын өндөр гүйцэтгэл, хайрцагнаас гадуур зэрэгцэн ажиллах энгийн хэрэгслүүд.
NB: Дашрамд хэлэхэд Go-д өөрийн мэдэгдлийг хэрхэн бичих вэ, бид
Гэхдээ цаг дутмаг, энгийнээр хэлбэл урам зоригоос болж та Go сурахад саад болж байвал яах вэ? Энэ нийтлэлд бараг бүх DevOps инженерүүдийн мэддэг хамгийн алдартай хэлнүүдийг ашиглан хэрхэн сайн мэдэгдэл бичих жишээг өгсөн болно. Python.
Уулзах: Хувилагч - хуулбарлагч!
Жишээ болгон, шинэ нэрийн орон зай гарч ирэх эсвэл ConfigMap ба Нууц гэсэн хоёр объектын аль нэг нь өөрчлөгдөх үед ConfigMap-ийг хуулах энгийн хэллэг боловсруулах талаар бодож үзээрэй. Практик талаас нь авч үзвэл оператор нь програмын тохиргоог бөөнөөр нь шинэчлэх (ConfigMap-ийг шинэчлэх замаар) эсвэл нууц өгөгдлийг шинэчлэхэд тустай байж болно - жишээлбэл, Docker Бүртгэлтэй ажиллах түлхүүрүүд (нэрийн зайд Нууцыг нэмэх үед).
Тэгэхээр сайн оператор ямар байх ёстой:
- Оператортой харилцах нь ашиглан хийгддэг
Тусгай нөөцийн тодорхойлолтууд (цаашид CRD гэх). - Операторыг тохируулах боломжтой. Үүнийг хийхийн тулд бид командын мөрийн туг болон орчны хувьсагчдыг ашиглана.
- Docker контейнер болон Helm диаграмыг бүтээх нь хэрэглэгчдэд хялбар (шууд утгаараа нэг тушаалаар) Кубернетес кластерт операторыг суулгах боломжтой байхаар бүтээгдсэн.
CRD
Оператор ямар нөөц хайх, хаанаас хайхаа мэдэхийн тулд бид түүнд дүрэм тогтоох хэрэгтэй. Дүрэм бүрийг нэг CRD объект хэлбэрээр харуулах болно. Энэ CRD ямар талбартай байх ёстой вэ?
- Нөөцийн төрөл, бид үүнийг хайх болно (ConfigMap эсвэл Нууц).
- Нэрийн орон зайн жагсаалт, аль нь нөөцийг байрлуулах ёстой.
- Сонгогч, үүгээр бид нэрийн талбараас нөөц хайх болно.
CRD-ийг тайлбарлая:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: copyrator.flant.com
spec:
group: flant.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: copyrators
singular: copyrator
kind: CopyratorRule
shortNames:
- copyr
validation:
openAPIV3Schema:
type: object
properties:
ruleType:
type: string
namespaces:
type: array
items:
type: string
selector:
type: string
Мөн бид үүнийг шууд бүтээх болно энгийн дүрэм — нэрийн талбарт нэрээр хайх default
гэх мэт шошготой бүх ConfigMap copyrator: "true"
:
apiVersion: flant.com/v1
kind: CopyratorRule
metadata:
name: main-rule
labels:
module: copyrator
ruleType: configmap
selector:
copyrator: "true"
namespace: default
Бэлэн! Одоо бид ямар нэгэн байдлаар дүрмийнхээ талаар мэдээлэл авах хэрэгтэй. Бид өөрсдөө кластерийн API серверт хүсэлт бичихгүй гэдгээ шууд захиалгаа өгье. Үүний тулд бид бэлэн Python номын санг ашиглах болно
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')}
Энэ кодыг ажиллуулсны үр дүнд бид дараахь зүйлийг авна.
{'ruleType': 'configmap', 'selector': {'copyrator': 'true'}, 'namespace': ['default']}
Гайхалтай: бид операторын дүрмийг авч чадсан. Хамгийн гол нь бид Кубернетес арга гэж нэрлэгддэг зүйлийг хийсэн.
Орчны хувьсагч эсвэл туг? Бид бүгдийг нь авдаг!
Үндсэн операторын тохиргоо руу шилжье. Програмыг тохируулах хоёр үндсэн арга байдаг:
- тушаалын мөрийн сонголтыг ашиглах;
- орчны хувьсагчдыг ашиглах.
Тушаалын мөрийн сонголтууд нь өгөгдлийн төрлийн дэмжлэг, баталгаажуулалтын тусламжтайгаар тохиргоог илүү уян хатан унших боломжийг танд олгоно. Python-ийн стандарт номын сан нь модультай argparser
, бид үүнийг ашиглах болно. Түүний чадварын талаархи дэлгэрэнгүй мэдээлэл, жишээг эндээс авах боломжтой
Манай тохиолдолд унших командын тугуудыг тохируулах жишээ ийм байна:
parser = ArgumentParser(
description='Copyrator - copy operator.',
prog='copyrator'
)
parser.add_argument(
'--namespace',
type=str,
default=getenv('NAMESPACE', 'default'),
help='Operator Namespace'
)
parser.add_argument(
'--rule-name',
type=str,
default=getenv('RULE_NAME', 'main-rule'),
help='CRD Name'
)
args = parser.parse_args()
Нөгөөтэйгүүр, Kubernetes дахь орчны хувьсагчдыг ашигласнаар та савны доторх pod-ийн талаарх үйлчилгээний мэдээллийг хялбархан дамжуулах боломжтой. Жишээ нь, бид дараах бүтэцтэй pod ажиллаж байгаа нэрийн талбарын талаар мэдээлэл авах боломжтой.
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
Операторын логик
ConfigMap болон Secret-тэй ажиллах аргуудыг хэрхэн салгах талаар ойлгохын тулд бид тусгай газрын зураг ашиглах болно. Дараа нь бид объектыг хянах, бүтээхэд ямар аргууд хэрэгтэйг ойлгох болно:
LIST_TYPES_MAP = {
'configmap': 'list_namespaced_config_map',
'secret': 'list_namespaced_secret',
}
CREATE_TYPES_MAP = {
'configmap': 'create_namespaced_config_map',
'secret': 'create_namespaced_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 нь гайхалтай энгийн байх болно: үндсэн python-alpine зургийг аваад манай багцыг суулгаарай. Түүний оновчлолыг илүү сайн цаг хүртэл хойшлуулъя:
FROM python:3.7.3-alpine3.9
ADD . /app
RUN pip3 install /app
ENTRYPOINT ["copyrator"]
Операторыг байрлуулах нь бас маш энгийн:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}
spec:
selector:
matchLabels:
name: {{ .Chart.Name }}
template:
metadata:
labels:
name: {{ .Chart.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: privaterepo.yourcompany.com/copyrator:latest
imagePullPolicy: Always
args: ["--rule-type", "main-rule"]
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
serviceAccountName: {{ .Chart.Name }}-acc
Эцэст нь та шаардлагатай эрх бүхий операторын зохих үүргийг бий болгох хэрэгтэй.
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Chart.Name }}-acc
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: {{ .Chart.Name }}
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["secrets", "configmaps"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ .Chart.Name }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ .Chart.Name }}
subjects:
- kind: ServiceAccount
name: {{ .Chart.Name }}
Үр дүн
Ингэснээр бид айдас, зэмлэл, Go-г сурахгүйгээр Python дээр Kubernetes-д зориулж өөрийн операторыг бүтээх боломжтой болсон. Мэдээжийн хэрэг, энэ нь өсөх зайтай хэвээр байна: ирээдүйд энэ нь олон дүрмийг боловсруулах, олон хэлхээнд ажиллах, CRD-ийн өөрчлөлтийг бие даан хянах боломжтой болно ...
Кодыг илүү нарийвчлан үзэхийн тулд бид үүнийг орууллаа
Жич Хэрэв та Kubernetes-ийн үйл явдлуудтай харьцахаас залхуурсан эсвэл Bash-ийг ашиглахад илүү дассан бол манай хамт олон бэлэн шийдлийг хэлбэрээр бэлтгэсэн болно.
PPS
Мөн манай блог дээрээс уншина уу:
- «
Kubernetes кластер бэлтгэх нь хялбар бөгөөд тохиромжтой юу? Нэмэлт операторыг зарлаж байна "; - «
Бүрхүүлийн операторыг танилцуулж байна: Kubernetes-д оператор үүсгэх нь илүү хялбар болсон "; - «
Kubernetes-ийг өргөжүүлж, нөхөж байна (хяналт болон видео тайлан) "; - «
Голанг дахь Kubernetes-д оператор бичиж байна "; - «
Kubernetes-д зориулсан операторууд: төлөвтэй програмуудыг хэрхэн ажиллуулах вэ ".
Эх сурвалж: www.habr.com