Serverless

Depuis toujours, les sociétés essaient de se concentrer sur le développement de nouvelles fonctionnalités plutôt que de perdre du temps à gérer une infrastructure ; c’est dans ce contexte que le Serverless est apparu. Dans cet article, nous allons aborder le serverless et faire un focus sur OpenFaaS dans Kubernetes.

Public visé : utilisateurs k8s et développeurs

Par Florian Davasse, Stagiaire Consultant DevOps @ Objectif-Libre

Introduction à OpenFaaS : le serverless rendu accessible

Définitions préalables

Le Serverless

Le Serverless répond à un besoin : se concentrer uniquement sur l’essentiel, c’est-à-dire l’application. Toute la gestion (scaling, monitoring, updates..) est masquée et vous n’avez plus qu’à vous concentrer sur votre « delivery ».
Présenté de cette manière, le Serverless semble résoudre tous les problèmes, sauf que cette abstraction a un coût qui peut être difficile à anticiper. D’où l’intérêt de déployer sa propre plateforme de FaaS, afin de se faire une idée des ressources consommées ou simplement de garder le contrôle de ses données.

FaaS

Le FaaS (Function-as-a-Service) est un service Cloud lié au Serverless Computing. Les développeurs peuvent s’en servir pour déployer une fonction individuelle. La fonction démarre en quelques millisecondes et traite la ou les requêtes qui arrivent. Dès que la fonction n’est plus sollicitée, elle s’arrête.

OpenFaaS

Pré-requis

Pour ce tutoriel, nous allons avoir besoin :

  • d’un cluster Kubernetes déjà installé
  • de Helm, déployé et configuré sur le cluster
  • d’un client Helm sur votre machine
  • de kubectl sur votre machine pour gérer le cluster

Installation

Il est possible d’installer OpenFaas de plusieurs manières : vous pouvez appliquer tous les fichiers yaml manuellement, ou vous pouvez utiliser Helm qui va installer et configurer simplement OpenFaaS. L’autre avantage de passer par Helm est l’installation ainsi que la configuration automatique de Prometheus pour OpenFaaS.

L’installation par Helm

Nous allons avoir besoin de deux namespaces, un pour les services core de OpenFaaS et un pour accueillir les fonctions que nous allons déployer. Par souci de simplicité, nous allons garder les valeurs recommandées par OpenFaaS, à savoir : « openfaas » pour les services core et « openfaas-fn » pour les fonctions.

$ kubectl apply -f https://raw.githubusercontent.com/openfaas/faas-netes/master/namespaces.yml

Pour se connecter à la gateway, nous allons avoir besoin d’un secret.
# generate a random password
$ PASSWORD=$(head -c 12 /dev/urandom | shasum| cut -d' ' -f1)
# create the secret
$ kubectl -n openfaas create secret generic basic-auth \
--from-literal=basic-auth-user=admin \
--from-literal=basic-auth-password="$PASSWORD"

Nous allons maintenant ajouter le repo Helm d’OpenFaaS :
$ helm repo add openfaas https://openfaas.github.io/faas-netes/

$ helm repo update && helm upgrade openfaas --install openfaas/openfaas \
--namespace openfaas \
--set basic_auth=true \
--set functionNamespace=openfaas-fn

Dernière étape, nous allons installer faas-cli sur votre machine afin de pouvoir gérer OpenFaaS à distance, mais aussi de pouvoir build nos fonctions en local.$ curl -sSL https://cli.openfaas.com | sudo sh

Maintenant qu’OpenFaaS est installé, nous allons pouvoir développer puis déployer nos fonctions !

Développement d’une fonction

Avant de développer la fonction, nous avons besoin d’un agent qui va rediriger le trafic web vers cette fonction ou vers son entrée standard. Dans OpenFaaS, cet agent s’appelle le « watchdog ». Cet agent est fourni via une image Docker et est inclus de manière masquée via les templates que nous allons voir plus bas (Doc de l’agent).

Pour initialiser une nouvelle fonction en python, nous allons nous appuyer sur faas-cli afin de créer un template de notre fonction dans le langage de notre choix :

$ export USER=VotreNomDuserDocker
$ faas-cli new hello-world --image=$USER/hello-world --lang python3

