Programowanie do produkcji w 3 prostych krokach dzięki Cloud Run

1. Wprowadzenie

Dlaczego zarządzanie aplikacjami jest tak trudne?

Jednym z głównych powodów jest to, że programiści często muszą być administratorami systemów w niepełnym wymiarze czasu. Aby opracować, wdrożyć i zarządzać nowoczesną aplikacją internetową klasy produkcyjnej, weź pod uwagę tę (częściową) listę problemów :

4d018476b4a73b47.png

Nie wiem, jak Ty, ale ja nie chcę się tym martwić. Chcę się skupić na logice aplikacji:

6dfd143d20e5548b.png

Właśnie na tym polega Cloud Run – możesz skupić się na aplikacji, a całą administracją i konserwacją zajmie się ktoś inny, czyli Google, która zainwestowała miliony godzin w doskonalenie swoich umiejętności w tej dziedzinie.

Oprócz wspomnianych wyżej wyzwań administracyjnych musisz też zmierzyć się z tymi problemami:

  • Zależności – środowisko, w którym działa aplikacja, powinno w miarę możliwości dokładnie odpowiadać środowisku, w którym była testowana. Może to obejmować kilka wymiarów, w tym system operacyjny, biblioteki pomocy, interpreter lub kompilator języka, konfigurację sprzętu i wiele innych czynników.
  • Dystrybucja – przejście od lokalnej wersji aplikacji do wersji udostępnianej w internecie często wymaga zmiany środowiska wykonawczego, ogromnego wzrostu złożoności i stromej krzywej uczenia się.

Cloud Run zajmie się tymi i wieloma innymi kwestiami. Zamiast jednak wierzyć mi na słowo, zbudujmy razem aplikację i zobaczmy, jak łatwo jest przejść z lokalnego środowiska programistycznego do aplikacji w chmurze klasy produkcyjnej w kilku prostych krokach.

Co musisz zrobić...

  • Utworzysz prostą aplikację internetową i sprawdzisz, czy działa ona zgodnie z oczekiwaniami w środowisku programistycznym.
  • Następnie przejdziesz do wersji kontenerowej tej samej aplikacji. Po drodze dowiesz się, co to jest konteneryzacja i dlaczego jest tak przydatna.
  • Na koniec wdrożysz aplikację w chmurze i zobaczysz, jak łatwo jest zarządzać usługą Cloud Run za pomocą wiersza poleceń i konsoli Google Cloud.

Czego się nauczysz...

  • Jak utworzyć prostą aplikację serwera WWW w Pythonie
  • Jak spakować aplikację do kontenera Dockera, który można uruchomić w dowolnym miejscu
  • Jak wdrożyć aplikację w chmurze, aby każdy mógł wypróbować Twoje nowe dzieło
  • Jak jeszcze bardziej uprościć powyższe kroki za pomocą pakietów Buildpack
  • Jak korzystać z narzędzia wiersza poleceń Google Cloud i interfejsu internetowego konsoli Cloud

Co będzie Ci potrzebne...

  • przeglądarki internetowej,
  • konto Google,

Ten moduł jest przeznaczony dla deweloperów na wszystkich poziomach zaawansowania, w tym dla początkujących. Chociaż będziesz używać języka Python, nie musisz znać jego programowania, aby zrozumieć, co się dzieje, ponieważ wyjaśnimy cały używany kod.

2. Konfiguracja

5110b5081a1e1c49.png

W tej sekcji znajdziesz wszystko, co musisz zrobić, aby rozpocząć ten moduł.

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. (Jeśli nie masz jeszcze konta Gmail lub Google Workspace, musisz je utworzyć).

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Zapamiętaj identyfikator projektu, czyli unikalną nazwę we wszystkich projektach Google Cloud (podana powyżej nazwa jest już zajęta i nie będzie działać w Twoim przypadku). W dalszej części tego laboratorium będzie on nazywany PROJECT_ID.

  1. Następnie musisz włączyć rozliczenia w konsoli Cloud, aby korzystać z zasobów Google Cloud.

Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Wykonaj instrukcje z sekcji „Czyszczenie”, w której znajdziesz informacje o tym, jak wyłączyć zasoby, aby uniknąć naliczenia opłat po zakończeniu tego samouczka. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Uruchom Cloud Shell.

W tym module będziesz pracować w sesji Cloud Shell, czyli w interpreterze poleceń hostowanym przez maszynę wirtualną działającą w chmurze Google. Możesz równie łatwo uruchomić tę sekcję lokalnie na własnym komputerze, ale korzystanie z Cloud Shell zapewnia wszystkim możliwość odtworzenia działania w spójnym środowisku. Po zakończeniu modułu możesz spróbować ponownie wykonać tę sekcję na własnym komputerze.

704a7b7491bd157.png

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell 4292cbf4971c9786.png.

