kirjoitin hiljattain
Kysymyksen tausta on tämä: kerran oli yksi projekti, se oli aluksi pieni monoliitti apuohjelmien ja skriptien kanssa, mutta ajan myötä se kasvoi, jakautui palveluiksi, jotka puolestaan alkoivat jakaa mikropalveluiksi, ja sitten skaalata. Aluksi kaikki tämä tehtiin paljaalla VPS:llä, jossa koodin asennus- ja käyttöönottoprosessit automatisoitiin Ansiblen avulla, ja jokainen palvelu koottiin YAML-konfiguraatiolla tarvittavilla asetuksilla ja avaimilla, ja vastaavaa konfigurointitiedostoa käytettiin paikalliset käynnistykset, mikä oli erittäin kätevää, koska .k tämä konfiguraatio ladataan globaaliin objektiin, joka on käytettävissä mistä tahansa projektin kohdasta.
Kuitenkin mikropalveluiden määrän kasvu, niiden yhteydet ja
Tässä suhteessa määritysobjektin rakennusmekanismia muokattiin, jotta se voisi toimia sekä klassisen konfigurointitiedoston että Kuberin salaisuuksien kanssa. Myös jäykempi konfigurointirakenne määriteltiin kolmannen Pythonin kielellä seuraavasti:
Dict[str, Dict[str, Union[str, int, float]]]
Toisin sanoen viimeinen hammasfig on sanakirja, jossa on nimetyt osiot, joista jokainen on sanakirja, jossa on arvoja yksinkertaisista tyypeistä. Ja osiot kuvaavat tietyntyyppisten resurssien määritystä ja pääsyä niihin. Esimerkki kokoonpanostamme:
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"
Samaan aikaan kenttä engine
tietokannat voidaan asentaa SQLiteen ja redis
asetettu mock
, joka määrittää myös tallennettavan tiedoston nimen - nämä parametrit tunnistetaan ja käsitellään oikein, mikä tekee koodin suorittamisesta paikallisesti helppoa virheenkorjausta, yksikkötestausta ja muita tarpeita varten. Tämä on meille erityisen tärkeää, koska on monia muita tarpeita - osa koodistamme on tarkoitettu erilaisiin analyyttisiin laskelmiin, se toimii paitsi orkestroiduilla palvelimilla, myös erilaisilla skripteillä ja analyytikoiden tietokoneilla, jotka tarvitsevat läpi. ja korjaa monimutkaisia tietojenkäsittelyputkia ilman huolestuttavia tausta-ongelmia. Muuten, ei haittaisi kertoa, että tärkeimmät työkalumme, mukaan lukien asetusten asettelukoodi, asennetaan setup.py
– tämä yhdistää koodimme yhdeksi ekosysteemiksi alustasta ja käyttötavasta riippumatta.
Kuvaus Kubernetes podista näyttää tältä:
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
Eli jokainen salaisuus kuvaa yhtä osaa. Itse salaisuudet luodaan seuraavasti:
apiVersion: v1
kind: Secret
metadata:
name: db-main-secret
type: Opaque
stringData:
db_main.yaml: |
engine: sqlite
filename: main.sqlite3
Yhdessä tämä johtaa YAML-tiedostojen luomiseen polun varrella /etc/secrets/db-main/section_name.yaml
Ja paikallisissa käynnistyksissä käytetään konfiguraatiota, joka sijaitsee projektin juurihakemistossa tai ympäristömuuttujassa määritettyä polkua pitkin. Näistä mukavuuksista vastaava koodi näkyy spoilerissa.
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()
Logiikka tässä on melko yksinkertainen: yhdistämme suuret konfiguraatiot projektihakemistosta ja polut ympäristömuuttujien mukaan sekä pienet konfiguraatioosiot Kuber-salaisuuksista ja esikäsittelemme niitä sitten hieman. Lisäksi muutama muuttuja. Huomaan, että haettaessa tiedostoja salaisuuksista käytetään syvyysrajoitusta, koska K8s luo jokaiseen salaisuuteen piilotetun kansion, johon itse salaisuudet tallennetaan, ja vain linkki sijaitsee korkeammalla tasolla.
Toivottavasti kuvatusta on jollekin hyötyä :) Kaikki kommentit ja suositukset koskien turvallisuutta tai muita parannuskohteita otetaan vastaan. Yhteisön mielipide on myös mielenkiintoinen, ehkä kannattaa lisätä tuki ConfigMapsille (projektimme ei vielä käytä niitä) ja julkaista koodi GitHubissa / PyPI:ssä? Henkilökohtaisesti olen sitä mieltä, että tällaiset asiat ovat liian yksilöllisiä, jotta hankkeet olisivat yleismaailmallisia, ja pientä kurkistamista muiden toteutuksiin, kuten tässä annettu, ja keskustelua vivahteista, vinkeistä ja parhaista käytännöistä, joita toivon näkeväni kommenteissa , riittää 😉
Vain rekisteröityneet käyttäjät voivat osallistua kyselyyn.
Pitäisikö minun julkaista projektina/kirjastona?
-
0,0%Kyllä, käyttäisin /contribution0
-
33,3%Kyllä, kuulostaa hyvältä 4
-
41,7%Ei, kenen pitää tehdä se itse omassa muodossaan ja tarpeidensa mukaan5
-
25,0%Jätän vastaamatta 3
12 käyttäjää äänesti. 3 käyttäjää pidättyi äänestämästä.
Lähde: will.com