ืชืฆื•ืจืช ืคืจื•ื™ืงื˜ ื‘ืชื•ืš ื•ืžื—ื•ืฅ Kubernetes

ืœื ืžื–ืžืŸ ื›ืชื‘ืชื™ ืชืฉื•ื‘ื” ืขืœ ื—ื™ื™ ื”ืคืจื•ื™ืงื˜ ื‘-Docker ื•ืื™ืชื•ืจ ื‘ืื’ื™ื ื‘ืงื•ื“ ืžื—ื•ืฆื” ืœื•, ืฉื ื”ื•ื ื”ื–ื›ื™ืจ ื‘ืงืฆืจื” ืฉืืชื” ื™ื›ื•ืœ ืœื™ืฆื•ืจ ืžืขืจื›ืช ืชืฆื•ืจื” ืžืฉืœืš ื›ืš ืฉื”ืฉื™ืจื•ืช ื™ืขื‘ื•ื“ ื”ื™ื˜ื‘ ื‘-Kuber, ื™ื’ืœื” ืกื•ื“ื•ืช ื•ื™ืคืขืœ ื‘ืฆื•ืจื” ื ื•ื—ื” ืžืงื•ืžื™ืช, ืืคื™ืœื• ืžื—ื•ืฅ ืœื“ื•ืงืจ ื‘ื›ืœืœ. ืฉื•ื ื“ื‘ืจ ืžืกื•ื‘ืš, ืื‘ืœ ื”"ืžืชื›ื•ืŸ" ื”ืžืชื•ืืจ ืขืฉื•ื™ ืœื”ื™ื•ืช ืฉื™ืžื•ืฉื™ ืœืžื™ืฉื”ื• :) ื”ืงื•ื“ ื”ื•ื ื‘-Python, ืื‘ืœ ื”ื”ื™ื’ื™ื•ืŸ ืื™ื ื• ืงืฉื•ืจ ืœืฉืคื”.

ืชืฆื•ืจืช ืคืจื•ื™ืงื˜ ื‘ืชื•ืš ื•ืžื—ื•ืฅ Kubernetes

ื”ืจืงืข ืœืฉืืœื” ื”ื•ื ื–ื”: ืคืขื ื”ื™ื” ืคืจื•ื™ืงื˜ ืื—ื“, ื‘ื”ืชื—ืœื” ื–ื” ื”ื™ื” ืžื•ื ื•ืœื™ื˜ ืงื˜ืŸ ืขื ื›ืœื™ ืขื–ืจ ื•ืชืกืจื™ื˜ื™ื, ืื‘ืœ ืขื ื”ื–ืžืŸ ื”ื•ื ื’ื“ืœ, ื”ืชื—ืœืง ืœืฉื™ืจื•ืชื™ื, ืฉื‘ืชื•ืจื ื”ืชื—ื™ืœื• ืœื”ืชื—ืœืง ืœืžื™ืงืจื•-ืฉื™ืจื•ืชื™ื, ื•. ืœืื—ืจ ืžื›ืŸ ื”ื’ื“ื™ืœื” ืืช ื”ื’ื•ื“ืœ. ื‘ื”ืชื—ืœื” ื›ืœ ื–ื” ื ืขืฉื” ื‘-VPS ื—ืฉื•ืฃ, ืฉืชื”ืœื™ื›ื™ ื”ื”ื’ื“ืจื” ื•ื”ืคืจื™ืกื” ืฉืœ ื”ืงื•ื“ ืขืœื™ื• ื”ื™ื• ืื•ื˜ื•ืžื˜ื™ื™ื ื‘ืืžืฆืขื•ืช Ansible, ื•ื›ืœ ืฉื™ืจื•ืช ื”ื•ืจื›ื‘ ืขื ืชืฆื•ืจืช YAML ืขื ื”ื”ื’ื“ืจื•ืช ื•ื”ืžืคืชื—ื•ืช ื”ื“ืจื•ืฉื™ื, ื•ืงื•ื‘ืฅ ืชืฆื•ืจื” ื“ื•ืžื” ืฉื™ืžืฉ ืขื‘ื•ืจ ื”ืฉืงื•ืช ืžืงื•ืžื™ื•ืช, ื•ื–ื” ื”ื™ื” ืžืื•ื“ ื ื•ื—, ืžื›ื™ื•ื•ืŸ ืฉ-.k ื”ืชืฆื•ืจื” ื”ื–ื• ื ื˜ืขื ืช ื‘ืื•ื‘ื™ื™ืงื˜ ื’ืœื•ื‘ืœื™, ื ื’ื™ืฉ ืžื›ืœ ืžืงื•ื ื‘ืคืจื•ื™ืงื˜.

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

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

