Stack Labs Blog moves to Dev.to | Le Blog Stack Labs déménage sur Dev.to 🚀

13 février 2019 | Cloud | Chabane Refes

OpenFaaS - Un FaaS sur son orchestrateur de conteneurs

Temps de lecture estimé : 7 minutes

Si vous possédez un cloud privé et que vous rêvez d’y installer une infrastructure Serverless ; si vous avez un compte sur un cloud public et que vous hésitez encore à utiliser ses services Serverless pour garder un contrôle sur vos fonctions, sachez que vous pouvez installer une plateforme Function As a Service sur votre orchestrateur de conteneurs avec la solution OpenFaaS.

Note : Cet article présente un exemple de déploiement d’OpenFaas sur AWS EKS. La même technique s’applique au déploiement d’OpenFaaS sur un minikube, un serveur on-premise ou toute autre plateforme cloud telle que GKE ou OpenShift.

Serverless, c’est quoi déjà ?

Dans une architecture traditionnelle, on a toujours besoin d’un backend pour les traitements côté serveur. L’idée d’une architecture Serverless est de se passer de ce serveur d’application et de son infrastructure. Comment ? En exécutant le code qui représente le backend sur une plateforme Function As a Service. Toute l’architecture devra être pensée en fonctions. Le code de la fonction devra être léger et s’exécuter rapidement.

Pourquoi OpenFaaS ?

Les cloud publics proposent tous une plateforme Function As a Service. Leur solution répond à la plupart des cas d’usage et nous aide à gagner du temps et à reduire nos coûts. Mais selon certains besoins métiers, on peut être freiné par certaines limitations comme l’accès aux logs du système, la durée du timeout, les ressources mémoires ou encore le langage utilisé. Heureusement aujourd’hui, des solutions alternatives existent pour déployer sa propre infrastructure Serverless. On peut citer OpenFaaS, Apache OpenWhisk ou knative. Celui qui est le plus en vogue aujourd’hui est incontestablement OpenFaaS.

OpenFaaS est un framework, il permet d’exécuter des fonctions Serverless sur du Docker ou du Kubernetes. OpenFaaS supporte aujourd’hui les langages suivants : Node.js, Python, Go, Java, C#, PHP, et Ruby. Il nous suffit de spécifier un fichier (handler.py/handler.js) et le framework se chargera de créer l’image Docker pour nous. Il est aussi possible de construire sa propre image.

Architecture

Chaque fonction déployée sur OpenFaaS a pour effet de créer sur Kubernetes un Deployment et un Service. Le Deployment a par défaut un seul réplica et donc au minimum un seul pod pour servir le trafic. On peut le voir sur le schéma ci-dessous OpenFaaS operator, qui est accessible via kubectl ou faas-cli :

Credits image

Pour en savoir plus sur l’Architecture d’OpenFaaS

Installation

Il y a différentes manières d’installer OpenFaaS sur son orchestrateur de containers. Soit manuellement via un kubectl ou directement depuis un package helm. Dans cet article nous allons décrire les étapes permettant de déployer OpenFaaS sur un cluster Kubernetes sur AWS via Helm. Voir avec minikube

Prerequis

Créer le cluster EKS

On va créer un cluster simple sur AWS EKS sur la région Ireland avec 2 nodes.

eksctl create cluster --name=eks-openfaas-overview --nodes-min=2 --nodes-max=3 --node-type=t3.medium --node-volume-size=5 --auto-kubeconfig --region=eu-west-1 --version=1.11 

eksctl est basé sur aws cloudformation et nous aide à déployer rapidement un cluster sur aws.

Installer le serveur Helm sur le cluster

Helm est le meilleur outil permettant d’installer des packages sur K8S.

kubectl -n kube-system create sa tiller

serviceaccount/tiller created
kubectl create clusterrolebinding tiller-cluster-rule \
    --clusterrole=cluster-admin \
    --serviceaccount=kube-system:tiller 

clusterrolebinding.rbac.authorization.k8s.io/tiller-cluster-rule created
helm init --upgrade --service-account tiller

$HELM_HOME has been configured at $HOME/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

[..]
Happy Helming!

Installer les namespaces OpenFaaS

Les services core d’OpenFaaS sont créés dans le namespace openfaas tandis que les services de chaque fonction sont dans openfaas-fn

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

namespace/openfaas created
namespace/openfaas-fn created

Déployer OpenFaaS sur le cluster

Première étape, récupèrer le repo openfaas depuis helm

helm repo add openfaas https://openfaas.github.io/faas-netes/

"openfaas" has been added to your repositories

Seconde étape, déployer OpenFaaS avec Helm

(Si vous faites les tests depuis votre propre compte AWS, il est recommandé de créer un secret pour sécuriser votre API Gateway, voir Secrets et Auth)

helm upgrade openfaas --install openfaas/openfaas \
    --namespace openfaas  \
    --set functionNamespace=openfaas-fn \
    --set serviceType=LoadBalancer \
    --set gateway.replicas=2 \
    --set queueWorker.replicas=2

Release "openfaas" does not exist. Installing it now.
NAME:   openfaas
LAST DEPLOYED: Mon Jan 28 19:06:13 2019
NAMESPACE: openfaas
STATUS: DEPLOYED    
[..]
==> v1/Service
NAME              TYPE          CLUSTER-IP      EXTERNAL-IP  PORT(S)         AGE
alertmanager      ClusterIP     10.104.93.105   <none>       9093/TCP        1s
gateway-external  LoadBalancer  10.110.3.97     <pending>    8080:30950/TCP  1s
gateway           ClusterIP     10.109.238.95   <none>       8080/TCP        1s
nats              ClusterIP     10.103.150.181  <none>       4222/TCP        1s
prometheus        ClusterIP     10.99.131.109   <none>       9090/TCP        1s

