ኩበርኔትስ ኦፕሬተር በፓይዘን ያለ ማዕቀፎች እና ኤስዲኬዎች

ኩበርኔትስ ኦፕሬተር በፓይዘን ያለ ማዕቀፎች እና ኤስዲኬዎች

Go በአሁኑ ጊዜ ሰዎች ለኩበርኔትስ መግለጫ ለመጻፍ በመረጡት የፕሮግራም አወጣጥ ቋንቋዎች ላይ ሞኖፖሊ አለው። ለዚህ ተጨባጭ ምክንያቶች አሉ, ለምሳሌ:

  1. በ Go ውስጥ ኦፕሬተሮችን ለማዳበር ኃይለኛ ማዕቀፍ አለ - ኦፕሬተር ኤስዲኬ.
  2. እንደ Docker እና Kubernetes ያሉ ጨዋታን የሚቀይሩ መተግበሪያዎች በ Go ውስጥ ተጽፈዋል። ኦፕሬተርዎን በ Go ውስጥ መጻፍ ማለት ከሥነ-ምህዳር ጋር አንድ አይነት ቋንቋ መናገር ማለት ነው።
  3. የ Go መተግበሪያዎች ከፍተኛ አፈፃፀም እና ከሳጥን ውጭ ከኮንፈረንስ ጋር ለመስራት ቀላል መሳሪያዎች።

NB: በነገራችን ላይ የእራስዎን መግለጫ በ Go ውስጥ እንዴት እንደሚጽፉ, እኛ አስቀድሞ ተገልጿል በእኛ ትርጉሞች በአንዱ የውጭ ደራሲዎች.

ነገር ግን ሂድን በጊዜ እጥረት ወይም በቀላል አነጋገር ተነሳሽ እንዳትማር ብትከለከልስ? ጽሑፉ እያንዳንዱ የዴቭኦፕ መሐንዲስ የሚያውቀውን በጣም ታዋቂ ቋንቋዎችን በመጠቀም ጥሩ መግለጫ እንዴት እንደሚጽፍ ምሳሌ ይሰጣል - ዘንዶ.

ይተዋወቁ፡ ኮፒየር - ኮፒ ኦፕሬተር!

እንደ ምሳሌ፣ አዲስ የስም ቦታ ሲመጣ ወይም ከሁለቱ አካላት አንዱ ሲቀየር ConfigMapን ለመቅዳት የተቀየሰ ቀላል መግለጫ ማዘጋጀት ያስቡበት፡ ConfigMap እና Secret። ከተግባራዊ እይታ አንጻር ኦፕሬተሩ የመተግበሪያ አወቃቀሮችን በጅምላ ለማዘመን (ConfigMapን በማዘመን) ወይም ሚስጥራዊ መረጃን ለማሻሻል ጠቃሚ ሊሆን ይችላል - ለምሳሌ ከዶከር መዝገብ ቤት ጋር ለመስራት ቁልፎች (ስምምነት በሚጨምርበት ጊዜ)።

እና ስለዚህ, ጥሩ ኦፕሬተር ምን ሊኖረው ይገባል:

  1. ከኦፕሬተር ጋር መስተጋብር የሚከናወነው በመጠቀም ነው ብጁ ምንጭ ፍቺዎች (ከዚህ በኋላ ሲአርዲ ይባላል)።
  2. ኦፕሬተሩ ሊዋቀር ይችላል። ይህንን ለማድረግ የትእዛዝ መስመር ባንዲራዎችን እና የአካባቢ ተለዋዋጮችን እንጠቀማለን።
  3. የዶከር ኮንቴይነር እና የሄልም ቻርት ግንባታ ተጠቃሚዎች በቀላሉ (በጥሬው በአንድ ትዕዛዝ) ኦፕሬተሩን ወደ ኩበርኔትስ ክላስተር እንዲጭኑ ታስቦ ነው።

ሲ.አር.ዲ.

ኦፕሬተሩ ምን ዓይነት ሀብቶች እንደሚፈልጉ እና የት እንደሚፈልጉ ለማወቅ, ለእሱ ህግ ማዘጋጀት አለብን. እያንዳንዱ ህግ እንደ ነጠላ ሲአርዲ ነገር ይወከላል። ይህ ሲአርዲ ምን መስኮች ሊኖረው ይገባል?

  1. የንብረት አይነትየምንፈልገው (ConfigMap or Secret) ነው።
  2. የስም ቦታዎች ዝርዝር, ሀብቶቹ በየትኛው ውስጥ መቀመጥ አለባቸው.
  3. መራጭ, በስም ቦታ ውስጥ ሀብቶችን የምንፈልግበት.

ሲአርዲውን እንግለጽ፡-

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

እና ወዲያውኑ እንፈጥራለን ቀላል ደንብ - በስም ቦታ ውስጥ በስም ለመፈለግ default ሁሉም ConfigMap ከመሰየሚያዎች ጋር copyrator: "true":

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

ዝግጁ! አሁን ስለ ደንባችን እንደምንም መረጃ ማግኘት አለብን። ለክላስተር ኤፒአይ አገልጋይ እኛ እራሳችንን እንደማንጽፍ ወዲያውኑ ቦታ አስይዝ። ይህንን ለማድረግ, ዝግጁ የሆነ የ Python ቤተ-መጽሐፍትን እንጠቀማለን kubernetes-ደንበኛ:

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

ይህን ኮድ በማስኬድ ምክንያት የሚከተለውን እናገኛለን፡-

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

