Kubernetes ichida va tashqarisida loyiha konfiguratsiyasi

Yaqinda yozdim Docker-dagi loyiha hayoti va undan tashqaridagi disk raskadrovka kodlari haqida javob bering, u erda u xizmat Kuberda yaxshi ishlashi, sirlarni ochishi va mahalliy sharoitda, hatto Dockerdan tashqarida ham qulay ishlashi uchun o'z konfiguratsiya tizimingizni yaratishingiz mumkinligini qisqacha aytib o'tdi. Hech qanday murakkab narsa yo'q, lekin tavsiflangan "retsept" kimgadir foydali bo'lishi mumkin :) Kod Python-da, lekin mantiq tilga bog'liq emas.

Kubernetes ichida va tashqarisida loyiha konfiguratsiyasi

Savolning foni quyidagicha: bir vaqtlar bitta loyiha bor edi, dastlab u yordamchi dasturlar va skriptlarga ega kichik monolit edi, lekin vaqt o'tishi bilan u o'sib bordi, xizmatlarga bo'lindi, ular o'z navbatida mikroservislarga bo'linishni boshladilar va keyin kattalashtirildi. Avvaliga bularning barchasi yalang'och VPS-da amalga oshirildi, kodni o'rnatish va joylashtirish jarayonlari Ansible yordamida avtomatlashtirilgan va har bir xizmat kerakli sozlamalar va kalitlarga ega YAML konfiguratsiyasi bilan tuzilgan va shunga o'xshash konfiguratsiya fayli uchun ishlatilgan. mahalliy ishga tushirildi, bu juda qulay edi, chunki .k ushbu konfiguratsiya global ob'ektga yuklangan, loyihaning istalgan joyidan foydalanish mumkin.

Biroq, mikroservislar sonining o'sishi, ularning ulanishlari va markazlashtirilgan ro'yxatga olish va monitoringga ehtiyoj, Kuberga ko'chib o'tishni bashorat qildi, bu hali ham davom etmoqda. Yuqoridagi muammolarni hal qilishda yordam berish bilan birga, Kubernetes infratuzilmani boshqarish bo'yicha o'z yondashuvlarini taklif qiladi, shu jumladan sirlar deb ataladi ΠΈ ular bilan ishlash usullari. Mexanizm standart va ishonchli, shuning uchun uni ishlatmaslik tom ma'noda gunohdir! Shu bilan birga, men konfiguratsiya bilan ishlash uchun hozirgi formatimni saqlab qolmoqchiman: birinchidan, uni loyihaning turli mikroservislarida bir xilda ishlatish, ikkinchidan, bitta oddiy dastur yordamida kodni mahalliy mashinada ishga tushirish imkoniyatiga ega bo'lish. konfiguratsiya fayli.

Shu munosabat bilan, konfiguratsiya ob'ektini yaratish mexanizmi klassik konfiguratsiya faylimiz bilan ham, Kuber sirlari bilan ham ishlash imkoniyatiga ega bo'lishi uchun o'zgartirildi. Uchinchi Python tilida yanada qattiqroq konfiguratsiya tuzilishi ham quyidagicha belgilandi:

Dict[str, Dict[str, Union[str, int, float]]]

Ya'ni, yakuniy tishli lug'at nomli bo'limlari bo'lgan lug'at bo'lib, ularning har biri oddiy turdagi qiymatlardan iborat lug'atdir. Va bo'limlar konfiguratsiya va ma'lum turdagi resurslarga kirishni tavsiflaydi. Konfiguratsiyamizning bir qismiga misol:

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"

