Budowanie własnego serwera bezserwerowego w oparciu o Fn
Przetwarzanie bezserwerowe to jeden z najważniejszych trendów w chmurze obliczeniowej. Podstawowa zasada działania jest taka, że infrastruktura nie jest przedmiotem zainteresowania DevOps, ale dostawcy usług. Skalowanie zasobów automatycznie dostosowuje się do obciążenia i charakteryzuje się dużą szybkością zmian.
Inną wspólną cechą jest tendencja do minimalizowania i skupiania kodu, dlatego też przetwarzanie bezserwerowe jest czasami nazywane funkcją jako usługą (FaaS).
Historycznie rzecz biorąc, pierwszym dostawcą chmury oferującym FaaS z AWS Lambda był Amazon, stąd nazwa. Inni dostawcy usług w chmurze również oferują podobne:
Funkcje chmury od Google
Azure Functions od Microsoftu
Wszystkie te firmy zapewniają przetwarzanie bezserwerowe, automatyczne skalowanie i płacą tylko za to, z czego faktycznie korzystasz, ale blokują klientów w swoim zastrzeżonym produkcie. Istnieją jednak bezpłatne i otwarte alternatywy dla przetwarzania bezserwerowego. To jest nic nie warte:
Funkcje chmury wiosennej, w ramach dość bogatego ekosystemu Spring Framework, który może służyć również jako fasada dla AWS Lambda, Azure Functions i OpenWhisk,
Wszystkie są całkowicie niezależne od chmur, czyli można je zainstalować w dowolnej chmurze, także tej własnej, publicznej czy prywatnej i oczywiście w Exoscale.
Jak działa projekt Fn
Fn jest całkowicie oparty na Dockerze, składa się z dwóch głównych komponentów:
Program CLI przeznaczony do zarządzania wszystkimi aspektami infrastruktury Fn i współdziałający z serwerem Fn,
Sam serwer Fn to zwykła aplikacja spakowana w kontenerze Docker.
Funkcje zaimplementowane w Fn są również wykonywane w oddzielnych kontenerach, co pozwala na obsługę wielu języków programowania, na przykład... Clojure!
Argumenty funkcji przekazywane są na standardowe wejście (STDIN), wyniki zapisywane są na standardowe wyjście (STDOUT). Jeśli argumenty lub zwracane wartości nie są wartościami prostymi (jak np. obiekt JSON), można je skonwertować za pomocą warstwy abstrakcji dostarczonej przez samo Fn w postaci zestawu Function Development Kit (FDK).
Dla wygody oferowane są wbudowane zestawy szablonów ułatwiające wdrożenie FaaS w obszernej liście różnych języków i ich wersji (Go, różne wersje Java, Python itp.).
Tworzenie FaaS jest łatwe, jeśli zastosujesz się do poniższego diagramu:
Wdrażanie funkcji za pomocą Fn CLI: na podstawie wybranego szablonu tworzony jest plik konfiguracyjny aplikacji dla Fn.
Wdrażamy własną funkcję, ponownie wykorzystując CLI Fn: obraz kontenera jest umieszczany w określonym repozytorium, po czym serwer jest powiadamiany o istnieniu i umieszczeniu tego obrazu.
Zasada dostarczania funkcji do Fn
Lokalna instalacja i testowanie funkcji bezserwerowych
Zacznijmy instalować Fn na komputerze lokalnym. Najpierw instalowany jest Docker, zgodnie z wymaganiami Fn. Zakładając, że korzystamy z Debiana/Ubuntu:
Lub użyj menedżera pakietów/kompilacji Dockera zgodnie z twoim systemem. Następnie możesz przejść od razu do instalacji Fn CLI. Na przykład używając curl:
$ curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
Jeśli korzystasz z systemu OSX z zainstalowanym Homebrew, możesz przejść w drugą stronę:
Jesteśmy teraz gotowi do wstępnego wdrożenia naszej funkcji za pomocą interfejsu CLI. Dla uproszczenia użyjemy wbudowanego środowiska startowego, takiego jak Node:
$ fn init --runtime node --trigger http hellonode
Creating function at: /hellonode
Function boilerplate generated.
func.yaml created.
Zostanie utworzony nowy katalog hellonode aby dalej rozwijać naszą funkcję Fn za pomocą kilku podstawowych plików konfiguracyjnych. W nowo utworzonym katalogu możesz stworzyć swoją aplikację zgodnie ze standardami wybranego języka lub środowiska wykonawczego:
# Каталог с node выглядит так:
hellonode
├── func.js
├── func.yaml
└── package.json
# Свежеустановленное окружение Java11 такое:
hellojava11
├── func.yaml
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── example
│ └── fn
│ └── HelloFunction.java
└── test
└── java
└── com
└── example
└── fn
└── HelloFunctionTest.java
Fn tworzy początkową strukturę projektu, tworzy plik func.yaml, zawierający niezbędne ustawienia dla Fn i ustawia szablon kodu w wybranym przez Ciebie języku.
W przypadku środowiska uruchomieniowego Node oznacza to:
$ cat hellonode/func.js
const fdk=require('@fnproject/fdk');
fdk.handle(function(input){
let name = 'World';
if (input.name) {
name = input.name;
}
return {'message': 'Hello ' + name}
})
Teraz szybko przetestujemy naszą funkcję lokalnie, aby zobaczyć, jak wszystko działa.
Najpierw uruchomimy serwer Fn. Jak już wspomniano, serwer Fn jest kontenerem Dockera, dlatego po uruchomieniu pójdzie i pobierze obraz z rejestru Dockera.
$ fn start -d # запускаем локальный сервер в фоне
Unable to find image 'fnproject/fnserver:latest' locally
latest: Pulling from fnproject/fnserver
ff3a5c916c92: Pull complete
1a649ea86bca: Pull complete
ce35f4d5f86a: Pull complete
...
Status: Downloaded newer image for fnproject/fnserver:latest
668ce9ac0ed8d7cd59da49228bda62464e01bff2c0c60079542d24ac6070f8e5
Aby nasza funkcja mogła działać, należy ją „wdrożyć”. To wymaga имя приложения: W Fn wszystkie aplikacje muszą być określone jako przestrzenie nazw dla powiązanych funkcji.
Fn CLI wyszuka plik func.yaml w bieżącym katalogu, który będzie używany do konfigurowania funkcji. Najpierw musisz przejść do naszego katalogu hellonode.
$ cd hellonode
$ fn deploy --app fnexo --local # выкатываем функцию локально, имя приложения - fnexo.
# параметр local не заливает образ в удаленный реестр,
# запуская его напрямую
Deploying hellonode to app: fnexo
Bumped to version 0.0.2
Building image nfrankel/hellonode:0.0.3 .
Updating function hellonode using image nfrankel/hellonode:0.0.3...
Successfully created app: fnexo
Successfully created function: hellonode with nfrankel/hellonode:0.0.3
Successfully created trigger: hellonode-trigger
Jak widać z wyniku polecenia, tworzony jest nowy obraz kontenera Docker zawierający naszą funkcję. Funkcja jest gotowa do wywołania i mamy na to dwa sposoby:
za pomocą polecenia Fn invoke
dzwoniąc bezpośrednio przez http
Zadzwoń invoke przez Fn po prostu emuluje pracę przez HTTP do testów, co jest wygodne do szybkiego testowania:
Serwer Fn udostępnia swoje funkcje na porcie 8080, a adres URL funkcji wydaje się pasować do wzorca t/app/function, ale nie całkowicie. Poprzez HTTP funkcja nie jest wywoływana bezpośrednio, lecz poprzez tzw. wyzwalacz, który zgodnie ze swoją nazwą „uruchamia” wywołanie funkcji. Wyzwalacze są zdefiniowane w `func.yml projekt:
Wszystko działa! Czas przejść do eksperymentów na pełną skalę i opublikować nasz FaaS na serwerze!
Instalowanie usług funkcji bezserwerowych na własnej infrastrukturze
Zainstalujmy szybko maszynę wirtualną za pomocą interfejsu CLI Exoscale. Jeśli jeszcze tego nie skonfigurowałeś, możesz użyć nasz przewodnik szybkiego startu. To fajne narzędzie, które jeszcze bardziej zwiększy Twoją produktywność. Nie zapomnij, że musisz skonfigurować regułę otwierającą port 8080 w grupie zabezpieczeń! Następujące polecenia uruchomią czystą maszynę wirtualną, gotową do hostowania naszych funkcji:
Następnie możesz połączyć się przez ssh z maszyną wirtualną i zainstalować zdalny serwer Fn:
$ exo ssh fn-server
The authenticity of host '185.19.30.175 (185.19.30.175)' can't be established.
ECDSA key fingerprint is SHA256:uaCKRYeX4cvim+Gr8StdPvIQ7eQgPuOKdnj5WI3gI9Q.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '185.19.30.175' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-20-generic x86_64)
Następnie zainstaluj Dockera i serwer Fn w taki sam sposób, jak zostało to już zrobione na komputerze lokalnym, uruchom serwer:
Fn jest gotowy do odbioru funkcji! Do ukierunkowanego przeniesienia funkcji na zdalny serwer użyjemy polecenia deploy z komputera lokalnego, pomijając flagę --local.
Ponadto Fn wymaga określenia lokalizacji serwera Fn i rejestru Docker. Opcje te można ustawić za pomocą zmiennych środowiskowych FN_API_URL и FN_REGISTRY odpowiednio, ale oferuje także wygodniejszy sposób łatwego zarządzania tworzeniem i zarządzaniem konfiguracjami do wdrożenia.
W terminologii Fn nazywana jest konfiguracja do wdrożenia context. Następujące polecenie utworzy kontekst:
Dostępne konteksty możesz przeglądać w następujący sposób:
$ fn list contexts
CURRENT NAME PROVIDER API URL REGISTRY
default default http://localhost:8080/
exoscale default http://185.19.30.175:8080 nfrankel
I przejdź do kontekstu, który właśnie został utworzony w ten sposób:
$ fn use context exoscale
Now using context: exoscale
Odtąd funkcja Fn będzie pobierać obrazy Dockera przy użyciu wybranego konta DockerHub (w moim przypadku - nfrankel), a następnie powiadom zdalny serwer (w tym przykładzie - http://185.19.30.175:8080) o lokalizacji i wersji najnowszego obrazu zawierającego Twoją funkcję.
$ fn deploy --app fnexo . # выполняется на локальной машине из каталога hellonode
Deploying function at: /.
Deploying hellonode to app: fnexo
Bumped to version 0.0.5
Building image nfrankel/hellonode:0.0.5 .
Cykl życia funkcji w obliczeniach bezserwerowych opartych na technologii Fn
Zalety przetwarzania bezserwerowego we własnym zakresie
Przetwarzanie bezserwerowe to wygodne rozwiązanie umożliwiające szybkie wdrażanie niezależnych części aplikacji, które współdziałają z bardziej złożonymi aplikacjami lub mikrousługami.
Często wynika to z ukrytych kosztów związanych z wybranym dostawcą, co w zależności od konkretnego przypadku użycia i wolumenu może prowadzić do wyższych kosztów i mniejszej elastyczności w przyszłości.
Architektury multi-cloud i chmury hybrydowe również ucierpią na tym przypadku, ponieważ łatwo można znaleźć się w sytuacji, w której chciałbyś korzystać z przetwarzania bezserwerowego, ale ze względu na politykę korporacyjną może to nie być możliwe.
Fn jest dość łatwy w użyciu i może zapewnić prawie taki sam interfejs FaaS, przy niewielkim obciążeniu. Eliminuje zależność od dostawcy i można ją zainstalować lokalnie lub u dowolnego wybranego dostawcy rozwiązań chmurowych. Istnieje także dowolność w wyborze języka programowania.
W tym artykule omówiono tylko podstawy Fn, ale utworzenie własnego środowiska wykonawczego jest dość proste, a ogólną architekturę można wdrożyć szerzej za pomocą modułu równoważenia obciążenia Fn lub umieszczając Fn za serwerem proxy w celu ochrony.