Bu yaxınlarda yazdım
Sualın arxa planı belədir: bir vaxtlar bir layihə var idi, əvvəlcə kommunal və skriptləri olan kiçik bir monolit idi, lakin zaman keçdikcə böyüdü, xidmətlərə bölündü, o da öz növbəsində mikroservislərə bölünməyə başladı və sonra böyüdü. Əvvəlcə bütün bunlar çılpaq VPS-də edildi, kodun qurulması və yerləşdirilməsi prosesləri Ansible vasitəsilə avtomatlaşdırıldı və hər bir xidmət lazımi parametrlər və açarlarla YAML konfiqurasiyası ilə tərtib edildi və oxşar konfiqurasiya faylı üçün istifadə edildi. yerli işə salındı, bu çox rahat idi, çünki .k bu konfiqurasiya qlobal obyektə yüklənir, layihənin istənilən yerindən əlçatandır.
Bununla belə, mikroservislərin sayının artması, onların əlaqəsi və
Bununla əlaqədar olaraq, konfiqurasiya obyektinin qurulması mexanizmi həm klassik konfiqurasiya faylımızla, həm də Kuber-in sirləri ilə işləyə bilmək üçün dəyişdirildi. Üçüncü Python dilində daha sərt konfiqurasiya strukturu da aşağıdakı kimi göstərilmişdir:
Dict[küç, Dict[küç, Union[str, int, float]]]
Yəni, son dişli, hər biri sadə növlərdən dəyərləri olan bir lüğət olan adlandırılmış bölmələri olan bir lüğətdir. Və bölmələr konfiqurasiyanı və müəyyən bir növ resurslara çıxışı təsvir edir. Konfiqurasiyamızın bir parçasına bir nümunə:
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"
Eyni zamanda, sahə engine
verilənlər bazası SQLite-də quraşdırıla bilər və redis
təyin edin mock
, saxlanacaq faylın adının da göstərilməsi - bu parametrlər düzgün şəkildə tanınır və işlənir, bu, sazlama, vahid testi və hər hansı digər ehtiyaclar üçün kodu yerli olaraq işə salmağı asanlaşdırır. Bu, bizim üçün xüsusilə vacibdir, çünki bir çox başqa ehtiyaclar da var - kodun bir hissəsi müxtəlif analitik hesablamalar üçün nəzərdə tutulub, o, təkcə orkestrasiya ilə serverlərdə deyil, həm də müxtəlif skriptlərlə və işləməli olan analitiklərin kompüterlərində işləyir. və arxa uç problemlərini narahat etmədən mürəkkəb məlumat emal boru kəmərlərini sazlayın. Yeri gəlmişkən, əsas alətlərimizin, o cümlədən konfiqurasiya layout kodunun vasitəsilə quraşdırıldığını bölüşmək zərər verməz. setup.py
– birlikdə bu, kodumuzu platformadan və istifadə üsulundan asılı olmayaraq vahid ekosistemdə birləşdirir.
Kubernetes podunun təsviri belə görünür:
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
Yəni hər sirr bir bölməni təsvir edir. Sirlərin özləri belə yaradılmışdır:
apiVersion: v1
kind: Secret
metadata:
name: db-main-secret
type: Opaque
stringData:
db_main.yaml: |
engine: sqlite
filename: main.sqlite3
Birlikdə bu, yol boyunca YAML fayllarının yaradılması ilə nəticələnir /etc/secrets/db-main/section_name.yaml
Yerli işə salınmalar üçün layihənin kök qovluğunda və ya mühit dəyişənində göstərilən yolda yerləşən konfiqurasiya istifadə olunur. Bu rahatlıqlara cavabdeh olan kodu spoylerdə görmək olar.
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()
Buradakı məntiq olduqca sadədir: biz layihə kataloqundan və ətraf mühit dəyişəninə görə yollardan böyük konfiqurasiyaları və Kuber sirlərindən kiçik konfiqurasiya bölmələrini birləşdiririk və sonra onları bir az əvvəlcədən emal edirik. Üstəlik bəzi dəyişənlər. Qeyd edirəm ki, sirlərdən faylları axtararkən dərinlik məhdudiyyətindən istifadə olunur, çünki K8s hər bir sirrdə sirlərin özlərinin saxlandığı gizli qovluq yaradır və sadəcə bir keçid daha yüksək səviyyədə yerləşir.
Ümid edirəm ki, təsvir edilənlər kimsə üçün faydalı olacaq :) Təhlükəsizlik və ya təkmilləşdirmə üçün digər sahələrlə bağlı hər hansı şərh və tövsiyələr qəbul edilir. İcmanın rəyi də maraqlıdır, bəlkə ConfigMaps (bizim layihəmiz hələ onlardan istifadə etmir) üçün dəstək əlavə etməyə və kodu GitHub / PyPI-də dərc etməyə dəyər? Şəxsən mən hesab edirəm ki, bu cür şeylər layihələrin universal olması üçün çox fərdidir və burada verilən kimi digər insanların tətbiqlərinə bir az nəzər salmaq və şərhlərdə görəcəyimə ümid etdiyim nüansların, məsləhətlərin və ən yaxşı təcrübələrin müzakirəsi. , kifayətdir 😉
Sorğuda yalnız qeydiyyatdan keçmiş istifadəçilər iştirak edə bilər.
Layihə/kitabxana kimi dərc etməliyəm?
-
0,0%Bəli, /contribution0 istifadə edərdim
-
33,3%Bəli, əla səslənir4
-
41,7%Xeyr, bunu kimin öz formatında və ehtiyaclarına uyğun olaraq etməsi lazımdır5
-
25,0%Cavab verməkdən çəkinəcəyəm3
12 istifadəçi səs verib. 3 istifadəçi bitərəf qalıb.
Mənbə: www.habr.com