Shu bilan birga, dala engine ma'lumotlar bazalari SQLite-ga o'rnatilishi mumkin va redis sozlang mock, shuningdek, saqlash uchun fayl nomini ko'rsatish - bu parametrlar to'g'ri tan olinadi va qayta ishlanadi, bu esa disk raskadrovka, birlik testi va boshqa ehtiyojlar uchun kodni mahalliy sifatida ishlatishni osonlashtiradi. Bu biz uchun ayniqsa muhimdir, chunki boshqa ko'plab ehtiyojlar mavjud - bizning kodimizning bir qismi turli xil analitik hisob-kitoblar uchun mo'ljallangan, u nafaqat orkestratsiyalangan serverlarda, balki turli xil skriptlar bilan ishlaydi va tahlilchilarning kompyuterlarida ishlaydi. va murakkab ma'lumotlarni qayta ishlash quvurlarini disk raskadrovka bilan bog'liq muammolarsiz disk raskadrovka. Aytgancha, bizning asosiy vositalarimiz, jumladan, konfiguratsiya tartibi kodi orqali o'rnatilganligini baham ko'rish zarar qilmaydi. setup.py – birgalikda bu bizning kodimizni platforma va foydalanish usulidan mustaqil yagona ekotizimga birlashtiradi.

Kubernetes podining tavsifi quyidagicha ko'rinadi:

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

Ya'ni, har bir sir bir qismni tasvirlaydi. Sirlarning o'zi quyidagicha yaratilgan:

apiVersion: v1
kind: Secret
metadata:
  name: db-main-secret
type: Opaque
stringData:
  db_main.yaml: |
    engine: sqlite
    filename: main.sqlite3

Birgalikda bu yo'l bo'ylab YAML fayllarini yaratishga olib keladi /etc/secrets/db-main/section_name.yaml

Mahalliy ishga tushirish uchun esa loyihaning asosiy katalogida yoki muhit o'zgaruvchisida ko'rsatilgan yo'lda joylashgan konfiguratsiya ishlatiladi. Ushbu qulayliklar uchun javobgar kodni spoylerda ko'rish mumkin.

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()

Bu erda mantiq juda oddiy: biz loyiha katalogidagi katta konfiguratsiyalarni va atrof-muhit o'zgaruvchisi bo'yicha yo'llarni va Kuber sirlaridan kichik konfiguratsiya bo'limlarini birlashtiramiz va keyin ularni biroz oldindan qayta ishlaymiz. Bundan tashqari, ba'zi o'zgaruvchilar. Shuni ta'kidlaymanki, sirlardan fayllarni qidirishda chuqurlik chegarasi qo'llaniladi, chunki K8s har bir sirda sirlarning o'zi saqlanadigan yashirin papkani yaratadi va shunchaki havola yuqori darajada joylashgan.

Umid qilamanki, tasvirlangan narsa kimgadir foydali bo'ladi :) Xavfsizlik yoki yaxshilash uchun boshqa sohalarga oid har qanday sharh va tavsiyalar qabul qilinadi. Jamiyatning fikri ham qiziq, ehtimol ConfigMaps-ni qo'shish (bizning loyihamiz hali ulardan foydalanmaydi) va kodni GitHub / PyPI-da nashr qilish kerakmi? Shaxsan menimcha, bunday narsalar loyihalar universal bo'lishi uchun juda individualdir va bu erda keltirilgan kabi boshqa odamlarning amalga oshirishlariga biroz nazar tashlash va sharhlarda ko'rishga umid qilaman. , yetarli πŸ˜‰

So'rovda faqat ro'yxatdan o'tgan foydalanuvchilar ishtirok etishlari mumkin. tizimga kirishiltimos.

Loyiha/kutubxona sifatida nashr qilishim kerakmi?

  • 0,0%Ha, men /contribution0 dan foydalanardim

  • 33,3%Ha, bu ajoyib eshitiladi4

  • 41,7%Yo'q, kim buni o'z formatida va ehtiyojlariga mos ravishda qilish kerak5

  • 25,0%Men javob berishdan tiyilaman3

12 nafar foydalanuvchi ovoz berdi. 3 nafar foydalanuvchi betaraf qolgan.

Manba: www.habr.com

a Izoh qo'shish