በጣም ጥሩ፡ ለኦፕሬተሩ ህግ ለማግኘት ችለናል። እና ከሁሉም በላይ ደግሞ የኩበርኔትስ መንገድ ተብሎ የሚጠራውን አደረግን.

የአካባቢ ተለዋዋጮች ወይስ ባንዲራዎች? ሁሉንም ነገር እንወስዳለን!

ወደ ዋናው ኦፕሬተር ውቅር እንሂድ። መተግበሪያዎችን ለማዋቀር ሁለት መሠረታዊ ዘዴዎች አሉ-

  1. የትእዛዝ መስመር አማራጮችን ተጠቀም;
  2. የአካባቢ ተለዋዋጮችን ይጠቀሙ.

የትእዛዝ መስመር አማራጮች በመረጃ አይነት ድጋፍ እና ማረጋገጫ አማካኝነት ቅንብሮችን በተለዋዋጭ እንዲያነቡ ያስችሉዎታል። የፓይዘን መደበኛ ላይብረሪ ሞጁል አለው። argparser, የምንጠቀመው. የችሎታው ዝርዝሮች እና ምሳሌዎች በ ውስጥ ይገኛሉ ኦፊሴላዊ ሰነዶች.

በእኛ ሁኔታ፣ የትእዛዝ መስመር ባንዲራዎችን የማንበብ ምሳሌ ይህን ይመስላል።

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

በሌላ በኩል፣በኩበርኔትስ ውስጥ የአካባቢ ተለዋዋጮችን በመጠቀም፣በኮንቴይነር ውስጥ ስላለው ፖድ በቀላሉ የአገልግሎት መረጃ ማስተላለፍ ይችላሉ። ለምሳሌ ፣ ፖዱ በሚከተለው ግንባታ ስለሚሠራበት የስም ቦታ መረጃ ማግኘት እንችላለን ።

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

ኦፕሬተር አመክንዮ

ከConfigMap እና Secret ጋር ለመስራት ዘዴዎችን እንዴት እንደሚለያዩ ለመረዳት ልዩ ካርታዎችን እንጠቀማለን። ከዚያ እቃውን ለመከታተል እና ለመፍጠር ምን ዘዴዎች እንደሚያስፈልጉን እንረዳለን-

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

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

በመቀጠል ከኤፒአይ አገልጋይ ክስተቶችን መቀበል አለቦት። እንደሚከተለው እንተገብረው።

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)

ክስተቱን ከተቀበልን በኋላ ወደ ዋናው የማስኬጃ ሎጂክ እንሸጋገራለን፡-

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

ዋናው አመክንዮ ዝግጁ ነው! አሁን ይህንን ሁሉ ወደ አንድ የፓይዘን ጥቅል ማሸግ አለብን። ፋይሉን እናዘጋጃለን setup.pyስለ ፕሮጀክቱ ሜታ መረጃን እዚያ ይፃፉ፡-

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የ Python kubernetes ደንበኛ የራሱ የሆነ ስሪት አለው። በደንበኛ ስሪቶች እና በ Kubernetes ስሪቶች መካከል ስላለው ተኳሃኝነት ተጨማሪ መረጃ በ ውስጥ ይገኛል። የተኳኋኝነት ማትሪክስ.

አሁን የእኛ ፕሮጀክት ይህን ይመስላል:

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

ዶከር እና ሄልም

Dockerfile በሚገርም ሁኔታ ቀላል ይሆናል፡ የመሠረት python-alpine ምስልን ያንሱ እና ጥቅላችንን ይጫኑ። ማትቡን ወደ ተሻለ ጊዜ እናራዝመው፡-

FROM python:3.7.3-alpine3.9

ADD . /app

RUN pip3 install /app

ENTRYPOINT ["copyrator"]

ለኦፕሬተሩ ማሰማራት እንዲሁ በጣም ቀላል ነው-

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

በመጨረሻም ለኦፕሬተሩ አስፈላጊ የሆኑ መብቶችን በመጠቀም ተገቢውን ሚና መፍጠር አለብዎት:

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

ውጤቱ

በዚህ መንገድ ነው፣ ያለ ፍርሃት፣ ነቀፋ ወይም Goን ሳንማር የራሳችንን ኦፕሬተር ለኩበርኔትስ በፓይዘን መገንባት የቻልነው። እርግጥ ነው፣ አሁንም ለማደግ ቦታ አላት፣ ወደፊት ብዙ ሕጎችን ማስተናገድ፣ በበርካታ ክሮች ውስጥ መሥራት፣ በሲአርዲዎቹ ላይ ያለውን ለውጥ ራሱን ችሎ መከታተል ይችላል...

ኮዱን በቅርበት ለማየት፣ አስገብተናል የህዝብ ማከማቻ. ይበልጥ ከባድ የሆኑ ኦፕሬተሮችን ፓይዘንን በመጠቀም የሚተገበሩ ምሳሌዎችን ከፈለጉ፣ mongodb (Mongodb) ለማሰማራት ትኩረትዎን ወደ ሁለት ኦፕሬተሮች ማዞር ይችላሉ።первый и ሁለተኛው).

PS እና የኩበርኔትስ ዝግጅቶችን ለመቋቋም በጣም ሰነፍ ከሆንክ ወይም በቀላሉ ባሽ መጠቀምን ከተለማመድክ ባልደረቦቻችን በቅጹ የተዘጋጀ መፍትሄ አዘጋጅተዋል ሼል-ኦፕሬተር (እኛ ይፋ ተደርጓል በሚያዝያ ወር)።

ፒፒኤስ

በብሎጋችን ላይ ያንብቡ፡-

ምንጭ: hab.com

አስተያየት ያክሉ