Kaiwhakahaere Kubernetes i te Python kahore he anga me te SDK

Kaiwhakahaere Kubernetes i te Python kahore he anga me te SDK

I tenei wa kei a Go te mana whakahaere mo nga reo hootaka e whiriwhiria e te tangata ki te tuhi korero mo Kubernetes. He take whaitake mo tenei, penei:

  1. He anga kaha mo te whakawhanake i nga kaiwhakahaere i Go - Kaiwhakahaere SDK.
  2. Ko nga tono huri keemu penei i a Docker me Kubernetes kua tuhia ki te Haere. Ko te tuhi i to kaiwhakahaere i roto i te Haere ko te korero i te reo kotahi me te puunaha rauwiringa kaiao.
  3. Mahinga teitei o nga tono Haere me nga taputapu ngawari mo te mahi me te whakakotahitanga i waho o te pouaka.

NB: Ma te ara, me pehea te tuhi i to ake korero ki roto Haere, matou kua oti te korero i tetahi o a matou whakamaoritanga na nga kaituhi ke.

Engari he aha mena ka aukatihia koe ki te ako Haere na te kore o te wa, me te korero noa, te hihiri? Ko te tuhinga he tauira mo te tuhi i tetahi korero pai ma te whakamahi i tetahi o nga reo rongonui e tino mohio ana nga miihini DevOps katoa - nānati.

Tutaki: Kaituhi - kaiwhakahaere kape!

Hei tauira, whakaarohia te whakawhanake i tetahi korero ngawari i hangaia hei kape i te ConfigMap ka puta mai he mokowāingoa hou, ka huri ranei tetahi o nga hinonga e rua: ConfigMap me Secret. Mai i te tirohanga whaitake, ka whai hua te kaiwhakahaere mo te whakahou i te nuinga o nga whirihoranga tono (ma te whakahou i te ConfigMap) mo te whakahou ranei i nga raraunga ngaro - hei tauira, nga taviri mo te mahi tahi me te Docker Registry (i te taapiri i te mea ngaro ki te waahi ingoa).

Na he aha te pai o te kaiwhakahaere:

  1. Ko te taunekeneke me te kaiwhakahaere ka mahia ma te whakamahi Whakaritenga Rauemi Ritenga (i muri nei ka kiia ko CRD).
  2. Ka taea te whirihora i te kaiwhakahaere. Hei mahi i tenei, ka whakamahia e matou nga haki raina whakahau me nga taurangi taiao.
  3. Ko te hanga o te ipu Docker me te tūtohi Helm i hangaia kia ngawari ai nga kaiwhakamahi (me te tono kotahi) te whakauru i te kaiwhakahaere ki roto i a raatau roopu Kubernetes.

CRD

Kia mohio ai te kai-whakahaere he aha nga rauemi hei rapu me te waahi hei titiro, me whakatakoto he ture mona. Ka whakaatuhia ia ture hei ahanoa CRD kotahi. He aha nga mara ma tenei CRD?

  1. Momo rauemi, ka rapua e matou (ConfigMap or Secret).
  2. Te rarangi ingoa mokowā, kei reira nga rauemi e tika ana kia noho.
  3. Kaiwhiri, ma reira ka rapua e matou nga rauemi kei te waahi ingoa.

Me whakaahua te 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

A ka hanga tonu e matou ture ngawari — ki te rapu i roto i te mokowāingoa me te ingoa default ConfigMap katoa me nga tapanga penei copyrator: "true":

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

Kua rite! Inaianei me whiwhi korero mo ta tatou ture. Tukua ahau kia rahui i tenei wa tonu kia kore matou e tuhi tono ki te Pumau API roopu. Hei mahi i tenei, ka whakamahia e matou he whare pukapuka Python kua rite kubernetes-kiritaki:

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

Ko te hua o te whakahaere i tenei waehere, ka whiwhi tatou i nga mea e whai ake nei:

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