2019/07/25 11:16:19 No templates found in current directory.
2019/07/25 11:16:19 Attempting to expand templates from https://github.com/openfaas/templates.git
2019/07/25 11:16:21 Fetched 16 template(s) : [csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java8 node node-arm64 node-armhf php7 python python-armhf python3 python3-armhf ruby] from https://github.com/openfaas/templates.git
Folder: hello-world created.
___ _____ ____
/ _ \ _ __ ___ _ __ | ___|_ _ __ _/ ___|
| | | | '_ \ / _ \ '_ \| |_ / _` |/ _` \___ \
| |_| | |_) | __/ | | | _| (_| | (_| |___) |
\___/| .__/ \___|_| |_|_| \__,_|\__,_|____/
|_|
Function created in folder: hello-world
Stack file written: hello-world.yml

$ tree -I template
.
├── hello-world
│   ├── handler.py
│   ├── __init__.py
│   └── requirements.txt
└── hello-world.yml

1 directory, 4 files

  • hello-world.yml va contenir toutes les informations nécessaires à OpenFaaS pour générer l’image Docker
  • requirements.txt pour les dépendances
  • handler.py contient votre fonction

Il ne nous reste plus qu’à construire notre fonction avec la commande $ faas-cli build -f hello-world.yml.
Cette commande va créer l’image Docker avec l’agent « watchdog » inclus et y ajouter le tag « latest ».
Vous pouvez aussi automatiser le push de l’image sur un registre public/privé.

Déploiement d’une fonction

Le déploiement de fonctions peut se faire de plusieurs manières : par la Gateway, par l’API, ou via la CLI.

Gateway

Nous allons rediriger le trafic local du port 31112 vers le port distant 8080 du service « gateway ».
$ kubectl port-forward svc/gateway -n openfaas 31112:8080 &
Nous allons pouvoir nous connecter à la Gateway via l’url : http://127.0.0.1:31112/ en utilisant l’utilisateur admin et le mot de passe contenu dans la variable d’environnement $PASSWORD.

Une fois connecté, il suffit de cliquer sur « Deploy new function ».

Sur cette page, vous allez pouvoir déployer en un clic des fonctions prêtes à l’emploi mais aussi déployer votre propre fonction dans l’onglet « custom ».

Dans cet onglet, vous pourrez spécifier l’image Docker à utiliser, les variables d’environnement à utiliser, etc.

CLI

La CLI de OpenFaaS permet d’effectuer toutes les opérations nécessaires : build une fonction, deploy, regarder les logs, décrire une fonction…

Nous allons rediriger le trafic local du port 31112 vers le port distant 8080 du service « gateway ».
$ kubectl port-forward svc/gateway -n openfaas 31112:8080 &

Une fois le port redirigé, nous pouvons nous authentifier via la Gateway.
$ echo $PASSWORD | faas-cli login --gateway http://127.0.0.1:31112 --password-stdin

Nous allons push l’image que nous venons de build sur l’image registry de Docker :
$ faas-cli push -f hello-world.yml

Une fois l’image déployée sur notre registry ou celui de Docker, nous pouvons déployer la fonction sur OpenFaaS :
$ faas-cli deploy --image $USER/hello-world --name hello-word --gateway 127.0.0.1:31112

Dans cet article, nous avons pris le temps de décomposer toutes les phases (build, push, deploy). Cependant, toutes ces étapes auraient pu être résumées avec une seule commande :
$ faas-cli up -f hello-world.yml --gateway 127.0.0.1:31112

Monitoring / Scaling

Un autre aspect intéressant d’OpenFaaS se situe sur le monitoring ainsi que le scaling. Pour scaler les fonctions, OpenFaaS définit une règle dans l’AlertManager de Prometheus et se sert des métriques que Prometheus va récupérer pour voir s’il observe des latences pour servir telle ou telle fonction. Si Prometheus déclenche une alerte, OpenFaaS va scaler cette fonction et donc lancer d’autres pods.

Sur la partie monitoring, nous pouvons observer plusieurs éléments: la latence de la Gateway, le temps d’exécution des fonctions, le nombre de réplicas… Toutes les métriques sont disponibles sur cette page : OpenFaaS Docs

Conclusion

Si la simplicité d’OpenFaaS et son abstraction sont ses principaux atouts, son manque de fonctionnalités serait sa faiblesse. Pour combler tous les manques, vous devrez vous tourner vers des solutions plus complètes telles que Knative (lire notre article de blog sur le sujet) ou OpenFaaS Cloud.