1. Wprowadzenie
Ostatnia aktualizacja: 1.11.2024
Jak zmodernizować starą aplikację PHP do Google Cloud?
(📽️ obejrzyj 7-minutowy film wprowadzający do tego ćwiczenia z programowania)
Często zdarza się, że w firmie działają starsze aplikacje, które wymagają modernizacji. Oznacza to, że muszą być one skalowalne, bezpieczne i możliwe do wdrożenia w różnych środowiskach.
W ramach warsztatów:
- Skonteneryzuj aplikację PHP.
- Przejdź na zarządzaną bazę danych ( Cloud SQL).
- Wdróż aplikację w Cloud Run (to alternatywa dla GKE/Kubernetes, która nie wymaga obsługi).
- Zabezpiecz aplikację za pomocą usługi Identity and Access Management (IAM) i Secret Manager.
- zdefiniuj potok CI/CD za pomocą Cloud Build. Cloud Build można połączyć z repozytorium Git hostowanym w popularnych usługach Git, takich jak GitHub czy GitLab, i aktywować na przykład przy każdym wysłaniu do głównego repozytorium.
- Przechowuj zdjęcia aplikacji w Cloud Storage. Osiąga się to przez zamontowanie, a aby zmienić aplikację, nie trzeba pisać kodu.
- Wprowadzenie funkcji Gen AI w Gemini, skoordynowanych za pomocą funkcji Cloud Functions (bez serwera).
- Zapoznaj się z SLOs i działaniem odświeżonej aplikacji.
Dzięki tym czynnościom możesz stopniowo modernizować aplikację PHP, zwiększając jej skalowalność, bezpieczeństwo i elastyczność wdrożenia. Przejście na Google Cloud umożliwia też korzystanie z jego potężnej infrastruktury i usług, aby zapewnić płynne działanie aplikacji w środowisku natywnym dla chmury.
Wierzymy, że to, czego się nauczysz, wykonując te proste czynności, możesz zastosować w swojej aplikacji i organizacji z użyciem innego języka lub zestawu narzędzi oraz w innych przypadkach użycia.
Informacje o aplikacji
Aplikacja ( kod na podstawie licencji MIT), którą rozgałęzisz, to podstawowa aplikacja PHP 5.7 z uwierzytelnianiem MySQL. Głównym założeniem aplikacji jest zapewnienie platformy, na której użytkownicy mogą przesyłać zdjęcia, a administratorzy mogą oznaczać nieodpowiednie obrazy. Aplikacja ma 2 tabele:
- Użytkownicy. Wstępnie skompilowane z administratorami. Mogą się rejestrować nowi użytkownicy.
- Obrazy. Zawiera kilka przykładowych obrazów. Zalogowani użytkownicy mogą przesyłać nowe zdjęcia. Dodamy tu trochę magii.
Twój cel
Chcemy zmodernizować starą aplikację, aby działała w Google Cloud. Będziemy korzystać z tych narzędzi i usług, aby zwiększyć skalowalność, poprawić bezpieczeństwo, zautomatyzować zarządzanie infrastrukturą oraz integrować zaawansowane funkcje, takie jak przetwarzanie obrazów, monitorowanie i przechowywanie danych, korzystając z usług takich jak Cloud SQL, Cloud Run, Cloud Build, Secret Manager i innych.
Co ważniejsze, chcemy, abyś poznawał te informacje krok po kroku, abyś dowiadywał się, jak przebiega proces myślowy związany z każdym krokiem. Zazwyczaj każdy krok otwiera nowe możliwości dla kolejnych (np. moduły 2 -> 3 i 6 -> 7).
Nie jesteś jeszcze przekonany? Obejrzyj ten 7-minutowy film w YouTube.
Czego potrzebujesz
- Komputer z przeglądarką i połączeniem z internetem.
- Niektóre środki w Google Cloud Platform. Zapytaj lokalnego fana Google o pomoc ;)
- Polecenie
gcloud
działa. - Pracujesz lokalnie? Pobierz aplikację tutaj. Potrzebujesz też dobrego edytora (np. vscode lub intellij).
- Czy chcesz robić wszystko „w chmurze”? Możesz wtedy użyć Cloud Shell.
- Użytkownik GitHuba. Potrzebujesz go, aby utworzyć gałąź oryginalnego kodu 🧑🏻💻 gdgpescara/app-mod-workshop w swoim repozytorium Git. Jest to konieczne, aby mieć własny potok CI/CD (automatyczne potwierdzenie > kompilacja > wdrożenie).
Przykładowe rozwiązania znajdziesz tutaj:
- Repozytorium autora: https://github.com/Friends-of-Ricc/app-mod-workshop
- Pierwotna wersja repozytorium warsztatów w folderach
.solutions/
w przypadku każdego rozdziału.
Warsztaty można oglądać na komputerze lokalnym lub przeprowadzić całkowicie w przeglądarce.
2. Konfiguracja kredytu i Fork
Wykorzystanie środków w GCP i skonfigurowanie środowiska GCP [opcjonalnie]
Aby przeprowadzić to szkolenie, musisz mieć konto rozliczeniowe z dodatkiem środków. Jeśli masz już własne ustawienia płatności, możesz pominąć ten krok.
Utwórz zupełnie nowe konto Gmail Google (*), aby połączyć je z środkami na koncie Google Cloud Platform. Poproś nauczyciela o link do wykorzystania środków w GCP lub skorzystaj z nich tutaj: bit.ly/PHP-Amarcord-credits .
Zaloguj się na nowo utworzone konto i postępuj zgodnie z instrukcjami.
(
) Dlaczego potrzebuję zupełnie nowego konta Gmail?*
Mieliśmy przypadki, że użytkownicy nie byli w stanie ukończyć Codelab, ponieważ ich konto (zwłaszcza adresy e-mail służbowe lub studenckie) było wcześniej używane do korzystania z Google Cloud Platform i miało ograniczone możliwości. Zalecamy utworzenie nowego konta Gmail lub użycie istniejącego konta Gmail (gmail.com), które nie było wcześniej używane do korzystania z GCP.
Kliknij przycisk, aby wykorzystać środki.
Wypełnij formularz, podając swoje imię i nazwisko oraz zaakceptuj Warunki korzystania z usługi.
Może być konieczne odczekanie kilku sekund, aż konto rozliczeniowe pojawi się tutaj: https://console.cloud.google.com/billing
Gdy to zrobisz, otwórz konsolę Google Cloud i utwórz nowy projekt, klikając selektor projektu w menu w lewym górnym rogu, gdzie wyświetla się „Brak organizacji”. Szczegółowe informacje znajdziesz poniżej
Jeśli jeszcze nie masz projektu, utwórz go, jak pokazano na poniższym zrzucie ekranu. W prawym górnym rogu znajduje się opcja „NOWY PROJEKT”.
Połącz nowy projekt z kontem rozliczeniowym GCP w wersji próbnej w ten sposób:
Możesz już korzystać z Google Cloud Platform. Jeśli jesteś początkującym użytkownikiem lub chcesz wykonywać wszystkie czynności w środowisku chmury, możesz uzyskać dostęp do Cloud Shell i jego edytora za pomocą przycisku w lewym górnym rogu, jak pokazano poniżej.
Upewnij się, że w lewym górnym rogu wybrany jest nowy projekt:
Nie wybrano (nieprawidłowe):
Wybrany (dobry):
Utwórz rozwidlenie aplikacji na GitHubie
- Otwórz aplikację demonstracyjną: https://github.com/gdgpescara/app-mod-workshop
- Kliknij 🍴 widelec.
- Jeśli nie masz konta GitHub, musisz je utworzyć.
- Edytuj je według własnych potrzeb.
- Sklonuj kod aplikacji za pomocą
git clone
https://github.com/
YOUR-GITHUB-USER/YOUR-REPO-NAME
- Otwórz folder z klonowanym projektem w ulubionym edytorze. Jeśli wybierzesz Cloud Shell, możesz to zrobić, klikając „Otwórz edytor”, jak pokazano poniżej.
W edytorze Google Cloud Shell masz wszystko, czego potrzebujesz.
Aby to zrobić, kliknij „Otwórz folder” i wybierz folder, prawdopodobnie app-mod-workshop
w folderze głównym.
3. Moduł 1. Tworzenie instancji SQL
Utwórz instancję Google Cloud SQL
Nasza aplikacja PHP będzie się łączyć z bazą danych MySQL, dlatego musimy ją skopiować do Google Cloud, aby migracja przebiegła bezproblemowo. Cloud SQL to idealne rozwiązanie, ponieważ umożliwia uruchamianie w chmurze w pełni zarządzanej bazy danych MySQL. Aby to zrobić:
- Otwórz stronę Cloud SQL: https://console.cloud.google.com/sql/instances
- Kliknij „Utwórz instancję”.
- Włącz interfejs API (w razie potrzeby). Może to potrwać kilka sekund.
- Wybierz MySQL.
- (staramy się zaoferować najtańszą wersję, która będzie działać dłużej):
- Wersja: Enterprise
- Wstępnie: development (próbowaliśmy piaskownicy, ale nie zadziałało)
- MySQL w wersji 5.7 (wow, to jest powrót do przeszłości!)
- Identyfikator instancji: wybierz
appmod-phpapp
(jeśli go zmienisz, pamiętaj, aby odpowiednio zmienić przyszłe skrypty i rozwiązania). - Hasło: dowolne, ale zapisz je jako CLOUDSQL_INSTANCE_PASSWORD
- Region: pozostaw ten sam co w pozostałych częściach aplikacji (np. Mediolan =
europe-west8
). - Dostępność strefowa: jedna strefa (oszczędzamy na potrzeby wersji demonstracyjnej)
Kliknij przycisk Utwórz instancję, aby wdrożyć bazę danych Cloud SQL. ⌛ Zajmie to około 10 minut.⌛ W międzyczasie kontynuuj czytanie dokumentacji. Możesz też przejść do rozwiązywania kolejnego modułu („Konteneryzacja aplikacji PHP”), ponieważ nie ma on zależności od tej części pierwszej części (dopóki nie naprawisz połączenia z bazą danych).
Uwaga. Ta instancja powinna kosztować około 7 USD dziennie. Pamiętaj, aby wyłączyć go po zakończeniu warsztatów.
Tworzenie bazy danych image_catalog i użytkownika w Cloud SQL
Projekt aplikacji zawiera folder db/
z 2 plikami SQL:
- 01_schema.sql : zawiera kod SQL do utworzenia 2 tabel, które zawierają dane o użytkownikach i obrazach.
- 02_seed.sql: zawiera kod SQL do zainicjowania danych w uprzednio utworzonych tabelach.
Te pliki zostaną użyte później, gdy utworzysz bazę danych image_catalog
. Aby to zrobić:
- Otwórz instancję i kliknij kartę Bazy danych:
- kliknij „Utwórz bazę danych”.
- nazwij go
image_catalog
(tak jak w konfiguracji aplikacji PHP).
Następnie tworzymy użytkownika bazy danych. Dzięki temu możemy uwierzytelnić się w bazie danych image_catalog.
- Teraz kliknij kartę Użytkownicy.
- Kliknij „Dodaj konto użytkownika”.
- Użytkownik: Utwórzmy jeden:
- Nazwa użytkownika:
appmod-phpapp-user
- Hasło: wybierz coś, co możesz zapamiętać, lub kliknij „Wygeneruj”.
- Pozostaw opcję „Zezwalaj na dowolnego hosta (%)”.
- kliknij DODAJ.
Otwórz bazę danych dla znanych adresów IP.
Pamiętaj, że wszystkie bazy danych w Cloud SQL są „odizolowane” od samego początku. Musisz wyraźnie skonfigurować sieć, z której ma być dostępny.
- Kliknij instancję.
- Otwórz menu „Połączenia”.
- Kliknij kartę „Networking” (Sieć).
- Kliknij w sekcji „Autoryzowane sieci”. Teraz dodaj sieć (czyli podsieć).
- Na razie wybierzmy szybkie, ale NIEBEZPIECZNE ustawienia, aby umożliwić działanie aplikacji. Możesz później ograniczyć dostęp do adresów IP, którym ufasz:
- Nazwa: „Everyone in the world - INSECURE”.
- Sieć: „
0.0.0.0/0"
(Uwaga: to jest NIEBEZPIECZNA część!) - Kliknij GOTOWE.
- Kliknij Zapisz.
Powinien pojawić się ekran podobny do tego:
Uwaga. To rozwiązanie jest dobrym kompromisem, który pozwala zakończyć warsztaty w czasie rzędu O(hours). Sprawdź jednak dokument Bezpieczeństwo, aby dowiedzieć się, jak zabezpieczyć rozwiązanie do użytku produkcyjnego.
Czas przetestować połączenie z bazą danych.
Sprawdźmy, czy utworzony wcześniej użytkownik image_catalog
działa.
Wejdź do „Cloud SQL Studio” w instancji i wpisz bazę danych, użytkownika i hasło, aby uwierzytelnić się, jak pokazano poniżej:
Teraz możesz otworzyć edytor SQL i przejść do następnej sekcji.
Importowanie bazy danych z kodu źródłowego
Zaimportuj tabele image_catalog
z ich danymi za pomocą Edytora SQL. Skopiuj kod SQL z plików w repozytorium ( 01_schema.sql, a potem 02_seed.sql) i wykonaj je jeden po drugim w kolejności.
Wtedy w tabeli image_catalog powinny pojawić się 2 tabele: users i images, jak pokazano poniżej:
Możesz to przetestować, wykonując w edytorze tę czynność: select * from images;
Zapisz też publiczny adres IP instancji Cloud SQL, będzie Ci on potrzebny później. Aby uzyskać adres IP, otwórz stronę główną instancji Cloud SQL na stronie Przegląd. (Omówienie > Połącz z tą instancją > Publiczny adres IP).
4. Moduł 2. Konteneryzowanie aplikacji PHP
Chcemy stworzyć tę aplikację na chmurę.
Oznacza to spakowanie kodu w pliku ZIP, który zawiera wszystkie informacje potrzebne do jego uruchomienia w chmurze.
Możesz to zrobić na kilka sposobów:
- Docker. Bardzo popularna, ale dość skomplikowana w prawidłowej konfiguracji.
- Buildpacks. Mniej popularna, ale zwykle „automatycznie odgaduje”, co należy skompilować i uruchomić. Często to działa.
W ramach tych warsztatów zakładamy, że używasz Dockera.
Jeśli chcesz użyć Cloud Shell, otwórz go ponownie (kliknij w prawym górnym rogu konsoli Cloud).
Spowoduje to otwarcie wygodnej powłoki u dołu strony, gdzie w kroku konfiguracji powinieneś utworzyć odgałęzienie kodu.
Docker
Jeśli chcesz mieć kontrolę, to jest odpowiednie rozwiązanie dla Ciebie. Ma to sens, gdy trzeba skonfigurować określone biblioteki i wstrzyknąć pewne nieoczywiste zachowania (np. chmod w przesyłanych plikach lub niestandardowy plik wykonywalny w aplikacji).
Ponieważ chcemy wdrożyć naszą aplikację konteneryzowaną w Cloud Run, zapoznaj się z tą dokumentacją. Jak można przenieść kod z PHP 8 do PHP 5.7? Możesz do tego wykorzystać Gemini. Możesz też użyć tej wersji:
Najnowszą wersję Dockerfile
znajdziesz tutaj.
Aby przetestować aplikację lokalnie, musimy zmienić plik config.php w taki sposób, aby aplikacja PHP połączyła się z bazą danych MySQL dostępną w Google CloudSQL. Na podstawie wcześniejszych ustawień wypełnij puste pola:
<?php
// Database configuration
$db_host = '____________';
$db_name = '____________';
$db_user = '____________';
$db_pass = '____________';
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Errore di connessione: " . $e->getMessage());
}
session_start();
?>
DB_HOST
to publiczny adres IP Cloud SQL. Znajdziesz go w konsoli SQL:
DB_NAME
nie powinien się zmienić:image_catalog
DB_USER
powinna mieć wartośćappmod-phpapp-user
DB_PASS
to coś, co wybrałeś(-aś). Ustaw go w cudzysłowie i w razie potrzeby użyj znaku ucieczki.
Możesz też przetłumaczyć kilka 🇮🇹 włoskich tekstów na angielski za pomocą Gemini.
Ok, teraz, gdy masz już Dockerfile
i skonfigurowałeś aplikację PHP do połączenia z bazą danych, możesz to wypróbować.
Zainstaluj Dockera, jeśli jeszcze go nie masz ( link). Nie musisz tego robić, jeśli używasz Cloud Shell (jak to jest fajne).
Teraz spróbuj utworzyć i uruchomić aplikację PHP w kontenerze za pomocą odpowiednich poleceń docker build i run.
# Build command - don't forget the final . This works if Dockerfile is inside the code folder:
$ docker build -t my-php-app-docker .
# Local Run command: most likely ports will be 8080:8080
$ docker run -it -p <CONTAINER_PORT>:<LOCAL_MACHINE_PORT> my-php-app-docker
Jeśli wszystko działa prawidłowo, po połączeniu z hostem lokalnym powinna wyświetlić się ta strona internetowa. Teraz Twoja aplikacja działa na porcie 8080. Kliknij ikonę „Podgląd w przeglądarce” (ikona oka) i wybierz Podejrzyj na porcie 8080 (lub „Zmień port”, aby wybrać inny port).
Testowanie wyniku w przeglądarce
Twoja aplikacja powinna teraz wyglądać mniej więcej tak:
Jeśli zalogujesz się jako Admin/admin123, powinieneś zobaczyć coś takiego.
Świetnie! Poza tekstem w języku włoskim wszystko działa. 🎉🎉🎉
Jeśli dockeryzacja jest prawidłowa, ale dane logowania do bazy danych są nieprawidłowe, możesz zobaczyć komunikat podobny do tego:
Spróbuj jeszcze raz, jesteś blisko!
Zapisywanie w Artifact Registry [opcjonalnie]
Do tej pory powinnaś/powinieneś mieć działającą aplikację PHP w kontenerze gotową do wdrożenia w chmurze. Następnie potrzebujemy miejsca w chmurze, w którym będziemy mogli przechowywać obraz Dockera i udostępniać go do wdrożenia w usługach Google Cloud, takich jak Cloud Run. To rozwiązanie do przechowywania nosi nazwę Artifact Registry. Jest to w pełni zarządzana usługa Google Cloud zaprojektowana do przechowywania artefaktów aplikacji, w tym obrazów kontenerów Dockera, pakietów Maven, modułów npm i innych.
Utwórz repozytorium w Google Cloud Artifact Registry, używając odpowiedniego przycisku.
Wybierz prawidłową nazwę, format i region odpowiedni do przechowywania artefaktów.
Wróć do tagu środowiska programistycznego lokalnego i prześlij obraz kontenera aplikacji do utworzonego przed chwilą repozytorium Artifact Registry. Aby to zrobić, wykonaj te polecenia.
- docker tag ŹRÓDŁO_OBRAZU[:TAG] DOCEL_OBRAZU[:TAG]
- docker push TARGET_IMAGE[:TAG]
Wynik powinien wyglądać jak na poniższym zrzucie ekranu.
Hura 🎉🎉🎉, możesz przejść na wyższy poziom. Zanim to zrobisz, poświęć 2 minuty na zapoznanie się z punktami końcowymi aplikacji oraz przesłaniem i zalogowaniem się.Potrzebujesz ich później.
Możliwe błędy
Jeśli wystąpią błędy związane z tworzeniem kontenerów, spróbuj użyć Gemini, aby wyjaśnić i naprawić błąd. Podaj:
- bieżący plik Dockerfile,
- otrzymany błąd;
- [w razie potrzeby] kod PHP, który ma być wykonywany.
Uprawnienia dotyczące przesyłania danych. Spróbuj też użyć punktu końcowego /upload.php
i prześlij zdjęcie. Może pojawić się błąd poniżej. Jeśli tak, musisz wprowadzić poprawki w sekcji chmod/chown
.Dockerfile
Ostrzeżenie: move_uploaded_file(uploads/image (3).png): nie udało się otworzyć strumienia: Permission denied in /var/www/html/upload.php on line 11
Błąd PDOException „could not find driver” (lub „Errore di connessione: could not find driver”). Upewnij się, że plik Dockerfile zawiera odpowiednie biblioteki PDO dla MySQL (pdo_mysql
), aby nawiązać połączenie z bazą danych. Zainspiruj się rozwiązaniami tutaj.
Nie udało się przekazać Twojej prośby do backendu. Nie udało się połączyć z serwerem na porcie 8080. Oznacza to, że prawdopodobnie udostępniasz niewłaściwy port. Upewnij się, że udostępniasz port, z którego serwer Apache lub Nginx faktycznie obsługuje żądania. To nie jest proste. Jeśli to możliwe, spróbuj ustawić port 8080 (ułatwia korzystanie z Cloud Run). Jeśli chcesz zachować port 80 (np. dlatego, że Apache wymaga tego), uruchom go za pomocą innego polecenia:
$ docker run -it -p 8080:80 # force 80
# Use the PORT environment variable in Apache configuration files.
# https://cloud.google.com/run/docs/reference/container-contract#port
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
5. Moduł 3. Wdrażanie aplikacji w Cloud Run
Dlaczego warto wybrać Cloud Run?
Dobre pytanie. Jeszcze kilka lat temu z pewnością wybrałbyś/wybrałabyś Google App Engine.
Mówiąc wprost, Cloud Run ma obecnie nowszy pakiet technologiczny, jest łatwiejszy do wdrożenia, tańszy i skaluje się do 0, gdy go nie używasz. Dzięki możliwości uruchamiania dowolnego bezstanowego kontenera i integracji z różnymi usługami Google Cloud jest to idealne rozwiązanie do wdrażania mikroserwisów i nowoczesnych aplikacji z minimalnym nakładem pracy i maksymalną wydajnością.
Cloud Run to w pełni zarządzana platforma Google Cloud, która umożliwia uruchamianie bezstanowych aplikacji konteneryzowanych w środowisku bezserwerowym. Automatycznie obsługuje całą infrastrukturę, skalując ją od zera do poziomu odpowiadającego napływającemu ruchowi i zmniejszając ją, gdy jest nieaktywna. Dzięki temu jest ekonomiczna i wydajna. Cloud Run obsługuje dowolny język lub bibliotekę, o ile są one zapakowane w kontener, co zapewnia dużą elastyczność podczas tworzenia. Łatwo się integruje z innymi usługami Google Cloud i nadaje się do tworzenia mikroserwisów, interfejsów API, stron internetowych i aplikacji sterowanych zdarzeniami bez konieczności zarządzania infrastrukturą serwerową.
Wymagania wstępne
Aby wykonać to zadanie, musisz mieć zainstalowaną na komputerze lokalnym wersję gcloud
. Jeśli nie, instrukcje znajdziesz tutaj. Jeśli korzystasz z Google Cloud Shell, nie musisz nic robić.
Przed wdrożeniem...
Jeśli pracujesz w środowisku lokalnym, uwierzytelnij się w Google Cloud za pomocą tych danych:
$ gcloud auth login –update-adc # not needed in Cloud Shell
W tym celu musisz się zalogować w przeglądarce za pomocą OAuth. Zaloguj się w Chrome tym samym użytkownikiem (np. vattelapesca@gmail.com), który jest zalogowany w Google Cloud z włączonym rozliczaniem.
Włącz interfejs Cloud Run API za pomocą tego polecenia:
$ gcloud services enable run.googleapis.com cloudbuild.googleapis.com
W tym momencie wszystko jest gotowe do wdrożenia w Cloud Run.
Wdrażanie aplikacji w Cloud Run za pomocą gcloud
Polecenie, które umożliwia wdrożenie aplikacji w Cloud Run, to gcloud run deploy
. Aby osiągnąć swój cel, możesz ustawić kilka opcji. Minimalny zestaw opcji (które możesz podać w wierszu poleceń lub za pomocą interaktywnego promptu):
- Nazwa usługi Cloud Run, którą chcesz wdrożyć w aplikacji. Usługa Cloud Run zwróci adres URL, który zawiera punkt końcowy aplikacji.
- Region Google Cloud, w którym będzie działać aplikacja. (
--region
REGION) - obraz kontenera, który zawiera Twoją aplikację.
- Zmienne środowiskowe, których aplikacja musi używać podczas wykonywania.
- Flaga Allow-Unauthenticated, która zezwala wszystkim użytkownikom na dostęp do aplikacji bez dodatkowego uwierzytelniania.
Aby dowiedzieć się, jak zastosować tę opcję w wierszu poleceń, zapoznaj się z dokumentacją (lub przewiń w dół, aby znaleźć możliwe rozwiązanie).
Wdrażanie może potrwać kilka minut. Jeśli wszystko jest w porządku, w konsoli Google Cloud Console powinna wyświetlić się informacja podobna do tej.
Kliknij adres URL podany przez Cloud Run i przetestuj aplikację. Po uwierzytelnieniu powinno pojawić się coś takiego.
„gcloud run deploy” bez argumentów
Zauważysz, że gcloud run deploy
zadaje Ci odpowiednie pytania i wypełnia puste miejsca. Jest niesamowicie!
Jednak w kilku modułach dodamy to polecenie do reguły Cloud Build, ponieważ nie możemy sobie pozwolić na interaktywne pytania. Musimy wypełnić wszystkie opcje w komendzie. Chcesz utworzyć złotą gcloud run deploy --option1 blah --foo bar --region your-fav-region
. Jak to zrobisz?
- powtarzaj kroki 2–3–4, aż gcloud przestanie zadawać pytania:
- [LOOP]
gcloud run deploy
z opcjami znalezionymi do tej pory - [LOOP] systems ask for option X
- [LOOP] Wyszukaj w dokumentach publicznych informacje o konfigurowaniu X za pomocą opcji dodawania w interfejsie wiersza poleceń
--my-option [my-value]
. - Wróć do kroku 2, chyba że gcloud zakończy się bez dodatkowych pytań.
- To wdrożenie gcloud run BLAH BLAH BLAH jest świetne! Zapisz to polecenie gdzieś, ponieważ będzie Ci ono potrzebne w etapu Cloud Build.
Możliwe rozwiązanie znajdziesz tutaj. Dokumenty znajdziesz tutaj.
Hura! 🎉🎉🎉 Twoja aplikacja została wdrożona w Google Cloud, co oznacza, że wykonałeś/wykonałaś pierwszy krok w modernizacji.
6. Moduł 4. Czyste hasło za pomocą usługi Secret Manager
W poprzednim kroku udało nam się wdrożyć i uruchomić aplikację w Cloud Run. Zrobiliśmy to jednak w sposób niezgodny ze standardami bezpieczeństwa: podając niektóre sekrety w postaci zwykłego tekstu.
Pierwsza iteracja: zaktualizuj plik config.php w celu użycia zmiennych środowiskowych
Zauważysz, że hasło do bazy danych zostało umieszczone bezpośrednio w pliku config.php. To wystarczy do celów testowych i sprawdzenia, czy aplikacja działa. Nie możesz jednak używać takiego kodu w środowisku produkcyjnym. Hasło (i inne parametry połączenia z bazą danych) powinny być odczytywane dynamicznie i przekazywane aplikacji w czasie wykonywania. Zmień plik config.php, aby odczytywał parametry bazy danych z ustawień środowiskowych. Jeśli się nie uda, rozważ ustawienie wartości domyślnych. Jest to przydatne, gdy nie uda Ci się załadować pliku ENV. Wyjście strony poinformuje Cię, czy używa wartości domyślnych. Uzupełnij puste pola i zastąp kod w pliku config.php.
<?php
// Database configuration with ENV variables. Set default values as well
$db_host = getenv('DB_HOST') ?: 'localhost';
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: 'wrong_password';
// Note getenv() is PHP 5.3 compatible
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Errore di connessione: " . $e->getMessage());
}
session_start();
?>
Aplikacja jest skonteneryzowana, więc musisz określić sposób dostarczania aplikacji zmiennych środowiskowych. Możesz to zrobić na kilka sposobów:
- W momencie kompilacji w pliku Dockerfile. Dodaj do poprzedniego pliku Dockerfile 4 parametry, używając składni ENV DB_VAR=ENV_VAR_VALUE. Spowoduje to ustawienie wartości domyślnych, które można zastąpić w czasie wykonywania. Na przykład zmienne „DB_NAME” i „DB_USER” mogą być ustawione tylko tutaj.
- W czasie wykonywania. Te zmienne możesz skonfigurować w Cloud Run, korzystając z interfejsu wiersza poleceń lub interfejsu użytkownika. To jest odpowiednie miejsce na umieszczenie wszystkich 4 zmiennych (chyba że chcesz zachować domyślne wartości ustawione w pliku Dockerfile).
W localhost możesz umieścić zmienne środowiskowe w pliku .env
(sprawdź folder solutions).
Upewnij się też, że plik .env został dodany do .gitignore
: nie chcesz przecież przesłać swoich tajemnic na Githuba.
echo .env >> .gitignore
Następnie możesz przetestować instancję lokalnie:
docker run -it -p 8080:8080 --env-file .env my-php-app-docker
Udało Ci się już:
- Aplikacja będzie odczytywać zmienną dynamicznie z pliku ENV.
- Zwiększyłeś/zwiększyłaś bezpieczeństwo, usuwając z kodu hasło do bazy danych.
Możesz teraz wdrożyć nową wersję w Cloud Run. Przejdźmy do interfejsu użytkownika i ręcznie ustaw zmienne środowiskowe:
- Wejdź na https://console.cloud.google.com/run.
- Kliknij swoją aplikację.
- Kliknij „Edytuj i wdróż nową wersję”.
- Na pierwszej karcie „Kontenery” kliknij dolną kartę „Zmienne i obiekty tajne”.
- Kliknij „+ Dodaj zmienną” i dodaj wszystkie potrzebne zmienne. Powinieneś uzyskać coś takiego:
Czy to jest OK? Nie. Twój identyfikator PASS jest nadal widoczny dla większości operatorów. Można temu zapobiec, korzystając z usługi Google Cloud Secret Manager.
Druga iteracja: Secret Manager
Twoje hasła zniknęły z Twojego kodu: sukces! Ale czy na pewno jesteśmy już bezpieczni?
Twoje hasła są nadal widoczne dla każdego, kto ma dostęp do konsoli Google Cloud. Jeśli otworzysz plik YAML wdrożenia Cloud Run, możesz go pobrać. Jeśli spróbujesz edytować lub wdrożyć nową wersję Cloud Run, hasło będzie widoczne w sekcji „Zmienne i sekrety”, jak pokazano na poniższych zrzutach ekranu.
Secret Manager w Google Cloud to bezpieczna, scentralizowana usługa do zarządzania informacjami poufnymi, takimi jak klucze interfejsu API, hasła, certyfikaty i inne obiekty tajne.
Umożliwia przechowywanie obiektów tajnych, zarządzanie nimi i uzyskiwanie do nich dostępu za pomocą szczegółowych uprawnień i solidnego szyfrowania. Menedżer obiektów tajnych jest zintegrowany z usługą Google Cloud Identity and Access Management (IAM) i umożliwia kontrolowanie, kto ma dostęp do określonych obiektów tajnych, co zapewnia bezpieczeństwo danych i zgodność z przepisami.
Umożliwia też automatyczną rotację i wersjonowanie kluczy, upraszcza zarządzanie cyklem życia kluczy oraz zwiększa bezpieczeństwo aplikacji w usługach Google Cloud.
Aby uzyskać dostęp do Menedżera sekretów, otwórz menu hamburgera, przejdź do usług Bezpieczeństwo i znajdź go w sekcji Ochrona danych, jak pokazano na poniższym zrzucie ekranu.
Gdy tam dotrzesz, włącz interfejs Secret Manager API, jak pokazano na poniższym obrazie.
- Teraz kliknij „Utwórz obiekt tajny”: nazwij go na przykład „racjonalnie”:
- Nazwa:
php-amarcord-db-pass
- Wartość tajna: „hasło do bazy danych” (pomiń część „prześlij plik”).
- Dodaj adnotację do tego linku do obiektu tajnego, który powinien wyglądać tak:
projects/123456789012/secrets/php-amarcord-db-pass
. To jest unikalny wskaźnik do Twojego obiektu tajnego (w przypadku Terraform, Cloud Run i innych). Numer jest Twoim unikalnym numerem projektu.
Wskazówka: staraj się stosować spójne konwencje nazewnictwa dla swoich sekretów, na przykład: cloud-devrel-phpamarcord-dbpass
- Organizacja (z firmą)
- Zespół (w organizacji)
- Aplikacja (w zespole)
- Nazwa zmiennej (w aplikacji)
Dzięki temu możesz łatwo znaleźć wszystkie sekrety dotyczące jednej aplikacji.
Tworzenie nowej wersji Cloud Run
Teraz, gdy mamy już nowy tajny klucz, musimy usunąć zmienną środowiskową DB_PASS i zastąpić ją nowym tajnym kluczem. Przykłady:
- Dostęp do Cloud Run w konsoli Google Cloud
- Wybierz aplikację.
- Kliknij „Edytuj i wdróż nową wersję”.
- odszukaj kartę „Zmienne i obiekty tajne”.
- Aby zresetować zmienną środowiskową DB_PASS, użyj przycisku „+ Odwołaj się do tajnego klucza”.
- Użyj tej samej wartości „DB_PASS” dla odwołujących się obiektów tajnych i użyj najnowszej wersji.
Po zakończeniu powinien pojawić się ten błąd
Spróbuj znaleźć rozwiązanie. Aby rozwiązać ten problem, musisz otworzyć sekcję Administracja i zmienić uprawnienia. Powodzenia w debugowaniu
Gdy to zrobisz, wróć do Cloud Run i ponownie wdrocz nową wersję. Wynik powinien wyglądać tak:
Wskazówka: konsola programisty (UI) świetnie wskazuje problemy z uprawnieniami. Poświęć trochę czasu na przejście do wszystkich linków dotyczących Twoich elementów w Cloud.
7. Moduł 5. Konfigurowanie CI/CD za pomocą Cloud Build
Dlaczego warto korzystać z potoku CI/CD?
Do tej pory pewnie kilka razy wpisałaś/eś gcloud run deploy
, odpowiadając na to samo pytanie.
Masz dość ręcznego wdrażania aplikacji za pomocą polecenia gcloud run deploy? Czy nie byłoby świetnie, gdyby Twoja aplikacja była wdrażana automatycznie za każdym razem, gdy przenosisz nowe zmiany do repozytorium Git?
Aby korzystać z potoku CI/CD, musisz mieć:
- Osobisty repozytorium Git: w kroku 2. powinieneś już utworzyć rozwidlenie repozytorium warsztatów na swoim koncie GitHub. Jeśli nie, wróć i wykonaj ten krok. Twoje rozwidlone repozytorium powinno wyglądać tak:
https://github.com/<YOUR_GITHUB_USER>/app-mod-workshop
- Cloud Build. Ta niesamowita i tania usługa umożliwia konfigurowanie automatyzacji kompilacji praktycznie wszystkiego: Terraform, aplikacji w kontenerach Dockera,
W tej sekcji omówimy konfigurowanie Cloud Build.
Zacznij korzystać z Cloud Build
W tym celu użyjemy Cloud Build:
- skompilować źródło (za pomocą pliku Dockerfile). Wyobraź sobie, że jest to „duży plik ZIP”, który zawiera wszystko, czego potrzebujesz do jego skompilowania i uruchomienia (tzw. „element kompilacji”).
- prześlij go do Artifact Registry (AR).
- Następnie zleć wdrożenie z AR do Cloud Run dla aplikacji „php-amarcord”.
- Spowoduje to utworzenie nowej wersji („wersji”) dotychczasowej aplikacji (czyli warstwy z nowym kodem). Jeśli przesyłanie danych uda się, skonfigurujemy ją tak, aby przekierowywać ruch do nowej wersji.
Oto przykłady niektórych wersji aplikacji php-amarcord
:
Jak to wszystko robimy?
- Utwórz jeden idealny plik YAML:
cloudbuild.yaml
- Utwórz aktywator Cloud Build.
- Połącz się z naszym repozytorium GitHub za pomocą interfejsu Cloud Build.
Tworzenie reguły (i łączenie repozytorium)
- Otwórz stronę https://console.cloud.google.com/cloud-build/triggers.
- Kliknij „Utwórz aktywator”.
- Kompilacja:
- Nazwa: coś znaczącego, np.
on-git-commit-build-php-app
- Zdarzenie: wypchnięcie do gałęzi
- Źródło: „Połącz nowe repozytorium”
- Po prawej stronie otworzy się okno „Połącz repozytorium”.
- Dostawca źródłowy: „Github” (pierwszy)
- „Dalej”
- Po kliknięciu opcji uwierzytelnienia otworzy się okno w GitHub, w którym będzie można przeprowadzić uwierzytelnienie. Postępuj zgodnie z instrukcjami i zachowaj cierpliwość. Jeśli masz dużo repozytoriów, może to zająć trochę czasu.
- „Select repo” (Wybierz repozytorium) Wybierz swoje konto lub repozytorium i zaznacz pole „I understand…” (Rozumiem…).
- Jeśli otrzymasz błąd: „Aplikacja na GitHubie nie jest zainstalowana w żadnym z Twoich repozytoriów”, kliknij „Zainstaluj Google Cloud Build” i postępuj zgodnie z instrukcjami.
Kliknij Połącz
- Bingo! Twoje repozytorium jest teraz połączone.
- Wróć do części dotyczącej reguły.
- Konfiguracja: wykrywanie automatyczne (*)
- Zaawansowane: wybierz konto usługi „[PROJECT_NUMBER]- compute@developer.gserviceaccount.com”.
- xxxxx to identyfikator Twojego projektu
- Domyślne konto usługi Compute jest odpowiednie do zastosowań laboratoryjnych. Nie używaj go w środowisku produkcyjnym. ( więcej informacji).
- Pozostaw wszystko inne bez zmian.
- Kliknij przycisk „Utwórz”.
(*) Jest to najprostszy sposób, ponieważ sprawdza plik Dockerfile lub cloudbuild.yaml. Jednak cloudbuild.yaml
daje Ci realną możliwość decydowania, co należy zrobić na danym etapie.
Mam moc!
Aktywator nie będzie działać, dopóki nie przyznasz kontu usługi Cloud Build (czym jest konto usługi? Adres e-mail „robota”, który działa w Twoim imieniu w ramach zadania (w tym przypadku tworzenia elementów w chmurze).
Jeśli nie dasz mu uprawnień, nie będzie mógł tworzyć ani wdrażać. Na szczęście to proste.
- otwórz „Budowa w chmurze” > Ustawienia.
- Konto usługi „[PROJECT_NUMBER]- compute@developer.gserviceaccount.com”
- Zaznacz te pola:
- Cloud Run
- Secret Manager
- Konta usługi
- Cloud Build
- Zaznacz też pole „Ustaw jako preferowane konto usługi”.
Gdzie jest plik YAML Cloud Build?
Zalecamy poświęcenie trochę czasu na utworzenie własnego pliku YAML usługi cloud Build.
Jeśli jednak nie masz czasu lub nie chcesz poświęcić go na tworzenie rozwiązań, możesz znaleźć inspirację w tym folderze rozwiązań: .solutions
Teraz możesz przesłać zmiany do GitHub i obserwować Cloud Build.
Konfigurowanie Cloud Build może być trudne. Możesz spodziewać się kilkukrotnego przesyłania i odbierania plików:
- Sprawdzanie logów na stronie https://console.cloud.google.com/cloud-build/builds;region=global
- Znajdowanie błędu.
- Naprawić kod i ponownie wydać polecenie git commit / git push.
- Czasami błąd nie jest związany z kodem, ale z jakiś ustawieniami. W takim przypadku możesz utworzyć nową wersję w interfejsie (Cloud Build > „Wyzwalacze” > Uruchom).
Pamiętaj, że jeśli korzystasz z tego rozwiązania, musisz jeszcze wykonać kilka czynności. Musisz na przykład ustawić zmienne środowiskowe dla nowo utworzonych punktów końcowych w wersji deweloperskiej i produkcyjnej:
Można to zrobić na dwa sposoby:
- Za pomocą interfejsu użytkownika – przez ponowne ustawienie zmiennych środowiskowych.
- Za pomocą CLI, który utworzy dla Ciebie „idealny” skrypt. Przykład: gcloud-run-deploy.sh . Musisz zmienić kilka rzeczy, np. punkt końcowy i numer projektu. Numer projektu znajdziesz w sekcji Przegląd Cloud.
Jak zatwierdzić kod na GitHubie?
W ramach tego warsztatu nie będziemy uczyć, jak najlepiej przekazać git push
do GitHuba. Jeśli jednak masz problemy i znajdujesz się w Cloud Shell, możesz skorzystać z jednego z tych 2 sposobów:
- CLI. Dodaj klucz SSH lokalnie i dodaj zdalne repozytorium za pomocą git@github.com:TWÓJ_UŻYTKOWNIK/app-mod-workshop.git (zamiast http).
- VSCode. Jeśli używasz edytora Cloud Shell, możesz użyć karty Zarządzanie źródłem (Ctrl+Shift+G), kliknąć „Synchronizuj zmiany” i postępować zgodnie z instrukcjami. Powinieneś mieć możliwość uwierzytelnienia swojego konta GitHub w VSCode, dzięki czemu przeciąganie/wrzucanie stanie się dziecinnie proste.
Pamiętaj, aby git add clodubuild.yaml
wśród innych plików, bo inaczej nie zadziała.
Porównanie głębokich i płytkich testów „równości wersji deweloperskiej i produkcyjnej” [opcjonalnie]
Jeśli skopiujesz wersję modelu tutaj, będziesz mieć 2 identyczne wersje: DEV i PROD. To świetne rozwiązanie, zgodne z regułą 10 aplikacji 12-czynnikowej.
Używamy jednak 2 różnych punktów końcowych w internecie, aby aplikacja wskazywała tę samą bazę danych. Wystarczy to na warsztaty, ale w rzeczywistych warunkach warto poświęcić trochę czasu na stworzenie odpowiedniego środowiska produkcyjnego. Oznacza to posiadanie 2 baz danych (jednej na potrzeby testów, a drugiej na potrzeby produkcji) oraz wybranie miejsca, w którym mają się one znajdować na potrzeby odtwarzania awaryjnego lub wysokiej dostępności. To wykracza poza zakres tego warsztatu, ale warto się nad tym zastanowić.
Jeśli masz czas na „głęboką” wersję produkcji, pamiętaj o wszystkich zasobach, które musisz powielić, takich jak:
- Bazy danych Cloud SQL (i prawdopodobnie instancji SQL).
- Zasobnik GCS
- funkcji w Cloud Functions,
- Możesz używać modelu Gemini 1.5 Flash jako modelu w wersji rozwojowej (tańszy, szybszy) i modelu Gemini 1.5 Pro (bardziej wydajny).
Za każdym razem, gdy coś zmieniasz w aplikacji, zastanów się, czy w wersji produkcyjnej powinna być ta sama wartość. Jeśli nie, powtórz te czynności. Jest to oczywiście dużo łatwiejsze w przypadku Terraform, gdzie możesz dodać środowisko (-dev, -prod) jako sufiks do swoich zasobów.
8. Moduł 6. Przenoszenie do Google Cloud Storage
Miejsce na dane
Obecnie aplikacja przechowuje stan w kontenerze Dockera. Jeśli maszyna się zepsuje, aplikacja eksploduje lub po prostu wprowadzisz nową wersję, nowa wersja zostanie zaplanowana z nowym, pustym miejscem na dane: 🙈
Jak to naprawić? Istnieje kilka sposobów.
- przechowywać obrazy w DB. Tak było w przypadku mojej poprzedniej aplikacji PHP. To najprostsze rozwiązanie, ponieważ nie zwiększa złożoności. Zwiększa jednak opóźnienie i obciążenie bazy danych.
- Chcesz przenieść aplikację Cloud Run do rozwiązania przyjaznego dla miejsca na dane: GCE + dysk stały? Może GKE + Storage? Uwaga: im większą kontrolę masz nad projektem, tym mniej masz swobody w jego modyfikowaniu.
- Przejdź do GCS. Google Cloud Storage to najlepsza usługa przechowywania danych w Google Cloud i najbardziej typowe rozwiązanie w chmurze. Wymaga to jednak korzystania z bibliotek PHP. Czy mamy biblioteki PHP 5.7 dla GCS? Czy
PHP 5.7
obsługujeComposer
(wygląda na to, że PHP 5.3.2 to najstarsza wersja obsługiwana przez Composer)? - Możesz użyć kontenera Dockera.
- Możesz też użyć punktów zamontowania woluminów Cloud Run w GCS. Brzmi świetnie.
🤔 Migracja miejsca na dane (otwarte)
[Open Ended] W tym ćwiczeniu chcemy, abyś znalazł rozwiązanie, które pozwoli na przenoszenie obrazów w sposób trwały.
Test weryfikacyjny
Nie chcę Ci podpowiadać rozwiązania, ale chciałbym, żeby tak się stało:
- Przesyłanie
newpic.jpg
. Zobaczysz je w aplikacji. - Przejdź na nową wersję aplikacji.
newpic.jpg
jest nadal widoczny.
💡 Możliwe rozwiązanie (montowanie woluminów Cloud Run w GCS)
Jest to bardzo eleganckie rozwiązanie, które umożliwia przesyłanie plików ze stanem, bez konieczności dotykania kodu (poza wyświetlaniem opisu obrazu, ale to jest trywialne i tylko dla przyjemności).
Dzięki temu możesz zamontować folder z Cloud Run w GCS:
- Wszystkie przesłane do GCS pliki będą widoczne w aplikacji.
- Wszystkie przesłane do aplikacji pliki zostaną faktycznie przesłane do GCS.
- Z obiektami przesłanymi do GCS dzieją się cuda (rozdział 7).
Uwaga. Zapoznaj się z drobnym drukiem dotyczącym FUSE. Nie jest to dopuszczalne, jeśli wydajność jest problemem.
Tworzenie zasobnika GCS
GCS to wszechobecna usługa przechowywania danych w Google Cloud. Jest ona sprawdzona i używana przez wszystkie usługi GCP, które potrzebują miejsca na dane.
Pamiętaj, że Cloud Shell eksportuje PROJECT_ID jako GOOGLE_CLOUD_PROJECT:
$ export PROJECT_ID=$GOOGLE_CLOUD_PROJECT
#!/bin/bash
set -euo pipefail
# Your Cloud Run Service Name, eg php-amarcord-dev
SERVICE_NAME='php-amarcord-dev'
BUCKET="${PROJECT_ID}-public-images"
GS_BUCKET="gs://${BUCKET}"
# Create bucket
gsutil mb -l "$GCP_REGION" -p "$PROJECT_ID" "$GS_BUCKET/"
# Copy original pictures there - better if you add an image of YOURS before.
gsutil cp ./uploads/*.png "$GS_BUCKET/"
Konfigurowanie Cloud Run do zamontowania zasobnika w folderze /uploads/
Teraz przejdźmy do eleganckiej części. Tworzymy wolumin php_uploads
i dajemy Cloud Run instrukcje, aby zamontował go w kontekście MOUNT_PATH
(coś w stylu /var/www/html/uploads/
):
#!/bin/bash
set -euo pipefail
# .. keep variables from previous script..
# Uploads folder within your docker container.
# Tweak it for your app code.
MOUNT_PATH='/var/www/html/uploads/'
# Inject a volume mount to your GCS bucket in the right folder.
gcloud --project "$PROJECT_ID" beta run services update "$SERVICE_NAME" \
--region $GCP_REGION \
--execution-environment gen2 \
--add-volume=name=php_uploads,type=cloud-storage,bucket="$BUCKET" \
--add-volume-mount=volume=php_uploads,mount-path="$MOUNT_PATH"
Powtórz ten krok w przypadku wszystkich punktów końcowych, które chcesz wskazać do Cloud Storage.
To samo możesz zrobić w interfejsie
- Na karcie „Woluminy” utwórz punkty montowania woluminu wskazujące na zasobnik typu „Zbiornik Cloud Storage”, np. o nazwie „php_uploads”.
- W sekcji Kontenery > Punkty montowania woluminu zamontuj wolumin, który został utworzony na żądanym przez aplikację punkcie woluminu. Zależnie od pliku dockerfile może to wyglądać tak:
var/www/html/uploads/
.
W każdym razie, jeśli wszystko działa, po edytowaniu nowej wersji Cloud Run powinno pojawić się coś takiego:
Teraz przetestuj nową aplikację, przesyłając jeden nowy obraz do punktu końcowego /upload.php
.
Obrazy powinny płynnie przepływać w GCS bez konieczności pisania ani jednej linii kodu PHP:
Co się właśnie stało?
Stało się coś bardzo magicznego.
Stara aplikacja ze starym kodem nadal działa. Nowy, zmodernizowany pakiet komponentów pozwala nam wygodnie przechowywać wszystkie obrazy w naszej aplikacji w zasobniku Cloud z stanem. Nie ma już żadnych ograniczeń:
- Chcesz wysyłać e-maila za każdym razem, gdy pojawi się obraz z „niebezpieczną” lub „nagą” treścią? Możesz to zrobić bez modyfikowania kodu PHP.
- Czy chcesz, aby model multimodaly Gemini opisywał każdy obraz, który otrzymasz, i przesyłał opis do bazy danych? Możesz to zrobić bez modyfikowania kodu PHP. Nie wierzysz? Czytaj dalej w rozdziale 7.
Właśnie otworzyliśmy przed Tobą nowe możliwości.
9. Moduł 7. Wzmocnij swoją aplikację dzięki Google Gemini
Teraz masz świetną zmodernizowaną, nową aplikację PHP (np. 2024 Fiat 126
) z magazynem w chmurze.
Do czego służy
Wymagania wstępne
W poprzednim rozdziale rozwiązanie modelowe pozwoliło nam zamontować obrazy /uploads/
w GCS, de facto oddzielając logikę aplikacji od magazynu obrazów.
W tym ćwiczeniu musisz:
- Ukończone ćwiczenie z rozdziału 6 (magazynowanie).
- Utwórz zasobnik GCS z przesyłanymi obrazami, do którego użytkownicy będą przesyłać zdjęcia w Twojej aplikacji.
Konfigurowanie funkcji w Cloud Functions (w Pythonie)
Zastanawiasz się, jak zaimplementować aplikację opartą na zdarzeniach? Na przykład:
- gdy <event> wystąpi => wyślij e-maila
- gdy <event> wystąpi => jeśli <condition> jest prawdziwe, zaktualizuj bazę danych.
Może to być cokolwiek: nowy rekord dostępny w BigQuery, nowy obiekt zmieniony w folderze w GCS lub nowa wiadomość oczekująca w kolejce w Pub/Sub.
Google Cloud obsługuje wiele paradygmatów, które umożliwiają to osiągnąć. Najważniejsze:
- EventArc. Dowiedz się, jak odbierać zdarzenia GCS. Umożliwia tworzenie DAG-ów i sterowanie działaniami na podstawie instrukcji „jeśli-to-wówczas-wtedy” w chmurze.
- Cloud Scheduler. Jest to świetne rozwiązanie np. w przypadku nocnego zadania cron w chmurze.
- Przepływy pracy w chmurze. Podobnie jak Event Arc, umożliwia:
- Funkcje Cloud Run (znane również jako
lambdas
). - Cloud Composer. Jest to w podstawie wersja Apache Airflow od Google, która świetnie sprawdza się też w przypadku DAG-ów.
W tym ćwiczeniu przyjrzymy się bliżej Cloud Functions, aby uzyskać spektakularny efekt. Przekażemy Ci też opcjonalne ćwiczenia.
Pamiętaj, że przykładowy kod jest dostępny w sekcji .solutions/
.
Konfigurowanie funkcji w Cloud Functions (🐍 Python)
Staramy się stworzyć bardzo ambitny GCF.
- Gdy w GCS zostanie utworzony nowy obraz (prawdopodobnie ktoś przesłał je w aplikacji, ale nie tylko)
- .. call Gemini to describe it and get a textual description of the image .. (would be nice to check the MIME and ensure its an image and not a PDF, MP3, or Text)
- .. i zaktualizować bazę danych o ten opis. (może to wymagać zmodyfikowania bazy danych w celu dodania do tabeli
images
kolumnydescription
).
Zmodyfikuj bazę danych, aby dodać description
do obrazów.
- Otwórz Cloud SQL Studio:
- Wpisz użytkownika i hasło do bazy danych Images
- Wstrzyknij ten kod SQL, który dodaje kolumnę opisu obrazu:
ALTER TABLE images ADD COLUMN description TEXT;
I bingo! Aby sprawdzić, czy udało się to zrobić, wykonaj te czynności:
SELECT * FROM images;
Powinna pojawić się nowa kolumna opisu:
Wpisz f(x) w Gemini.
Uwaga. Ta funkcja została utworzona przy użyciu Gemini Code Assist.
Uwaga. Podczas tworzenia tej funkcji mogą wystąpić błędy uprawnień IAM. Niektóre z nich zostały opisane poniżej w sekcji „Możliwe błędy”.
- Włącz interfejsy API
- Otwórz stronę https://console.cloud.google.com/functions/list.
- Kliknij „Utwórz funkcję”.
- Włącz interfejsy API za pomocą kreatora API:
Możesz utworzyć GCF w interfejsie lub z poziomu wiersza poleceń. Tutaj użyjemy wiersza poleceń.
Możliwy kod można znaleźć w sekcji .solutions/
- Utwórz folder na kod, np. „gcf/”. Otwórz folder.
- Utwórz plik
requirements.txt
:
google-cloud-storage
google-cloud-aiplatform
pymysql
- Utwórz funkcję w Pythonie. Przykładowy kod: gcf/main.py.
#!/usr/bin/env python
"""Complete this"""
from google.cloud import storage
from google.cloud import aiplatform
import vertexai
from vertexai.generative_models import GenerativeModel, Part
import os
import pymysql
import pymysql.cursors
# Replace with your project ID
PROJECT_ID = "your-project-id"
GEMINI_MODEL = "gemini-1.5-pro-002"
DEFAULT_PROMPT = "Generate a caption for this image: "
def gemini_describe_image_from_gcs(gcs_url, image_prompt=DEFAULT_PROMPT):
pass
def update_db_with_description(image_filename, caption, db_user, db_pass, db_host, db_name):
pass
def generate_caption(event, context):
"""
Cloud Function triggered by a GCS event.
Args:
event (dict): The dictionary with data specific to this type of event.
context (google.cloud.functions.Context): The context parameter contains
event metadata such as event ID
and timestamp.
"""
pass
- Prześlij funkcję. Możesz użyć skryptu podobnego do tego: gcf/push-to-gcf.sh.
Uwaga 1. Upewnij się, że źródła środowiskowe mają prawidłowe wartości, lub po prostu dodaj je na górze (GS_BUCKET=blah
, ..):
Uwaga 2. Spowoduje to przesłanie całego kodu lokalnego (.
), więc pamiętaj, aby otoczyć kod określonym folderem i użyć .gcloudignore
jak profesjonalista, aby uniknąć przesyłania ogromnych bibliotek. ( na przykład).
#!/bin/bash
set -euo pipefail
# add your logic here, for instance:
source .env || exit 2
echo "Pushing ☁️ f(x)☁ to 🪣 $GS_BUCKET, along with DB config.. (DB_PASS=$DB_PASS)"
gcloud --project "$PROJECT_ID" functions deploy php_amarcord_generate_caption \
--runtime python310 \
--region "$GCP_REGION" \
--trigger-event google.cloud.storage.object.v1.finalized \
--trigger-resource "$BUCKET" \
--set-env-vars "DB_HOST=$DB_HOST,DB_NAME=$DB_NAME,DB_PASS=$DB_PASS,DB_USER=$DB_USER" \
--source . \
--entry-point generate_caption \
--gen2
Uwaga: w tym przykładzie wywoływana będzie metoda generate_caption
, a funkcja usługi w chmurze przekaże jej zdarzenie GCS wraz ze wszystkimi istotnymi informacjami (nazwa zasobnika, nazwa obiektu itp.). Poświęć trochę czasu na debugowanie tego słownika Pythona.
Testowanie funkcji
Testy jednostek
Funkcja ma wiele elementów. Możesz chcieć przetestować wszystkie pojedyncze elementy.
Przykład znajdziesz w pliku gcf/test.py.
Interfejs Cloud Functions
Poświęć też trochę czasu na zapoznanie się z funkcją w interfejsie. Warto zapoznać się z każdą kartą, zwłaszcza Source
(moja ulubiona), Variables
, Trigger
i Logs
. Na karcie Logs
spędzisz dużo czasu, rozwiązując błędy (patrz też możliwe błędy na dole tej strony). Sprawdź też kartę Permissions
.
Test E2E
Czas na ręczne przetestowanie funkcji.
- Otwórz aplikację i zaloguj się.
- Prześlij zdjęcie (nie za duże, mieliśmy problemy z dużymi obrazami)
- sprawdzić w interfejsie, czy zdjęcie zostało przesłane.
- Sprawdź w Cloud SQL Studio, czy opis został zaktualizowany. Zaloguj się i uruchom to zapytanie:
SELECT * FROM images
.
I to działa. Możemy też chcieć zaktualizować interfejs, aby wyświetlał ten opis.
Aktualizowanie PHP, aby wyświetlać [opcjonalnie]
Udowodniliśmy, że aplikacja działa. Byłoby jednak miło, gdyby użytkownicy mogli też zobaczyć ten opis.
Aby dodać opis do index.php
, nie musisz być ekspertem w języku PHP. Ten kod powinien działać (tak, Gemini napisał go też dla mnie):
<?php if (!empty($image['description'])): ?>
<p class="font-bold">Gemini Caption:</p>
<p class="italic"><?php echo $image['description']; ?></p>
<?php endif; ?>
Umieść ten kod wewnątrz foreach
według własnego uznania.
W kolejnych krokach zobaczysz też ładniejszą wersję interfejsu użytkownika dzięki Gemini Code Assist. Ładniejsza wersja może wyglądać tak:
Wnioski
W przypadku nowych obiektów w GCS została uruchomiona funkcja Cloud Functions, która może dodawać adnotacje do obrazu tak jak człowiek i automatycznie aktualizować bazę danych. Niesamowite!
Co dalej? Możesz postępować tak samo, aby uzyskać 2 przydatne funkcje.
[Opcjonalnie] Dodawanie kolejnych funkcji Cloud Functions [nieograniczone]
Mam na myśli kilka dodatkowych funkcji.
📩 Aktywator e-maila
Reguła e-mailowa, która wysyła Ci e-maila za każdym razem, gdy ktoś wyśle zdjęcie.
- Zbyt często? Dodaj kolejny warunek: duża grafika lub grafika, której treść zawiera słowa „nagość” lub „przemoc”.
- Zapoznaj się z artykułem
EventArc
.
🚫 Automatyczna moderacja niestosownych zdjęć
Obecnie administrator oznacza obrazy jako „nieodpowiednie”. A może Gemini wykona za Ciebie całą robotę i zmoderuje pokój? Dodaj test, aby oznaczać flagą nieodpowiednie treści w aktywatorze, i zaktualizuj bazę danych zgodnie z informacjami z poprzedniej funkcji. Oznacza to, że trzeba wziąć poprzednią funkcję, zmienić prompt i zaktualizować bazę danych na podstawie odpowiedzi.
Zastrzeżenie: Generatywna AI może generować nieprzewidywalne wyniki. Upewnij się, że „wyjście kreacji” z Gemini jest „na szynach”. Możesz poprosić o deterministyczną odpowiedź, np. o wynik wiarygodności od 0 do 1 lub dane w formacie JSON. Możesz to zrobić na wiele sposobów, np.: * Używając bibliotek Pythona pydantic
, langchain
, .. * Używając uporządkowanych danych Gemini.
Wskazówka: Możesz mieć WIELE funkcji lub pojedynczy prompt, który wymusza odpowiedź w formacie JSON (działa to świetnie z „Gemini Structured Output”, jak zaznaczono powyżej), np.:
Jaki prompt został użyty do wygenerowania tego obrazu?
{
"description": "This is the picture of an arrosticino",
"suitable": TRUE
}
Możesz dodać w prośbie dodatkowe pola, aby uzyskać informacje, np. „Czy jest w tym coś dobrego?”. Nie podoba Ci się to? Czy rozpoznajesz to miejsce? Czy jest jakiś tekst (OCR nigdy nie było prostsze):
goods
: „Wygląda jak pyszne jedzenie”bads
: „Wygląda jak niezdrowe jedzenie”OCR
: "Da consumare preferibilmente prima del 10 Novembre 2024"location
: „Pescara, Lungomare”
Zwykle lepiej jest mieć funkcję N dla N wyników, ale warto też mieć funkcję, która wykonuje 10 działań. Aby dowiedzieć się, jak to zrobić, przeczytaj ten artykuł autorstwa Riccardo.
Możliwe błędy (głównie dotyczące uprawnień)
Gdy zaczęłam opracowywać to rozwiązanie, napotkałam na problemy z uprawnieniami IAM. Dodam je tutaj, aby pokazać Ci, z czym masz do czynienia, i podać kilka pomysłów na rozwiązanie problemu.
Błąd: niewystarczające uprawnienia konta usługi
- Pamiętaj, że aby wdrożyć funkcję GCF, która nasłuchuje zasobnika GCS, musisz skonfigurować odpowiednie uprawnienia dla konta usługi, którego używasz do wykonywania zadania, jak pokazano na rysunku:
Może też być konieczne włączenie interfejsów EventArc API na kilka minut przed tym, jak staną się one w pełni dostępne.
Błąd: brakujący wywołujący Cloud Run
- Kolejny komentarz z interfejsu dotyczący uprawnień GCF: (rola wywołującego w Cloud Run):
Ten błąd można naprawić, wykonując polecenie na obrazie, które jest podobne do fix-permissions.sh.
Ten problem jest opisany tutaj: https://cloud.google.com/functions/docs/securing/authenticating
Błąd: przekroczono limit pamięci
Gdy uruchomiłem go po raz pierwszy, w logach pojawiła się wiadomość: „Przekroczony limit pamięci 244 MiB, wykorzystano 270 MiB. Rozważ zwiększenie limitu pamięci. Więcej informacji znajdziesz na stronie https://cloud.google.com/functions/docs/configuring/memory. Ponownie dodaj pamięć RAM do GCF. W interfejsie jest to bardzo proste. Oto możliwe rozwiązanie:
Możesz też poprawić skrypt wdrażania Cloud Run, aby zwiększyć MEM/CPU. Może to trochę potrwać.
Błąd: PubSub opublikowany
Podczas tworzenia aktywatora za pomocą GCF w wersji 1 wystąpił ten błąd:
To też można łatwo naprawić, przechodząc na stronę IAM i przypisując do konta usługi rolę „Publikujący w Pub/Sub”.
Błąd: usługa Vertex AI nie została użyta
Jeśli pojawi się ten błąd:
Odmowa dostępu: 403 Interfejs Vertex AI API nie był wcześniej używany w projekcie YOUR_PROJECT lub jest wyłączony. Aby go włączyć, wejdź na https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOR_PROJECT.
Wystarczy, że włączysz interfejsy API Vertex AI. Najprostszym sposobem włączenia WSZYSTKICH potrzebnych interfejsów API jest:
- https://console.cloud.google.com/vertex-ai
- Kliknij „Włącz wszystkie zalecane interfejsy API”.
Błąd: nie znaleziono aktywatora Eventarc
Jeśli otrzymasz takie powiadomienie, ponownie wdróż funkcję.
Błąd: 400 usługa jest przygotowywana
400 agentów usługi są przygotowywane ( https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). Agenty usługi są potrzebne do odczytu przesłanego pliku Cloud Storage. Spróbuj ponownie za kilka minut.
Jeśli tak się stanie, odczekaj chwilę lub poproś o pomoc Googlera.
10. Moduł 8. Tworzenie SLA dostępności
W tym rozdziale staramy się osiągnąć te cele:
- Tworzenie SLI
- Tworzenie SLA na podstawie SLI
- Tworzenie alertów na podstawie docelowych poziomów usług
Jest to bardzo ważny temat dla autora, ponieważ Riccardo pracuje w Google Cloud w obszarze SRE / DevOps.
(otwarte) Utwórz SLI i docelowe poziomy usług dla tej aplikacji
Jak dobra jest aplikacja, jeśli nie można sprawdzić, kiedy jest niedostępna?
Co to jest poziom usług?
O rany! Google wymyśliło docelowe poziomy usług. Aby dowiedzieć się więcej na ten temat, możesz:
- Książka o SRE – rozdział 2 – Wdrażanie docelowych poziomów. ( 👉 więcej informacji o SREbooks)
- Sztuka tworzenia docelowych poziomów usług ( świetny film). To świetne szkolenie, które pozwoli Ci dowiedzieć się, jak stworzyć idealne SLO dla swojej usługi.
- Kurs SRE w Coursera. Ja też dołożyłem(-am) do tego cegiełkę.
Krok 1. Utwórz SLI/SLO dotyczący dostępności
Zacznijmy od dostępności, ponieważ jest to najprostszy i najważniejszy parametr do pomiaru.
Na szczęście Cloud Run jest wyposażony w wstępnie skonfigurowane wsparcie w zakresie docelowego poziomu usług dzięki Istio.
Gdy aplikacja jest uruchomiona w Cloud Run, jest to bardzo proste. Zajmuje to 30 sekund.
- Otwórz stronę Cloud Run.
- Kliknij lub wybierz aplikację.
- Wybierz kartę
SLOs
. - Kliknij „+ Utwórz SLA”.
- Dostępność, na podstawie żądania
- Dalej
- Miesiąc kalendarzowy / 99%.
- kliknij „Utwórz SLA”.
Krok 2. Skonfiguruj alerty dotyczące tego poziomu usług
Proponuję utworzyć 2 alerty:
- Jeden z niskim współczynnikiem spalania („Slowburn”), aby wysyłać powiadomienia e-mailem (symuluje zgłoszenie o niskim priorytecie).
- Jeden z wysokim współczynnikiem spalania („Fastburn”), aby wysyłać powiadomienia SMS-em (symuluje wysoki priorytet zgłoszenia / pagera).
Wróć do wcześniejszego SLO tab
.
Zrób to 2 razy:
- Kliknij „Utwórz alert docelowego poziomu usług” (przycisk 🔔 z plusem po prawej stronie).
- Okres wyszukiwania wstecz, próg tempa wykorzystania:
- [FAST]. Pierwszy:
60
min /10
x - [SLOW]. Druga:
720
min /2
x - Kanał powiadomień: kliknij Zarządzaj kanałami powiadomień.
- Najpierw kliknij „E-mail” > Dodaj nowy >.
- Po drugie, „SMS” -> Dodaj nowy -> Potwierdź na telefonie.
- Wskazówka: lubię używać emotikonów w nazwach. To świetna opcja na potrzeby prezentacji.
- Gdy skończysz, kliknij duży X w prawym górnym rogu.
- Najpierw wybierz telefon (szybko), a potem e-maila (wolno).
- Dodaj przykładową dokumentację, np.:
[PHP Amarcord] Riccardo told me to type sudo reboot or to check documentation in http://example.com/playbooks/1.php but I guess he was joking
.
Bingo!
Wynik końcowy
Zadania można uznać za zakończone, gdy masz 1 działający SLO i 2 alerty dotyczące dostępności, a powiadomienia są wysyłane na Twój adres e-mail i na telefon.
Jeśli chcesz, możesz dodać opóźnienie (bardzo to polecam) lub nawet bardziej złożone opóźnienie. W przypadku opóźnienia wybierz wartość, która wydaje Ci się odpowiednia. W razie wątpliwości wybierz 200 ms.
11. Dalsze kroki
Wszystko jest gotowe. Czego brakuje?
Pomysły do przemyślenia:
Graj z Gemini
Z Gemini możesz korzystać na 2 sposoby:
- Vertex AI. „Metoda Enterprise”, która łączy się z GCP, o której mówiliśmy w rozdziale 7 (GCF+Gemini). Cała magia uwierzytelniania działa, a usługi są ze sobą pięknie połączone.
- AI od Google „Sposób konsumenta”. Pobierasz klucz interfejsu Gemini API tutaj i zaczynasz tworzyć małe skrypty, które można powiązać z dowolnym zbiorem zadań (prace zastrzeżone, inne chmury, localhost itp.). Wystarczy, że zastąpisz klucz interfejsu API, a kod zacznie działać.
Zachęcamy do samodzielnego zbadania opcji (2) w przypadku własnych projektów dotyczących zwierząt.
Przeniesienie interfejsu użytkownika
Nie jestem dobra w interfejsach. Ale Gemini – tak. Możesz wziąć jedną stronę PHP i powiedzieć coś takiego:
I have a VERY old PHP application. I want to touch it as little as possible. Can you help me:
1. add some nice CSS to it, a single static include for tailwind or similar, whatever you prefer
2. Transform the image print with description into cards, which fit 4 per line in the canvas?
Here's the code:
-----------------------------------
[Paste your PHP page, for instance index.php - mind the token limit!]
Możesz to zrobić w mniej niż 5 minut za pomocą jednej kompilacji w chmurze. :)
Odpowiedź Gemini była idealna (nie musiałam niczego zmieniać):
A tak wygląda nowy układ w aplikacji osobistej autora:
Uwaga: kod jest wklejany jako obraz, ponieważ nie chcemy, abyś go kopiował, ale aby Gemini napisał go za Ciebie z uwzględnieniem ograniczeń interfejsu użytkownika lub front-endu Twojej kreacji. Uwierz nam, że po tym pozostaną Ci bardzo drobne zmiany.
Bezpieczeństwo
Podczas 4-godzinnego warsztatu nie zajmujemy się prawidłowym zabezpieczeniem tej aplikacji, ponieważ wydłużyłoby to czas potrzebny na przeprowadzenie warsztatów o 1–2 rzędy wielkości.
Ten temat jest jednak bardzo ważny. Zebraliśmy kilka pomysłów w SECURITY
.
12. Gratulacje!
Gratulacje! 🎉🎉🎉 udało Ci się zmodernizować Twoją starszą aplikację PHP za pomocą Google Cloud.
Podsumowując, w tym ćwiczeniu dowiesz się:
- Jak wdrożyć bazę danych w Google Cloud SQL i jak przenieść do niej istniejącą bazę danych.
- Jak skonteneryzować aplikację PHP za pomocą Dockera i Buildpacków oraz przechowywać jej obraz w Google Cloud Artifact Registry
- Jak wdrożyć aplikację konteneryzowaną do Cloud Run i uruchomić ją z Cloud SQL
- Jak w tajnych miejscach przechowywać i wykorzystywać poufne parametry konfiguracji (np. hasło do bazy danych) za pomocą usługi Google Secret Manager
- Jak skonfigurować potok CI/CD za pomocą Google Cloud Build, aby automatycznie kompilować i wdrażać aplikację PHP po każdym przesłaniu kodu do repozytorium GitHub.
- Jak korzystać z Cloud Storage, aby „przenosić” zasoby aplikacji do chmury
- Jak korzystać z technologii bezserwerowych, aby tworzyć w Google Cloud niesamowite przepływy pracy bez konieczności modyfikowania kodu aplikacji.
- Używaj multimodalnych możliwości Gemini w odpowiednich przypadkach.
- Wdrażanie zasad SRE w Google Cloud
To świetny początek modernizacji aplikacji z Google Cloud.
🔁 Opinie
Jeśli chcesz podzielić się z nami opinią na temat warsztatów, wypełnij ten formularz.
Czekamy na Twoją opinię oraz promocję za fragmenty kodu, z których jesteś szczególnie dumny.
🙏 Pozdrawiam
Autor chciałby podziękować Mirko Gilioli i Maurizio Ipsale z Datatonic za pomoc w sporządzeniu dokumentacji i przetestowaniu rozwiązania.