Dict[str, Dict[str, Union[str, int, float]]]

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

adminka:
  django_secret: "ExtraLongAndHardCode"

db_main:
  engine: mysql
  host: 256.128.64.32
  user: cool_user
  password: "SuperHardPassword"

redis:
  host: 256.128.64.32
  pw: "SuperHardPassword"
  port: 26379

smtp:
  server: smtp.gmail.com
  port: 465
  email: [email protected]
  pw: "SuperHardPassword"

ื‘ืžืงื‘ื™ืœ, ื”ืฉื“ื” engine ื ื™ืชืŸ ืœื”ืชืงื™ืŸ ืžืกื“ื™ ื ืชื•ื ื™ื ืขืœ SQLite, ื• redis ืžื›ื•ื•ืŸ ืœ mock, ืฆื™ื•ืŸ ื’ื ืืช ืฉื ื”ืงื•ื‘ืฅ ืœืฉืžื™ืจื” - ืคืจืžื˜ืจื™ื ืืœื” ืžื–ื•ื”ื™ื ื•ืžืขื•ื‘ื“ื™ื ื‘ืฆื•ืจื” ื ื›ื•ื ื”, ืžื” ืฉืžืงืœ ืขืœ ื”ืคืขืœืช ื”ืงื•ื“ ืžืงื•ืžื™ืช ืœืฆื•ืจืš ืื™ืชื•ืจ ื‘ืื’ื™ื, ื‘ื“ื™ืงืช ื™ื—ื™ื“ื•ืช ื•ื›ืœ ืฆื•ืจืš ืื—ืจ. ื–ื” ื—ืฉื•ื‘ ืœื ื• ื‘ืžื™ื•ื—ื“ ืžื›ื™ื•ื•ืŸ ืฉื™ืฉ ืขื•ื“ ื”ืจื‘ื” ืฆืจื›ื™ื - ื—ืœืง ืžื”ืงื•ื“ ืฉืœื ื• ืžื™ื•ืขื“ ืœื—ื™ืฉื•ื‘ื™ื ืื ืœื™ื˜ื™ื™ื ืฉื•ื ื™ื, ื”ื•ื ืคื•ืขืœ ืœื ืจืง ืขืœ ืฉืจืชื™ื ืขื ืชื–ืžื•ืจ, ืืœื ื’ื ืขื ืกืงืจื™ืคื˜ื™ื ืฉื•ื ื™ื, ื•ืขืœ ืžื—ืฉื‘ื™ื ืฉืœ ืื ืœื™ืกื˜ื™ื ืฉืฆืจื™ื›ื™ื ืœืขื‘ื•ื“ ื“ืจืš ื•ื ื™ืคื•ื™ ื‘ืื’ื™ื ื‘ืฆื™ื ื•ืจื•ืช ืขื™ื‘ื•ื“ ื ืชื•ื ื™ื ืžื•ืจื›ื‘ื™ื ืžื‘ืœื™ ืœื”ื“ืื™ื’ ื‘ืขื™ื•ืช ืงืฆื”. ืื’ื‘, ืœื ื™ื–ื™ืง ืœืฉืชืฃ ืฉื”ื›ืœื™ื ื”ืขื™ืงืจื™ื™ื ืฉืœื ื•, ื›ื•ืœืœ ืงื•ื“ ืคืจื™ืกืช ื”ืชืฆื•ืจื”, ืžื•ืชืงื ื™ื ื‘ืืžืฆืขื•ืช setup.py - ื‘ื™ื—ื“ ื–ื” ืžืื—ื“ ืืช ื”ืงื•ื“ ืฉืœื ื• ืœืืงื•ืกื™ืกื˜ื ืื—ื“, ืœืœื ืชืœื•ืช ื‘ืคืœื˜ืคื•ืจืžื” ื•ื‘ืฉื™ื˜ืช ื”ืฉื™ืžื•ืฉ.