bce75f34b2c53987.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni (część strony widoczna po przewinięciu) z opisem tego środowiska. W takim przypadku kliknij Dalej, a ten ekran nie będzie się już wyświetlać. Ten wyświetlany jednorazowo ekran wygląda tak:

70f315d7b402b476.png

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

fbe3a0674c982259.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce lub na Chromebooku.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik polecenia

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

Ustaw w terminalu zmienne środowiskowe, które ułatwią Ci pracę w kolejnych krokach:

export PROJ=$GOOGLE_CLOUD_PROJECT 
export APP=hello 
export PORT=8080
export REGION="us-central1"
export TAG="gcr.io/$PROJ/$APP"

Włączanie interfejsów API

W dalszych krokach dowiesz się, gdzie te usługi są potrzebne (i dlaczego), ale na razie uruchom to polecenie, aby przyznać projektowi dostęp do usług Cloud Build, Container Registry i Cloud Run:

gcloud services enable cloudbuild.googleapis.com         \
                       containerregistry.googleapis.com  \
                       run.googleapis.com          

Powinien wyświetlić się komunikat o powodzeniu podobny do tego:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

3. Tworzenie prostej aplikacji internetowej

eef530b56b8e93a3.png

Zacznij od kliknięcia przycisku Open Editor u góry panelu Cloud Shell. Wygląda on następująco:

9b81c8a37a6bcdd8.png

Następnie przejdziesz do środowiska IDE podobnego do Visual Studio Code, w którym możesz tworzyć projekty, edytować kod źródłowy, uruchamiać programy itp. Jeśli ekran jest zbyt mały, możesz powiększyć lub zmniejszyć linię podziału między konsolą a oknem edycji/terminala, przeciągając poziomą linię między tymi dwoma obszarami, która jest tutaj wyróżniona:

8dea35450851af53.png

Możesz przełączać się między edytorem a terminalem, klikając odpowiednio przyciski Open EditorOpen Terminal. Spróbuj teraz przełączać się między tymi dwoma środowiskami.

Następnie utwórz folder, w którym będziesz przechowywać wyniki tego ćwiczenia. W tym celu wybierz kolejno File (Plik) –> New Folder (Nowy folder), wpisz hello i kliknij OK. Wszystkie pliki utworzone w tym module i wszystkie zadania wykonane w Cloud Shell będą znajdować się w tym folderze.

Teraz utwórz plik requirements.txt. Dzięki temu Python wie, od których bibliotek zależy Twoja aplikacja. W przypadku tej prostej aplikacji internetowej użyjesz popularnego modułu Pythona do tworzenia serwerów WWW o nazwie Flask oraz platformy serwera WWW o nazwie gunicorn. W oknie edytora Cloud kliknij menu Plik –> Nowy plik, aby utworzyć nowy plik. Gdy pojawi się prośba o podanie nazwy nowego pliku, wpisz requirements.txt i naciśnij przycisk OK. Upewnij się, że nowy plik trafił do folderu projektu hello.

Wpisz w nowym pliku te wiersze, aby określić, że Twoja aplikacja zależy od pakietu Pythona Flask i serwera WWW gunicorn.

Flask
gunicorn

Nie musisz zapisywać tego pliku, ponieważ Edytor w chmurze automatycznie zapisuje zmiany.

Wersja 1. Witaj świecie!

Korzystając z tej samej techniki, utwórz kolejny nowy plik o nazwie main.py. Będzie to główny (i jedyny) plik źródłowy Pythona w Twojej aplikacji. Ponownie upewnij się, że nowy plik trafił do folderu projektu hello.

Wstaw do tego pliku ten kod:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from the environment.

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
@app.route("/", methods=["GET"])
def say_hello():
    html = "<h1>Hello world!</h1>"
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

Wróć do terminala i przejdź do folderu projektu za pomocą tego polecenia:

cd hello

Aby zainstalować zależności projektu, uruchom to polecenie:

pip3 install -r requirements.txt

Teraz uruchom aplikację, wpisując w terminalu to polecenie:

python3 main.py

W tym momencie aplikacja działa na maszynie wirtualnej przeznaczonej dla sesji Cloud Shell. Cloud Shell zawiera mechanizm proxy, który umożliwia dostęp do serwerów internetowych (takich jak ten, który właśnie został uruchomiony) działających na maszynie wirtualnej z dowolnego miejsca w globalnej sieci internet.

Kliknij przycisk web preview, a następnie element menu Preview on Port 8080:

fe45e0192080efd6.png

Spowoduje to otwarcie karty przeglądarki z aplikacją do biegania, która powinna wyglądać mniej więcej tak:

b1f06501509aefb9.png

Wersja 2. Odbijanie ścieżki adresu URL

Wróć do edytora Cloud (klikając przycisk Open Editor) i dodaj obsługę opcjonalnego sufiksu adresu URL, aktualizując plik main.py w ten sposób:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])     # ← NEW
def say_hello(name="world"):               # ← MODIFIED
    html = f"<h1>Hello {name}!</h1>"       # ← MODIFIED
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

