Jak mam przechowywać moje zmienne środowiskowe?

11

To jest bardzo szerokie pytanie dotyczące metod i porad dotyczących zmiennych / struktury środowiska. Ale ostatecznie szukam odpowiedzi na bardzo szczegółowe pytanie „Jak przechowywać moje zmienne środowiskowe?”

Po pierwsze kilka wyjaśnień:

  • Dla mnie środowisko może mieć od 3 do 10 serwerów i jest sposobem na ograniczenie infrastruktury konkretnego klienta.
  • W każdym środowisku znajduje się kilka zmiennych, które są w większości automatycznie generowane na podstawie kilku kluczowych danych wejściowych (nazwa, rozmiar itp.).

Na obecnym etapie przechowujemy wszystkie nasze zmienne środowiskowe w takiej strukturze:

<playbook>.yml                   # Various playbooks for deployment
roles/windows                    # Ansible role for Ubuntu
roles/ubuntu                     # Ansible role for Ubuntu
config/hosts/<name>.yml          # Ansible inventory
config/hosts/vars/<name>.json    # Environment specific variables 

W tej chwili konfiguracja jest inicjowana jako submoduł w powyższym repozytorium git. Ponieważ plik zmiennych zmienia się dość często, spowodowało to problemy ze zmianą danych, raz, dwa lub nawet trzy razy między zatwierdzeniami, przez co zmiany są coraz trudniejsze do śledzenia.

Ponieważ osobiście widzę to w przyszłości, powinniśmy starać się przechowywać wszystkie zmienne naszych klientów w scentralizowany / skalowalny sposób, a następnie połączyć się z nimi za pomocą dynamicznej inwentaryzacji z .

Rozumiem, że istnieje kilka technologii, które wydają się wykonywać część tego, co może być wymagane, takie jak Consul, ale wydają się one działać najlepiej w środowisku obsługującym jedną dużą aplikację, a nie wiele mniejszych, nieco różniących się.

Zasadniczo widzę, że musimy napisać skrypt inwentaryzacyjny, a następnie po prostu wepchnąć wszystkie nasze dane do jakiejś nieprzeznaczonej do tego bazy danych, a następnie kontynuować, jak gdyby nic się nie zmieniło. Widzę to jako sposób na potencjalne ograniczenie dużej ilości danych, które obecnie przechowujemy, i być może przyglądam się różnym sposobom przechowywania danych, a nie tylko skalowaniu tego, co je ponownie obsługuje.

Mam nadzieję, że ktoś ma jakieś doświadczenie we wdrażaniu infrastruktury jako kodu, gdy ma do czynienia z wieloma mniejszymi środowiskami w przeciwieństwie do jednego, dwóch lub trzech dużych.

Jakieś sugestie?

Nafta
źródło

Odpowiedzi:

13

Miałem dwa przebiegi w wykonywaniu zmiennych środowiskowych w skalowalny sposób i żadne z nich nie skończyło się idealnie, ponieważ, jak odkryłem, bardzo trudna rzecz jest naprawić. Poniżej podsumuję oba moje doświadczenia:

Wspólne czynniki

  • Zmienne środowiskowe są przechowywane w oddzielnym repozytorium od oryginalnego kodu źródłowego (są one poddawane podmodulowi razem, ale nadal są oparte na osobnych repozytoriach)
  • Dla artefaktu i jego zmiennych istnieje osobny proces „kompilacji”.
  • Jest nie oddzielny proces dopuszczenia do zmiennych środowiskowych. Jeśli chcesz zmienić zmienne środowiskowe, musisz przejść przez te same tablice przeglądu zmian i zwykle

Korzystanie z par Consul KV

Zmienne środowiskowe są ładowane z repozytorium artefaktów (nigdy oryginalnego repozytorium git) i ładowane na przykład do drzewa par KV z przestrzenią nazw

/env/dev1/my/application/v1.1.1

Tam, gdzie poprzedni dev1 to nazwa środowiska, my / application to przestrzeń nazw aplikacji, a v1.1.1 to wersja zmiennych środowiskowych, których należy użyć.

