රාමු සහ SDK නොමැතිව පයිතන් හි Kubernetes ක්රියාකරු

රාමු සහ SDK නොමැතිව පයිතන් හි Kubernetes ක්රියාකරු

මිනිසුන් Kubernetes සඳහා ප්‍රකාශ ලිවීමට තෝරා ගන්නා ක්‍රමලේඛන භාෂා පිළිබඳ Go ට දැනට ඒකාධිකාරයක් ඇත. මේ සඳහා වෛෂයික හේතු තිබේ, වැනි:

  1. Go හි ක්‍රියාකරුවන් සංවර්ධනය කිරීම සඳහා ප්‍රබල රාමුවක් ඇත - ක්රියාකරු SDK.
  2. Docker සහ Kubernetes වැනි ක්‍රීඩාව වෙනස් කරන යෙදුම් Go හි ලියා ඇත. Go හි ඔබේ ක්‍රියාකරු ලිවීම යන්නෙන් අදහස් වන්නේ පරිසර පද්ධතිය සමඟ එකම භාෂාව කතා කිරීමයි.
  3. Go යෙදුම්වල ඉහළ කාර්ය සාධනය සහ කොටුවෙන් පිටත සමගාමීව වැඩ කිරීම සඳහා සරල මෙවලම්.

NB: මාර්ගය වන විට, Go හි ඔබේම ප්රකාශය ලියන්නේ කෙසේද, අපි දැනටමත් විස්තර කර ඇත විදේශීය කතුවරුන් විසින් අපගේ පරිවර්තන වලින් එකක.

නමුත් කාලය නොමැතිකම හෝ, සරලව කිවහොත්, අභිප්‍රේරණය නිසා ඔබට Go ඉගෙනීමෙන් වළක්වන්නේ නම් කුමක් කළ යුතුද? සෑම DevOps ඉංජිනේරුවෙකුම පාහේ දන්නා වඩාත් ජනප්‍රිය භාෂාවක් භාවිතයෙන් ඔබට හොඳ ප්‍රකාශයක් ලිවිය හැකි ආකාරය පිළිබඳ උදාහරණයක් ලිපිය සපයයි - Python මීට උදාහරණ.

හමුවන්න: පිටපත් කරන්නා - පිටපත් කරන්නා!

උදාහරණයක් ලෙස, නව නාම අවකාශයක් දිස්වන විට හෝ ආයතන දෙකෙන් එකක් වෙනස් වන විට ConfigMap පිටපත් කිරීමට නිර්මාණය කර ඇති සරල ප්‍රකාශයක් සංවර්ධනය කිරීම සලකා බලන්න: ConfigMap සහ Secret. ප්‍රායෝගික දෘෂ්ටි කෝණයකින්, යෙදුම් වින්‍යාසයන් තොග වශයෙන් යාවත්කාලීන කිරීම සඳහා (ConfigMap යාවත්කාලීන කිරීමෙන්) හෝ රහස් දත්ත යාවත්කාලීන කිරීම සඳහා ක්‍රියාකරුට ප්‍රයෝජනවත් විය හැකිය - උදාහරණයක් ලෙස, ඩොකර් රෙජිස්ට්‍රිය සමඟ වැඩ කිරීම සඳහා යතුරු (නාම අවකාශයට රහස එකතු කිරීමේදී).

එසේ නම්, හොඳ මෙහෙයුම්කරුවෙකුට තිබිය යුතු දේ:

  1. ක්රියාකරු සමඟ අන්තර් ක්රියා කිරීම සිදු කරනු ලැබේ අභිරුචි සම්පත් අර්ථ දැක්වීම් (මෙතැන් සිට CRD ලෙස හැඳින්වේ).
  2. ක්රියාකරු වින්යාසගත කළ හැක. මෙය සිදු කිරීම සඳහා, අපි විධාන රේඛා ධජ සහ පරිසර විචල්යයන් භාවිතා කරමු.
  3. ඩොකර් බහාලුම් සහ හෙල්ම් ප්‍රස්ථාරය නිර්මාණය කර ඇත්තේ පරිශීලකයින්ට පහසුවෙන් (වචනාර්ථයෙන් එක් විධානයකින්) ක්‍රියාකරු ඔවුන්ගේ කුබර්නෙටස් පොකුරට ස්ථාපනය කළ හැකි වන පරිදි ය.

සී.ආර්.ඩී.