Wróć do terminala (klikając przycisk Open Terminal) i wpisz control-C (przytrzymaj klawisz Control i naciśnij „C”), aby zatrzymać działającą aplikację, a następnie uruchom ją ponownie, wpisując:

python3 main.py

Ponownie kliknij przycisk web preview, a następnie element menu Preview on Port 8080, aby otworzyć kartę przeglądarki internetowej z uruchomioną aplikacją. Ponownie powinien pojawić się komunikat „Hello world!”, ale teraz zastąp tekst adresu URL po znaku ukośnika dowolnym ciągiem znaków (np. /your-name) i sprawdź, czy widzisz coś takiego:

93b87996f88fa370.png

Wersja 3. Losowe kolory

Teraz dodaj obsługę losowych kolorów tła, wracając do Cloud Editora (za pomocą przycisku Open Editor) i aktualizując plik main.py w ten sposób:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from the environment.

# This function decides whether foreground text should be
# displayed in black or white, to maximize fg/bg contrast.
def set_text_color(rgb):                      # ← NEW
    sum = round(                              # ← NEW
        (int(rgb[0]) * 0.299)                 # ← NEW
        + (int(rgb[1]) * 0.587)               # ← NEW
        + (int(rgb[2]) * 0.114)               # ← NEW
    )                                         # ← NEW
    return "black" if sum > 186 else "white"  # ← NEW


# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
# To verify each new invocation of these requests, the HTML document
# includes CSS styling to produce a randomly colored background.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])
def say_hello(name="world"):
    bg = random.sample(range(1, 255), 3)                       # ← NEW
    hex = (int(bg[0]) * 256) + (int(bg[1]) * 16) + int(bg[2])  # ← NEW
    fg_color = set_text_color(bg)                              # ← NEW
    bg_color = f"#{hex:06x}"                                   # ← NEW
    style = f"color:{fg_color}; background-color:{bg_color}"   # ← NEW
    html = f'<h1 style="{style}">Hello {name}!</h1>'           # ← MODIFIED
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

Wróć do terminala (klikając przycisk Open Terminal) i wpisz control-C (przytrzymaj klawisz Control i naciśnij „C”), aby zatrzymać działającą aplikację, a następnie uruchom ją ponownie, wpisując:

python3 main.py

Ponownie kliknij przycisk web preview, a potem element menu Preview on Port 8080, aby otworzyć kartę przeglądarki z uruchomioną aplikacją. Powinien się wyświetlić wygenerowany tekst z określonym sufiksem lub domyślnym ciągiem znaków „Hello world!” na losowo pokolorowanym tle, np. tak:

baf8d028f15ea7f4.png

Odśwież stronę kilka razy, aby sprawdzić, czy losowy kolor tła zmienia się przy każdej wizycie w aplikacji.

To wszystko. Aplikacja jest gotowa. Gratulacje! W następnym kroku dowiesz się, jak spakować aplikację do kontenera i dlaczego jest to przydatne.

4. Konteneryzacja aplikacji

17cc234ec3325a8a.png

Co to jest kontener?

Kontenery, a w szczególności Docker, umożliwiają tworzenie modułowego środowiska, w którym można uruchamiać aplikację wraz ze wszystkimi powiązanymi zależnościami. Wynik nazywamy obrazem kontenera. W tej sekcji utworzysz obraz kontenera, który posłuży do zamknięcia aplikacji i wszystkich jej zależności.

W poprzednim kroku, gdy aplikacja była uruchamiana w środowisku deweloperskim, trzeba było uruchomić pip3 install -r requirements.txt i upewnić się, że plik requirements.txt zawiera wszystkie biblioteki zależne i odpowiednie wersje. W przypadku kontenerów wymagania te są instalowane podczas generowania obrazu kontenera, więc użytkownik kontenera nie musi się martwić o instalowanie czegokolwiek.

Ten obraz kontenera będzie podstawowym elementem składowym do wdrożenia aplikacji w Cloud Run. Kontenery można stosować na niemal każdym serwerze wirtualnym lub fizycznym, co pozwala nam wdrażać aplikację w dowolnym miejscu i przenosić ją od jednego dostawcy usług do drugiego lub ze środowiska lokalnego do chmury.

Kontenery pomagają sprawić, że aplikacje:

  • powtarzalne – kontenery są samodzielne i kompletne;
  • przenośne – kontenery to uniwersalne elementy składowe, które umożliwiają przenoszenie aplikacji między dostawcami usług chmurowych i środowiskami;

Krótko mówiąc, kontenery umożliwiają wreszcie „napisanie kodu raz i uruchomienie go wszędzie”. Wyjątkiem od tej reguły jest to, że wygenerowany kontener może działać tylko na typie procesora, na którym został utworzony. Istnieją jednak sposoby generowania wersji kontenera dla innych konfiguracji sprzętowych.