Dla programistów wszystkie te rzeczy są niewidoczne. W czasie wykonywania platforma sprawdza, czy środowisko istnieje w bieżącym klastrze konsulów (jeśli nie ma problemu i nie ma błędów), a następnie sprawdza poddrzewo dla przestrzeni nazw aplikacji (w ten sposób nie może wystąpić zanieczyszczenie krzyżowe w przypadku jednej aplikacji odwołuje się do innych aplikacji), następnie numer wersji konfiguracji jest pobierany z etykiety połączonej z artefaktem do wdrożenia. Aktualizacja tej etykiety jest tutaj kluczowa, ponieważ oznacza to, że jeśli stracimy oba produkcyjne centra danych, możemy ponownie postawić środowisko, po prostu odczytując metadane z naszych artefaktów do wdrożenia i ładując wszystkie zmienne środowiskowe do magazynu KV.

Problemy z tym podejściem Programiści zawsze, i mam na myśli za każdym razem, znaleźli sposób na wprowadzenie zmian konfiguracji w środowisku, które miały znaczący wpływ na sposób działania aplikacji. Ponieważ zawsze łatwiej było zatwierdzić zmiany konfiguracji niż zmiany kodu.

Przechowywanie artefaktu „Wdrożenie” z osadzonymi zmiennymi

To ściśle łączy dokładną wersję artefaktu z wersją konfiguracji. Jeśli zmieniłeś konfigurację, musisz odbudować ten artefakt wdrażania.

Sam artefakt wdrażania był zasadniczo plikiem yaml, który zawierał adres URL do binarnego pliku binarnego i całą konfigurację do niego dołączoną.

Platforma zawiera komponent do odczytu zmiennych, a następnie przeniesienia ich do drzewa procesów aplikacji podczas uruchamiania.

