Gnìomhaiche Kubernetes ann am Python às aonais frèaman agus SDK

Gnìomhaiche Kubernetes ann am Python às aonais frèaman agus SDK

Tha monopoly aig Go an-dràsta air na cànanan prògramaidh a thaghas daoine airson aithrisean a sgrìobhadh airson Kubernetes. Tha adhbharan reusanta ann airson seo, leithid:

  1. Tha frèam cumhachdach ann airson luchd-obrachaidh a leasachadh ann an Go - SDK gnìomhaiche.
  2. Tha tagraidhean a tha ag atharrachadh geama mar Docker agus Kubernetes sgrìobhte ann an Go. Tha sgrìobhadh do ghnìomhaiche ann an Go a’ ciallachadh a bhith a’ bruidhinn an aon chànan ris an eag-shiostam.
  3. Coileanadh àrd de thagraidhean Go agus innealan sìmplidh airson a bhith ag obair le concurrency a-mach às a ’bhogsa.

NB: Co-dhiù, mar a sgrìobhas tu an aithris agad fhèin ann an Go, sinn air a mhìneachadh mar-thà ann an aon de na h-eadar-theangachaidhean againn le ùghdaran cèin.

Ach dè ma tha thu air do chasg bho bhith ag ionnsachadh Rach le dìth ùine no, dìreach cuir, togradh? Tha an artaigil a’ toirt seachad eisimpleir air mar as urrainn dhut aithris mhath a sgrìobhadh a’ cleachdadh aon de na cànanan as mòr-chòrdte a tha fios aig cha mhòr a h-uile innleadair DevOps - Python.

Coinnich: Copier - gnìomhaiche leth-bhreac!

Mar eisimpleir, smaoinich air a bhith a’ leasachadh aithris shìmplidh a chaidh a dhealbhadh gus ConfigMap a chopaigeadh an dàrna cuid nuair a nochdas àite ainm ùr no nuair a dh’ atharraicheas aon de dhà bhuidheann: ConfigMap agus Secret. Bho shealladh practaigeach, faodaidh an gnìomhaiche a bhith feumail airson ùrachadh mòr a dhèanamh air rèiteachaidhean tagraidh (le bhith ag ùrachadh an ConfigMap) no airson dàta dìomhair ùrachadh - mar eisimpleir, iuchraichean airson a bhith ag obair le Clàr Docker (nuair a chuireas tu Dìomhaireachd ris an àite ainm).

Agus mar sin, dè bu chòir a bhith aig gnìomhaiche math:

  1. Thathas a’ dèanamh eadar-obrachadh leis a’ ghnìomhaiche a’ cleachdadh Mìneachadh Goireasan Custom (ris an canar CRD an-seo).
  2. Faodar an gnìomhaiche a rèiteachadh. Gus seo a dhèanamh, cleachdaidh sinn brataichean loidhne-àithne agus caochladairean àrainneachd.
  3. Tha togail clàr Docker container agus Helm air a dhealbhadh gus an urrainn do luchd-cleachdaidh gu furasta (gu litearra le aon àithne) an gnìomhaiche a chuir a-steach don bhuidheann Kubernetes aca.

CRD

Gus am bi fios aig a 'ghnìomhaiche dè na goireasan a bu chòir a bhith a' coimhead agus càite an coimhead e, feumaidh sinn riaghailt a shuidheachadh dha. Bidh gach riaghailt air a riochdachadh mar aon nì CRD. Dè na raointean a bu chòir a bhith aig an CRD seo?

  1. Seòrsa stòrais, a choimheadas sinn (ConfigMap or Secret).
  2. Liosta de dh'àiteachan ainmean, anns am bu chòir na goireasan a bhith suidhichte.
  3. Roghnaiche, leis am bi sinn a’ lorg ghoireasan san àrainn-ainm.

Bheir sinn cunntas air an 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

Agus cruthaichidh sinn e sa bhad riaghailt shìmplidh - gus rannsachadh a dhèanamh anns an àrainn ainm leis an ainm default uile ConfigMap le bileagan mar copyrator: "true":

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

Deiseil! A-nis feumaidh sinn dòigh air choireigin fiosrachadh fhaighinn mun riaghailt againn. Leig leam glèidheadh ​​​​sa bhad nach sgrìobh sinn iarrtasan gu frithealaiche API brabhsair sinn fhìn. Gus seo a dhèanamh, cleachdaidh sinn leabharlann Python deiseil kubernetes-client:

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')}

Mar thoradh air a’ chòd seo a ruith, gheibh sinn na leanas:

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

Sgoinneil: chaidh againn air riaghailt fhaighinn airson a’ ghnìomhaiche. Agus as cudromaiche, rinn sinn rud ris an canar an dòigh Kubernetes.

Caochladairean àrainneachd no brataichean? Gabhaidh sinn a h-uile càil!

