I-Kubernetes Operator kwiPython ngaphandle kwesakhelo kunye ne-SDK

I-Kubernetes Operator kwiPython ngaphandle kwesakhelo kunye ne-SDK

I-Go ngoku inokuzimela kwiilwimi zenkqubo abantu abakhetha ukubhala iinkcazo zeKubernetes. Kukho izizathu ezingundoqo zoku, ezifana:

  1. Kukho isakhelo esinamandla sokuphuhlisa abaqhubi kwi-Go - I-SDK yoMsebenzisi.
  2. Izicelo zokutshintsha umdlalo ezifana neDocker kunye neKubernetes zibhalwe kwiGo. Ukubhala umsebenzisi wakho kwi-Go kuthetha ukuthetha ulwimi olufanayo ne-ecosystem.
  3. Ukusebenza okuphezulu kwezicelo zeGo kunye nezixhobo ezilula zokusebenza kunye ne-concurrency ngaphandle kwebhokisi.

NB: Ngendlela, ubhala njani ingxelo yakho kwi-Go, thina sele ichaziwe kwenye yeenguqulelo zethu ngababhali bamanye amazwe.

Kodwa kuthekani ukuba uthintelwa ekufundeni Hamba ngenxa yokungabi naxesha okanye, ukubeka nje, inkuthazo? Eli nqaku libonelela ngomzekelo wendlela onokuthi ubhale ngayo ingxelo elungileyo usebenzisa enye yezona lwimi zidumileyo phantse zonke iinjineli zeDevOps ziyazazi - Python.

Dibana: Umkhupheli - ikopi yomsebenzisi!

Njengomzekelo, cinga ngokuphuhlisa ingxelo elula eyilelwe ukukopa iConfigMap xa kuvela isithuba esitsha samagama okanye xa elinye lamaqumrhu amabini litshintsha: ConfigMap kunye neMfihlo. Ukusuka kwimbono ebonakalayo, umqhubi unokuba luncedo kuhlaziyo oluninzi lwezicwangciso zesicelo (ngokuhlaziya i-ConfigMap) okanye ukuhlaziya idatha eyimfihlo - umzekelo, izitshixo zokusebenza kunye ne-Docker Registry (xa ukongeza iMfihlo kwindawo yegama).

Kwaye ke, kufuneka abe nomsebenzi olungileyo:

  1. Ukusebenzisana nomsebenzisi kuqhutywa kusetyenziswa Custom Resource Iinkcazelo (emva koku kubhekiselwa kuyo njengeCRD).
  2. Umsebenzisi unokuqwalaselwa. Ukwenza oku, siya kusebenzisa iiflegi zomgca womyalelo kunye noguquguquko lwemekobume.
  3. Ukwakhiwa kwesikhongozeli seDocker kunye netshathi yeHelm yenzelwe ukuba abasebenzisi babe lula (ngokoqobo ngomyalelo omnye) ukufaka umqhubi kwiqela labo leKubernetes.

I-CRD

Ukuze umqhubi azi ukuba zeziphi izixhobo anokuzijonga kwaye ajonge phi, kufuneka simmisele umgaqo. Umgaqo ngamnye uya kumelwa njengento enye yeCRD. Ngawaphi amabakala ekufanele abe nawo le CRD?

  1. Uhlobo lovimba, esiya kuyijonga (ConfigMap okanye iMfihlo).
  2. Uluhlu lwezithuba zamagama, apho izibonelelo kufuneka zibekwe khona.
  3. Ukhethi, apho siya kukhangela izixhobo kwindawo yamagama.

Makhe sichaze iCRD:

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

Kwaye siya kuyidala kwangoko Umgaqo olula β€” ukukhangela kwisithuba segama ngegama default yonke ConfigMap eneeleyibheli ezifana copyrator: "true":

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

Ulungile! Ngoku kufuneka sifumane ulwazi malunga nomthetho wethu. Makhe ndenze ugcino ngoko nangoko ukuba asizukubhala izicelo kwi-cluster API Server ngokwethu. Ukwenza oku, siya kusebenzisa ilayibrari yePython esele yenziwe kubernetes-umthengi:

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

Njengesiphumo sokusebenzisa le khowudi, sifumana oku kulandelayo:

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

Khulu: sikwazile ukufumana umthetho kumqhubi. Kwaye okona kubaluleke kakhulu, senze into ebizwa ngokuba yindlela yeKubernetes.