Do tej pory było to o wiele bardziej skuteczne, ponieważ istnieje artefakt, który możemy prześledzić historię, i który możemy utrzymać na dowolnej tablicy przeglądowej i powiedzieć „to jedyny artefakt, na którym nam zależy, nie musimy na niego patrzeć wszelkie inne zmiany, tylko zmiany tej rzeczy ”(tj. wersja aplikacji do wdrożenia, uwzględnione zmienne środowiskowe itp.

To sprawia, że ​​deweloperom trudniej jest zbudować w swojej aplikacji logikę, która zmieni swoje zachowanie w oparciu o zmienne, dzięki czemu będą mogli wprowadzać zmiany bez przechodzenia przez odpowiednie cykle testowe.

Punkty bonusowe

Rozważ tajemnice aplikacji. Do tej pory naszym rozwiązaniem było udostępnienie publicznego klucza RSA, którego zespoły programistyczne używają do szyfrowania rozszerzonego magazynu kluczy Java (prawie każdy język ma bibliotekę, która może odczytywać magazyny kluczy Java), jest to następnie traktowane jak trzeci rodzaj artefaktu i jest pobierany na serwer, odszyfrowywany za pomocą naszego prywatnego klucza platformy i dostarczany do aplikacji w czasie wykonywania.

Trzeba przyznać, że zarządzanie sekretami to własna puszka robaków. Ale prawdopodobnie warto to rozważyć.

hvindin
źródło
2
Re: tajemnice aplikacji, proponuję rzucić okiem na Vault ( vaultproject.io ), ponieważ jest on również częścią łańcucha narzędzi Hashicorp i dość dobrze integruje się z konsulem (i innymi narzędziami z tego pudełka)
Michael Bravo
W rzeczywistości byłem bardzo rozczarowany skarbcem, biorąc pod uwagę, jak zwykle świetne są haszypory. Zasadniczo trzy główne luki w ich produkcie w porównaniu z resztą rynku - 1. „Sekrety tajemnic” są zasadniczo tym, co sprowadza się do modelu. Dostaję dzielenie lub używanie HSM. Ale w gruncie rzeczy jest to po prostu wymiana tajemnic. 2. Kompatybilność narzędzi, w przeciwieństwie do innych narzędzi, nie ma wsparcia dla wtyczek 3. Cena. Nie wierzyłem, kiedy powiedziałem firmie, że mam wrażenie, że skarbiec jest drogi. Odrzucili produkty, ponieważ są zbyt tanie, to popsute. Ale skarbiec był tak wielki, że nawet go nie rozważali.
hvindin
Warto zauważyć, że jest to nieopłacalne tylko w przypadku korzystania z płatnej wersji . Podstawowym produktem Vault jest oprogramowanie typu open source. Oczywiście nie podają cen dla wersji pro / korporacyjnych na swojej stronie, więc nie mam pojęcia, jak [nie] rozsądne może być dla tych wydań.
Adrian
Hm, nie zauważyłem tego pominięcia w moim komentarzu, chociaż szczerze mówiąc, moje pierwsze dwa problemy ze skarbcem nadal istnieją. Chociaż, aby się zakwalifikować, takie są moje przemyślenia na temat skarbca w porównaniu z innymi produktami hashicorp, z których wszystkie uważam za całkiem świetne. W porównaniu z innymi produktami na rynku, wykonywanie podobnej funkcji jest prawdopodobnie na równi, z jakiegoś powodu znacznie droższe niż oczekiwano.
hvindin
Czy możesz podać przykład „wbudowania logiki w ich aplikację, która zmieni swoje zachowanie w oparciu o zmienne, aby mogły wślizgiwać się w zmiany bez przechodzenia przez odpowiednie cykle testowe”? Brzmi jak coś naprawdę powszechnego, ale nie wyobrażam sobie konkretnego przykładu.
kenchew
3

Jeśli twoje środowiska dotyczą jednego klienta, sugerowałbym w twoim konkretnym przypadku utworzenie repozytorium dla każdego klienta . (Ogólnie rzecz biorąc, jest to repozytorium według środowiska.) To repozytorium miałoby standardową strukturę katalogów dla zmiennych środowiskowych, zmiennych ansible i inwentarzy, silnie zaszyfrowanych tajemnic (tokeny dostępu do konta, klucze prywatne itp.). Dostarczyłbyś kod podrzędny do tych repozytoriów. Prawdopodobnie zrobiłbym to w wielu repozytoriach. Jeden dla odpowiedzialnych ról i modułów, jeden dla skryptów konserwacji i wdrażania, jeden dla każdej głównej aplikacji działającej w środowisku.

Teraz możesz opcjonalnie rozwidlić kod lub w inny sposób przypiąć podmoduł do określonego znacznika do wydania , upewniając się, że kod zarządzający środowiskiem klienta nie zmieni się, chyba że zostanie przetestowany i wydany.

Jeśli używasz repozytorium artefaktów , upewnij się, że artefakty są odpowiednio wersjonowane, a wersje te są poprawnie określone w zmiennych środowiskowych.

Automatyzacja jest ważna, ponieważ zmienne środowiskowe nie powinny być aktualizowane przez ludzi, jeśli to możliwe, ale generowane przez skrypty. Upewnij się, że prawie nie ma ręcznych aktualizacji w spisie dla poszczególnych klientów, a programiści aktualizują tylko repozytoria kodów. Jeśli chcą zmienić konfigurację, należy to zrobić w jednym ze skryptów generujących, który jest następnie uruchamiany w celu wygenerowania zmiennych, a różnicę zapisuje się w repozytorium klienta. Opłaca się ustawić ciągłą integrację tego procesu. Bez tego w pewnym momencie będzie zbyt wiele repozytoriów do utrzymania .

Jiri Klouda
źródło
Tylko jeden sprzeciw: tajemnice nie powinny wchodzić do repozytorium kontroli wersji, chyba że ma ścisłą obsługę kontroli dostępu. Git nie - ktokolwiek wyciągnie repozytorium, może zobaczyć sekrety, co może być problemem - nie są już tajemnicami.
Dan Cornilescu,
Dobry chwyt To zaszyfrowane tajemnice. Klucze odszyfrowujące są kłopotliwe.
Jiri Klouda