ื”ืชื™ืื•ืจ ืฉืœ ืชืจืžื™ืœ Kubernetes ื ืจืื” ื›ืš:

containers:
  - name : enter-api
    image: enter-api:latest
    ports:
      - containerPort: 80
    volumeMounts:
      - name: db-main-secret-volume
        mountPath: /etc/secrets/db-main

volumes:
  - name: db-main-secret-volume
    secret:
      secretName: db-main-secret

ื›ืœื•ืžืจ, ื›ืœ ืกื•ื“ ืžืชืืจ ืงื˜ืข ืื—ื“. ื”ืกื•ื“ื•ืช ืขืฆืžื ื ื•ืฆืจื™ื ื›ืš:

apiVersion: v1
kind: Secret
metadata:
  name: db-main-secret
type: Opaque
stringData:
  db_main.yaml: |
    engine: sqlite
    filename: main.sqlite3

ื™ื—ื“ ื–ื” ืžื‘ื™ื ืœื™ืฆื™ืจืช ืงื‘ืฆื™ YAML ืœืื•ืจืš ื”ื ืชื™ื‘ /etc/secrets/db-main/section_name.yaml

ื•ืขื‘ื•ืจ ื”ืฉืงื•ืช ืžืงื•ืžื™ื•ืช, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืชืฆื•ืจื”, ื”ืžืžื•ืงืžืช ื‘ืกืคืจื™ื™ืช ื”ื‘ืกื™ืก ืฉืœ ื”ืคืจื•ื™ืงื˜ ืื• ืœืื•ืจืš ื”ื ืชื™ื‘ ื”ืžืฆื•ื™ืŸ ื‘ืžืฉืชื ื” ื”ืกื‘ื™ื‘ื”. ืืช ื”ืงื•ื“ ื”ืื—ืจืื™ ืœื ื•ื—ื•ืช ืืœื• ื ื™ืชืŸ ืœืจืื•ืช ื‘ืกืคื•ื™ืœืจ.

config.py

__author__ = 'AivanF'
__copyright__ = 'Copyright 2020, AivanF'

import os
import yaml

__all__ = ['config']
PROJECT_DIR = os.path.abspath(__file__ + 3 * '/..')
SECRETS_DIR = '/etc/secrets'
KEY_LOG = '_config_log'
KEY_DBG = 'debug'

def is_yes(value):
    if isinstance(value, str):
        value = value.lower()
        if value in ('1', 'on', 'yes', 'true'):
            return True
    else:
        if value in (1, True):
            return True
    return False

def update_config_part(config, key, data):
    if key not in config:
        config[key] = data
    else:
        config[key].update(data)

def parse_big_config(config, filename):
    '''
    Parse YAML config with multiple section
    '''
    if not os.path.isfile(filename):
        return False
    with open(filename) as f:
        config_new = yaml.safe_load(f.read())
        for key, data in config_new.items():
            update_config_part(config, key, data)
        config[KEY_LOG].append(filename)
        return True

def parse_tiny_config(config, key, filename):
    '''
    Parse YAML config with a single section
    '''
    with open(filename) as f:
        config_tiny = yaml.safe_load(f.read())
        update_config_part(config, key, config_tiny)
        config[KEY_LOG].append(filename)

def combine_config():
    config = {
        # To debug config load code
        KEY_LOG: [],
        # To debug other code
        KEY_DBG: is_yes(os.environ.get('DEBUG')),
    }
    # For simple local runs
    CONFIG_SIMPLE = os.path.join(PROJECT_DIR, 'config.yaml')
    parse_big_config(config, CONFIG_SIMPLE)
    # For container's tests
    CONFIG_ENVVAR = os.environ.get('CONFIG')
    if CONFIG_ENVVAR is not None:
        if not parse_big_config(config, CONFIG_ENVVAR):
            raise ValueError(
                f'No config file from EnvVar:n'
                f'{CONFIG_ENVVAR}'
            )
    # For K8s secrets
    for path, dirs, files in os.walk(SECRETS_DIR):
        depth = path[len(SECRETS_DIR):].count(os.sep)
        if depth > 1:
            continue
        for file in files:
            if file.endswith('.yaml'):
                filename = os.path.join(path, file)
                key = file.rsplit('.', 1)[0]
                parse_tiny_config(config, key, filename)
    return config

