我最近寫的
這個問題的背景是這樣的:從前有一個項目,起初它是一個帶有實用程式和腳本的小型整體,但隨著時間的推移,它不斷增長,分為服務,服務又開始分為微服務,然後擴大規模。 起初,所有這些都是在裸 VPS 上完成的,設定和部署程式碼的過程是使用 Ansible 自動完成的,每個服務都使用帶有必要設定和金鑰的 YAML 配置進行編譯,並且使用類似的設定文件本地啟動,這非常方便,因為.k 此配置被載入到全域物件中,可以從專案中的任何位置存取。
然而,微服務數量、連接數和連接數的增長
在這方面,建構配置物件的機制被修改為能夠使用我們的經典設定檔和來自 Kuber 的秘密。 在第三種 Python 語言中也指定了更嚴格的配置結構,如下所示:
Dict[str, Dict[str, Union[str, int, float]]]
也就是說,最終的 cogfig 是一個具有命名部分的字典,每個部分都是一個包含來自簡單類型的值的字典。 各節描述了某種類型資源的配置和存取。 我們的配置的一個範例:
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
– 這將我們的程式碼統一到一個生態系統中,獨立於平台和使用方法。
Kubernetes pod 的描述如下所示:
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
對於本機啟動,使用位於專案根目錄或沿著環境變數中指定的路徑的配置。 負責這些便利的程式碼可以在劇透中看到。
設定檔
__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()
這裡的邏輯非常簡單:我們透過環境變數組合專案目錄和路徑中的大型配置,以及 Kuber 機密中的小型配置部分,然後對它們進行一些預處理。 加上一些變數。 我注意到,當從秘密中搜尋文件時,會使用深度限制,因為 K8s 在每個秘密中建立一個隱藏資料夾,其中儲存秘密本身,並且只有一個連結位於更高層級。
我希望所描述的內容對某人有用:) 任何有關安全性或其他需要改進的領域的評論和建議都會被接受。 社群的意見也很有趣,也許值得添加對 ConfigMaps 的支援(我們的專案還沒有使用它們)並在 GitHub / PyPI 上發布程式碼? 就我個人而言,我認為這樣的事情對於專案來說太個體化了,無法通用,並且稍微看看其他人的實現,就像這裡給出的那樣,以及對細微差別、技巧和最佳實踐的討論,希望在評論中看到,就夠了😉
只有註冊用戶才能參與調查。
我應該作為項目/庫發布嗎?
-
企業排放佔全球 0,0%是的,我會使用 /contribution0
-
企業排放佔全球 33,3%是的,聽起來不錯4
-
企業排放佔全球 41,7%不,誰需要以自己的格式自己做並滿足自己的需求5
-
企業排放佔全球 25,0%我不會回答3
12 位用戶投票。 3 名用戶棄權。
來源: www.habr.com