Oibreoir Kubernetes i Python gan creataí agus SDK

Oibreoir Kubernetes i Python gan creataí agus SDK

Tá monaplacht ag Go faoi láthair ar na teangacha ríomhchlárúcháin a roghnaíonn daoine ráitis a scríobh do Kubernetes. Tá cúiseanna oibiachtúla ann leis seo, mar:

  1. Tá creat cumhachtach ann chun oibreoirí a fhorbairt in Go - Tiománaí SDK.
  2. Tá feidhmchláir a athraíonn cluichí ar nós Docker agus Kubernetes scríofa in Go. Is éard atá i gceist le scríobh d'oibreoir in Go ná an teanga chéanna a labhairt leis an éiceachóras.
  3. Ardfheidhmíocht na n-iarratas Go agus uirlisí simplí le haghaidh oibriú le concurrency amach as an mbosca.

NB: Dála an scéil, conas do ráiteas féin a scríobh i Téigh, muid cur síos air cheana i gceann dár n-aistriúcháin ó údair iasachta.

Ach cad a tharlóidh má tá cosc ​​ort ó fhoghlaim Téigh ag easpa ama nó, go simplí, spreagadh? Soláthraíonn an t-alt sampla de conas is féidir leat ráiteas maith a scríobh ag baint úsáide as ceann de na teangacha is coitianta atá ar eolas ag beagnach gach innealtóir DevOps - Python.

Buail le: Copier - oibreoir cóip!

Mar shampla, smaoinigh ar ráiteas simplí a fhorbairt atá deartha chun ConfigMap a chóipeáil nuair a thagann ainmspás nua nó nuair a athraíonn ceann amháin den dá eintiteas: ConfigMap agus Secret. Ó thaobh praiticiúil de, is féidir leis an oibreoir a bheith úsáideach chun cumraíochtaí feidhmchláir a nuashonrú go mórchóir (trí an ConfigMap a nuashonrú) nó chun sonraí rúnda a nuashonrú - mar shampla, eochracha le haghaidh oibriú le Clárlann Docker (agus Rún á chur leis an ainmspás).

Mar sin, cad ba cheart a bheith ag oibreoir maith:

  1. Déantar idirghníomhaíocht leis an oibreoir trí úsáid a bhaint as Sainmhínithe Acmhainní Saincheaptha (dá ngairtear CRD anseo feasta).
  2. Is féidir an t-oibreoir a chumrú. Chun seo a dhéanamh, úsáidfimid bratacha na n-orduithe agus athróga timpeallachta.
  3. Tá tógáil an choimeádáin Docker agus cairt Helm deartha ionas gur féidir le húsáideoirí go héasca (go litriúil le hordú amháin) an t-oibreoir a shuiteáil ina mbraisle Kubernetes.

CRD

Ionas go mbeidh a fhios ag an oibreoir cad iad na hacmhainní atá le lorg agus cá háit le breathnú, ní mór dúinn riail a leagan síos dó. Léireofar gach riail mar rud amháin CRD. Cad iad na réimsí ar cheart a bheith ag an TRC seo?

  1. Cineál acmhainne, a bheidh á lorg againn (ConfigMap nó Rúnda).
  2. Liosta spásanna ainmneacha, inar cheart na hacmhainní a lonnú.
  3. Roghnóir, trína gcuardóidh muid acmhainní san ainmspás.

Déanaimis cur síos ar 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 cruthóimid láithreach é riail shimplí — chun cuardach a dhéanamh san ainmspás leis an ainm default gach ConfigMap le lipéid mar copyrator: "true":

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

Réidh! Anois caithfimid eolas a fháil ar ár riail. Lig dom áirithint a dhéanamh láithreach nach scríobhfaimid iarratais chuig an Freastalaí API braisle sinn féin. Chun seo a dhéanamh, úsáidfimid leabharlann Python réidh kubernetes-cliant:

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 ar an gcód seo a rith, faigheann muid na rudaí seo a leanas:

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

Go hiontach: d'éirigh linn riail a fháil don oibreoir. Agus is tábhachtaí fós, rinneamar rud ar a dtugtar bealach Kubernetes.

