Para pak sa shkruaja , ku pĂ«rmenda nĂ« kalim se Ă«shtĂ« e mundur tĂ« krijosh sistemin tĂ«nd tĂ« konfigurimit, nĂ« mĂ«nyrĂ« qĂ« shĂ«rbimi tĂ« funksiononte mirĂ« edhe nĂ« Kubernetes, tĂ« merrte sekrete, dhe tĂ« niste nĂ« mĂ«nyrĂ« komode edhe jashtĂ« Dockerit. AsgjĂ« e komplikuar, por "receta" e pĂ«rshkruar mund tĂ« jetĂ« e dobishme pĂ«r dikĂ« đ Kodi Ă«shtĂ« nĂ« Python, por logjika nuk lidhet me gjuhĂ«n.

Historiku i pyetjes është si më poshtë: ka qenë një projekt, fillimisht ishte një monolit i vogël me utilitarë dhe skripte, por me kalimin e kohës u rrit, u ndan në shërbime, të cilat nga ana e tyre filluan të ndaheshin në mikroshërbime, dhe më pas edhe të shkalloheshin. Fillimisht, të gjitha këto ishin realizuar në VPS të thjeshtë, proceset e konfigurimit dhe vendosjes së kodit ishin automatizuar me Ansible, dhe për çdo shërbim ishte hartuar një YAML-konfigurim me cilësimet dhe çelësat e nevojshëm, dhe një skedar konfigurimi i ngjashëm përdorej për nisjet lokale, që ishte shumë e përshtatshme, pasi ky konfigurim ngarkohet në një objekt global, të disponueshëm nga çdo vend në projekt.
Megjithatë, rritja e numrit të mikroshërbimeve, lidhjeve të tyre, si dhe , parashikon zhvendosjen në Kubernetes, e cila ende është në proces. Përveç ndihmës në zgjidhjen e problemeve të përmendura, Kubernetes ofron qasje të tij për menaxhimin e infrastrukturës, përfshirë dhe . Mekanizmi është standard dhe i besueshëm, prandaj në sensin e drejtë është mëkat të mos e shfrytëzosh! Por, me këtë do të dëshironim të ruanim formatin tonë aktual të punës me konfigurimin: së pari, të përdorim në mënyrë uniforme atë në mikroshërbime të ndryshme të projektit, dhe së dyti, të kemi mundësinë të nisim kodin në makinën lokale duke përdorur një skedar të thjeshtë konfigurimi.
Me këtë në mendje, mekanizmi i ndërtimit të objektit të konfigurimit u përmirësua në mënyrë që të dinte të punonte si me skedarin tonë klasik të konfigurimit, ashtu edhe me sekretet nga Kubernetes. Po ashtu, u caktua një strukturë më e fortë për konfigurimin, duke folur në gjuhën e tretë të Python:
Dict[str, Dict[str, Union[str, int, float]]]
Domethënë, konfigurimi përfundimtar është një fjalor me seksione të emëruara, secila prej të cilave është një fjalor me vlera nga llojet e thjeshta. Seksionet përshkruajnë konfigurimin dhe akseset deri në burime të një lloji të caktuar. Një shembull i një pjese të konfigurimit tonë:
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: info@test.com
pw: "SuperHardPassword"NĂ« tĂ« njĂ«jtĂ«n kohĂ«, fusha engine e bazĂ«s sĂ« tĂ« dhĂ«nave mund tĂ« vendoset nĂ« SQLite, ndĂ«rsa redis konsolidohet nĂ« mock, duke specifikuar gjithashtu emrin e skedarit pĂ«r ruajtje, - kĂ«to parametra njihen dhe pĂ«rpunohen siç duhet, gjĂ« qĂ« lejon qe tĂ« filloni lehtĂ«sisht kodin lokal pĂ«r shqyrtim, testim njĂ«si dhe çdo nevojĂ« tjetĂ«r. Kjo Ă«shtĂ« veçanĂ«risht e rĂ«ndĂ«sishme pĂ«r ne, pasi kĂ«to nevoja janĂ« tĂ« shumta - njĂ« pjesĂ« e kodit tonĂ« Ă«shtĂ« e destinuar pĂ«r llogaritje analitike tĂ« ndryshme, e cila ekzekutohet jo vetĂ«m nĂ« serverĂ« me orkestrim, por dhe me skedarĂ« tĂ« ndryshĂ«m, dhe nĂ« kompjuterĂ«t e analistĂ«ve, tĂ« cilĂ«t kanĂ« nevojĂ« tĂ« punojnĂ« pĂ«rmes dhe tĂ« rregullojnĂ« konvejerĂ«t e ndĂ«rlikuar tĂ« pĂ«rpunimit tĂ« tĂ« dhĂ«nave pa u shqetĂ«suar pĂ«r pyetjet lidhur me back-end-in. NĂ« fakt, nuk do tĂ« ishte e tepĂ«rt tĂ« ndajmĂ« se mjetet tona kryesore, duke pĂ«rfshirĂ« kodin e montimit tĂ« konfiguracionit, instalohen pĂ«rmes setup.py â sĂ« bashku kjo bashkon kodin tonĂ« nĂ« njĂ« ekosistem tĂ« vetme, tĂ« pavarur nga platforma dhe mĂ«nyra e pĂ«rdorimit.
Përshkrimi i pod-it në Kubernetes duket kështu:
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-secretPra, në secilin sekret përshkruhet një seksion. Sekretet krijohen kështu:
apiVersion: v1
kind: Secret
metadata:
name: db-main-secret
type: Opaque
stringData:
db_main.yaml: |
engine: sqlite
filename: main.sqlite3Kjo së bashku çon në krijimin e skedarëve YAML në rrugën /etc/secrets/db-main/section_name.yaml
Dhe për ekzekutimet lokale përdoret konfigurimi, i vendosur në drejtorinë kryesore të projektit ose në rrugën e specifikuar në variablin e ambientit. Kodi, i cili është përgjegjës për këto lehtësira, mund të shihet në 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()Logjika këtu është mjaft e thjeshtë: bashkojmë konfigurimet e mëdha nga direktoria e projektit dhe rruga nga variabla mjedisor, dhe konfigurimet e vogla-seksione nga sekretet e Kubernetes, më pas pak i përpunojmë ato. Plus ndonjë variabël. Vërej se kur kërkohen skedarë nga sekretet, përdoret një kufizim thellësie, pasi K8s në secilin sekret krijon një dosje të fshehtë ku vetë sekretet ruhen, dhe një nivel lart është thjesht një lidhje.
Shpresoj qĂ« ajo qĂ« pĂ«rshkruhet do t'i vlejĂ« dikujt đ Pranohet çdo koment dhe rekomandim nĂ« lidhje me sigurinĂ« ose aspekte tĂ« tjera pĂ«r pĂ«rmirĂ«sim. Gjithashtu, mĂ« intereson mendimi i komunitetit, ndoshta duhet tĂ« shtojmĂ« mbĂ«shtetje pĂ«r ConfigMaps (nĂ« projektin tonĂ« ato ende nuk pĂ«rdoren) dhe tĂ« publikojmĂ« kodin nĂ« GitHub / PyPI? Personalish mendoj se kĂ«to gjĂ«ra janĂ« shumĂ« tĂ« individualizuara pĂ«r projekte pĂ«r t'u bĂ«rĂ« universale, dhe mjafton tĂ« kemi pak shikim nĂ« realizimet e tĂ« tjerĂ«ve, siç Ă«shtĂ« e pĂ«rmendur kĂ«tu, dhe tĂ« diskutojmĂ« nuancat, kĂ«shillat dhe praktikat mĂ« tĂ« mira, tĂ« cilat shpresoj t'i shoh nĂ« komentet đ
Vetëm përdoruesit e regjistruar mund të marrin pjesë në anketë. , ju lutem.
A duhet ta publikoj si projekt / bibliotekë?
0,0%Po, do ta përdorja / kontribuoj.
33,3%Po, tingëllon mirë.
41,7%Jo, kush ka nevojë do ta bëjë vetë në formatin e tij dhe për nevojat e tij.
25,0%Do të abstinoj nga përgjigjja.
12 përdorues kanë votuar. 3 përdorues janë abstenuar.
Burimi: habr.com
