Kubernetes Operator ee Python oo aan lahayn qaab-dhismeedka iyo SDK

Kubernetes Operator ee Python oo aan lahayn qaab-dhismeedka iyo SDK

Go hadda waxa ay kali ku tahay luuqadaha barnaamijyada ay dadku doortaan in ay qoraal u qoraan Kubernetes. Waxaa jira sababo ujeedo ah oo tan, sida:

  1. Waxaa jira qaab-dhismeed awood leh oo loogu talagalay horumarinta hawlwadeennada Go - Hawlwadeenka SDK.
  2. Codsiyada beddela ciyaarta sida Docker iyo Kubernetes waxay ku qoran yihiin Go. Ku qoritaanka hawl wadeenkaaga Go waxay la macno tahay inaad isla luqad kula hadasho nidaamka deegaanka.
  3. Waxqabadka sare ee codsiyada Go iyo aaladaha fudud ee la shaqaynta isdhaafsiga ee sanduuqa.

NBBy the way, sida loo qoro bayaan adiga kuu gaar ah in Go, annagu hore u tilmaamay mid ka mid ah turjumaadayada ay qoreen qorayaasha ajnabiga ah.

Laakiin ka waran haddii lagaa ilaaliyo inaad wax barato Go waqti la'aan ama, si fudud loo dhigo, dhiirigelin? Maqaalku wuxuu bixiyaa tusaale sida aad u qori karto bayaan wanaagsan adoo isticmaalaya mid ka mid ah luqadaha ugu caansan ee ku dhawaad ​​​​injineer kasta oo DevOps ah uu yaqaan - Python.

La kulan: Copier - koobi wadayaasha!

Tusaale ahaan, ka fiirso horumarinta qoraal fudud oo loogu talagalay in lagu koobiyo ConfigMap marka magac cusubi soo baxo ama marka labada hay'adood midkood isbeddelo: ConfigMap iyo Secret. Marka laga eego aragtida dhabta ah, hawlwadeenku wuxuu faa'iido u yeelan karaa cusboonaysiinta guud ee habaynta codsiyada (adigoo cusboonaysiinaya ConfigMap) ama cusboonaysiinta xogta sirta ah - tusaale ahaan, furayaasha la shaqaynta Diiwaanka Docker (marka lagu daro siraha magaca).

Sidaas waxa uu leeyahay hawlwadeenka wanaagsan:

  1. Isdhexgalka lala yeesho hawlwadeenka waxaa lagu fuliyaa iyadoo la isticmaalayo Qeexitaannada Kheyraadka Gaarka ah (kadibna loo yaqaan CRD).
  2. Hawlwadeenka waa la habayn karaa. Si tan loo sameeyo, waxaan isticmaali doonaa calanka khadka taliska iyo doorsoomayaasha deegaanka.
  3. Dhismaha weelka Docker iyo jaantuska Helm waxaa loo qaabeeyey si ay isticmaalayaashu si fudud (macno ahaan hal amar wata) ugu rakibaan hawlwadeenka kutladooda Kubernetes.

CRD

Si uu hawlwadeenku u ogaado agabka uu raadinayo iyo halka uu eegayo, waxa aanu u baahanahay in aanu u dejino xeer. Xeer kastaa waxa loo metelayaa hal shay oo CRD ah. Goobahee waa in CRD-dan ay lahaataa?

  1. Nooca kheyraadka, kaas oo aan raadin doono (ConfigMap ama Secret).
  2. Liiska magacyada meelaha, kaas oo ay tahay in kheyraadku ku jiro.
  3. Selector, kaas oo aan ku raadin doonno kheyraadka magaca goobta.

Aynu qeexno 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

Oo waxaan isla markiiba u abuuri doonaa xeer fudud - si aad u raadiso goobta magaca oo leh magaca default dhammaan ConfigMap oo leh calaamado sida copyrator: "true":

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

Diyaar! Hadda waxaan u baahanahay inaan si uun u helno macluumaadka ku saabsan xeerkeena. Aan isla markaaba ballan-qaado in aanan u qori doonin codsiyada kooxda API Server nafteena. Si tan loo sameeyo, waxaan isticmaali doonaa maktabad Python oo diyaarsan kubernetes-macmiil:

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

Natiijada socodsiinta koodkan, waxaanu helnaa kuwa soo socda:

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

Wayn: waxaan ku guuleysanay inaan u helno sharci hawlwadeenka. Iyo tan ugu muhiimsan, waxaan sameynay waxa loo yaqaan habka Kubernetes.

