W tej serii artykułów przybliżę Ci jeden z moich ostatnich projektów do domowego labu. Nie ukrywam, że lubię mieć lab always-on, czyli taki, który działa, który ma skonfigurowane pewne funkcjonalności, do których w każdej chwili mogę się odwołać, sprawdzić je czy zmodyfikować. Powstała więc potrzeba zautomatyzowania procesu budowania maszyny wirtualnej z Cisco ISE oraz odtwarzania konfiguracji ISE z kopi zapasowej. W pierwszym odcinku spójrzmy jak wygląda automatyzacja odtwarzania Cisco ISE i z jakich komponentów będę korzystał.
Spis treści
- Część I: Opis projektu
- Część II: Przygotowanie środowiska Jenkins i Ansible
- Część III: Sprawdzamy datę ostatniego backupu
- Część IV: Sprawdzamy ważność licencji trial na Cisco ISE
- Część V: Zatrzymujemy ISE i wyłączamy maszynę wirtualną
- Część VI: Zero Touch Provisioning
- Część VII: Odtworzenie konfiguracji z kopii zapasowej
Dlaczego jest mi to potrzebne?
Przeprowadzając testy PoC u klientów, często instalujemy wirtualne instancje Cisco ISE by przetestować funkcjonalności. W przypadku długich testów napotykamy jeden problem. Licencja trial Cisco ISE jest tylko na 90 dni. Zatem co 90 dni konieczne jest zbudowanie nowej maszyny wirtualnej i przywrócenie konfiguracji z kopii zapasowej. Dlatego przygotowałem rozwiązanie, które proces ten zautomatyzuje. Nie polecam tego rozwiązania do sieci produkcyjnych, gdzie powinniśmy używać zakupionych licencji, a nie ewaluacyjnych.
Mój pomysł jest taki, by co 75 dni maszyna wirtualna z Cisco ISE się sama ponownie instalowała i odtwarzała z backupu. Najlepiej w nocy kiedy śpię, bo proces ten trwa parę godzin. Licencja się nie zapisuje w kopii zapasowej zatem otworzenie konfiguracji na nowej instalacji restartuje jej timer.
Przedstawione rozwiązanie przygotowałem pod Cisco ISE 3.2. Powinno działać z wcześniejszymi wersjami linii 3.x, ale nie będzie działać z linią 2.x. Mój lab stoi na Cisco UCS (to akurat nie jest istotne, bo serwer może być dowolny) z hypervisorem VMware ESXi 7.0U3.
Projektowane przeze mnie rozwiązanie jest wieloetapowym scenariuszem z warunkami przerwania jego wykonania w różnych jego etapach. Przykładowo – jeżeli ważność licencji trial jest dłuższa niż 15 dni to cały proces nie powinien się wykonać. Tak samo ciąg zdarzeń powinien zostać przerwany jeżeli nie ma lub nie jest dostępna kopia zapasowa. Jak w każdym projekcie chciałem też zastosować odpowiednią jego modularyzację. Tutaj wynikała też z czysto operacyjnych elementów jak między innymi to, z jakimi urządzeniami muszę się komunikować. Mój wybór padł na GitLab, Jenkins i Ansible.
Komponenty rozwiązania
GitLab pełni rolę repozytorium, na którym trzymam pliki poszczególnych komponentów projektu. Znajdują się tu playbooki Ansible jak i definicja pipeline projektu w Jenkins. Pełni więc on klasyczną rolę “mózgu” projektu. Wykorzystałem do tego prywatną instancję GitLaba w moim labie.
Do zarządzania procesem CI\CD postanowiłem wykorzystać prywatną instancję Jenkinsa. Nie ukrywam, że mimo wielu niedoskonałości jest to jedno z lepszych narzędzi do tworzenia zaawansowanych projektów CI/CD. Zamknięcie całego procesu w pojedynczym playbooku Ansible byłoby dość karkołomne, o czym za chwile. Dlatego poszczególne zadania podzieliłem na mniejsze części (playbooki), których wykonaniem coś musiało zarządzać. Mogłem pokusić się o użycie GitLab Runnera, ale Jenkins zapewnia lepsze narzędzia choćby do zarządzania danymi wrażliwymi jak dane do logowania. Moja instalacja Jenkinsa ma wszystkie niezbędne komponenty by wykonać playbooki Ansible z tego projektu, czyli między innymi zainstalowane odpowiednie biblioteki Pythona wymagane przez kolekcje do obsługi VMware ESXi czy połączeń do Cisco ISE. Alternatywnie do Jenkinsa mógłbym wykorzystać AWX (Ansible Automation Platform w wersji darmowej), ale nie mam uruchomionego i na stałe działającego tego produktu w swoim labie.
Poszczególne zadania zamknięte są w playbookach Ansible. Dlaczego nie w jednym? Dlatego, że sterowanie takim projektem jest prostsze przez jego modularyzację i wykorzystanie zewnętrznego narzędzia jakim jest Jenkins. Poza tym różne zadania zapisane w playbookach wymagają innego inventory czy przekazania innych parametrów logowania. Część zadań jest wykonywana lokalnie, inne na zdalnym systemie, jeszcze inne korzystając z API. Dodatkowym pozytywnym aspektem podziału projektu na niezależne playbooki jest też to, że mogę je potem wykorzystać w innych projektach wprowadzając tylko niezbędne modyfikacje. Uzyskuję zatem powtarzalność i przenaszalność utworzonego kodu.
Projekt w Jenkins
Jako typ projektu w Jenkins wybrałem Pipeline.
W konfiguracji projektu uwzględniłem przekazywanie do niego parametrów wykonania. Parametry te potem będę przekazywał do wywołania playbooków Ansible w poszczególnych krokach. Parametry to zmienne takie jak na przykład nazwa maszyny wirtualnej z Cisco ISE czy dane do logowania. Do przechowywania wrażliwych informacji wykorzystuję bezpieczne obiekty z kategorii Credentials.
Plik konfiguracyjny pipeline jak już wcześniej wspomniałem jest także przechowywany na repozytorium GitLab. Z punktu widzenia bezpieczeństwa i dobrych zasad budowania systemów automatyzacji jest to lepsze rozwiązanie niż przechowywanie go w projekcie Jenkinsa. Poza tym w ten sposób przechowywana jest historia edycji.