Kubernetes Operator ื‘- Python ืœืœื ืžืกื’ืจื•ืช ื•-SDK

Kubernetes Operator ื‘- Python ืœืœื ืžืกื’ืจื•ืช ื•-SDK

ืœ-Go ื™ืฉ ื›ืจื’ืข ืžื•ื ื•ืคื•ืœ ืขืœ ืฉืคื•ืช ื”ืชื›ื ื•ืช ืฉืื ืฉื™ื ื‘ื•ื—ืจื™ื ืœื›ืชื•ื‘ ื”ืฆื”ืจื•ืช ืขื‘ื•ืจ Kubernetes. ื™ืฉ ืœื›ืš ืกื™ื‘ื•ืช ืื•ื‘ื™ื™ืงื˜ื™ื‘ื™ื•ืช, ื›ื’ื•ืŸ:

  1. ื™ืฉ ืžืกื’ืจืช ื—ื–ืงื” ืœืคื™ืชื•ื— ืื•ืคืจื˜ื•ืจื™ื ื‘-Go - SDK ืฉืœ ืžืคืขื™ืœ.
  2. ื™ื™ืฉื•ืžื™ื ืžืฉื ื™ื ืžืฉื—ืงื™ื ื›ืžื• Docker ื•-Kubernetes ื›ืชื•ื‘ื™ื ื‘-Go. ื›ืชื™ื‘ืช ื”ืžืคืขื™ืœ ืฉืœืš ื‘-Go ืคื™ืจื•ืฉื” ื“ื™ื‘ื•ืจ ื‘ืื•ืชื” ืฉืคื” ืขื ื”ืžืขืจื›ืช ื”ืืงื•ืœื•ื’ื™ืช.
  3. ื‘ื™ืฆื•ืขื™ื ื’ื‘ื•ื”ื™ื ืฉืœ ื™ื™ืฉื•ืžื™ Go ื•ื›ืœื™ื ืคืฉื•ื˜ื™ื ืœืขื‘ื•ื“ื” ืขื ื‘ื• ื–ืžื ื™ืช ืžื—ื•ืฅ ืœืงื•ืคืกื”.

NB: ืื’ื‘, ืื™ืš ืœื›ืชื•ื‘ ื”ืฆื”ืจื” ืžืฉืœืš ื‘ื’ื•, ืื ื—ื ื• ื›ื‘ืจ ืชื•ืืจ ื‘ืื—ื“ ืžื”ืชืจื’ื•ืžื™ื ืฉืœื ื• ืขืœ ื™ื“ื™ ืกื•ืคืจื™ื ื–ืจื™ื.

ืื‘ืœ ืžื” ืื ื ืžื ืข ืžืžืš ืœืœืžื•ื“ Go ื‘ื’ืœืœ ื—ื•ืกืจ ื–ืžืŸ ืื•, ื‘ืžื™ืœื™ื ืคืฉื•ื˜ื•ืช, ืžื•ื˜ื™ื‘ืฆื™ื”? ื”ืžืืžืจ ืžืกืคืง ื“ื•ื’ืžื” ื›ื™ืฆื“ ื ื™ืชืŸ ืœื›ืชื•ื‘ ื”ืฆื”ืจื” ื˜ื•ื‘ื” ื‘ืืžืฆืขื•ืช ืื—ืช ื”ืฉืคื•ืช ื”ืคื•ืคื•ืœืจื™ื•ืช ื‘ื™ื•ืชืจ ืฉื›ืžืขื˜ ื›ืœ ืžื”ื ื“ืก DevOps ืžื›ื™ืจ - ืคื™ืชื•ืŸ.

ื”ื›ื™ืจื•: ืžื›ื•ื ืช ืฆื™ืœื•ื - ืžืคืขื™ืœ ืขื•ืชืงื™ื!

ื›ื“ื•ื’ืžื”, ืฉืงื•ืœ ืœืคืชื— ื”ืฆื”ืจื” ืคืฉื•ื˜ื” ืฉื ื•ืขื“ื” ืœื”ืขืชื™ืง ConfigMap ื›ืืฉืจ ืžื•ืคื™ืข ืžืจื—ื‘ ืฉืžื•ืช ื—ื“ืฉ ืื• ื›ืืฉืจ ืื—ืช ืžืฉืชื™ ื™ืฉื•ื™ื•ืช ืžืฉืชื ื”: ConfigMap ื•-Secret. ืžื ืงื•ื“ืช ืžื‘ื˜ ืžืขืฉื™ืช, ื”ืžืคืขื™ืœ ื™ื›ื•ืœ ืœื”ื™ื•ืช ืฉื™ืžื•ืฉื™ ืœืขื“ื›ื•ืŸ ื‘ื›ืžื•ืช ื’ื“ื•ืœื” ืฉืœ ืชืฆื•ืจื•ืช ืืคืœื™ืงืฆื™ื•ืช (ืขืœ ื™ื“ื™ ืขื“ื›ื•ืŸ ื”-ConfigMap) ืื• ืœืขื“ื›ื•ืŸ ื ืชื•ื ื™ื ืกื•ื“ื™ื™ื - ืœืžืฉืœ ืžืคืชื—ื•ืช ืœืขื‘ื•ื“ื” ืขื Docker Registry (ื‘ืขืช ื”ื•ืกืคืช Secret ืœืžืจื—ื‘ ื”ืฉืžื•ืช).