ක්‍රියාකරුට සෙවිය යුතු සම්පත් මොනවාද සහ සොයන්නේ කොතැනදැයි දැන ගැනීමට, අපි ඔහු සඳහා රීතියක් සැකසිය යුතුය. සෑම රීතියක්ම තනි CRD වස්තුවක් ලෙස නිරූපණය කෙරේ. මෙම CRD සතුව තිබිය යුතු ක්ෂේත්‍ර මොනවාද?

  1. සම්පත් වර්ගය, අපි සොයන්නේ (ConfigMap හෝ Secret).
  2. නාම අවකාශයන් ලැයිස්තුව, සම්පත් පිහිටා තිබිය යුතු ය.
  3. තේරීම් කාරකය, අපි නාම අවකාශයේ සම්පත් සොයන්නෙමු.

අපි 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 වැනි ලේබල් සහිත සියලුම වින්‍යාස සිතියම copyrator: "true":

apiVersion: flant.com/v1
kind: CopyratorRule
metadata:
  name: main-rule
  labels:
    module: copyrator
ruleType: configmap
selector:
  copyrator: "true"
namespace: default

සූදානම්! දැන් අපි කොහොම හරි අපේ පාලනය ගැන තොරතුරු ගන්න ඕන. අප විසින්ම පොකුරු 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')}

මෙම කේතය ක්‍රියාත්මක කිරීමේ ප්‍රතිඵලයක් ලෙස, අපට පහත දේ ලැබේ:

{'ruleType': 'configmap', 'selector': {'copyrator': 'true'}, 'namespace': ['default']}

නියමයි: අපි ක්රියාකරු සඳහා රීතියක් ලබා ගැනීමට සමත් විය. වැදගත්ම දෙය නම්, අපි කුබර්නෙටේස් මාර්ගය ලෙස හඳුන්වන දේ කළා.

පාරිසරික විචල්යයන් හෝ කොඩි? අපි හැම දෙයක්ම ගන්නවා!

අපි ප්රධාන ක්රියාකරු වින්යාසය වෙත යමු. යෙදුම් වින්‍යාස කිරීම සඳහා මූලික ප්‍රවේශයන් දෙකක් තිබේ:

  1. විධාන රේඛා විකල්ප භාවිතා කරන්න;
  2. පරිසර විචල්‍යයන් භාවිතා කරන්න.

විධාන රේඛා විකල්පයන් ඔබට දත්ත ආකාරයේ සහය සහ වලංගුකරණය සමඟින් වඩාත් නම්‍යශීලීව සිටුවම් කියවීමට ඉඩ සලසයි. 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 හි පාරිසරික විචල්‍යයන් භාවිතා කිරීමෙන්, ඔබට පහසුවෙන් බහාලුම් තුළ ඇති පොඩ් පිළිබඳ සේවා තොරතුරු මාරු කළ හැකිය. උදාහරණයක් ලෙස, පහත සඳහන් ඉදිකිරීම් සමඟ පොඩ් එක ක්‍රියාත්මක වන නාම අවකාශය පිළිබඳ තොරතුරු අපට ලබා ගත හැක:

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 අනුවාද අතර ගැළපුම පිළිබඳ වැඩිදුර තොරතුරු සොයා ගත හැක අනුකූලතා matrices.

දැන් අපගේ ව්‍යාපෘතිය මේ ආකාරයෙන් පෙනේ:

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 වෙනුවෙන් අපේම operator එකක් හදන්න පුළුවන් වුනා. ඇත්ත වශයෙන්ම, එය තවමත් වර්ධනය වීමට ඉඩ ඇත: අනාගතයේ දී එය බහු නීති සැකසීමට, බහු නූල්වල වැඩ කිරීමට, ස්වාධීනව එහි CRD වල වෙනස්කම් නිරීක්ෂණය කිරීමට හැකි වනු ඇත ...

ඔබට කේතය දෙස සමීපව බැලීමට, අපි එය ඇතුළත් කළෙමු පොදු ගබඩාව. Python භාවිතයෙන් ක්‍රියාත්මක කරන ලද වඩාත් බරපතල ක්‍රියාකරුවන්ගේ උදාහරණ ඔබට අවශ්‍ය නම්, ඔබට mongodb යෙදවීම සඳහා ක්‍රියාකරුවන් දෙදෙනෙකු වෙත ඔබේ අවධානය යොමු කළ හැක (පළමුවැන්න и දෙවැන්නයි).

PS සහ ඔබ Kubernetes සිදුවීම් සමඟ කටයුතු කිරීමට කම්මැලි නම් හෝ ඔබ සරලවම Bash භාවිතා කිරීමට හුරුපුරුදු නම්, අපගේ සගයන් විසින් පෝරමයේ සූදානම් කළ විසඳුමක් සකස් කර ඇත. shell-operator (අප නිවේදනය කරන ලදි එය අප්රේල් මාසයේදී).

පීපීඑස්

අපගේ බ්ලොග් අඩවියේ ද කියවන්න:

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න