Gluaisidh sinn air adhart gu rèiteachadh a 'phrìomh ghnìomhaiche. Tha dà dhòigh bunaiteach ann airson tagraidhean a rèiteachadh:

  1. cleachd roghainnean loidhne-àithne;
  2. cleachdadh caochladairean àrainneachd.

Leigidh roghainnean loidhne-àithne leat roghainnean a leughadh ann an dòigh nas sùbailte, le taic seòrsa dàta agus dearbhadh. Tha modal aig leabharlann àbhaisteach Python argparser, a chleachdas sinn. Tha mion-fhiosrachadh agus eisimpleirean de na comasan aige rim faighinn ann an sgrìobhainnean oifigeil.

Airson ar cùise, seo mar a bhiodh eisimpleir de bhith a’ stèidheachadh brataichean loidhne-àithne leughaidh coltach:

   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()

Air an làimh eile, a ’cleachdadh caochladairean àrainneachd ann an Kubernetes, is urrainn dhut gu furasta fiosrachadh seirbheis mun pod a ghluasad taobh a-staigh an t-soithich. Mar eisimpleir, gheibh sinn fiosrachadh mun ainm-àite anns a bheil am pod a’ ruith leis an togail a leanas:

env:
- name: NAMESPACE
  valueFrom:
     fieldRef:
         fieldPath: metadata.namespace 

Logic gnìomhaiche

Gus tuigse fhaighinn air mar a nì sinn sgaradh air dòighean airson a bhith ag obair le ConfigMap agus Secret, cleachdaidh sinn mapaichean sònraichte. An uairsin tuigidh sinn dè na dòighean a dh’ fheumas sinn gus an nì a lorg agus a chruthachadh:

LIST_TYPES_MAP = {
    'configmap': 'list_namespaced_config_map',
    'secret': 'list_namespaced_secret',
}

CREATE_TYPES_MAP = {
    'configmap': 'create_namespaced_config_map',
    'secret': 'create_namespaced_secret',
}

An ath rud, feumaidh tu tachartasan fhaighinn bhon t-seirbheisiche API. Feuch an cuir sinn an gnìomh e mar a leanas:

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)

Às deidh dhuinn an tachartas fhaighinn, gluaisidh sinn air adhart gu prìomh loidsig a ghiullachd:

# Типы событий, на которые будем реагировать
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)

Tha am prìomh loidsig deiseil! A-nis feumaidh sinn seo uile a phacadh ann an aon phasgan Python. Bidh sinn ag ullachadh am faidhle setup.py, sgrìobh meta-fhiosrachadh mun phròiseact an sin:

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: Tha an dreach fhèin aig an neach-dèiligidh kubernetes airson Python. Gheibhear tuilleadh fiosrachaidh mu cho-chòrdalachd eadar dreachan teachdaiche agus dreachan Kubernetes ann an matrics co-chòrdalachd.

A-nis tha am pròiseact againn a’ coimhead mar seo:

copyrator
├── copyrator
│   ├── cli.py # Логика работы с командной строкой
│   ├── constant.py # Константы, которые мы приводили выше
│   ├── load_crd.py # Логика загрузки CRD
│   └── operator.py # Основная логика работы оператора
└── setup.py # Оформление пакета

Docker agus Helm

Bidh an Dockerfile gu math sìmplidh: gabh an ìomhaigh python-alpach bunaiteach agus stàlaich ar pasgan. Nach cuir sinn dheth an optimization aige gu amannan nas fheàrr:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Tha cleachdadh airson a 'ghnìomhaiche cuideachd gu math sìmplidh:

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

Mu dheireadh, feumaidh tu àite iomchaidh a chruthachadh don ghnìomhaiche leis na còraichean riatanach:

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 }}

An toradh

Sin mar a bha e comasach dhuinn ar gnìomhaiche fhèin a thogail airson Kubernetes ann am Python, gun eagal, tàmailt no ionnsachadh Go. Gu dearbh, tha àite ann fhathast airson fàs: san àm ri teachd bidh e comasach dha grunn riaghailtean a phròiseasadh, obrachadh ann an grunn snàithleanan, sùil a chumail gu neo-eisimeileach air atharrachaidhean anns na CRDan aige ...

Gus sùil nas mionaidiche a thoirt dhut air a’ chòd, tha sinn air a chuir a-steach ionad-tasgaidh poblach. Ma tha thu ag iarraidh eisimpleirean de ghnìomhaichean nas cunnartaiche air an cur an gnìomh a’ cleachdadh Python, faodaidh tu d’ aire a thionndadh gu dà ghnìomhaiche airson mongodb a chleachdadh (первый и an dàrna fear).

PS Agus ma tha thu ro leisg a bhith a’ dèiligeadh ri tachartasan Kubernetes no gu bheil thu dìreach nas cleachdte ri bhith a’ cleachdadh Bash, tha ar co-obraichean air fuasgladh deiseil ullachadh san fhoirm slige-ghnìomhaiche (Sinn ainmeachadh e sa Ghiblean).

Pps

Leugh cuideachd air ar blog:

Source: www.habr.com

Cuir beachd ann