Onye ọrụ Kubernetes na Python na-enweghị usoro na SDK

Onye ọrụ Kubernetes na Python na-enweghị usoro na SDK

Go nwere ikike ugbu a na asụsụ mmemme ndị mmadụ na-ahọrọ ide nkwupụta maka Kubernetes. Enwere ebumnobi kpatara nke a, dịka:

  1. Enwere usoro siri ike maka ndị na-emepe emepe na Go - SDK onye ọrụ.
  2. Ngwa na-agbanwe egwuregwu dịka Docker na Kubernetes ka edere na Go. Ide onye ọrụ gị na Go pụtara ịsụ otu asụsụ na gburugburu ebe obibi.
  3. Ịrụ ọrụ dị elu nke ngwa Go na ngwaọrụ dị mfe maka ịrụ ọrụ na concurrency si na igbe.

NB: Site n'ụzọ, otu esi ede nkwupụta nke gị na Go, anyị akọwaralarị n'otu n'ime ntụgharị asụsụ anyị nke ndị ode akwụkwọ si mba ofesi.

Ma gịnị ma ọ bụrụ na-egbochi gị ịmụ Go site na enweghị oge ma ọ bụ, n'ikwu ya n'ụzọ dị mfe, mkpali? Edemede a na-enye ihe atụ nke otu ị ga-esi dee nkwupụta dị mma site na iji otu n'ime asụsụ ndị ama ama nke fọrọ nke nta ka ọ bụrụ injinia DevOps ọ bụla maara - Python.

Zute: Copier - onye ọrụ nnomi!

Dịka ọmụmaatụ, tụlee ịmepụta nkwupụta dị mfe emebere iji detuo ConfigMap ma mgbe oghere aha ọhụrụ pụtara ma ọ bụ mgbe otu n'ime ụlọ ọrụ abụọ gbanwere: ConfigMap na Nzuzo. Site n'echiche bara uru, onye ọrụ nwere ike ịba uru maka imelite nhazi ngwa ngwa (site na imelite ConfigMap) ma ọ bụ maka imelite data nzuzo - dịka ọmụmaatụ, igodo maka ịrụ ọrụ na Docker Registry (mgbe ị na-agbakwunye Nzuzo na aha aha).

Ya mere, ihe ezigbo onye ọrụ kwesịrị inwe:

  1. A na-eme mmekọrịta ya na onye ọrụ site na iji Nkọwa akụrụngwa omenala (nke a na-akpọ CRD).
  2. Enwere ike ịhazi onye ọrụ. Iji mee nke a, anyị ga-eji ọkọlọtọ ahịrị iwu na mgbanwe gburugburu ebe obibi.
  3. Emebere akpa Docker na eserese Helm ka ndị ọrụ nwee ike ngwa ngwa (n'ụzọ nkịtị na otu iwu) tinye onye ọrụ n'ime ụyọkọ Kubernetes ha.

CRD

Ka onye ọrụ wee mara ihe akụrụngwa ọ ga-achọ na ebe ọ ga-ele anya, anyị kwesịrị ịtọ ya iwu. A ga-anọchi anya iwu ọ bụla dị ka otu ihe CRD. Kedu ngalaba CRD kwesịrị inwe?

  1. Ụdị akụrụngwa, nke anyị ga-achọ (ConfigMap ma ọ bụ Nzuzo).
  2. Ndepụta oghere aha, nke ihe onwunwe kwesịrị ịdị.
  3. Nhọrọ, site na nke anyị ga-achọ ihe onwunwe na namespace.

Ka anyị kọwaa 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

Na anyị ga-emepụta ya ozugbo iwu dị mfe - iji aha chọọ na oghere aha default ConfigMap niile nwere akara dị ka copyrator: "true":

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

Njikere! Ugbu a, anyị kwesịrị inweta ozi gbasara ọchịchị anyị. Ka m mee ndoputa ozugbo na anyị agaghị edegara ụyọkọ API Sava n'onwe anyị arịrịọ. Iji mee nke a, anyị ga-eji ọba akwụkwọ Python emebere ya kubernetes-onye ahịa:

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

Site na iji koodu a, anyị na-enweta ihe ndị a:

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

Ọ dị mma: anyị jisiri ike nweta iwu maka onye ọrụ. Na nke kachasị mkpa, anyị mere ihe a na-akpọ ụzọ Kubernetes.

Ụdị mgbanwe gburugburu ma ọ bụ ọkọlọtọ? Anyị na-ewere ihe niile!

Ka anyị gaa n'ihu na nhazi onye ọrụ isi. Enwere ụzọ abụọ bụ isi maka ịhazi ngwa:

  1. jiri nhọrọ ahịrị iwu;
  2. jiri mgbanwe gburugburu ebe obibi.

Nhọrọ ahịrị iwu na-enye gị ohere ịgụ ntọala nke ọma karịa, yana nkwado ụdị data na nkwado. Ọbá akwụkwọ ọkọlọtọ Python nwere modul argparser, nke anyị ga-eji. Nkọwa na ihe atụ nke ike ya dị na akwụkwọ ikike.

Maka ikpe anyị, nke a bụ ihe atụ nke ịtọọ ọkọlọtọ ahịrị iwu ọgụgụ ga-adị ka:

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

N'aka nke ọzọ, iji mgbanwe gburugburu ebe obibi na Kubernetes, ị nwere ike ịnyefe ozi ọrụ gbasara pọd n'ime akpa ahụ ngwa ngwa. Dịka ọmụmaatụ, anyị nwere ike nweta ozi gbasara oghere aha nke pọd na-eji ihe owuwu a na-arụ:

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

Ihe mgbagha onye ọrụ

Iji ghọta otu esi ekewa ụzọ maka ịrụ ọrụ na ConfigMap na Nzuzo, anyị ga-eji maapụ pụrụ iche. Mgbe ahụ, anyị nwere ike ịghọta ụzọ anyị kwesịrị iji soro na ịmepụta ihe ahụ:

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

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

Na-esote, ị ga-enweta mmemme site na sava API. Ka anyị mejuputa ya dị ka ndị a:

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)

