Kubernetes Operator ku Python opanda ma framework ndi SDK

Kubernetes Operator ku Python opanda ma framework ndi SDK

Go pano ali ndi ufulu wolamulira zilankhulo zomwe anthu amasankha kulemba mawu a Kubernetes. Pali zifukwa zomveka za izi, monga:

  1. Pali chikhazikitso champhamvu chopangira opangira mu Go - Othandizira SDK.
  2. Mapulogalamu osintha masewera monga Docker ndi Kubernetes amalembedwa mu Go. Kulemba opareshoni yanu mu Go kumatanthauza kulankhula chinenero chomwecho ndi chilengedwe.
  3. Kuchita kwakukulu kwa mapulogalamu a Go ndi zida zosavuta zogwirira ntchito ndi concurrency kunja kwa bokosi.

NB: Mwa njira, momwe mungalembere mawu anu mu Go, ife zafotokozedwa kale m'modzi mwa zomasulira zathu ndi olemba akunja.

Koma bwanji ngati mwalepheretsedwa kuphunzira Pitani chifukwa chosowa nthawi kapena, mwachidule, zolimbikitsa? Nkhaniyi ikupereka chitsanzo cha momwe mungalembe mawu abwino pogwiritsa ntchito zilankhulo zodziwika bwino zomwe pafupifupi mainjiniya onse a DevOps amadziwa - Python.

Kumanani ndi: Copier - copy operator!

Mwachitsanzo, lingalirani kupanga chiganizo chosavuta chopangidwa kuti mukopere ConfigMap mwina malo atsopano awonekera kapena chimodzi mwazinthu ziwiri zisintha: ConfigMap ndi Chinsinsi. Kuchokera pakuwona kothandiza, wogwiritsa ntchitoyo akhoza kukhala wothandiza pakusintha kochulukira kwa kasinthidwe ka pulogalamu (posintha ConfigMap) kapena kukonzanso zinsinsi - mwachitsanzo, makiyi ogwirira ntchito ndi Docker Registry (powonjezera Chinsinsi ku malo a mayina).

Ndipo kotero, zomwe wogwiritsa ntchito wabwino ayenera kukhala nazo:

  1. Kulumikizana ndi opareshoni kumachitika pogwiritsa ntchito Tanthauzo la Custom Resource (pamenepa amatchedwa CRD).
  2. Wothandizira akhoza kukhazikitsidwa. Kuti tichite izi, tidzagwiritsa ntchito mbendera za mzere wa malamulo ndi zosintha zachilengedwe.
  3. Kumanga kwa chidebe cha Docker ndi tchati cha Helm kudapangidwa kuti ogwiritsa ntchito azitha (kwenikweni ndi lamulo limodzi) kukhazikitsa woyendetsa mu gulu lawo la Kubernetes.

CRD

Kuti wogwiritsa ntchitoyo adziwe zomwe angayang'ane komanso komwe angayang'ane, tiyenera kumuikira lamulo. Lamulo lililonse lidzayimiridwa ngati chinthu chimodzi cha CRD. Kodi CRD iyi iyenera kukhala ndi magawo otani?

  1. Mtundu wothandizira, zomwe tidzayang'ana (ConfigMap kapena Chinsinsi).
  2. Mndandanda wa mayina, momwe zinthu ziyenera kukhalira.
  3. Chisankho, momwe tidzasaka zothandizira mu malo a mayina.

Tiyeni tifotokoze za 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

Ndipo tidzapanga nthawi yomweyo lamulo losavuta β€” kusaka mu malo a mayina ndi dzina default onse ConfigMap okhala ndi zilembo ngati copyrator: "true":

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

Okonzeka! Tsopano tiyenera mwanjira inayake kudziwa zambiri zaulamuliro wathu. Ndiroleni ndisungitseko nthawi yomweyo kuti tisalembe zopempha ku gulu la API Server tokha. Kuti tichite izi, tidzagwiritsa ntchito laibulale ya Python yopangidwa kale 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')}

Chifukwa chogwiritsa ntchito code iyi, timapeza zotsatirazi:

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

Zabwino: takwanitsa kupeza lamulo kwa wogwiritsa ntchito. Ndipo chofunika kwambiri, tinachita zomwe zimatchedwa Kubernetes njira.

Zosintha zachilengedwe kapena mbendera? Timatenga chilichonse!

Tiyeni tipitirire ku kasinthidwe ka woyendetsa wamkulu. Pali njira ziwiri zoyambira kukhazikitsa mapulogalamu:

  1. gwiritsani ntchito zosankha za mzere wamalamulo;
  2. gwiritsani ntchito zosintha zachilengedwe.