ืœืคื™ื›ืš, ืžื” ืฆืจื™ืš ืœื”ื™ื•ืช ืœืžืคืขื™ืœ ื˜ื•ื‘:

  1. ื”ืื™ื ื˜ืจืืงืฆื™ื” ืขื ื”ืžืคืขื™ืœ ืžืชื‘ืฆืขืช ื‘ืืžืฆืขื•ืช ื”ื’ื“ืจื•ืช ืžืฉืื‘ื™ื ืžื•ืชืืžื•ืช ืื™ืฉื™ืช (ืœื”ืœืŸ: CRD).
  2. ื ื™ืชืŸ ืœื”ื’ื“ื™ืจ ืืช ื”ืžืคืขื™ืœ. ืœืฉื ื›ืš, ื ืฉืชืžืฉ ื‘ื“ื’ืœื™ ืฉื•ืจืช ื”ืคืงื•ื“ื” ื•ื‘ืžืฉืชื ื™ ืกื‘ื™ื‘ื”.
  3. ื”ืžื‘ื ื” ืฉืœ ืชืจืฉื™ื ื”-Docker ื•-Helm ืชื•ื›ื ืŸ ื›ืš ืฉืžืฉืชืžืฉื™ื ื™ื›ื•ืœื™ื ื‘ืงืœื•ืช (ืžืžืฉ ื‘ืคืงื•ื“ื” ืื—ืช) ืœื”ืชืงื™ืŸ ืืช ื”ืžืคืขื™ืœ ื‘ืืฉื›ื•ืœ Kubernetes ืฉืœื”ื.

CRD

ื›ื“ื™ ืฉื”ืžืคืขื™ืœ ื™ื™ื“ืข ืื™ืœื• ืžืฉืื‘ื™ื ืœื—ืคืฉ ื•ื”ื™ื›ืŸ ืœื—ืคืฉ, ืขืœื™ื ื• ืœืงื‘ื•ืข ืœื• ื›ืœืœ. ื›ืœ ื›ืœืœ ื™ื•ืฆื’ ื›ืื•ื‘ื™ื™ืงื˜ CRD ื™ื—ื™ื“. ืื™ืœื• ืฉื“ื•ืช ืฆืจื™ื›ื™ื ืœื”ื™ื•ืช ื‘-CRD ื”ื–ื”?

  1. ืกื•ื’ ืžืฉืื‘, ืฉื ื—ืคืฉ (ConfigMap ืื• Secret).
  2. ืจืฉื™ืžื” ืฉืœ ืžืจื—ื‘ื™ ืฉืžื•ืช, ืฉื‘ื• ื™ืฉ ืœืžืงื ืืช ื”ืžืฉืื‘ื™ื.
  3. ื‘ื•ืจืจ, ืฉื‘ืืžืฆืขื•ืชื• ื ื—ืคืฉ ืžืฉืื‘ื™ื ื‘ืžืจื—ื‘ ื”ืฉืžื•ืช.

ื‘ื•ืื• ื ืชืืจ ืืช ื”-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

ื•ืื ื—ื ื• ื ื™ืฆื•ืจ ืืช ื–ื” ืžื™ื“ ื›ืœืœ ืคืฉื•ื˜ โ€” ื›ื“ื™ ืœื—ืคืฉ ื‘ืžืจื—ื‘ ื”ืฉืžื•ืช ืขื ื”ืฉื default ื”ื›ืœ ConfigMap ืขื ืชื•ื•ื™ื•ืช ื›ืžื• copyrator: "true":

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

ืžื•ึผื›ึธืŸ! ืขื›ืฉื™ื• ืื ื—ื ื• ืฆืจื™ื›ื™ื ืื™ื›ืฉื”ื• ืœืงื‘ืœ ืžื™ื“ืข ืขืœ ื”ื›ืœืœ ืฉืœื ื•. ื”ืจืฉื• ืœื™ ืœื‘ืฆืข ื”ื–ืžื ื” ืžื™ื“ ืฉืœื ื ื›ืชื•ื‘ ื‘ืงืฉื•ืช ืœืฉืจืช ื”-API ืฉืœ ืืฉื›ื•ืœ ื‘ืขืฆืžื ื•. ืœืฉื ื›ืš, ื ืฉืชืžืฉ ื‘ืกืคืจื™ื™ืช Python ืžื•ื›ื ื” kubernetes-client:

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