Nui: i taea e matou te tiki ture mo te kaiwhakahaere. Ko te mea nui, i mahia e matou te mea e kiia nei ko te huarahi Kubernetes.

Taurangi taiao, haki ranei? Ka tangohia e matou nga mea katoa!

Me neke atu ki te whirihoranga kaiwhakahaere matua. E rua nga huarahi matua ki te whirihora i nga tono:

  1. whakamahi kōwhiringa raina whakahau;
  2. whakamahi taurangi taiao.

Ko nga whiringa raina whakahau ka taea e koe te panui i nga tautuhinga kia ngawari ake, me te tautoko momo raraunga me te whakamana. He kōwae te whare pukapuka paerewa a Python argparser, ka whakamahia e matou. Kei te waatea nga korero me nga tauira o ona kaha tuhinga whaimana.

Mo ta matou keehi, koinei te tauira o te whakatuu panui i nga haki raina whakahau:

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

I tetahi atu taha, ma te whakamahi i nga taurangi taiao i Kubernetes, ka taea e koe te whakawhiti i nga korero ratonga mo te pene i roto i te ipu. Hei tauira, ka taea e tatou te tiki korero mo te mokowāingoa e rere ana te pākākano me te hanga e whai ake nei:

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

Te arorau kaiwhakahaere

Kia mohio koe me pehea te wehe i nga tikanga mo te mahi me te ConfigMap me te Secret, ka whakamahi matou i nga mapi motuhake. Na ka mohio tatou he aha nga tikanga hei whai me te hanga i te ahanoa:

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

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

I muri mai, me whiwhi koe i nga huihuinga mai i te tūmau API. Me whakatinana e whai ake nei:

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)

I muri i te whiwhinga i te huihuinga, ka neke atu ki te kaupapa matua mo te tukatuka:

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

Kua reri te arorau matua! Inaianei me kii tatou i enei mea katoa ki tetahi kete Python. Ka whakareri matou i te konae setup.py, tuhia nga korero meta mo te kaupapa ki reira:

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: Kei te kiritaki kubernetes mo Python tana ake putanga. Ka kitea etahi atu korero mo te hototahitanga i waenga i nga putanga kiritaki me nga putanga Kubernetes matrices hototahi.

Inaianei he penei te ahua o ta maatau kaupapa:

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

Docker me Helm

He maamaa noa te Dockerfile: tango i te ahua python-alpine turanga ka whakauru i ta maatau kete. Me hikitia tana arotautanga mo nga wa pai ake:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

He tino ngawari te whakatakotoranga mo te kaiwhakahaere:

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

Hei whakamutunga, me hanga e koe he mahi tika mo te kaiwhakahaere me nga mana tika:

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

Ko te hua

Koia, karekau he mataku, he tawai, he ako ranei i a Haere, ka taea e matou te hanga i a matou ake kaiwhakahaere mo Kubernetes i roto i te Python. Ko te tikanga, he waahi tonu ki te tipu: i te wa kei te heke mai ka taea e ia te whakahaere i nga ture maha, te mahi i roto i nga miro maha, te aroturuki takitahi i nga huringa o ana CRD...

Kia ata titiro koe ki te waehere, kua whakauruhia e matou putunga tūmatanui. Mena kei te hiahia koe ki nga tauira o nga kaiwhakahaere tino nui ka whakatinanahia ma te whakamahi i te Python, ka taea e koe te huri i to aro ki nga kaiwhakahaere e rua mo te tuku mongodb (первый и te tuarua).

PS A, ki te mea he mangere koe ki te whakahaere i nga huihuinga Kubernetes, kua waia noa atu ranei koe ki te whakamahi i te Bash, kua whakaritea e o maatau hoa he otinga kua rite ki te ahua. anga-kaiwhakahaere (Ko matou i panuihia i te Paenga-whāwhā).

PPS

Pānuihia hoki i runga i ta maatau blog:

Source: will.com

Tāpiri i te kōrero