Proiektuaren konfigurazioa Kubernetesen barruan eta kanpoan

Duela gutxi idatzi dut erantzun Docker-en proiektuaren bizitzari eta hortik kanpo arazketa kodeari buruz, non laburki aipatu zuen zure konfigurazio-sistema propioa egin dezakezula, zerbitzuak Kuber-en ondo funtziona dezan, sekretuak bildu eta lokalean eroso exekutatzeko, Dockerretik kanpo ere. Ez dago ezer konplikatua, baina deskribatutako "errezeta" baliagarria izan daiteke norbaitentzat :) Kodea Python-en dago, baina logika ez dago hizkuntzari lotuta.

Proiektuaren konfigurazioa Kubernetesen barruan eta kanpoan

Galderaren atzeko planoa hau da: garai batean proiektu bat zegoen, hasieran utilitateak eta script-ak zituen monolito txiki bat zen, baina denborarekin haziz joan zen, zerbitzuetan banatuz, eta, aldi berean, mikrozerbitzuetan banatzen hasi ziren, eta gero eskalatu. Hasieran, hori guztia VPS hutsean egiten zen, Ansible erabiliz kodea konfiguratzeko eta zabaltzeko prozesuak automatizatu ziren, eta zerbitzu bakoitza YAML konfigurazio batekin konpilatu zen beharrezko ezarpen eta gakoekin, eta antzeko konfigurazio fitxategi bat erabili zen. tokiko abiarazteak, oso erosoa izan zen, zeren .k konfigurazio hau objektu global batean kargatzen da, proiektuko edozein lekutatik eskuragarria.

Hala ere, mikrozerbitzuen kopuruaren hazkundea, haien konexioak eta erregistro eta monitorizazio zentralizatuaren beharra, Kuber-era mugimendu bat iragarri zuen, oraindik abian dagoena. Aipatutako arazoak konpontzeko laguntzarekin batera, Kubernetesek azpiegituren kudeaketarako bere ikuspegiak eskaintzen ditu, besteak beste. Sekretuak deiturikoak и haiekin lan egiteko moduak. Mekanismoa estandarra eta fidagarria da, beraz, literalki bekatua da ez erabiltzea! Baina, aldi berean, konfigurazioarekin lan egiteko gaur egungo formatua mantendu nahiko nuke: lehenik eta behin, proiektuko mikrozerbitzu desberdinetan uniformeki erabiltzea, eta, bigarrenik, kodea tokiko makinan exekutatu ahal izatea sinple bat erabiliz. konfigurazio fitxategia.

Zentzu honetan, konfigurazio-objektu bat eraikitzeko mekanismoa aldatu egin zen, gure konfigurazio-fitxategi klasikoarekin zein Kuber-en sekretuekin lan egin ahal izateko. Konfigurazio-egitura zurrunago bat ere zehaztu zen, hirugarren Python-en hizkuntzan, honela:

Dict[str, Dict[str, Batasuna[str, int, float]]]

Hau da, azken cogfig atal izendunen hiztegi bat da, eta horietako bakoitza mota sinpleetako balioak dituen hiztegi bat da. Eta atalek mota jakin bateko baliabideetarako konfigurazioa eta sarbidea deskribatzen dituzte. Gure konfigurazioaren zati baten adibidea:

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"

Aldi berean, zelaia engine datu-baseak SQLite-n instalatu daitezke, eta redis ezarri mock, gorde beharreko fitxategiaren izena ere zehaztuz - parametro hauek behar bezala ezagutzen eta prozesatzen dira, eta horri esker, kodea lokalean exekutatzeko erraza da arazketa, unitate-probak eta beste edozein beharretarako. Hau bereziki garrantzitsua da guretzat, beste behar asko daudelako: gure kodearen zati bat kalkulu analitiko ezberdinetarako dago pentsatuta, orkestrazioa duten zerbitzarietan ez ezik, hainbat scriptekin ere exekutatzen da eta lan egin behar duten analistaren ordenagailuetan. eta arazketa datuak prozesatzeko kanalizazio konplexuak backend-arazoak kezkatu gabe. Bide batez, ez legoke kalterik gure tresna nagusiak, konfigurazio diseinu-kodea barne, bidez instalatuta daudela partekatzea. setup.py – elkarrekin honek gure kodea ekosistema bakar batean batzen du, plataforma eta erabilera metodotik independentea.

Kubernetes pod baten deskribapena honelakoa da:

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

Hau da, sekretu bakoitzak atal bat deskribatzen du. Sekretuak berak honela sortzen dira:

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

Horrek batera, YAML fitxategiak sortzen ditu bidean zehar /etc/secrets/db-main/section_name.yaml

Eta tokiko abiarazteetarako, konfigurazioa erabiltzen da, proiektuaren erro-direktorioan edo ingurune-aldagaian zehaztutako bidetik. Erosotasun horien ardura duen kodea spoilerrean ikus daiteke.

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

Hemen logika nahiko sinplea da: proiektuaren direktorioko konfigurazio handiak eta bideak ingurune-aldagaiaren arabera konbinatzen ditugu eta Kuber-eko sekretuetako konfigurazio atal txikiak konbinatzen ditugu eta, ondoren, apur bat aldez aurretik prozesatzen ditugu. Gainera aldagai batzuk. Kontuan izan dut sekretuetatik fitxategiak bilatzean, sakontasun-muga bat erabiltzen dela, K8s-ek sekretuak gordeta dauden sekretu bakoitzean ezkutuko karpeta bat sortzen duelako eta esteka bat besterik ez dago maila altuago batean.

Deskribatzen dena norbaitentzat erabilgarria izatea espero dut :) Segurtasunari edo hobetzeko beste arlo batzuei buruzko iruzkinak eta gomendioak onartzen dira. Komunitatearen iritzia ere interesgarria da, agian merezi du ConfigMaps-en laguntza gehitzea (gure proiektuak oraindik ez ditu erabiltzen) eta kodea GitHub / PyPI-n argitaratzea? Pertsonalki, uste dut horrelako gauzak indibidualegiak direla proiektuak unibertsalak izateko, eta besteen inplementazioei begirada pixka bat, hemen ematen den moduan, eta ñabardura, aholku eta jardunbide egokien eztabaida, iruzkinetan ikustea espero dut. , nahikoa da 😉

Erregistratutako erabiltzaileek soilik parte hartu dezakete inkestan. Hasi saioa, mesedez.

Proiektu/liburutegi gisa argitaratu behar al dut?

  • 0,0%Bai, /contribution0 erabiliko nuke

  • 33,3%Bai, oso ona dirudi horrek4

  • 41,7%Ez, nork bere formatuan eta beharretara egokitzeko egin behar duena5

  • 25,0%Ez dut erantzunik3

12 erabiltzailek eman dute botoa. 3 erabiltzaile abstenitu ziren.

Iturria: www.habr.com

Gehitu iruzkin berria