Dość gadania – utwórzmy kontener! Do utworzenia kontenera użyjesz konkretnej technologii o nazwie Docker.

W edytorze Cloud utwórz nowy plik o nazwie Dockerfile. Ten plik to plan tworzenia obrazu. Informuje Dockera o środowisku operacyjnym i kodzie źródłowym, o tym, jak zainstalować zależności, skompilować aplikację i uruchomić kod.

# Use an official lightweight Python image.
FROM python:3.9-slim

# Copy local code to the container image.
WORKDIR /app
COPY main.py .
COPY requirements.txt .

# Install dependencies into this container so there's no need to 
# install anything at container run time.
RUN pip install -r requirements.txt

# Service must listen to $PORT environment variable.
# This default value facilitates local development.
ENV PORT 8080

# Run the web service on container startup. Here you use the gunicorn
# server, with one worker process and 8 threads. For environments 
# with multiple CPU cores, increase the number of workers to match 
# the number of cores available.
CMD exec gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 main:app

W terminalu Cloud utwórz obraz kontenera za pomocą Cloud Build, uruchamiając to polecenie:

gcloud builds submit --tag $TAG

Gdy kontener zostanie wypchnięty do rejestru, wyświetli się komunikat SUCCESS z nazwą obrazu, który powinien wyglądać mniej więcej tak: gcr.io/<project-id>/hello. Obraz jest teraz przechowywany w Google Container Registry i możesz go używać w dowolnym momencie i miejscu.

Użyj tego polecenia, aby sporządzić listę wszystkich obrazów kontenerów związanych z bieżącym projektem:

gcloud container images list

Teraz uruchom i przetestuj aplikację lokalnie w Cloud Shell, używając tych poleceń docker:

docker run -p $PORT:$PORT -e PORT=$PORT $TAG

Opcja -p $PORT:$PORT informuje Dockera, aby zmapował zewnętrzny port $PORT (ustawiony powyżej na 8080) w środowisku hosta na ten sam numer portu w działającym kontenerze. Ułatwia to pracę, ponieważ kod serwera, który piszesz, i zewnętrzny numer portu, z którym łączysz się podczas testowania aplikacji, będą takie same (8080). Możesz jednak równie łatwo użyć opcji -p, aby zmapować dowolny zewnętrzny port na hoście na dowolny wewnętrzny port w kontenerze.

Opcja -e PORT=$PORT informuje Dockera, że zmienna środowiskowa $PORT (ustawiona powyżej na 8080) ma być dostępna dla aplikacji działającej w kontenerze.

Możesz teraz przetestować aplikację, kierując przeglądarkę internetową na kod Pythona działający w kontenerze. W oknie Cloud Shell kliknij ikonę „Podgląd w przeglądarce” i wybierz „Podejrzyj na porcie 8080”, tak jak w poprzednim kroku.

Wynik powinien wyglądać znajomo – wygenerowany tekst powinien być widoczny na losowo pokolorowanym tle, tak jak w przypadku uruchomienia aplikacji bezpośrednio w terminalu Cloud Shell. Odśwież stronę kilka razy, aby sprawdzić, czy losowy kolor tła zmienia się przy każdej wizycie w aplikacji.

Gratulacje! Uruchomiono właśnie skonteneryzowaną wersję aplikacji. W następnej sekcji bez zmiany ani jednej linii kodu przekształcisz obraz kontenera w aplikację internetową o jakości produkcyjnej.

5. Do chmury…

1b0665d94750ded6.gif

Po skonteneryzowaniu aplikacji warto udostępnić ją reszcie świata, dlatego należy wdrożyć ją w chmurze. Chcesz jednak zrobić coś więcej niż tylko udostępnić film. Chcesz mieć pewność, że:

  • działa niezawodnie – w przypadku awarii komputera, na którym działa aplikacja, automatycznie uzyskasz odporność na błędy;
  • automatycznie się skaluje – Twoja aplikacja będzie w stanie obsłużyć ogromny ruch i automatycznie zmniejszy swoje wykorzystanie, gdy nie będzie używana;
  • minimalizuje koszty, ponieważ nie obciąża Cię opłatami za zasoby, których nie używasz – opłaty są naliczane tylko za zasoby wykorzystywane podczas odpowiadania na ruch;
  • jest dostępna pod niestandardową nazwą domeny – masz dostęp do rozwiązania, które pozwala przypisać do usługi niestandardową nazwę domeny jednym kliknięciem;
  • oferuje doskonały czas reakcji – uruchomienia „na zimno” są dość szybkie, ale możesz je dostroić, określając konfigurację minimalnej liczby instancji;
  • obsługuje szyfrowanie typu end-to-end za pomocą standardowego zabezpieczenia internetowego SSL/TLS – gdy wdrażasz usługę, automatycznie i bezpłatnie otrzymujesz standardowe szyfrowanie internetowe oraz odpowiednie wymagane certyfikaty;