Iinguqu zendalo okanye iiflegi? Sithatha yonke into!

Masiqhubele phambili kuqwalaselo lomsebenzisi oluphambili. Kukho iindlela ezimbini ezisisiseko zokuqwalasela usetyenziso:

  1. sebenzisa iinketho zelayini yomyalelo;
  2. sebenzisa iinguqu zemo engqongileyo.

Iinketho zomgca womyalelo zikuvumela ukuba ufunde izicwangciso ngokulula ngakumbi, kunye nohlobo lwenkxaso yedatha kunye nokuqinisekiswa. Ilayibrari eqhelekileyo yePython inemodyuli argparser, esiza kuyisebenzisa. Iinkcukacha kunye nemizekelo yezakhono zayo ziyafumaneka kwi amaxwebhu asemthethweni.

Kwimeko yethu, nantsi umzekelo wokuseta iiflegi zomgca womyalelo wokufunda okuya kujongeka ngathi:

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

Ngakolunye uhlangothi, usebenzisa izinto eziguquguqukayo zokusingqongileyo kwi-Kubernetes, unokudlulisa ngokulula ulwazi lwenkonzo malunga ne-pod ngaphakathi kwesitya. Umzekelo, sinokufumana ulwazi malunga nesithuba samagama apho i-pod isebenza khona ngolu hlobo lulandelayo:

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

Ingqiqo yomsebenzisi

Ukuqonda indlela yokwahlula iindlela zokusebenza ngeConfigMap kunye neMfihlo, siya kusebenzisa iimephu ezikhethekileyo. Emva koko sinokuqonda ukuba zeziphi iindlela esizifunayo ukulandelela kunye nokwenza into:

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

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

Okulandelayo, kufuneka ufumane iziganeko kwiseva ye-API. Masiyiphumeze ngolu hlobo lulandelayo:

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)

Emva kokufumana umsitho, siqhubela phambili kwingcinga ephambili yokuwuqhuba:

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

Ingqiqo ephambili ilungile! Ngoku kufuneka sipakishe yonke le nto kwiphakheji enye yePython. Silungisa ifayile setup.py, bhala ulwazi lwemeta malunga neprojekthi apho:

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: Umxhasi we-kubernetes wePython unoguqulelo lwayo. Ulwazi oluninzi malunga nokuhambelana phakathi kweenguqulelo zabathengi kunye neenguqulelo zeKubernetes zinokufumaneka kwi imatrics ukuhambelana.

Ngoku iprojekthi yethu ibonakala ngolu hlobo:

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

Docker kunye neHelm

I-Dockerfile iya kuba lula ngokumangalisayo: thatha umfanekiso wesiseko se-python-alpine kwaye ufake iphakheji yethu. Masikuhlehlise ukwenziwa kwayo kude kube ngamaxesha angcono:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Ukusasazwa komqhubi nako kulula kakhulu:

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

Ekugqibeleni, kufuneka wenze indima efanelekileyo kumqhubi onamalungelo ayimfuneko:

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

Isiphumo

Yiloo ndlela, ngaphandle koloyiko, ungcikivo, okanye ukufunda ukuya, sakwazi ukuzakhela eyethu i-Kubernetes kwiPython. Ngokuqinisekileyo, isenayo indawo yokukhula: kwixesha elizayo iya kukwazi ukucubungula imithetho emininzi, isebenze kwimicu emininzi, ibeke iliso ngokuzimeleyo utshintsho kwiiCRD zayo ...

Ukukunika ujongo olusondeleyo kwikhowudi, siyifakile indawo yokugcina uluntu. Ukuba ufuna imizekelo yabasebenzisi abanobuzaza ngakumbi abaphunyezwe kusetyenziswa iPython, ungajika ingqalelo yakho kubaqhubi ababini bokuhambisa imongodb (eyokuqala ΠΈ yesibini).

I-PS Kwaye ukuba uyonqena kakhulu ukujongana neziganeko ze-Kubernetes okanye uqhele kakhulu ukusebenzisa i-Bash, oogxa bethu balungiselele isisombululo esenziwe ngokufanelekileyo kwifom. iqokobhe-umqhubi (Thina kwaziswa ngoAprili).

Iipps

Funda nakwibhlog yethu:

umthombo: www.habr.com

Yongeza izimvo