Athróga comhshaoil ​​nó bratacha? Glacann muid gach rud!

A ligean ar bogadh ar aghaidh go dtí an chumraíocht príomh-oibreoir. Tá dhá chur chuige bhunúsacha ann maidir le feidhmchláir a chumrú:

  1. úsáid roghanna na n-orduithe;
  2. athróga timpeallachta a úsáid.

Ligeann roghanna na n-orduithe duit socruithe a léamh ar bhealach níos solúbtha, le tacaíocht agus bailíochtú cineál sonraí. Tá modúl i leabharlann caighdeánach Python argparser, a úsáidfimid. Tá sonraí agus samplaí dá chumais ar fáil i doiciméadú oifigiúil.

Maidir lenár gcás, is é seo an chuma a bheadh ​​ar shampla de bhratacha na n-orduithe léitheoireachta a bhunú:

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

Ar an láimh eile, ag baint úsáide as athróga timpeallachta i Kubernetes, is féidir leat faisnéis seirbhíse a aistriú go héasca faoin pod taobh istigh den choimeádán. Mar shampla, is féidir linn faisnéis a fháil faoin ainmspás ina bhfuil an pod ag rith leis an tógáil seo a leanas:

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

Loighic oibreoir

Chun tuiscint a fháil ar na modhanna oibre le ConfigMap agus Rúnda a scaradh, úsáidfimid léarscáileanna speisialta. Ansin is féidir linn a thuiscint cad iad na modhanna a theastaíonn uainn chun an réad a rianú agus a chruthú:

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

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

Ansin, ní mór duit imeachtaí a fháil ón bhfreastalaí API. Déanaimis é a chur i bhfeidhm mar seo 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)

Tar éis dúinn an t-imeacht a fháil, bogaimid ar aghaidh chuig an bpríomh-loighic chun é a phróiseáil:

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

Tá an príomh-loighic réidh! Anois ní mór dúinn é seo go léir a phacáistiú i bpacáiste Python amháin. Ullmhaímid an comhad setup.py, scríobh meitea-eolas faoin tionscadal ansin:

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: Tá a leagan féin ag cliant kubernetes Python. Is féidir tuilleadh faisnéise a fháil faoi chomhoiriúnacht idir leaganacha cliant agus leaganacha Kubernetes i maitrísí comhoiriúnachta.

Anois tá cuma mar seo ar ár dtionscadal:

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

Docker agus Helm

Beidh an Dockerfile thar a bheith simplí: tóg an buníomhá python-alpach agus suiteáil ár bpacáiste. Cuirimis a bharrfheabhsú siar go dtí am níos fearr:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Tá imscaradh don oibreoir an-simplí freisin:

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

Ar deireadh, ní mór duit ról cuí a chruthú don oibreoir leis na cearta riachtanacha:

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

Iomlán na

Sin é an chaoi, gan eagla, gan údar náire, ná ag foghlaim Go, bhíomar in ann ár n-oibreoir féin a thógáil do Kubernetes i Python. Ar ndóigh, tá spás ann fós le fás: sa todhchaí beidh sé in ann rialacha iomadúla a phróiseáil, oibriú i il-snáitheanna, monatóireacht neamhspleách a dhéanamh ar athruithe ar a CRDanna ...

Chun breathnú níos dlúithe a thabhairt duit ar an gcód, chuireamar isteach é stór poiblí. Más mian leat samplaí d'oibreoirí níos tromchúisí a chur i bhfeidhm ag baint úsáide as Python, is féidir leat d'aird a dhíriú ar dhá oibreoir chun mongodb a imscaradh (chéad и an dara).

PS Agus má tá tú ró-leisciúil déileáil le himeachtaí Kubernetes nó má tá tú i dtaithí ar Bash a úsáid, d'ullmhaigh ár gcomhghleacaithe réiteach réidh san fhoirm sliogán-oibreoir (Táimid D'fhógair é i mí Aibreáin).

PSP

Léigh freisin ar ár mblag:

Foinse: will.com

Add a comment