Kubernetes Operator hauv Python tsis muaj lub hauv paus thiab SDK

Kubernetes Operator hauv Python tsis muaj lub hauv paus thiab SDK

Mus tam sim no muaj kev ywj pheej ntawm cov lus programming tib neeg xaiv los sau nqe lus rau Kubernetes. Muaj cov laj thawj rau qhov no, xws li:

  1. Muaj lub hauv paus muaj zog rau kev tsim cov neeg ua haujlwm hauv Go - OS SDK.
  2. Kev hloov pauv kev ua si xws li Docker thiab Kubernetes tau sau rau hauv Go. Sau koj tus neeg teb xov tooj hauv Go txhais tau tias hais lus tib yam nrog lub ecosystem.
  3. Kev ua haujlwm siab ntawm Go daim ntawv thov thiab cov cuab yeej yooj yim rau kev ua haujlwm nrog concurrency tawm ntawm lub thawv.

NB: Los ntawm txoj kev, yuav ua li cas sau koj tus kheej nqe lus hauv Go, peb twb piav nyob rau hauv ib qho ntawm peb translations los ntawm txawv teb chaws sau ntawv.

Tab sis yuav ua li cas yog tias koj raug tiv thaiv los ntawm kev kawm Mus los ntawm tsis muaj sij hawm los yog, yooj yim muab, kev txhawb siab? Cov kab lus muab ib qho piv txwv ntawm yuav ua li cas koj tuaj yeem sau cov lus zoo siv ib hom lus nrov tshaj plaws uas yuav luag txhua tus kws ua haujlwm DevOps paub - Nab hab sej.

Ntsib: Luam theej duab - tus neeg teb xov tooj!

Ua piv txwv, xav txog kev tsim cov lus yooj yim uas tsim los luam tawm ConfigMap txawm tias thaum lub npe tshiab tshwm sim lossis thaum ib qho ntawm ob lub koom haum hloov pauv: ConfigMap thiab zais cia. Los ntawm qhov ua tau zoo ntawm qhov pom, tus neeg teb xov tooj tuaj yeem muaj txiaj ntsig zoo rau kev hloov kho ntau ntawm daim ntawv thov teeb tsa (los ntawm kev hloov kho ConfigMap) lossis hloov kho cov ntaub ntawv zais cia - piv txwv li, cov yuam sij rau kev ua haujlwm nrog Docker Registry (thaum ntxiv zais zais rau lub npe chaw).

Thiab yog li ntawd, dab tsi tus neeg ua haujlwm zoo yuav tsum muaj:

  1. Kev sib tham nrog tus neeg teb xov tooj yog ua los ntawm kev siv Custom Resource Txhais (tom qab no hu ua CRD).
  2. Tus neeg teb xov tooj tuaj yeem teeb tsa. Txhawm rau ua qhov no, peb yuav siv cov kab hais kom ua kab chij thiab ib puag ncig hloov pauv.
  3. Kev tsim ntawm Docker thawv thiab Helm daim ntawv yog tsim los kom cov neeg siv tau yooj yim (hais nrog ib qho lus txib) nruab tus neeg teb xov tooj rau hauv lawv cov Kubernetes pawg.

CRD

Yuav kom tus neeg teb xov tooj paub txog cov peev txheej twg los nrhiav thiab saib qhov twg, peb yuav tsum tau teeb tsa txoj cai rau nws. Txhua txoj cai yuav raug sawv cev ua ib qho khoom CRD. CRD no yuav tsum muaj dab tsi?

  1. Hom kev pab, uas peb yuav nrhiav (ConfigMap lossis zais cia).
  2. Daim ntawv teev npe, nyob rau hauv uas cov kev pab yuav tsum tau nyob.
  3. Xaiv, los ntawm qhov uas peb yuav tshawb nrhiav cov peev txheej hauv lub npe.

Cia peb piav qhia txog 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

Thiab peb yuav tsim nws tam sim ntawd txoj cai yooj yim - mus nrhiav hauv lub namespace nrog lub npe default tag nrho ConfigMap nrog cov ntawv zoo li copyrator: "true":

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

Npaj txhij! Tam sim no peb yuav tsum tau txais cov ntaub ntawv hais txog peb txoj cai. Cia kuv ua qhov tshwj xeeb tam sim ntawd tias peb yuav tsis sau ntawv thov rau pawg API Server peb tus kheej. Ua li no, peb yuav siv lub tsev qiv ntawv Python npaj txhij kubernetes-neeg:

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

Raws li kev khiav qhov chaws no, peb tau txais cov hauv qab no:

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