ื ื”ื“ืจ: ื”ืฆืœื—ื ื• ืœื”ืฉื™ื’ ื›ืœืœ ืœืžืคืขื™ืœ. ื•ื”ื›ื™ ื—ืฉื•ื‘, ืขืฉื™ื ื• ืืช ืžื” ืฉื ืงืจื ื“ืจืš Kubernetes.

ืžืฉืชื ื™ ืกื‘ื™ื‘ื” ืื• ื“ื’ืœื™ื? ืื ื—ื ื• ืœื•ืงื—ื™ื ื”ื›ืœ!

ื‘ื•ืื• ื ืขื‘ื•ืจ ืœืชืฆื•ืจืช ื”ืžืคืขื™ืœ ื”ืจืืฉื™. ืงื™ื™ืžื•ืช ืฉืชื™ ื’ื™ืฉื•ืช ื‘ืกื™ืกื™ื•ืช ืœื”ื’ื“ืจืช ืืคืœื™ืงืฆื™ื•ืช:

  1. ื”ืฉืชืžืฉ ื‘ืืคืฉืจื•ื™ื•ืช ืฉื•ืจืช ื”ืคืงื•ื“ื”;
  2. ืœื”ืฉืชืžืฉ ื‘ืžืฉืชื ื™ ืกื‘ื™ื‘ื”.

ืืคืฉืจื•ื™ื•ืช ืฉื•ืจืช ื”ืคืงื•ื“ื” ืžืืคืฉืจื•ืช ืœืš ืœืงืจื•ื ื”ื’ื“ืจื•ืช ื‘ืฆื•ืจื” ื’ืžื™ืฉื” ื™ื•ืชืจ, ืขื ืชืžื™ื›ื” ื•ืื™ืžื•ืช ืฉืœ ืกื•ื’ื™ ื ืชื•ื ื™ื. ื‘ืกืคืจื™ื™ื” ื”ืกื˜ื ื“ืจื˜ื™ืช ืฉืœ Python ื™ืฉ ืžื•ื“ื•ืœ 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()

ืžืฆื“ ืฉื ื™, ื‘ืืžืฆืขื•ืช ืžืฉืชื ื™ ืกื‘ื™ื‘ื” ื‘-Kubernetes, ื ื™ืชืŸ ืœื”ืขื‘ื™ืจ ื‘ืงืœื•ืช ืžื™ื“ืข ืฉื™ืจื•ืช ืขืœ ื”ืคื•ื“ ื‘ืชื•ืš ื”ืงื•ื ื˜ื™ื™ื ืจ. ืœื“ื•ื’ืžื”, ืื ื• ื™ื›ื•ืœื™ื ืœืงื‘ืœ ืžื™ื“ืข ืขืœ ืžืจื—ื‘ ื”ืฉืžื•ืช ื‘ื• ืคื•ืขืœ ื”ืคื•ื“ ืขื ื”ืžื‘ื ื” ื”ื‘ื:

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

ืœืื—ืจ ืžื›ืŸ, ืขืœื™ืš ืœืงื‘ืœ ืื™ืจื•ืขื™ื ืžืฉืจืช ื”-API. ื‘ื•ืื• ืœื™ื™ืฉื ืืช ื–ื” ื‘ืื•ืคืŸ ื”ื‘ื:

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)

ื”ื”ื™ื’ื™ื•ืŸ ื”ืขื™ืงืจื™ ืžื•ื›ืŸ! ื›ืขืช ืขืœื™ื ื• ืœืืจื•ื– ืืช ื›ืœ ื–ื” ื‘ื—ื‘ื™ืœืช Python ืื—ืช. ืื ื—ื ื• ืžื›ื™ื ื™ื ืืช ื”ืงื•ื‘ืฅ 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: ืœืœืงื•ื— kubernetes ืขื‘ื•ืจ Python ื™ืฉ ื’ื™ืจืกื” ืžืฉืœื•. ืžื™ื“ืข ื ื•ืกืฃ ืขืœ ืชืื™ืžื•ืช ื‘ื™ืŸ ื’ืจืกืื•ืช ืœืงื•ื— ื•ื’ืจืกืื•ืช Kubernetes ื ื™ืชืŸ ืœืžืฆื•ื ื‘ ืžื˜ืจื™ืฆื•ืช ืชืื™ืžื•ืช.