Doorsoomayaasha deegaanka mise calanka? Wax walba waan qaadanaa!

Aan u gudubno qaabeynta hawlwadeenka ugu weyn. Waxaa jira laba hab oo aasaasi ah oo loo habeeyo codsiyada:

  1. adeegso xulashooyinka khadka taliska;
  2. isticmaal doorsoomayaasha deegaanka.

Xulashooyinka khadka talisku waxay kuu oggolaanayaan inaad si dabacsan u akhrido dejinta, oo leh taageerada nooca xogta iyo ansaxinta. Maktabadda caadiga ah ee Python waxay leedahay module argparser, kaas oo aan isticmaali doono. Faahfaahinta iyo tusaalooyinka awooddeeda ayaa laga heli karaa gudaha dukumeenti rasmi ah.

Kiiskeena, tani waa waxa tusaale u ah dejinta calamada laynka taliska ee akhriska u ekaan lahaa:

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

Dhanka kale, adoo isticmaalaya doorsoomayaasha deegaanka ee Kubernetes, waxaad si fudud u wareejin kartaa macluumaadka adeega ee ku saabsan boodhka gudaha weelka. Tusaale ahaan, waxaan ka heli karnaa macluumaadka ku saabsan goobta magaceed ee boodhku ku socdo dhismaha soo socda:

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

macquulka hawlwadeenka

Si loo fahmo sida loo kala saaro hababka loogu shaqeeyo ConfigMap iyo Secret, waxaan isticmaali doonaa maab gaar ah. Markaa waxaan fahmi karnaa hababka aan u baahanahay si aan ula socono oo aan u abuurno shayga:

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

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

Marka xigta, waxaad u baahan tahay inaad dhacdooyinka ka hesho server-ka API. Aan u dhaqan galno sida soo socota:

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)

Ka dib markii aan helno dhacdada, waxaan u gudubnay macquulnimada ugu weyn ee habaynta:

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

Caqliga ugu weyn waa diyaar! Hadda waxaan u baahanahay inaan waxaas oo dhan ku xirno hal xirmo Python ah. Waxaan diyaarineynaa faylka setup.py, ku qor macluumaadka meta ee ku saabsan mashruuca halkaas:

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: Macmiilka kubernetes ee Python wuxuu leeyahay nuqul u gaar ah. Macluumaad dheeraad ah oo ku saabsan waafaqid ka dhexeeya noocyada macmiilka iyo noocyada Kubernetes ayaa laga heli karaa jaantusyada ku habboon.

Hadda mashruucayagu wuxuu u eg yahay sidan:

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

Docker iyo Helm

Dockerfile-ku wuxuu noqon doonaa mid si cajiib ah u fudud: qaado sawirka hoose ee python-alpine oo ku rakib xirmadayada. Aynu dib u dhigno tayaynteeda ilaa waqtiyo ka wanaagsan:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Gelida hawlwadeenku sidoo kale aad buu u fudud yahay:

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

Ugu dambeyntii, waxaad u baahan tahay inaad u abuurto door ku habboon hawlwadeenka oo leh xuquuqaha lagama maarmaanka ah:

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

Natiijada

Taasi waa sida, annagoo aan cabsi, canaan, ama baran Go, waxaan awoodnay inaan u dhisno hawlwadeenkeena Kubernetes ee Python. Dabcan, wali waxay haysataa meel ay ku koraan: mustaqbalka waxay awoodi doontaa inay socodsiiso xeerar kala duwan, ka shaqeyso mawduucyo badan, si madax banaan ula socoto isbeddelada CRDs.

Si aan si dhow kuugu eegno koodka, waanu gelinay kaydka dadweynaha. Haddii aad rabto tusaalayaal hawl wadeenno ka sii daran oo la hirgeliyo iyadoo la adeegsanayo Python, waxaad u jeedin kartaa dareenkaaga laba hawl wadeen si loo geeyo mongodb (ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈ labaad).

PS Oo haddii aad caajis u tahay inaad wax ka qabato dhacdooyinka Kubernetes ama aad si fudud u caadaysatay isticmaalka Bash, asxaabteena waxay diyaariyeen xal diyaar ah oo foomka ah. qolof-shaqaale (Anaga lagu dhawaaqay bishii April).

PPS

Sidoo kale ka akhri boggayaga:

Source: www.habr.com

Add a comment