Zoo: peb tau tswj kom tau ib txoj cai rau tus neeg teb xov tooj. Thiab qhov tseem ceeb tshaj, peb tau ua qhov hu ua Kubernetes txoj kev.

Ib puag ncig hloov pauv lossis chij? Peb noj txhua yam!

Cia peb mus rau lub ntsiab tus neeg teb xov tooj configuration. Muaj ob txoj hauv kev yooj yim rau kev teeb tsa cov ntawv thov:

  1. siv cov kab lus hais kom ua;
  2. siv cov kev hloov pauv ib puag ncig.

Cov kev xaiv kab hais kom ua tso cai rau koj nyeem cov teeb tsa yooj yim dua, nrog cov ntaub ntawv txhawb nqa thiab siv tau. Python tus qauv tsev qiv ntawv muaj ib qho module argparser, uas peb yuav siv. Cov ntsiab lus thiab cov piv txwv ntawm nws lub peev xwm muaj nyob hauv cov ntaub ntawv raug cai.

Rau peb cov ntaub ntawv, qhov no yog qhov piv txwv ntawm kev teeb tsa kev nyeem cov kab hais kom ua tus chij yuav zoo li:

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

Ntawm qhov tod tes, siv cov kev hloov pauv ib puag ncig hauv Kubernetes, koj tuaj yeem yooj yim hloov cov ntaub ntawv kev pabcuam txog cov pods hauv lub thawv. Piv txwv li, peb tuaj yeem tau txais cov ntaub ntawv hais txog lub npe qhov chaw uas lub plhaub taum ua haujlwm nrog kev tsim kho hauv qab no:

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

Operator logic

Txhawm rau nkag siab yuav ua li cas cais txoj hauv kev ua haujlwm nrog ConfigMap thiab zais cia, peb yuav siv daim duab qhia tshwj xeeb. Tom qab ntawd peb tuaj yeem nkag siab txog cov txheej txheem uas peb xav tau los taug qab thiab tsim cov khoom:

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

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

Tom ntej no, koj yuav tsum tau txais cov xwm txheej los ntawm API server. Cia peb ua raws li hauv qab no:

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)

Tom qab tau txais qhov kev tshwm sim, peb tsiv mus rau lub ntsiab logic ntawm kev ua nws:

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

Lub ntsiab logic yog npaj txhij! Tam sim no peb yuav tsum tau ntim tag nrho cov no rau hauv ib pob Python. Peb npaj cov ntaub ntawv setup.py, sau cov ntaub ntawv meta txog qhov project muaj:

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: Kubernetes tus thov kev pab rau Python muaj nws tus kheej versioning. Xav paub ntau ntxiv txog kev sib raug zoo ntawm cov neeg siv khoom siv thiab Kubernetes versions tuaj yeem pom hauv compatibility matrices.

Tam sim no peb qhov project zoo li no:

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

Docker thiab Helm

Dockerfile yuav yooj yim heev: nqa lub hauv paus python-alpine duab thiab nruab peb pob. Cia peb ncua nws qhov kev ua kom zoo kom txog thaum lub sijhawm zoo:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Kev xa mus rau tus neeg teb xov tooj kuj tseem yooj yim heev:

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

Thaum kawg, koj yuav tsum tsim lub luag haujlwm tsim nyog rau tus neeg teb xov tooj nrog cov cai tsim nyog:

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

Qhov no

Yog li ntawd, tsis muaj kev ntshai, thuam, lossis kawm Go, peb tuaj yeem tsim peb tus kheej tus neeg teb xov tooj rau Kubernetes hauv Python. Tau kawg, nws tseem muaj chaw loj hlob: yav tom ntej nws yuav muaj peev xwm ua ntau yam kev cai, ua haujlwm hauv ntau cov xov, nws tus kheej saib xyuas cov kev hloov hauv nws CRDs ...

Txhawm rau muab koj saib ze ntawm tus lej, peb tau muab tso rau hauv public repository. Yog tias koj xav tau cov piv txwv ntawm cov neeg ua haujlwm hnyav dua siv Python, koj tuaj yeem tig koj lub siab rau ob tus neeg ua haujlwm rau kev siv mongodb (thawj ΠΈ qhov thib ob).

PS Thiab yog tias koj tub nkees dhau los cuam tshuam nrog Kubernetes cov xwm txheej lossis koj tsuas yog siv ntau dua rau kev siv Bash, peb cov npoj yaig tau npaj cov kev daws teeb meem hauv daim ntawv. shell-operator (Peb tshaj tawm nws nyob rau lub Plaub Hlis).

PPS

Nyeem kuj ntawm peb blog:

Tau qhov twg los: www.hab.com

Ntxiv ib saib