Zosankha za mzere wamalamulo zimakulolani kuti muwerenge zosintha mosavuta, mothandizidwa ndi mtundu wa data ndikutsimikizira. Laibulale yokhazikika ya Python ili ndi gawo argparser, zomwe tidzagwiritse ntchito. Tsatanetsatane ndi zitsanzo za kuthekera kwake zilipo zolemba zovomerezeka.

Kwa ife, izi ndi zomwe chitsanzo chokhazikitsa mizere yowerengera chimawoneka ngati:

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

Kumbali ina, pogwiritsa ntchito zosintha zachilengedwe ku Kubernetes, mutha kusamutsa zambiri zautumiki za pod mkati mwa chidebecho. Mwachitsanzo, titha kudziwa zambiri za malo omwe pod ikugwira ntchito ndi mapangidwe awa:

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

Malingaliro oyendetsa

Kuti timvetsetse momwe tingalekanitsire njira zogwirira ntchito ndi ConfigMap ndi Chinsinsi, tidzagwiritsa ntchito mamapu apadera. Kenako titha kumvetsetsa njira zomwe tingafunikire kutsatira ndikupanga chinthucho:

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

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

Kenako, muyenera kulandira zochitika kuchokera ku seva ya API. Tiyeni tiyigwiritse ntchito motere:

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)

Titalandira chochitikacho, timapita ku lingaliro lalikulu lokonzekera:

# Π’ΠΈΠΏΡ‹ событий, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄Π΅ΠΌ Ρ€Π΅Π°Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
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)

Mfundo yaikulu ndi yokonzeka! Tsopano tiyenera kuyika zonsezi mu phukusi limodzi la Python. Timakonza fayilo setup.py, lembani zambiri zokhudza polojekitiyi:

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: Makasitomala a kubernetes a Python ali ndi mawonekedwe ake. Zambiri zokhudzana ndi kuyanjana pakati pamitundu yamakasitomala ndi mitundu ya Kubernetes zitha kupezeka mkati matrices ogwirizana.

Tsopano polojekiti yathu ikuwoneka motere:

copyrator
β”œβ”€β”€ copyrator
β”‚   β”œβ”€β”€ cli.py # Π›ΠΎΠ³ΠΈΠΊΠ° Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкой
β”‚   β”œβ”€β”€ constant.py # ΠšΠΎΠ½ΡΡ‚Π°Π½Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠ»ΠΈ Π²Ρ‹ΡˆΠ΅
β”‚   β”œβ”€β”€ load_crd.py # Π›ΠΎΠ³ΠΈΠΊΠ° Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ CRD
β”‚   └── operator.py # Основная Π»ΠΎΠ³ΠΈΠΊΠ° Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π°
└── setup.py # ΠžΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π°

Docker ndi Helm

Dockerfile idzakhala yosavuta modabwitsa: tengani chithunzi choyambira cha python-alpine ndikuyika phukusi lathu. Tiyeni tiyimitsa kukhathamiritsa kwake mpaka nthawi zabwinoko:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Kutumiza kwa opareshoni ndikosavuta kwambiri:

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

Pomaliza, muyenera kupanga gawo loyenera kwa wogwiritsa ntchito yemwe ali ndi ufulu wofunikira:

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

Zotsatira

Umu ndi momwe, popanda mantha, chitonzo, kapena kuphunzira Go, tinatha kupanga athu opangira Kubernetes ku Python. Inde, ikadali ndi malo oti ikule: m'tsogolomu idzatha kukonza malamulo angapo, kugwira ntchito mu ulusi wambiri, kuyang'anira pawokha kusintha kwa ma CRD ake ...

Kuti tikuwonetseni bwino pama code, tayiyikamo posungira anthu. Ngati mukufuna zitsanzo za ogwiritsa ntchito kwambiri omwe akugwiritsidwa ntchito pogwiritsa ntchito Python, mutha kuyang'ananso kwa ogwiritsa ntchito awiri kuti atumize mongodb (ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈ wachiwiri).

PS Ndipo ngati ndinu waulesi kwambiri kuti muthane ndi zochitika za Kubernetes kapena mumangozolowera kugwiritsa ntchito Bash, anzathu akonza yankho lokonzekera mwamawonekedwe. chipolopolo-woyendetsa (Ife adalengeza mu April).

Pps

Werenganinso pa blog yathu:

Source: www.habr.com

Kuwonjezera ndemanga