Niliandika hivi majuzi , ambapo nilitaja kwa ufupi kwamba unaweza kuunda mfumo wako wa usanidi ili huduma ifanye kazi vizuri katika Kubernetes, kuvuta kwa siri, na kukimbia kwa urahisi ndani ya nchi, hata nje ya Docker. Sio ngumu, lakini "mapishi" yaliyoelezwa yanaweza kuwa na manufaa kwa mtu :) Nambari iko kwenye Python, lakini mantiki haijafungwa kwa lugha.

Asili ya swali ni hii: kulikuwa na mradi. Ilianza kama monolith ndogo na huduma na maandishi, lakini baada ya muda ilikua, ikigawanyika katika huduma, ambayo kwa upande wake iligawanyika katika huduma ndogo, na kisha kuongeza. Hapo awali, kila kitu kiliendeshwa kwa VPS tupu, na usanidi na uwekaji wa nambari ukitumia kiotomatiki kwa kutumia Ansible. Kila huduma ilikuwa na faili ya usanidi ya YAML yenye mipangilio na vitufe vinavyohitajika, na faili sawa ya usanidi ilitumika kwa uzinduzi wa ndani. Hii ilikuwa rahisi sana, kwani usanidi huu ulipakiwa kwenye kitu cha kimataifa kinachoweza kufikiwa kutoka mahali popote kwenye mradi.
Hata hivyo, ukuaji wa idadi ya microservices, uhusiano wao, na , ilitangulia kuhamia Kubernetes, ambayo bado inaendelea. Pamoja na kusaidia kutatua matatizo yaliyotajwa hapo juu, Kubernetes inatoa mbinu zake za usimamizi wa miundombinu, ikiwa ni pamoja na и Utaratibu huo ni wa kawaida na wa kutegemewa, kwa hiyo itakuwa ni dhambi kutoutumia! Walakini, ningependa kudumisha umbizo langu la usanidi wa sasa: kwanza, kuitumia mara kwa mara katika huduma ndogo ndogo za mradi, na pili, kuweza kuendesha nambari kwenye mashine ya ndani kwa kutumia faili moja, rahisi ya usanidi.
Katika suala hili, utaratibu wa ujenzi wa kitu cha usanidi uliboreshwa ili kufanya kazi na faili zetu za usanidi wa kawaida na siri za Kubernetes. Muundo mgumu zaidi wa usanidi pia ulifafanuliwa, kwa lugha ya Python 3, kama ifuatavyo:
Dict[str, Dict[str, Union[str, int, float]]]
Kwa maneno mengine, usanidi wa mwisho ni kamusi iliyo na sehemu zilizotajwa, ambayo kila moja ni kamusi iliyo na maadili ya aina rahisi. Sehemu zinaelezea haki za usanidi na ufikiaji wa rasilimali za aina maalum. Hapa kuna mfano wa kijisehemu cha usanidi wetu:
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"Katika kesi hii, shamba engine hifadhidata zinaweza kusanikishwa kwenye SQLite, na redis kuanzisha kwa mock, ikibainisha jina la faili ili kuihifadhi—vigezo hivi vinatambulika kwa usahihi na kuchakatwa, huku kuruhusu kuendesha msimbo kwa urahisi ndani ya utatuzi, majaribio ya kitengo, na mahitaji mengine yoyote. Hili ni muhimu sana kwetu kwa sababu tuna mahitaji mengine mengi—sehemu ya msimbo wetu imeundwa kwa ajili ya hesabu mbalimbali za uchanganuzi na inaendeshwa sio tu kwenye seva za ochestration, lakini pia na hati mbalimbali, na kwenye kompyuta za wachambuzi wanaohitaji kuendeleza na kutatua mabomba changamano ya usindikaji wa data bila kuwa na wasiwasi kuhusu masuala ya nyuma. Kwa bahati mbaya, inafaa kutaja kuwa zana zetu kuu, pamoja na nambari ya ujenzi wa usanidi, zimesakinishwa kupitia setup.py - kwa pamoja hii inaunganisha msimbo wetu katika mfumo mmoja wa ikolojia, usiotegemea jukwaa na mbinu ya matumizi.
Maelezo ya pod katika Kubernetes inaonekana kama hii:
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-secretHiyo ni, kila siri inaelezea sehemu moja. Siri zenyewe zimeundwa kama ifuatavyo:
apiVersion: v1
kind: Secret
metadata:
name: db-main-secret
type: Opaque
stringData:
db_main.yaml: |
engine: sqlite
filename: main.sqlite3Kwa pamoja hii husababisha kuundwa kwa faili za YAML njiani /etc/secrets/db-main/section_name.yaml
Kwa uzinduzi wa ndani, faili ya usanidi iliyo katika saraka ya msingi ya mradi au kwenye njia iliyobainishwa katika kigezo cha mazingira hutumiwa. Nambari inayohusika na urahisishaji huu inaweza kuonekana kwenye kiharibifu.
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()Mantiki hapa ni rahisi sana: tunachanganya faili kubwa za usanidi kutoka kwa saraka ya mradi na njia kupitia utofauti wa mazingira na sehemu ndogo za usanidi kutoka kwa siri za Kubernetes, na kisha kuzishughulikia kidogo. Plus baadhi ya vigezo. Kumbuka kwamba kikomo cha kina kinatumika wakati wa kutafuta faili kutoka kwa siri, kwani K8s huunda folda iliyofichwa katika kila siri ambapo siri zenyewe zimehifadhiwa, na kiungo kinahifadhiwa tu ngazi moja ya juu.
Natumaini hii ni muhimu kwa mtu. 🙂 Maoni na mapendekezo yoyote kuhusu usalama au maeneo mengine ya kuboresha yanakaribishwa. Ninavutiwa pia na maoni ya jamii: labda tunapaswa kuongeza msaada kwa ConfigMaps (mradi wetu hautumii kwa sasa) na uweke nambari kwenye GitHub/PyPI? Binafsi, nadhani mambo haya ni mahususi sana kwa miradi kuwa ya ulimwengu wote, na utafiti mdogo juu ya utekelezaji mwingine, kama ule ulio hapa, na mjadala wa nuances, vidokezo, na mazoea bora, ambayo natumai kuona kwenye maoni, yatatosha. 😉
Watumiaji waliojiandikisha pekee ndio wanaweza kushiriki katika utafiti. tafadhali.
Je, nichapishe hii kama mradi/maktaba?
0,0%Ndio, ningetumia / kuchangia0
33,3%Ndio, inasikika vizuri4
41,7%Hapana, wale wanaohitaji wataifanya wenyewe katika muundo wao na kwa mahitaji yao wenyewe.
25,0%Nitaacha kujibu3
Watumiaji 12 walipiga kura. Watumiaji 3 walijizuia.
Chanzo: mapenzi.com
