Es nesen rakstīju
JautÄjuma fons ir Å”Äds: kÄdreiz bija viens projekts, sÄkumÄ tas bija mazs monolÄ«ts ar komunÄlajiem pakalpojumiem un skriptiem, bet laika gaitÄ tas pieauga, sadalÄ«jÄs pa servisiem, kurus savukÄrt sÄka sadalÄ«t mikropakalpojumos un pÄc tam palielinÄts. SÄkumÄ tas viss tika darÄ«ts tukÅ”Ä VPS, kurÄ koda iestatÄ«Å”anas un izvietoÅ”anas procesi tika automatizÄti, izmantojot Ansible, un katrs pakalpojums tika kompilÄts ar YAML konfigurÄciju ar nepiecieÅ”amajiem iestatÄ«jumiem un atslÄgÄm, kÄ arÄ« tika izmantots lÄ«dzÄ«gs konfigurÄcijas fails. lokÄlÄs palaiÅ”anas, kas bija ļoti Ärti, jo .k Ŕī konfigurÄcija tiek ielÄdÄta globÄlÄ objektÄ, kas ir pieejama no jebkuras vietas projektÄ.
TaÄu mikropakalpojumu skaita pieaugums, to pieslÄgumi un
Å ajÄ sakarÄ tika modificÄts konfigurÄcijas objekta konstruÄÅ”anas mehÄnisms, lai varÄtu strÄdÄt gan ar mÅ«su klasisko konfigurÄcijas failu, gan ar Kuber noslÄpumiem. TreÅ”Ä Python valodÄ tika norÄdÄ«ta arÄ« stingrÄka konfigurÄcijas struktÅ«ra:
Dict[str, Dict[str, Union[str, int, float]]]
Tas nozÄ«mÄ, ka pÄdÄjais zobrats ir vÄrdnÄ«ca ar nosauktÄm sadaļÄm, no kurÄm katra ir vÄrdnÄ«ca ar vienkÄrÅ”u veidu vÄrtÄ«bÄm. SadaļÄs ir aprakstÄ«ta noteikta veida konfigurÄcija un piekļuve tiem resursiem. MÅ«su konfigurÄcijas daļas piemÄrs:
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"
TajÄ paÅ”Ä laikÄ lauks engine
datu bÄzes var instalÄt SQLite, un redis
iestatīts uz mock
, norÄdot arÄ« saglabÄjamÄ faila nosaukumu ā Å”ie parametri tiek pareizi atpazÄ«ti un apstrÄdÄti, kas ļauj Ärti palaist kodu lokÄli atkļūdoÅ”anai, vienÄ«bu pÄrbaudei un citÄm vajadzÄ«bÄm. Tas mums ir Ä«paÅ”i svarÄ«gi, jo ir daudz citu vajadzÄ«bu - daļa mÅ«su koda ir paredzÄta dažÄdiem analÄ«tiskiem aprÄÄ·iniem, tas darbojas ne tikai serveros ar orÄ·estrÄÅ”anu, bet arÄ« ar dažÄdiem skriptiem un analÄ«tiÄ·u datoros, kuriem nepiecieÅ”ams strÄdÄt. un atkļūdojiet sarežģītus datu apstrÄdes cauruļvadus, neradot aizmugursistÄmas problÄmas. Starp citu, nenÄktu par ļaunu pastÄstÄ«t, ka mÅ«su galvenie rÄ«ki, tostarp konfigurÄcijas izkÄrtojuma kods, tiek instalÄti, izmantojot setup.py
ā kopÄ tas apvieno mÅ«su kodu vienÄ ekosistÄmÄ, kas nav atkarÄ«ga no platformas un lietoÅ”anas metodes.
Kubernetes pÄksts apraksts izskatÄs Å”Ädi:
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
Tas ir, katrs noslÄpums apraksta vienu sadaļu. PaÅ”i noslÄpumi tiek izveidoti Å”Ädi:
apiVersion: v1
kind: Secret
metadata:
name: db-main-secret
type: Opaque
stringData:
db_main.yaml: |
engine: sqlite
filename: main.sqlite3
KopÄ tas rada YAML failu izveidi ceÄ¼Ä /etc/secrets/db-main/section_name.yaml
Un vietÄjai palaiÅ”anai tiek izmantota konfigurÄcija, kas atrodas projekta saknes direktorijÄ vai pa ceļu, kas norÄdÄ«ts vides mainÄ«gajÄ. Par Ŕīm ÄrtÄ«bÄm atbildÄ«go kodu var redzÄt spoilerÄ«.
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()
LoÄ£ika Å”eit ir pavisam vienkÄrÅ”a: mÄs apvienojam lielas konfigurÄcijas no projekta direktorija un ceļus pÄc vides mainÄ«gÄ un mazas konfigurÄcijas sadaļas no Kuber noslÄpumiem, un pÄc tam tÄs nedaudz apstrÄdÄjam. Plus daži mainÄ«gie. Es atzÄ«mÄju, ka, meklÄjot failus no noslÄpumiem, tiek izmantots dziļuma ierobežojums, jo K8s katrÄ noslÄpumÄ izveido slÄptu mapi, kurÄ tiek glabÄti paÅ”i noslÄpumi, un tikai saite atrodas augstÄkÄ lÄ«menÄ«.
Ceru, ka aprakstÄ«tais kÄdam noderÄs :) Jebkuri komentÄri un ieteikumi saistÄ«bÄ ar droŔību vai citÄm uzlaboÅ”anas jomÄm tiek pieÅemti. Interesants ir arÄ« kopienas viedoklis, varbÅ«t ir vÄrts pievienot atbalstu ConfigMaps (mÅ«su projekts tos vÄl neizmanto) un publicÄt kodu GitHub / PyPI? Man personÄ«gi liekas, ka Å”Ädas lietas ir pÄrÄk individuÄlas, lai projekti bÅ«tu universÄli, un nedaudz palÅ«kojoties uz citu Ä«stenotajiem, kÄ Å”eit dotajiem, un niansÄm, padomiem un paraugpraksÄm, ko ceru redzÄt komentÄros. , pietiek š
AptaujÄ var piedalÄ«ties tikai reÄ£istrÄti lietotÄji.
Vai man jÄpublicÄ kÄ projekts/bibliotÄka?
-
0,0%JÄ, es izmantotu /contribution0
-
33,3%JÄ, tas izklausÄs lieliski 4
-
41,7%NÄ, kam tas jÄdara paÅ”am savÄ formÄtÄ un atbilstoÅ”i savÄm vajadzÄ«bÄm5
-
25,0%Es atturÄÅ”os atbildÄt 3
Nobalsoja 12 lietotÄji. 3 lietotÄji atturÄjÄs.
Avots: www.habr.com