ΠΠ΅ΠΎΠ΄Π°ΠΌΠ½Π° Π½Π°ΠΏΠΈΡΠ°Π²
ΠΠΎΠ·Π°Π΄ΠΈΠ½Π°ΡΠ° Π½Π° ΠΏΡΠ°ΡΠ°ΡΠ΅ΡΠΎ Π΅ ΠΎΠ²Π°: Π½Π΅ΠΊΠΎΠ³Π°Ρ ΠΏΠΎΡΡΠΎΠ΅ΡΠ΅ Π΅Π΄Π΅Π½ ΠΏΡΠΎΠ΅ΠΊΡ, Π²ΠΎ ΠΏΠΎΡΠ΅ΡΠΎΠΊΠΎΡ ΡΠΎΠ° Π±Π΅ΡΠ΅ ΠΌΠ°Π» ΠΌΠΎΠ½ΠΎΠ»ΠΈΡ ΡΠΎ ΠΊΠΎΠΌΡΠ½Π°Π»Π½ΠΈ ΡΡΠ»ΡΠ³ΠΈ ΠΈ ΡΠΊΡΠΈΠΏΡΠΈ, Π½ΠΎ ΡΠΎ ΡΠ΅ΠΊΠΎΡ Π½Π° Π²ΡΠ΅ΠΌΠ΅ΡΠΎ ΡΠ°ΡΡΠ΅ΡΠ΅, ΠΏΠΎΠ΄Π΅Π»Π΅Π½ Π½Π° ΡΡΠ»ΡΠ³ΠΈ, ΠΊΠΎΠΈ ΠΏΠ°ΠΊ ΠΏΠΎΡΠ½Π°Π° Π΄Π° ΡΠ΅ Π΄Π΅Π»Π°Ρ Π½Π° ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠΈ ΠΈ ΠΏΠΎΡΠΎΠ° ΡΠ΅ Π·Π³ΠΎΠ»Π΅ΠΌΠΈ. ΠΡΠΏΡΠ²ΠΈΠ½, ΡΠ΅ΡΠΎ ΠΎΠ²Π° Π±Π΅ΡΠ΅ Π½Π°ΠΏΡΠ°Π²Π΅Π½ΠΎ Π½Π° Π³ΠΎΠ»ΠΈ VPS, ΠΏΡΠΎΡΠ΅ΡΠΈΡΠ΅ Π½Π° ΠΏΠΎΡΡΠ°Π²ΡΠ²Π°ΡΠ΅ ΠΈ ΡΠ°ΡΠΏΠΎΡΠ΅Π΄ΡΠ²Π°ΡΠ΅ Π½Π° ΠΊΠΎΠ΄ΠΎΡ Π½Π° ΠΊΠΎΡ Π±Π΅Π° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠ°Π½ΠΈ ΡΠΎ ΠΏΠΎΠΌΠΎΡ Π½Π° Ansible, Π° ΡΠ΅ΠΊΠΎΡΠ° ΡΡΠ»ΡΠ³Π° Π±Π΅ΡΠ΅ ΠΊΠΎΠΌΠΏΠ°ΡΠ»ΠΈΡΠ°Π½Π° ΡΠΎ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ° YAML ΡΠΎ ΠΏΠΎΡΡΠ΅Π±Π½ΠΈΡΠ΅ ΠΏΠΎΡΡΠ°Π²ΠΊΠΈ ΠΈ ΠΊΠ»ΡΡΠ΅Π²ΠΈ, Π° ΡΠ»ΠΈΡΠ½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠΊΠ° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° Π±Π΅ΡΠ΅ ΠΈΡΠΊΠΎΡΠΈΡΡΠ΅Π½Π° Π·Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈ Π»Π°Π½ΡΠΈΡΠ°ΡΠ°, ΡΡΠΎ Π±Π΅ΡΠ΅ ΠΌΠ½ΠΎΠ³Ρ ΠΏΠΎΠ³ΠΎΠ΄Π½ΠΎ, Π±ΠΈΠ΄Π΅ΡΡΠΈ .k ΠΎΠ²Π°Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ° Π΅ Π²ΡΠΈΡΠ°Π½Π° Π²ΠΎ Π³Π»ΠΎΠ±Π°Π»Π΅Π½ ΠΎΠ±ΡΠ΅ΠΊΡ, Π΄ΠΎΡΡΠ°ΠΏΠ΅Π½ ΠΎΠ΄ ΠΊΠ°Π΄Π΅ Π±ΠΈΠ»ΠΎ Π²ΠΎ ΠΏΡΠΎΠ΅ΠΊΡΠΎΡ.
Π‘Π΅ΠΏΠ°ΠΊ, ΡΠ°ΡΡΠΎΡ Π½Π° Π±ΡΠΎΡΠΎΡ Π½Π° ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠΈ, Π½ΠΈΠ²Π½ΠΈΡΠ΅ Π²ΡΡΠΊΠΈ ΠΈ
ΠΠΎ ΠΎΠ²ΠΎΡ ΠΏΠΎΠ³Π»Π΅Π΄, ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠΎΡ Π·Π° ΠΊΠΎΠ½ΡΡΡΡΠΈΡΠ°ΡΠ΅ Π½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠΊΠΈ ΠΎΠ±ΡΠ΅ΠΊΡ Π±Π΅ΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Ρ Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ°Π±ΠΎΡΠΈ ΠΈ ΡΠΎ Π½Π°ΡΠ°ΡΠ° ΠΊΠ»Π°ΡΠΈΡΠ½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠΊΠ° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° ΠΈ ΡΠΎ ΡΠ°ΡΠ½ΠΈΡΠ΅ ΠΎΠ΄ Kuber. ΠΠ΅ΡΠ΅ Π½Π°Π²Π΅Π΄Π΅Π½Π° ΠΈ ΠΏΠΎΡΠΈΠ³ΠΈΠ΄Π½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠΊΠ° ΡΡΡΡΠΊΡΡΡΠ°, Π½Π° ΡΠ°Π·ΠΈΠΊΠΎΡ Π½Π° ΡΡΠ΅ΡΠΈΠΎΡ Python, ΠΊΠ°ΠΊΠΎ ΡΡΠΎ ΡΠ»Π΅Π΄ΡΠ²Π°:
ΠΠΈΠΊΡ[ΡΠ»ΠΈΡΠ°, ΠΠΈΠΊΡ[ΡΠ»ΠΈΡΠ°, Π£Π½ΠΈΡΠ°[ΡΠ», ΠΈΠ½Ρ, ΠΏΠ»ΠΎΠ²ΠΈ]]]
ΠΠ΄Π½ΠΎΡΠ½ΠΎ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΈΠΎΡ ΠΊΠΎΠ³ΡΠΈΠ³ Π΅ ΡΠ΅ΡΠ½ΠΈΠΊ ΡΠΎ ΠΈΠΌΠ΅Π½ΡΠ²Π°Π½ΠΈ Π΄Π΅Π»ΠΎΠ²ΠΈ, ΠΎΠ΄ ΠΊΠΎΠΈ ΡΠ΅ΠΊΠΎΡΠ° Π΅ ΡΠ΅ΡΠ½ΠΈΠΊ ΡΠΎ Π²ΡΠ΅Π΄Π½ΠΎΡΡΠΈ ΠΎΠ΄ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΈ ΡΠΈΠΏΠΎΠ²ΠΈ. Π Π΄Π΅Π»ΠΎΠ²ΠΈΡΠ΅ ΡΠ° ΠΎΠΏΠΈΡΡΠ²Π°Π°Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ°ΡΠ° ΠΈ ΠΏΡΠΈΡΡΠ°ΠΏΠΎΡ Π΄ΠΎ ΡΠ΅ΡΡΡΡΠΈΡΠ΅ ΠΎΠ΄ ΠΎΠ΄ΡΠ΅Π΄Π΅Π½ ΡΠΈΠΏ. ΠΡΠΈΠΌΠ΅Ρ Π·Π° Π΄Π΅Π» ΠΎΠ΄ Π½Π°ΡΠ°ΡΠ° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ°:
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"
ΠΠΎ ΠΈΡΡΠΎ Π²ΡΠ΅ΠΌΠ΅, ΡΠ΅ΡΠ΅Π½ΠΎΡ engine
Π±Π°Π·ΠΈΡΠ΅ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°Π°Ρ Π½Π° SQLite, ΠΈ redis
ΠΏΠΎΡΡΠ°Π²Π΅Π½ΠΈ Π½Π° mock
, Π½Π°Π²Π΅Π΄ΡΠ²Π°ΡΡΠΈ Π³ΠΎ ΠΈ ΠΈΠΌΠ΅ΡΠΎ Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ°ΡΠ° ΡΡΠΎ ΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ Π·Π°ΡΡΠ²Π° - ΠΎΠ²ΠΈΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈ ΡΠ΅ ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΡΠ΅ΠΏΠΎΠ·Π½Π°Π΅Π½ΠΈ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ΅Π½ΠΈ, ΡΡΠΎ Π³ΠΎ ΠΎΠ»Π΅ΡΠ½ΡΠ²Π° ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅ΡΠΎ Π½Π° ΠΊΠΎΠ΄ΠΎΡ Π»ΠΎΠΊΠ°Π»Π½ΠΎ Π·Π° Π΄Π΅Π±Π°Π³ΠΈΡΠ°ΡΠ΅, ΡΠ΅ΡΡΠΈΡΠ°ΡΠ΅ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡΠ°ΡΠ° ΠΈ ΠΊΠ°ΠΊΠ²ΠΈ Π±ΠΈΠ»ΠΎ Π΄ΡΡΠ³ΠΈ ΠΏΠΎΡΡΠ΅Π±ΠΈ. ΠΠ²Π° Π΅ ΠΎΡΠΎΠ±Π΅Π½ΠΎ Π²Π°ΠΆΠ½ΠΎ Π·Π° Π½Π°Ρ Π±ΠΈΠ΄Π΅ΡΡΠΈ ΠΈΠΌΠ° ΠΌΠ½ΠΎΠ³Ρ Π΄ΡΡΠ³ΠΈ ΠΏΠΎΡΡΠ΅Π±ΠΈ - Π΄Π΅Π» ΠΎΠ΄ Π½Π°ΡΠΈΠΎΡ ΠΊΠΎΠ΄ Π΅ Π½Π°ΠΌΠ΅Π½Π΅Ρ Π·Π° ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ Π°Π½Π°Π»ΠΈΡΠΈΡΠΊΠΈ ΠΏΡΠ΅ΡΠΌΠ΅ΡΠΊΠΈ, ΡΠ°Π±ΠΎΡΠΈ Π½Π΅ ΡΠ°ΠΌΠΎ Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠΈ ΡΠΎ ΠΎΡΠΊΠ΅ΡΡΡΠ°ΡΠΈΡΠ°, ΡΡΠΊΡ ΠΈ ΡΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΡΠΊΡΠΈΠΏΡΠΈ, ΠΊΠ°ΠΊΠΎ ΠΈ Π½Π° ΠΊΠΎΠΌΠΏΡΡΡΠ΅ΡΠΈΡΠ΅ Π½Π° Π°Π½Π°Π»ΠΈΡΠΈΡΠ°ΡΠΈΡΠ΅ ΠΊΠΎΠΈ ΡΡΠ΅Π±Π° Π΄Π° ΡΠ°Π±ΠΎΡΠ°Ρ ΠΏΡΠ΅ΠΊΡ ΠΈ Π΄Π΅Π±Π°Π³ΠΈΡΠ°ΡΡΠ΅ ΡΠ»ΠΎΠΆΠ΅Π½ΠΈ ΡΠ΅Π²ΠΊΠΎΠ²ΠΎΠ΄ΠΈ Π·Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π±Π΅Π· Π·Π°Π³ΡΠΈΠΆΡΠ²Π°ΡΠΊΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ. ΠΠ°ΡΠ΅ΠΌ, Π½Π΅ Π±ΠΈ Π±ΠΈΠ»ΠΎ Π»ΠΎΡΠΎ Π΄Π° ΡΠΏΠΎΠ΄Π΅Π»ΠΈΠΌΠ΅ Π΄Π΅ΠΊΠ° Π½Π°ΡΠΈΡΠ΅ Π³Π»Π°Π²Π½ΠΈ Π°Π»Π°ΡΠΊΠΈ, Π²ΠΊΠ»ΡΡΠΈΡΠ΅Π»Π½ΠΎ ΠΈ ΠΊΠΎΠ΄ΠΎΡ Π·Π° ΡΠ°ΡΠΏΠΎΡΠ΅Π΄ Π½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ°, ΡΠ΅ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°Π½ΠΈ ΠΏΡΠ΅ΠΊΡ setup.py
β Π·Π°Π΅Π΄Π½ΠΎ ΠΎΠ²Π° Π³ΠΎ ΠΎΠ±Π΅Π΄ΠΈΠ½ΡΠ²Π° Π½Π°ΡΠΈΠΎΡ ΠΊΠΎΠ΄ Π²ΠΎ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½ Π΅ΠΊΠΎΡΠΈΡΡΠ΅ΠΌ, Π½Π΅Π·Π°Π²ΠΈΡΠ΅Π½ ΠΎΠ΄ ΠΏΠ»Π°ΡΡΠΎΡΠΌΠ°ΡΠ° ΠΈ Π½Π°ΡΠΈΠ½ΠΎΡ Π½Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅.
ΠΠΏΠΈΡΠΎΡ Π½Π° ΠΏΠΎΠ΄Π»ΠΎΠ³Π°ΡΠ° Π½Π° ΠΡΠ±Π΅ΡΠ½Π΅ΡΠ΅Ρ ΠΈΠ·Π³Π»Π΅Π΄Π° Π²Π°ΠΊΠ°:
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
ΠΠ΄Π½ΠΎΡΠ½ΠΎ, ΡΠ΅ΠΊΠΎΡΠ° ΡΠ°ΡΠ½Π° ΠΎΠΏΠΈΡΡΠ²Π° Π΅Π΄Π΅Π½ Π΄Π΅Π». Π‘Π°ΠΌΠΈΡΠ΅ ΡΠ°ΡΠ½ΠΈ ΡΠ΅ ΡΠΎΠ·Π΄Π°Π΄Π΅Π½ΠΈ Π²Π°ΠΊΠ°:
apiVersion: v1
kind: Secret
metadata:
name: db-main-secret
type: Opaque
stringData:
db_main.yaml: |
engine: sqlite
filename: main.sqlite3
ΠΠ°Π΅Π΄Π½ΠΎ ΠΎΠ²Π° ΡΠ΅Π·ΡΠ»ΡΠΈΡΠ° ΡΠΎ ΡΠΎΠ·Π΄Π°Π²Π°ΡΠ΅ Π½Π° YAML-Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈ Π΄ΠΎΠ»ΠΆ ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ° /etc/secrets/db-main/section_name.yaml
Π Π·Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈ Π»Π°Π½ΡΠΈΡΠ°ΡΠ°, ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠ°ΡΠ°, ΠΊΠΎΡΠ° ΡΠ΅ Π½Π°ΠΎΡΠ° Π²ΠΎ root Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΠΌΠΎΡ Π½Π° ΠΏΡΠΎΠ΅ΠΊΡΠΎΡ ΠΈΠ»ΠΈ ΠΏΠΎ ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ° Π½Π°Π²Π΅Π΄Π΅Π½Π° Π²ΠΎ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°ΡΠ° Π½Π° ΠΆΠΈΠ²ΠΎΡΠ½Π°ΡΠ° ΡΡΠ΅Π΄ΠΈΠ½Π°. ΠΠΎΠ΄ΠΎΡ ΠΎΠ΄Π³ΠΎΠ²ΠΎΡΠ΅Π½ Π·Π° ΠΎΠ²ΠΈΠ΅ ΠΏΠΎΠ³ΠΎΠ΄Π½ΠΎΡΡΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π²ΠΈΠ΄ΠΈ Π²ΠΎ ΡΠΏΠΎΡΠ»Π΅ΡΠΎΡ.
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()
ΠΠΎΠ³ΠΈΠΊΠ°ΡΠ° ΠΎΠ²Π΄Π΅ Π΅ ΠΏΡΠΈΠ»ΠΈΡΠ½ΠΎ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½Π°: ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡΠ°ΠΌΠ΅ Π³ΠΎΠ»Π΅ΠΌΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΎΠ΄ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΠΌΠΎΡ Π½Π° ΠΏΡΠΎΠ΅ΠΊΡΠΎΡ ΠΈ ΠΏΠ°ΡΠ΅ΠΊΠΈ ΠΏΠΎ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° Π½Π° ΠΎΠΊΠΎΠ»ΠΈΠ½Π°ΡΠ° ΠΈ ΠΌΠ°Π»ΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΠΊΠΈ ΡΠ΅ΠΊΡΠΈΠΈ ΠΎΠ΄ ΡΠ°ΡΠ½ΠΈΡΠ΅ Π½Π° ΠΡΠ±Π΅Ρ, Π° ΠΏΠΎΡΠΎΠ° ΠΌΠ°Π»ΠΊΡ Π³ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠ²Π°ΠΌΠ΅ ΠΎΠ΄Π½Π°ΠΏΡΠ΅Π΄. ΠΠ»ΡΡ Π½Π΅ΠΊΠΎΠΈ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ. ΠΠ°Π±Π΅Π»Π΅ΠΆΡΠ²Π°ΠΌ Π΄Π΅ΠΊΠ° ΠΏΡΠΈ ΠΏΡΠ΅Π±Π°ΡΡΠ²Π°ΡΠ΅ Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈ ΠΎΠ΄ ΡΠ°ΡΠ½ΠΈ, ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ΅ Π½Π° Π΄Π»Π°Π±ΠΎΡΠΈΠ½Π°ΡΠ°, Π±ΠΈΠ΄Π΅ΡΡΠΈ K8s ΡΠΎΠ·Π΄Π°Π²Π° ΡΠΊΡΠΈΠ΅Π½Π° ΠΏΠ°ΠΏΠΊΠ° Π²ΠΎ ΡΠ΅ΠΊΠΎΡΠ° ΡΠ°ΡΠ½Π° ΠΊΠ°Π΄Π΅ ΡΡΠΎ ΡΠ΅ ΡΡΠ²Π°Π°Ρ ΡΠ°ΠΌΠΈΡΠ΅ ΡΠ°ΡΠ½ΠΈ, Π° ΡΠ°ΠΌΠΎ Π²ΡΡΠΊΠ°ΡΠ° ΡΠ΅ Π½Π°ΠΎΡΠ° Π½Π° ΠΏΠΎΠ²ΠΈΡΠΎΠΊΠΎ Π½ΠΈΠ²ΠΎ.
Π‘Π΅ Π½Π°Π΄Π΅Π²Π°ΠΌ Π΄Π΅ΠΊΠ° ΠΎΠΏΠΈΡΠ°Π½ΠΎΡΠΎ ΡΠ΅ Π±ΠΈΠ΄Π΅ ΠΊΠΎΡΠΈΡΠ½ΠΎ Π·Π° Π½Π΅ΠΊΠΎΠ³ΠΎ :) ΠΡΠΈΡΠ°ΡΠ΅Π½ΠΈ ΡΠ΅ ΡΠΈΡΠ΅ ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈ ΠΈ ΠΏΡΠ΅ΠΏΠΎΡΠ°ΠΊΠΈ Π²ΠΎ Π²ΡΡΠΊΠ° ΡΠΎ Π±Π΅Π·Π±Π΅Π΄Π½ΠΎΡΡΠ° ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈ ΠΎΠ±Π»Π°ΡΡΠΈ Π·Π° ΠΏΠΎΠ΄ΠΎΠ±ΡΡΠ²Π°ΡΠ΅. ΠΠΈΡΠ»Π΅ΡΠ΅ΡΠΎ Π½Π° Π·Π°Π΅Π΄Π½ΠΈΡΠ°ΡΠ° Π΅ ΠΈΡΡΠΎ ΡΠ°ΠΊΠ° ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎ, ΠΌΠΎΠΆΠ΅Π±ΠΈ Π²ΡΠ΅Π΄ΠΈ Π΄Π° ΡΠ΅ Π΄ΠΎΠ΄Π°Π΄Π΅ ΠΏΠΎΠ΄Π΄ΡΡΠΊΠ° Π·Π° ConfigMaps (Π½Π°ΡΠΈΠΎΡ ΠΏΡΠΎΠ΅ΠΊΡ ΡΓ¨ ΡΡΡΠ΅ Π½Π΅ Π³ΠΈ ΠΊΠΎΡΠΈΡΡΠΈ) ΠΈ Π΄Π° Π³ΠΎ ΠΎΠ±ΡΠ°Π²ΠΈΠΌΠ΅ ΠΊΠΎΠ΄ΠΎΡ Π½Π° GitHub / PyPI? ΠΠΈΡΠ½ΠΎ ΠΌΠΈΡΠ»Π°ΠΌ Π΄Π΅ΠΊΠ° ΡΠ°ΠΊΠ²ΠΈΡΠ΅ ΡΠ°Π±ΠΎΡΠΈ ΡΠ΅ ΠΏΡΠ΅ΠΌΠ½ΠΎΠ³Ρ ΠΈΠ½Π΄ΠΈΠ²ΠΈΠ΄ΡΠ°Π»Π½ΠΈ Π·Π° ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠ΅ Π΄Π° Π±ΠΈΠ΄Π°Ρ ΡΠ½ΠΈΠ²Π΅ΡΠ·Π°Π»Π½ΠΈ, ΠΈ ΠΌΠ°Π»ΠΊΡ Π΄Π° ΡΠ΅ ΡΠΈΡΠ½Π°Ρ ΡΡΡΠΈ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, ΠΊΠ°ΠΊΠΎ ΠΎΠ²Π°Π° Π΄Π°Π΄Π΅Π½Π° ΠΎΠ²Π΄Π΅, ΠΈ Π΄ΠΈΡΠΊΡΡΠΈΡΠ° Π·Π° Π½ΠΈΡΠ°Π½ΡΠΈ, ΡΠΎΠ²Π΅ΡΠΈ ΠΈ Π½Π°ΡΠ΄ΠΎΠ±ΡΠΈ ΠΏΡΠ°ΠΊΡΠΈΠΊΠΈ, ΠΊΠΎΠΈ ΡΠ΅ Π½Π°Π΄Π΅Π²Π°ΠΌ Π΄Π΅ΠΊΠ° ΡΠ΅ Π³ΠΈ Π²ΠΈΠ΄Π°ΠΌ Π²ΠΎ ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅ , Π΄ΠΎΠ²ΠΎΠ»Π½ΠΎ Π΅ π
Π‘Π°ΠΌΠΎ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠ°Π½ΠΈ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈ ΠΌΠΎΠΆΠ°Ρ Π΄Π° ΡΡΠ΅ΡΡΠ²ΡΠ²Π°Π°Ρ Π²ΠΎ Π°Π½ΠΊΠ΅ΡΠ°ΡΠ°.
ΠΠ°Π»ΠΈ ΡΡΠ΅Π±Π° Π΄Π° ΠΎΠ±ΡΠ°Π²ΡΠ²Π°ΠΌ ΠΊΠ°ΠΊΠΎ ΠΏΡΠΎΠ΅ΠΊΡ/Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°?
-
0,0%ΠΠ°, Π±ΠΈ ΠΊΠΎΡΠΈΡΡΠ΅Π» /contribution0
-
33,3%ΠΠ°, ΡΠΎΠ° Π·Π²ΡΡΠΈ ΠΎΠ΄Π»ΠΈΡΠ½ΠΎ4
-
41,7%ΠΠ΅, ΠΊΠΎΡ ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈ ΡΠΎΠ° ΡΠ°ΠΌ Π²ΠΎ ΡΠ²ΠΎΡ ΡΠΎΡΠΌΠ°Ρ ΠΈ Π΄Π° ΠΎΠ΄Π³ΠΎΠ²Π°ΡΠ° Π½Π° Π½ΠΈΠ²Π½ΠΈΡΠ΅ ΠΏΠΎΡΡΠ΅Π±ΠΈ5
-
25,0%ΠΠ΅ ΡΠ΅ Π²ΠΎΠ·Π΄ΡΠΆΠ°ΠΌ ΠΎΠ΄ ΠΎΠ΄Π³ΠΎΠ²ΠΎΡ3
ΠΠ»Π°ΡΠ°Π° 12 ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈ. 3 ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈ ΡΠ΅ Π²ΠΎΠ·Π΄ΡΠΆΠ°Π°.
ΠΠ·Π²ΠΎΡ: www.habr.com