def build_config():
    config = combine_config()
    # Preprocess
    for key, data in config.items():
        if key.startswith('db_'):
            if data['engine'] == 'sqlite':
                data['filename'] = os.path.join(PROJECT_DIR, data['filename'])
    # To verify correctness
    if config[KEY_DBG]:
        print(f'** Loaded config:n{yaml.dump(config)}')
    else:
        print(f'** Loaded config from: {config[KEY_LOG]}')
    return config

config = build_config()

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

ืื ื™ ืžืงื•ื•ื” ืฉืžื” ืฉืžืชื•ืืจ ื™ื”ื™ื” ืฉื™ืžื•ืฉื™ ืœืžื™ืฉื”ื• :) ื›ืœ ื”ืขืจื” ื•ื”ืžืœืฆื” ืœื’ื‘ื™ ืื‘ื˜ื—ื” ืื• ืชื—ื•ืžื™ื ืื—ืจื™ื ืœืฉื™ืคื•ืจ ืžืชืงื‘ืœื•ืช. ื’ื ื“ืขืช ื”ืงื”ื™ืœื” ืžืขื ื™ื™ื ืช, ืื•ืœื™ ื›ื“ืื™ ืœื”ื•ืกื™ืฃ ืชืžื™ื›ื” ื‘-ConfigMaps (ื”ืคืจื•ื™ืงื˜ ืฉืœื ื• ืขื“ื™ื™ืŸ ืœื ืžืฉืชืžืฉ ื‘ื”ื) ื•ืœืคืจืกื ืืช ื”ืงื•ื“ ื‘-GitHub / PyPI? ื‘ืื•ืคืŸ ืื™ืฉื™, ืื ื™ ื—ื•ืฉื‘ ืฉื“ื‘ืจื™ื ื›ืืœื” ืื™ื ื“ื™ื‘ื™ื“ื•ืืœื™ื™ื ืžื›ื“ื™ ืฉืคืจื•ื™ืงื˜ื™ื ื™ื”ื™ื• ืื•ื ื™ื‘ืจืกืœื™ื™ื, ื•ืงืฆืช ื”ืฆืฆื” ืœื™ื™ืฉื•ื ืฉืœ ืื ืฉื™ื ืื—ืจื™ื, ื›ืžื• ื–ื” ืฉื ื™ืชืŸ ื›ืืŸ, ื•ื“ื™ื•ืŸ ื‘ื ื™ื•ืื ืกื™ื, ื˜ื™ืคื™ื ื•ืฉื™ื˜ื•ืช ืขื‘ื•ื“ื” ืžื•ืžืœืฆื•ืช, ืฉืื ื™ ืžืงื•ื•ื” ืœืจืื•ืช ื‘ืชื’ื•ื‘ื•ืช. , ื–ื” ืžืกืคื™ืง ๐Ÿ˜‰

ืจืง ืžืฉืชืžืฉื™ื ืจืฉื•ืžื™ื ื™ื›ื•ืœื™ื ืœื”ืฉืชืชืฃ ื‘ืกืงืจ. ืœื”ืชื—ื‘ืจื‘ื‘ืงืฉื”.

ื”ืื ืขืœื™ ืœืคืจืกื ื›ืคืจื•ื™ืงื˜/ืกืคืจื™ื™ื”?

  • 0,0%ื›ืŸ, ื”ื™ื™ืชื™ ืžืฉืชืžืฉ ื‘-/contribution0

  • 33,3%ื›ืŸ, ื–ื” ื ืฉืžืข ื ื”ื“ืจ4

  • 41,7%ืœื, ืžื™ ืฆืจื™ืš ืœืขืฉื•ืช ืืช ื–ื” ื‘ืขืฆืžื• ื‘ืžืชื›ื•ื ืช ืฉืœื• ื•ื‘ื”ืชืื ืœืฆืจื›ื™ื•5

  • 25,0%ืื ื™ ืืžื ืข ืžืœืขื ื•ืช 3

12 ืžืฉืชืžืฉื™ื ื”ืฆื‘ื™ืขื•. 3 ืžืฉืชืžืฉื™ื ื ืžื ืขื•.

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

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