==> v1beta1/Deployment
NAME          DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
alertmanager  1        1        1           0          1s
faas-idler    1        1        1           0          1s
gateway       2        2        2           0          1s
nats          1        1        1           0          1s
prometheus    1        1        1           0          1s
queue-worker  2        2        2           0          1s
[..]

La commande va créer un loadbalancer, 2 réplicas et 2 queue-workers pour la haute disponibilité. Une fois les services déployés, l’External-IP sera disponible (à récupèrer depuis kubectl get svc -n openfaas -o wide). La dernière étape consiste à exporter l’URL d’OpenFaaS.

export OPENFAAS_URL=$(kubectl get svc -n openfaas gateway-external -o jsonpath='{.status.loadBalancer.ingress[*].hostname}'):8080

(sur minikube on ferait : export OPENFAAS_URL=http://$(minikube ip):31112)

Déployer une fonction

Il est possible de déployer sa fonction de 3 manières:

  • soit depuis l’UI,
  • soit depuis un appel REST,
  • ou via la cli d’OpenFaaS faas-cli installé préalablement.

Pour faire simple, nous allons prendre une fonction déjà créée depuis OpenFaaS Function Store. Vous pouvez voir la liste depuis faas-cli store list :

faas-cli store deploy colorise

Deployed. 202 Accepted.
URL: http://123456789.eu-west-1.elb.amazonaws.com:8080/function/colorise

La fonction sera automatiquement déployée sur OpenFaaS. Testons notre fonction avec la CLI :

echo -n 'https://www.stack-labs.com/images/cover.jpg' | faas-cli invoke colorise > stackerteam.jpg

Créer sa propre fonction

On peut écrire notre propre fonction avec un langage supporté par OpenFaaS ou en créant notre propre template. Un template OpenFaaS consiste en un Dockerfile et un entrypoint (pas accessible par l’utilisateur). Le code est à écrire dans un fichier handler.

On peut vérifier les images OpenFaaS disponibles en lançant les commandes :

faas-cli template pull
faas-cli new --list

La commande faas-cli new sert à initialiser une fonction. On indique le langage souhaité et le préfixe correspondant au repository du registry docker.

faas-cli new --lang go hey-stacker --prefix=123456789.dkr.ecr.eu-west-1.amazonaws.com

Cela créera les fichiers suivants :

./hey-stacker.yml
./hey-stacker/
./hey-stacker/handler.go

Editer handler.go :

package function

import (
	"fmt"
)

// Handle a serverless request
func Handle(req []byte) string {
	return fmt.Sprintf("Hey, Stacker. You said: %s", string(req))
}

Pour déployer la fonction sur OpenFaaS, on lance la commande :

faas-cli up -f hey-stacker.yml

[0] > Building hey-stacker.
Clearing temporary build folder: ./build/hey-stacker/
Preparing ./hey-stacker/ ./build/hey-stacker/function
Building: 123456789.dkr.ecr.eu-west-1.amazonaws.com/hey-stacker:latest with go template. Please wait..
Sending build context to Docker daemon  6.656kB
Step 1/20 : FROM golang:1.10.4-alpine3.8 as builder
[..]
Step 20/20 : CMD ["./fwatchdog"]
 ---> Using cache
 ---> a69c3283ca02
Successfully built a69c3283ca02
Successfully tagged 123456789.dkr.ecr.eu-west-1.amazonaws.com/hey-stacker:latest
Image: 123456789.dkr.ecr.eu-west-1.amazonaws.com/hey-stacker:latest built.
[0] < Building hey-stacker done.
[0] worker done.

[0] > Pushing hey-stacker [123456789.dkr.ecr.eu-west-1.amazonaws.com/hey-stacker:latest].
The push refers to repository [123456789.dkr.ecr.eu-west-1.amazonaws.com/hey-stacker]
[..]
[0] < Pushing hey-stacker [123456789.dkr.ecr.eu-west-1.amazonaws.com/hey-stacker:latest] done.
[0] worker done.

Deploying: hey-stacker.

Deployed. 202 Accepted.
URL: http://123456789.eu-west-1.elb.amazonaws.com:8080/function/hey-stacker

Cette commande est équivalente à l’ensemble de ces commandes : construction de l’image, push de l’image sur le registry et déploiement de la fonction sur OpenFaaS.

faas-cli build && \
faas-cli push && \
faas-cli deploy

On peut invoquer la fonction comme décrit plus haut ou via l’UI d’OpenFaaS. Dans cet exemple, on invoque la fonction directement depuis l’UI.

Monitoring

OpenFaaS met à notre disposition d’autres outils tels que Prometheus et Grafana pour monitorer nos applications.

kubectl -n openfaas run --image=stefanprodan/faas-grafana:4.6.3 --port=3000 grafana
kubectl expose deploy/grafana --type ClusterIP -n openfaas --port 3000
kubectl port-forward -n openfaas svc/grafana 3000:3000

On peut voir dans cet exemple, la liste des fonctions déployées.

Conclusion

OpenFaaS nous donne la possibilité de déployer des fonctions de façon plus custom qu’on le ferait avec une fonction Serverless sur un cloud public. Très pratique lorsqu’on souhaite déployer une infrastructure Serverless sur un orchestrateur existant et bénéficier de tous ses avantages.

Références :