ื›ืขืช ื”ืคืจื•ื™ืงื˜ ืฉืœื ื• ื ืจืื” ื›ืš:

copyrator
โ”œโ”€โ”€ copyrator
โ”‚   โ”œโ”€โ”€ cli.py # ะ›ะพะณะธะบะฐ ั€ะฐะฑะพั‚ั‹ ั ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะพะน
โ”‚   โ”œโ”€โ”€ constant.py # ะšะพะฝัั‚ะฐะฝั‚ั‹, ะบะพั‚ะพั€ั‹ะต ะผั‹ ะฟั€ะธะฒะพะดะธะปะธ ะฒั‹ัˆะต
โ”‚   โ”œโ”€โ”€ load_crd.py # ะ›ะพะณะธะบะฐ ะทะฐะณั€ัƒะทะบะธ CRD
โ”‚   โ””โ”€โ”€ operator.py # ะžัะฝะพะฒะฝะฐั ะปะพะณะธะบะฐ ั€ะฐะฑะพั‚ั‹ ะพะฟะตั€ะฐั‚ะพั€ะฐ
โ””โ”€โ”€ setup.py # ะžั„ะพั€ะผะปะตะฝะธะต ะฟะฐะบะตั‚ะฐ

ื“ื•ืงืจ ื•ื”ืœื

ื”-Dockerfile ื™ื”ื™ื” ืคืฉื•ื˜ ืœื”ืคืœื™ื: ืงื— ืืช ืชืžื•ื ืช ื”ืคื™ืชื•ืŸ-ืืœืคื™ื ื™ืช ื”ื‘ืกื™ืกื™ืช ื•ื”ืชืงืŸ ืืช ื”ื—ื‘ื™ืœื” ืฉืœื ื•. ื‘ื•ืื• ื ื“ื—ื” ืืช ื”ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืฉืœื• ืœื–ืžื ื™ื ื˜ื•ื‘ื™ื ื™ื•ืชืจ:

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, ื”ืฆืœื—ื ื• ืœื‘ื ื•ืช ืžืคืขื™ืœ ืžืฉืœื ื• ืขื‘ื•ืจ Kubernetes ื‘-Python. ื›ืžื•ื‘ืŸ, ืขื“ื™ื™ืŸ ื™ืฉ ืœื• ืžืงื•ื ืœืฆืžื•ื—: ื‘ืขืชื™ื“ ื”ื•ื ื™ื•ื›ืœ ืœืขื‘ื“ ืžืกืคืจ ื›ืœืœื™ื, ืœืขื‘ื•ื“ ื‘ืžืกืคืจ ืฉืจืฉื•ืจื™ื, ืœื ื˜ืจ ื‘ืื•ืคืŸ ืขืฆืžืื™ ืฉื™ื ื•ื™ื™ื ื‘-CRD ืฉืœื•...

ื›ื“ื™ ืœืชืช ืœืš ืžื‘ื˜ ืžืงืจื•ื‘ ืขืœ ื”ืงื•ื“, ื”ื›ื ืกื ื• ืื•ืชื• ืžืื’ืจ ืฆื™ื‘ื•ืจื™. ืื ืืชื” ืจื•ืฆื” ื“ื•ื’ืžืื•ืช ืœืื•ืคืจื˜ื•ืจื™ื ืจืฆื™ื ื™ื™ื ื™ื•ืชืจ ื”ืžื™ื•ืฉืžื™ื ื‘ืืžืฆืขื•ืช Python, ืืชื” ื™ื›ื•ืœ ืœื”ืคื ื•ืช ืืช ืชืฉื•ืžืช ืœื‘ืš ืœืฉื ื™ ืื•ืคืจื˜ื•ืจื™ื ืœืคืจื™ืกืช mongodb (ะฟะตั€ะฒั‹ะน ะธ ืฉื ื™).

ื .ื‘. ื•ืื ืืชื” ืขืฆืœืŸ ืžื›ื“ื™ ืœื”ืชืžื•ื“ื“ ืขื ืื™ืจื•ืขื™ Kubernetes ืื• ืฉืืชื” ืคืฉื•ื˜ ืจื’ื™ืœ ื™ื•ืชืจ ืœื”ืฉืชืžืฉ ื‘-Bash, ื”ืงื•ืœื’ื•ืช ืฉืœื ื• ื”ื›ื™ื ื• ืคืชืจื•ืŸ ืžื•ื›ืŸ ื‘ื˜ื•ืคืก ืžืคืขื™ืœ ืžืขื˜ืคืช (ืึธื ื•ึผ ื”ื•ื›ืจื– ื–ื” ื‘ืืคืจื™ืœ).

PPS

ืงืจื ื’ื ื‘ื‘ืœื•ื’ ืฉืœื ื•:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”