Proste pojemniki CI / CD w AWS

14

Korzystam z AWS Code Pipeline, Code Build, aby utworzyć nowy kontener Docker i przekazać go do ECR.

Moja aplikacja jest prosta, oparta na pojedynczym kontenerze. Co byłoby mniejszym tarciem, aby zlikwidować aktualnie działający kontener i ponownie uruchomić nowy kontener z rejestru ECS (dane wyjściowe z kompilacji kodu przez Code Pipeline).

Próbowałem CloudFormation z danymi użytkownika EC2, niestandardowymi skryptami z jednej strony i CloudFormation z ECS z definicją zadania z drugiej strony (jeszcze nie powiodło się). Mocno uważam, że musi istnieć bardziej oczywiste i prostsze podejście.

Naveen Vijay
źródło

Odpowiedzi:

16

Zatrzymałbym instancje kontenera ECS (mówię o hostach Docker - nie lubię tutaj terminologii AWS) i wdrożenie jako dwie osobne rzeczy.

Uruchom swój stos ECS. Możesz nim zarządzać za pomocą CloudFormation i grup Auto-Scaling, w porządku. Wystarczy pomyśleć o klastrze jako platforma, gdzie można wdrożyć do , a nie coś trzeba przesunięcie .

Następnie, w przypadku płyt CD, najłatwiejszą jak dotąd metodą jest aktualizacja definicji usługi w celu użycia nowej definicji zadania i umożliwienie ECS rolling aktualizacji kontenerów za Ciebie.

Za każdym razem, gdy uruchamia zadanie, ECS uruchamia okno dokujące pull image: tag, nawet jeśli ma obraz lokalnie, aby upewnić się, że ma najnowszą wersję tego image: tag. Tak więc znacznik graficzny, którego używasz, naprawdę nie ma znaczenia (nie trzeba zmieniać znacznika w każdej kompilacji).

Oznacza to, że możesz zbudować mójimage: najnowszy w kółko, aby łatwo go wdrożyć.

Potrzebujesz definicji zadania, w której obraz = mój obraz: najnowszy. Utwórz usługę z tą definicją zadania i za każdym razem, gdy ECS uruchomi zadanie (instancję twojej usługi), będzie to najnowsza wersja „myimage: latest”, którą zbudowałeś.

Stamtąd brakuje tylko jednego elementu układanki, z CodeDeploy możesz wywołać coś, być może funkcję lambda, aby utworzyć nową wersję definicji zadania i zaktualizować usługę, a ECS automatycznie utworzy nowe zadania dla tej zmiany i usuń stare zadania.

Przykład:

Załóżmy, że utworzyłeś usługę o nazwie MyService. Czy usługa została skonfigurowana do uruchamiania 2 zadań dla definicji zadania MyTaskDefinition: 1 (wersja 1). W tej definicji zadania masz jedną definicję kontenera, dla której obraz jest ustawiony na „myimage: latest”.

  1. Wczoraj zbudowałeś myimage: najnowszy, który miał identyfikator (SHA) 365d8f7bf565.
  2. Wystąpienie kontenera ABC uruchamia zadanie o nazwie MyTaskDefinition- 1 -containerName-someLongId. podczas sprawdzania tego kontenera jest wyświetlany obraz „sha256: 365d8f7bf565 ..........”
  3. Twoja inna instancja kontenera DEF uruchamia inne zadanie. Ma podobną nazwę (różni się tylko ID), ale działa z tym samym obrazem.
  4. Wprowadzasz zmianę w swoim repozytorium.
  5. CodePipeline przejmuje tę zmianę, buduje i publikuje obraz w ECR.
  6. Ten nowy obraz Dockera to także myimage: najnowszy, ale jego identyfikator (SHA) to f7ec5e54ac96
  7. Teraz musisz dodać krok do swojego potoku, aby użyć funkcji Lambda i zestawu AWS NodeJS SDK do wykonania niektórych wywołań do klastra:
    1. Utwórz nową definicję zadania (która będzie dokładnie taka sama jak poprzednio). To będzie MyTaskDefinition: 2
    2. Zaktualizuj swoją usługę MyService, aby korzystała z MyTaskDefinition: 2 (zamiast 1)
  8. ECS utworzy nowe zadania. Nazwy kontenerów będą MyTaskDefinition- 2 -containerName-someLongId. Gdy sprawdzisz te kontenery, zobaczysz, że będą działały „sha256: f7ec5e54ac96 .......”. Być może będziesz mieć 2 zadania na instancji kontenera ABC, być może zostaną one rozpylone (zależy to od konfiguracji usługi)
  9. Po pewnym czasie ECS usunie stare zadanie MyTaskDefinition-1-containerName-someLongId z ABC i DEF.

Uwaga: tak naprawdę nie musisz tworzyć nowej definicji zadania. Jeśli chcesz, możesz zamiast tego pobrać listę zadań usługi i ręcznie zatrzymać je jeden po drugim. Powinieneś poczekać, aż ECS zrestartuje zadanie przed zatrzymaniem nowego (to znaczy: zatrzymaj pierwszy kontener, poczekaj, aż ECS go zastąpi, zatrzymaj drugi kontener). Kiedy ECS ponownie uruchomi kontener, pobierze najnowszą wersję mojego obrazu: najnowszą wbudowaną, jak wyjaśniono wcześniej. Myślę, że utworzenie nowej definicji zadania jest łatwiejsze i mniej podatne na błędy (nie trzeba logiki czekać i sprawdzać, ECS zajmie się aktualizacją kroczącą, jeśli masz nową definicję zadania).

Alexandre
źródło
Niesamowite - nazwałbym twoją odpowiedź brakującą instrukcją dla CI / CD dla dokera. Dziękuję Ci.
Naveen Vijay
3

Dla prostego opisanego przypadku użycia sugerowałbym sprawdzenie Elastic Beanstalk dla Dockera, nie jest to minimalne rozwiązanie, takie jak samo korzystanie z ECS, ale możesz skorzystać z automatycznie zarządzanych i skonfigurowanych usług, takich jak ELB, AutoScale EC2, monitorowanie stanu zdrowia i wiele więcej.

Podsumowanie wysokiego poziomu:

  1. Skonfiguruj Elastic Beanstalk, aby używał określonego tagu myimage: przetestowano
  2. Użyj Code Pipeline / Build, aby budować, testować i promować tag „testowany”
  3. Uruchom instalację elastycznej fasoli, która przyciągnie promowany obraz myimage: przetestowany we wszystkich instancjach, dostępne różne strategie wdrażania.

Podejście to oparte na ponownym użyciu tego samego tagu, alternatywne podejście polegałoby na generowaniu tagu z identyfikatorem kompilacji, na przykład myimage: testowany-42, będzie to wymagało aktualizacji Elastic Beanstalk za każdym razem z nowym tagiem, ale daje bardziej szczegółową kontrolę nad wdrożoną wersją.

rombob
źródło
0

Druga elastyczna łodyga fasoli ze względu na jej prostotę; jest bardzo łatwy do skonfigurowania i wdrożenia.

Jeśli jesteś zaznajomiony z docker-compose, innym podejściem byłoby zdefiniowanie docker-compose.yml i bezpośrednie wdrożenie w ECS za pomocą ecs-cli.

AnthonyC
źródło