Mgbe anyị nwetasịrị mmemme ahụ, anyị ga-aga n'ihu na mgbagha bụ isi nke ịhazi ya:

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

Isi mgbagha dị njikere! Ugbu a, anyị kwesịrị ịkwakọ ihe a niile n'otu ngwugwu Python. Anyị na-akwadebe faịlụ ahụ setup.py, dee ozi meta gbasara ọrụ ahụ ebe ahụ:

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: Ndị ahịa kubernetes maka Python nwere nsụgharị nke ya. Enwere ike ịhụ ozi ndị ọzọ gbasara ndakọrịta n'etiti ụdị ndị ahịa na ụdị Kubernetes na ya matrices ndakọrịta.

Ugbu a ọrụ anyị dị ka nke a:

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

Docker na Helm

Dockerfile ga-adị mfe nke ukwuu: were foto isi python-alpine wee wụnye ngwugwu anyị. Ka anyị yigharịa njikarịcha ya ruo oge kacha mma:

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

Nbunye maka onye ọrụ dịkwa mfe:

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

N'ikpeazụ, ịkwesịrị ịmepụta ọrụ kwesịrị ekwesị maka onye ọrụ nwere ikike ndị dị mkpa:

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

Nsonaazụ

Nke ahụ bụ, na-enweghị egwu, nkọcha ma ọ bụ mmụta Go, anyị nwere ike wulite onye ọrụ nke anyị maka Kubernetes na Python. N'ezie, ọ ka nwere ohere itolite: n'ọdịnihu ọ ga-enwe ike ịhazi ọtụtụ iwu, rụọ ọrụ n'ọtụtụ eri, nyochaa onwe ya na mgbanwe na CRD ya ...

Iji nye gị nlele anya na koodu ahụ, anyị etinyela ya ebe nchekwa ọha. Ọ bụrụ na ịchọrọ ịma atụ nke ndị ọrụ ka njọ etinyere na iji Python, ị nwere ike tụgharịa uche gị na ndị ọrụ abụọ maka ibuga mongodb (первый и nke abụọ).

PS Ma ọ bụrụ na ị dị umengwụ ime ihe omume Kubernetes ma ọ bụ na ị maarala gị nke ọma iji Bash, ndị ọrụ ibe anyị akwadebela ihe edoziziri n'ụdị. shei-arụ ọrụ (Anyị mara ọkwa n'April).

Pps

Gụọkwa na blọọgụ anyị:

isi: www.habr.com

Tinye a comment