Wdrażając aplikację w Google Cloud Run, uzyskasz wszystkie wymienione wyżej korzyści i nie tylko.

Wdrażanie aplikacji w Cloud Run

Najpierw zmodyfikujmy aplikację, aby można było odróżnić nową wersję od starej. W tym celu zmodyfikuj plik main.py, aby domyślny komunikat zmienił się z „Hello world!” na „Hello from Cloud Run!”. Innymi słowy, zmień ten wiersz w pliku main.py z tego:

def say_hello(name="world"):

na:

def say_hello(name="from Cloud Run"):

Cloud Run działa regionalnie, co oznacza, że infrastruktura, która uruchamia usługi Cloud Run, znajduje się w określonym regionie i jest zarządzana przez Google w taki sposób, aby była redundantnie dostępna we wszystkich strefach w tym regionie. W sekcji „Konfiguracja” powyżej zdefiniowano region domyślny za pomocą zmiennej środowiskowej REGION.

Ponownie skompiluj obraz kontenera i wdroż skonteneryzowaną aplikację w Cloud Run za pomocą tego polecenia:

gcloud builds submit --tag $TAG
gcloud run deploy "$APP"   \
  --image "$TAG"           \
  --platform "managed"     \
  --region "$REGION"       \
  --allow-unauthenticated
  • Możesz też zdefiniować region domyślny za pomocą parametru gcloud config set run/region $REGION.
  • Opcja --allow-unauthenticated sprawia, że usługa jest dostępna publicznie. Aby uniknąć nieautoryzowanych żądań, użyj zasady --no-allow-unauthenticated.

Obraz określony w tym miejscu to obraz Dockera utworzony w ostatnim kroku. Dzięki usłudze Cloud Build, która zapisała wynikowy obraz w Google Container Registry, usługa Cloud Run może go znaleźć i wdrożyć.

Poczekaj chwilę na zakończenie wdrażania. Kiedy operacja zostanie wykonana, w wierszu poleceń wyświetli się URL usługi:

Deploying container to Cloud Run service [hello] in project [PROJECT_ID...
✓ Deploying new service... Done.                                   
  ✓ Creating Revision... Revision deployment finished. Waiting for health check...
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [hello] revision [hello-...] has been deployed and is serving 100 percent of traffic.
Service URL: https://hello-....a.run.app

Adres URL usługi możesz też pobrać za pomocą tego polecenia:

gcloud run services describe hello  \
  --platform managed                \
  --region $REGION                  \
  --format "value(status.url)"

Powinien pojawić się komunikat podobny do tego:

https://hello-....a.run.app

Ten link to dedykowany adres URL z zabezpieczeniami TLS dla Twojej usługi Cloud Run. Ten link jest stały (dopóki nie wyłączysz usługi) i można go używać w dowolnym miejscu w internecie. Nie korzysta z opisanego wcześniej mechanizmu serwera proxy Cloud Shell, który zależał od tymczasowej maszyny wirtualnej.

Kliknij wyróżniony symbol Service URL, aby otworzyć kartę przeglądarki z uruchomioną aplikacją. Powinien się wyświetlić komunikat „Hello from Cloud Run!” na losowo pokolorowanym tle.

Gratulacje! Twoja aplikacja działa już w chmurze Google. Twoja aplikacja jest publicznie dostępna, z szyfrowaniem TLS (HTTPS) i automatycznym skalowaniem do niewyobrażalnych poziomów ruchu.

Uważam jednak, że ten proces można jeszcze bardziej uprościć…

6. Automatyczne tworzenie kontenera

To wszystko jest bardzo ciekawe, ale co, jeśli nie chcę nawet myśleć o plikach Dockerfile i kontenerach? A co, jeśli tak jak większość deweloperów chcę się skupić na pisaniu kodu aplikacji i zostawić konteneryzację komuś innemu? Masz szczęście, ponieważ Cloud Run obsługuje standard open source o nazwie Buildpacks, który powstał właśnie w tym celu: aby zautomatyzować proces tworzenia kontenera z kolekcji plików źródłowych.

Pamiętaj, że w niektórych przypadkach deweloper może woleć użyć jawnego pliku Dockerfile, np. jeśli chce mieć dużą kontrolę nad sposobem tworzenia kontenera. W przypadku typowych sytuacji, takich jak to ćwiczenie, pakiety kompilacyjne działają dobrze i nie wymagają ręcznego tworzenia pliku Dockerfile. Zmodyfikujmy kod, aby używać pakietów buildpack.

Najpierw zmodyfikujmy aplikację, aby można było odróżnić nową wersję od starej. Aby to zrobić, zmień plik main.py tak, aby domyślny komunikat zmienił się z „Hello from Cloud Run!” na „Hello from Cloud Run with Buildpacks!”. Innymi słowy, zmień ten wiersz w pliku main.py z tego:

def say_hello(name="from Cloud Run"):

na:

def say_hello(name="from Cloud Run with Buildpacks"):

Teraz skorzystajmy z pakietów kompilacji, tworząc nowy plik o nazwie Procfile. Utwórz ten plik w edytorze Cloud i wstaw ten wiersz tekstu:

web: python3 main.py

Informuje to system kompilacji zwrotnej, jak uruchomić aplikację w automatycznie wygenerowanym kontenerze. Dzięki tej instrukcji nie potrzebujesz już nawet pliku Dockerfile. Aby to sprawdzić, usuń plik Dockerfile i uruchom w terminalu Cloud Shell to polecenie:

gcloud beta run deploy "$APP"  \
    --source .                 \
    --platform "managed"       \
    --region "$REGION"         \
    --allow-unauthenticated

Jest to podobne do polecenia uruchomionego w ostatnim kroku w celu wdrożenia aplikacji, ale tym razem opcję --image zastąpiono opcją --source .. To polecenie informuje polecenie gcloud, że chcesz użyć pakietów kompilacji do utworzenia obrazu kontenera na podstawie plików źródłowych znalezionych w bieżącym katalogu (dot w --source . to skrót oznaczający bieżący katalog). Usługa obsługuje obraz kontenera w sposób niejawny, więc nie musisz go określać w tym poleceniu gcloud.

Ponownie sprawdź, czy wdrożenie się powiodło. W tym celu kliknij wyróżniony symbol Service URL, aby otworzyć kartę przeglądarki internetowej z uruchomioną aplikacją. Upewnij się, że usługa wyświetla tekst „Hello from Cloud Run with Buildpacks!” (Cześć z Cloud Run z Buildpackami!) na losowo kolorowym tle.

Zwróć uwagę, że dzięki użyciu pakietów kompilacji do wyprodukowania Dockerfile udało Ci się skrócić 3 proste kroki do 2:

  1. Utwórz aplikację w środowisku programistycznym.
  2. Wdróż dokładnie ten sam kod w chmurze za pomocą jednego polecenia.

7. Czy muszę używać wiersza poleceń?

Nie! Podobnie jak w przypadku niemal każdej usługi Google Cloud, z Cloud Run można wchodzić w interakcje na 3 sposoby:

  • Narzędzie wiersza poleceń gcloud, które właśnie widzisz.
  • bogaty interfejs użytkownika w internecie dostępny w konsoli Cloud, który obsługuje intuicyjny styl interakcji typu „wskaż i kliknij”;
  • Programowo, za pomocą bibliotek klienta Google dostępnych w wielu popularnych językach, m.in. Java, C#, Python, Go, Javascript, Ruby, C/C++.

Wdróżmy dodatkową instancję aplikacji Cloud Run za pomocą interfejsu konsoli. Otwórz stronę docelową usługi Cloud Run, korzystając z menu w lewym górnym rogu:

e2b4983b38c81796.png

Powinno się wyświetlić podsumowanie usług Cloud Run, np. takie:

b335e7bf0a3af845.png

Aby rozpocząć proces wdrażania, kliknij link „Utwórz usługę”:

51f61a8ddc7a4c0b.png

Wpisz „hello-again” jako nazwę usługi, zaakceptuj domyślną platformę i region wdrażania i kliknij „Dalej”.

8a17baa45336c4c9.png

Wpisz ten adres URL obrazu kontenera: gcr.io/cloudrun/hello. Jest to kontener utworzony przez Google na potrzeby testów. Kliknij menu „Ustawienia zaawansowane”, aby zobaczyć niektóre z wielu dostępnych ustawień konfiguracyjnych. Oto kilka elementów, które możesz dostosować:

  • numer portu i punkt wejścia kontenera (który zastąpi punkt wejścia określony podczas tworzenia kontenera);
  • sprzęt: pamięć i liczba procesorów,
  • skalowanie: minimalna i maksymalna liczba instancji,
  • zmienne środowiskowe
  • inne: ustawienie limitu czasu żądania, maksymalna liczba żądań na kontener, HTTP/2.

Aby przejść dalej, kliknij przycisk „Dalej”. W następnym oknie możesz określić sposób wywoływania usługi. W sekcji „Ruch przychodzący” wybierz „Zezwalaj na cały ruch”, a w sekcji „Uwierzytelnianie” wybierz „Zezwalaj na nieuwierzytelniony ruch”.

e78281d1cff3418.png

Są to najbardziej liberalne ustawienia, ponieważ umożliwiają dostęp do aplikacji Cloud Run każdemu użytkownikowi z dowolnego miejsca w internecie publicznym bez podawania danych logowania. Możesz chcieć zastosować bardziej restrykcyjne ustawienia w przypadku swojej aplikacji, ale na potrzeby tego ćwiczenia uprościmy je.

Teraz kliknij przycisk Create, aby utworzyć usługę Cloud Run. Po kilku sekundach nowa usługa powinna pojawić się na liście podsumowującej usługi Cloud Run. W wierszu podsumowania znajdziesz informacje o ostatnim wdrożeniu (data i godzina oraz osoba, która je przeprowadziła) wraz z niektórymi kluczowymi ustawieniami konfiguracji. Kliknij link do nazwy usługi, aby wyświetlić szczegółowe informacje o nowej usłudze.

Aby zweryfikować usługę, kliknij adres URL widoczny u góry strony podsumowania, jak pokazano na przykładzie poniżej:

6c35cf0636dddc51.png

Powinien pojawić się ekran podobny do tego:

3ba6ab4fe0da1f84.png

Po wdrożeniu nowej usługi Cloud Run wybierz kartę REVISIONS, aby zobaczyć sposoby zarządzania wieloma wdrożeniami.

2351ee7ec4a356f0.png

Aby wdrożyć nowe wersje bezpośrednio z konsoli, możesz kliknąć przycisk EDIT & DEPLOY NEW REVISION, jak pokazano na przykładowym zrzucie ekranu poniżej:

a599fa88d00d6776.png

Kliknij ten przycisk, aby utworzyć nową wersję. Obok adresu URL kontenera kliknij przycisk SELECT, jak pokazano poniżej:

5fd1b1f8e1f11d40.png

W oknie, które się pojawi, znajdź prostą aplikację internetową wdrożoną wcześniej z Cloud Build za pomocą pakietów Buildpack, a następnie kliknij Wybierz. Upewnij się, że wybierasz obraz kontenera w sekcji

gcr.io/<project>/cloud-run-source-deploy

folder , na przykład:

8a756c6157face3a.png

Po wybraniu przewiń do dołu i kliknij przycisk DEPLOY. Wdrożyliśmy nową wersję aplikacji. Aby to sprawdzić, ponownie otwórz adres URL usługi i upewnij się, że widzisz kolorową aplikację internetową „Hello from Cloud Run with Buildpacks!”.

Jak widać, karta wersji zawiera podsumowanie każdej wdrożonej wersji. W przypadku tej usługi powinny być teraz widoczne 2 wersje. Aby wybrać daną wersję, kliknij przycisk opcji po lewej stronie nazwy wersji. Po prawej stronie ekranu pojawi się podsumowanie szczegółów wersji. Po kliknięciu tych przycisków zobaczysz, że 2 wersje pochodzą z 2 różnych obrazów kontenera.

Przycisk MANAGE TRAFFIC umożliwia modyfikowanie dystrybucji przychodzących żądań wysyłanych do danej wersji. Możliwość precyzyjnego dostosowywania ilości ruchu kierowanego do danej wersji umożliwia kilka przydatnych zastosowań:

  • testowanie nowej wersji aplikacji na niewielkiej części ruchu przychodzącego;
  • przywrócić ruch z problematycznej wersji do poprzedniej wersji,
  • Testy A/B

Przycisk MANAGE TRAFFIC znajdziesz tutaj:

519d3c22ae028287.png

Skonfiguruj podział ruchu 50/50 między 2 wersje, określając podział ruchu 50/50 w ten sposób:

8c37d4f115d9ded4.png

Teraz kliknij przycisk ZAPISZ i sprawdź podział 50/50, wielokrotnie otwierając adres URL usługi. Upewnij się, że średnio połowa żądań jest obsługiwana przez bieżącą wersję („Hello from Cloud Run with Buildpacks!”), a połowa przez poprzednią wersję („It's running!”).

Inne karty na stronie z informacjami o usłudze umożliwiają monitorowanie wydajności, ruchu i logów, które dostarczają cennych informacji o tym, jak ciężko i jak dobrze działa Twoja usługa. Możesz też dostosować dostęp do usługi na karcie „Uprawnienia”. Poświęć chwilę na zapoznanie się z kartami na tej stronie, aby poznać dostępne tu funkcje.

Interfejs automatyzacji

Jak wspomnieliśmy wcześniej, możesz też tworzyć, wdrażać usługi Cloud Run i nimi zarządzać programowo. W przypadku zadań wykonywanych ręcznie ta opcja jest bardziej zaawansowana niż wiersz poleceń czy konsola internetowa, ale zdecydowanie warto jej używać do automatyzacji usług Cloud Run. Możesz używać bibliotek klienta Google w kilku popularnych językach programowania.

8. Testowanie aplikacji

198ada162d1f0bf1.png

W tym ostatnim kroku przeprowadzisz test sztucznego obciążenia, aby przetestować aplikację pod kątem obciążenia i sprawdzić, jak skaluje się ona w odpowiedzi na rosnące zapotrzebowanie. Użyjesz narzędzia hey, które jest wstępnie zainstalowane w Cloud Shell i umożliwia przeprowadzanie testów obciążeniowych oraz prezentowanie wyników.

Przeprowadzanie testu

Aby uruchomić test obciążenia, w terminalu Cloud Shell uruchom to polecenie:

hey -q 1000 -c 200 -z 30s https://hello-...run.app

Argumenty polecenia są interpretowane w ten sposób:

  • -q 1000 – spróbuj wygenerować obciążenie na poziomie około 1000 żądań na sekundę.
  • -c 200 – przydziel 200 równoległych instancji roboczych
  • -z 30s – przeprowadź test obciążenia przez 30 sekund.
  • pamiętaj, aby użyć adresu URL usługi jako ostatniego argumentu w tym wierszu poleceń

Wyniki testu powinny wyglądać mniej więcej tak:

 Summary:
 Total:        30.2767 secs
 Slowest:      3.3633 secs
 Fastest:      0.1071 secs
 Average:      0.1828 secs
 Requests/sec: 1087.2387
 Total data:   3028456 bytes
 Size/request: 92 bytes

Response time histogram:
 0.107 [1]     |
 0.433 [31346] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
 0.758 [1472]  |■■
 1.084 [82]    |
 1.410 [4]     |
...

Latency distribution:
...
 50% in 0.1528 secs
 75% in 0.1949 secs
 90% in 0.2442 secs
 95% in 0.4052 secs
 99% in 0.7062 secs

Details (average, fastest, slowest):
...
 req write:    0.0000 secs, 0.0000 secs, 0.0232 secs
 resp wait:    0.1824 secs, 0.1070 secs, 3.2953 secs
 resp read:    0.0000 secs, 0.0000 secs, 0.0010 secs
Status code distribution:
 [200] 32918 responses

To podsumowanie zawiera kilka interesujących informacji:

  • Wysłano 32 918 żądań z częstotliwością około 1000 na sekundę przez 30 sekund.
  • Nie było żadnych błędów (tylko odpowiedzi HTTP 200).
  • Średni czas oczekiwania wynosił 180 ms.
  • Minimalny czas oczekiwania wynosił 107 ms, a w najgorszym przypadku – 3,3 s.
  • Czas oczekiwania w 90. percentylu wyniósł 244 ms.

Jeśli w konsoli Cloud Run otworzysz kartę METRICS, zobaczysz informacje o wydajności po stronie serwera:

e635c6831c468dd3.png

9. Czyszczenie

Cloud Run nie nalicza opłat, gdy usługa nie jest używana, ale może zostać pobrana należność za przechowywanie utworzonego obrazu kontenera.

Możesz usunąć projekt GCP, co spowoduje zaprzestanie naliczania opłat za wszelkie zasoby wykorzystywane w ramach tego projektu, albo usunąć tylko obraz kontenera przy użyciu tego polecenia:

gcloud container images delete $TAG

Aby usunąć usługi Cloud Run, użyj tych poleceń:

gcloud run services delete hello --platform managed --region $REGION --quiet
gcloud run services delete hello-again --platform managed --region $REGION --quiet

10. Udało się!

9a31f4fdbbf1ddcb.png

Gratulacje – udało Ci się utworzyć i wdrożyć produkcyjną aplikację Cloud Run. Przy okazji dowiedziałeś się więcej o kontenerach i o tym, jak utworzyć własny kontener. Pokazaliśmy też, jak łatwo wdrożyć aplikację za pomocą Cloud Run, korzystając z narzędzia wiersza poleceń gcloud i konsoli Cloud. Teraz już wiesz, jak udostępniać swoje wspaniałe dzieła całemu światu.

Chcę Ci zadać jedno ważne pytanie:

Gdy aplikacja zaczęła działać w środowisku deweloperskim, ile wierszy kodu trzeba było zmodyfikować, aby wdrożyć ją w chmurze ze wszystkimi atrybutami klasy produkcyjnej oferowanymi przez Cloud Run?

Odpowiedź to oczywiście zero. :)

Ćwiczenia do sprawdzenia…

Inne ciekawe funkcje, które warto poznać...

Dokumentacja referencyjna...

11. Wezwanie do działania

Logo Google Cloud

Jeśli podobały Ci się te ćwiczenia z programowania i chcesz poświęcić więcej czasu na praktyczne korzystanie z Google Cloud, dołącz do programu Google Cloud Innovators już dziś.

Logo odznaki ogólnego uczestnika programu Innovators

Program Google Cloud Innovators jest bezpłatny i obejmuje:

  • Prowadzone na żywo dyskusje, sesje pytań i odpowiedzi oraz sesje dotyczące harmonogramu, podczas których możesz poznać najnowsze informacje bezpośrednio od pracowników Google.
  • najnowsze wiadomości o Google Cloud prosto do Twojej skrzynki odbiorczej;
  • Cyfrowe logo i tło rozmowy wideo
  • 500 punktów na moduły i naukę na platformie Skills Boost

Aby się zarejestrować, kliknij tutaj.