DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Create a Kubernetes Cluster With Centos
  • Running SpringBoot Application On OpenShift
  • 13-Step Guide to Performance Testing in Kubernetes
  • Zero to Hero on Kubernetes With Devtron

Trending

  • Internal Developer Portals: Modern DevOps's Missing Piece
  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  • Streamlining Event Data in Event-Driven Ansible
  • How to Practice TDD With Kotlin
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Create Serverless Functions With OpenFaaS

Create Serverless Functions With OpenFaaS

By 
Sudip Sengupta user avatar
Sudip Sengupta
DZone Core CORE ·
Jun. 01, 20 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
8.7K Views

Join the DZone community and get the full member experience.

Join For Free

OpenFaaS is serverless functions framework that runs on top of Docker and Kubernetes. In this tutorial, you'll learn how to:

  • Deploy OpenFaaS to a Kubernetes cluster
  • Set up the OpenFaaS CLI
  • Create, build, and deploy serverless functions using the CLI
  • Invoke serverless functions using the CLI
  • Update an existing serverless function
  • Deploy serverless functions using the web interface
  • Monitor your serverless functions with Prometheus and Grafana

Prerequisites

  • A Kubernetes cluster. If you don't have a running Kubernetes cluster, follow the instructions from the Set Up a Kubernetes Cluster with Kind section below.
  • A Docker Hub Account. See the Docker Hub page for details about creating a new account.
  • kubectl. Refer the Install and Set Up kubectl page for details about installing kubectl.
  • Node.js 10 or higher. To check if Node.js is installed on your computer, type the following command:
Shell
 




x


 
1
node --version



The following example output shows that Node.js is installed on your computer:

Shell
 




xxxxxxxxxx
1


 
1
v10.16.3



If Node.js is not installed or you're running an older version, you can download the installer from the Downloads page.

  • This tutorial assumes basic familiarity with Docker and Kubernetes.

Set Up a Kubernetes Cluster With Kind (Optional)

With Kind, you can run a local Kubernetes cluster using Docker containers as nodes. The steps in this section are optional. Follow them only if you don't have a running Kubernetes cluster.

  1. Create a file named openfaas-cluster.yaml, and copy in the following spec:
Shell
 




xxxxxxxxxx
1


 
1
# three node (two workers) cluster config
2
kind: Cluster
3
apiVersion: kind.x-k8s.io/v1alpha4
4
nodes:
5
- role: control-plane
6
- role: worker
7
- role: worker


2. Use the kind create cluster command to create a Kubernetes cluster with one control plane and two worker nodes: 

Shell
 




xxxxxxxxxx
1


 
1
kind create cluster --config kind-specs/kind-cluster.yaml


Shell
 




xxxxxxxxxx
1
14


 
1
Creating cluster "kind" ...
2
 ✓ Ensuring node image (kindest/node:v1.17.0) ��
3
 ✓ Preparing nodes �� �� ��
4
 ✓ Writing configuration ��
5
 ✓ Starting control-plane ��️
6
 ✓ Installing CNI ��
7
 ✓ Installing StorageClass ��
8
 ✓ Joining worker nodes ��
9
Set kubectl context to "kind-kind"
10
You can now use your cluster with:
11

          
12
kubectl cluster-info --context kind-kind
13

          
14
Thanks for using kind! ��


Deploy OpenFaaS to a Kubernetes Cluster

You can install OpenFaaS using Helm, plain YAML files, or its own installer named arkade which provides a quick and easy way to get OpenFaaS running. In this section, you'll deploy OpenFaaS with arkade.

  1. Enter the following command to install arkade:
Shell
 




xxxxxxxxxx
1


 
1
curl -sLS https://dl.get-arkade.dev | sudo sh


Shell
 




xxxxxxxxxx
1
16


 
1
Downloading package https://github.com/alexellis/arkade/releases/download/0.1.10/arkade-darwin as /Users/andrei/Desktop/openFaaS/faas-hello-world/arkade-darwin
2
Download complete.
3

          
4
Running with sufficient permissions to attempt to move arkade to /usr/local/bin
5
New version of arkade installed to /usr/local/bin
6
Creating alias 'ark' for 'arkade'.
7
            _             _
8
  __ _ _ __| | ____ _  __| | ___
9
 / _` | '__| |/ / _` |/ _` |/ _ \
10
| (_| | |  |   < (_| | (_| |  __/
11
 \__,_|_|  |_|\_\__,_|\__,_|\___|
12

          
13
Get Kubernetes apps the easy way
14

          
15
Version: 0.1.10
16
Git Commit: cf96105d37ed97ed644ab56c0660f0d8f4635996


2. Now, install openfaas with: 

Shell
 




xxxxxxxxxx
1


 
1
arkade install openfaas


Shell
 




xxxxxxxxxx
1
60


 
1
Using kubeconfig: /Users/andrei/.kube/config
2
Using helm3
3
Node architecture: "amd64"
4
Client: "x86_64", "Darwin"
5
2020/03/10 16:20:40 User dir established as: /Users/andrei/.arkade/
6
https://get.helm.sh/helm-v3.1.1-darwin-amd64.tar.gz
7
/Users/andrei/.arkade/bin/helm3/darwin-amd64 darwin-amd64/
8
/Users/andrei/.arkade/bin/helm3/README.md darwin-amd64/README.md
9
/Users/andrei/.arkade/bin/helm3/LICENSE darwin-amd64/LICENSE
10
/Users/andrei/.arkade/bin/helm3/helm darwin-amd64/helm
11
2020/03/10 16:20:43 extracted tarball into /Users/andrei/.arkade/bin/helm3: 3 files, 0 dirs (1.633976582s)
12
"openfaas" has been added to your repositories
13
Hang tight while we grab the latest from your chart repositories...
14
...Successfully got an update from the "ibm-charts" chart repository
15
...Successfully got an update from the "openfaas" chart repository
16
...Successfully got an update from the "stable" chart repository
17
...Successfully got an update from the "bitnami" chart repository
18
Update Complete. ⎈ Happy Helming!⎈
19
VALUES values.yaml
20
Command: /Users/andrei/.arkade/bin/helm3/helm [upgrade --install openfaas openfaas/openfaas --namespace openfaas --values /var/folders/nz/2gtkncgx56sgrpqvr40qhhrw0000gn/T/charts/openfaas/values.yaml --set gateway.directFunctions=true --set faasnetes.imagePullPolicy=Always --set gateway.replicas=1 --set queueWorker.replicas=1 --set clusterRole=false --set operator.create=false --set openfaasImagePullPolicy=IfNotPresent --set basicAuthPlugin.replicas=1 --set basic_auth=true --set serviceType=NodePort]
21
Release "openfaas" does not exist. Installing it now.
22
NAME: openfaas
23
LAST DEPLOYED: Tue Mar 10 16:21:03 2020
24
NAMESPACE: openfaas
25
STATUS: deployed
26
REVISION: 1
27
TEST SUITE: None
28
NOTES:
29
To verify that openfaas has started, run:
30

          
31
  kubectl -n openfaas get deployments -l "release=openfaas, app=openfaas"
32
=======================================================================
33
= OpenFaaS has been installed.                                        =
34
=======================================================================
35

          
36
# Get the faas-cli
37
curl -SLsf https://cli.openfaas.com | sudo sh
38

          
39
# Forward the gateway to your machine
40
kubectl rollout status -n openfaas deploy/gateway
41
kubectl port-forward -n openfaas svc/gateway 8080:8080 &
42

          
43
# If basic auth is enabled, you can now log into your gateway:
44
PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
45
echo -n $PASSWORD | faas-cli login --username admin --password-stdin
46

          
47
faas-cli store deploy figlet
48
faas-cli list
49

          
50
# For Raspberry Pi
51
faas-cli store list \
52
 --platform armhf
53

          
54
faas-cli store deploy figlet \
55
 --platform armhf
56

          
57
# Find out more at:
58
# https://github.com/openfaas/faas
59

          
60
Thanks for using arkade!


3. To verify that the deployments were created, run the kubectl get deployments command. Specify the namespace and the selector using the -n and -l parameters as follows: 

Shell
 




xxxxxxxxxx
1


 
1
kubectl get deployments -n openfaas -l "release=openfaas, app=openfaas"



If the deployments are not yet ready, you should see something similar to the following example output: 

Shell
 




xxxxxxxxxx
1


 
1
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
2
alertmanager        0/1     1            0           45s
3
basic-auth-plugin   1/1     1            1           45s
4
faas-idler          0/1     1            0           45s
5
gateway             0/1     1            0           45s
6
nats                1/1     1            1           45s
7
prometheus          1/1     1            1           45s
8
queue-worker        1/1     1            1           45s



Once the installation is finished, the output should look like this:

Shell
 




xxxxxxxxxx
1


 
1
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
2
alertmanager        1/1     1            1           75s
3
basic-auth-plugin   1/1     1            1           75s
4
faas-idler          1/1     1            1           75s
5
gateway             1/1     1            1           75s
6
nats                1/1     1            1           75s
7
prometheus          1/1     1            1           75s
8
queue-worker        1/1     1            1           75s


4. Check the rollout status of the gateway deployment: 

Shell
 




xxxxxxxxxx
1


 
1
kubectl rollout status -n openfaas deploy/gateway



The following example output shows that the gateway deployment has been successfully rolled out: 

Shell
 




xxxxxxxxxx
1


 
1
deployment "gateway" successfully rolled out


Shell
 




xxxxxxxxxx
1


 
1
Use the kubectl port-forward command to forward all requests made to http://localhost:8080 to the pod running the gateway service:


Shell
 




xxxxxxxxxx
1


 
1
kubectl port-forward -n openfaas svc/gateway 8080:8080 &


Shell
 




xxxxxxxxxx
1


 
1
[1] 78674
2
Forwarding from 127.0.0.1:8080 -> 8080
3
Forwarding from [::1]:8080 -> 8080



Note that the ampersand sign (&) runs the process in the background. You can use the jobs command to show the status of your background processes: 

Shell
 




xxxxxxxxxx
1


 
1
jobs


Shell
 




xxxxxxxxxx
1


 
1
[1]  + running    kubectl port-forward -n openfaas svc/gateway 8080:8080


Shell
 




xxxxxxxxxx
1


 
1
Issue the following command to retrieve your password and save it into an environment variable named PASSWORD:


Shell
 




xxxxxxxxxx
1


 
1
PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)



Set Up the OpenFaaS CLI

OpenFaaS provides a command-line utility you can use to build and deploy your serverless functions. You can install it by following the steps from the Installation page.

Create a Serverless Function Using the CLI

Now that OpenFaaS and the faas-cli command-line utility are installed, you can create and deploy serverless functions using the built-in template engine. OpenFaaS provides two types of templates:

  • The Classic templates are based on the Classic Watchdog and use stdio to communicate with your serverless function. Refer to the Watchdog page for more details about how OpenFaaS Watchdog works.
  • The of-watchdog templates use HTTP to communicate with your serverless function. These templates are available through the OpenFaaS Incubator GitHub repository.

In this tutorial, you'll use a classic template.

  1. Run the following command to see the templates available in the official store:
Shell
 




xxxxxxxxxx
1


 
1
faas-cli template store list


Shell
 




xxxxxxxxxx
1
37


 
1
NAME                     SOURCE             DESCRIPTION
2
csharp                   openfaas           Classic C# template
3
dockerfile               openfaas           Classic Dockerfile template
4
go                       openfaas           Classic Golang template
5
java8                    openfaas           Classic Java 8 template
6
node                     openfaas           Classic NodeJS 8 template
7
php7                     openfaas           Classic PHP 7 template
8
python                   openfaas           Classic Python 2.7 template
9
python3                  openfaas           Classic Python 3.6 template
10
python3-dlrs             intel              Deep Learning Reference Stack v0.4 for ML workloads
11
ruby                     openfaas           Classic Ruby 2.5 template
12
node10-express           openfaas-incubator Node.js 10 powered by express template
13
ruby-http                openfaas-incubator Ruby 2.4 HTTP template
14
python27-flask           openfaas-incubator Python 2.7 Flask template
15
python3-flask            openfaas-incubator Python 3.6 Flask template
16
python3-http             openfaas-incubator Python 3.6 with Flask and HTTP
17
node8-express            openfaas-incubator Node.js 8 powered by express template
18
golang-http              openfaas-incubator Golang HTTP template
19
golang-middleware        openfaas-incubator Golang Middleware template
20
python3-debian           openfaas           Python 3 Debian template
21
powershell-template      openfaas-incubator Powershell Core Ubuntu:16.04 template
22
powershell-http-template openfaas-incubator Powershell Core HTTP Ubuntu:16.04 template
23
rust                     booyaa             Rust template
24
crystal                  tpei               Crystal template
25
csharp-httprequest       distantcam         C# HTTP template
26
csharp-kestrel           burtonr            C# Kestrel HTTP template
27
vertx-native             pmlopes            Eclipse Vert.x native image template
28
swift                    affix              Swift 4.2 Template
29
lua53                    affix              Lua 5.3 Template
30
vala                     affix              Vala Template
31
vala-http                affix              Non-Forking Vala Template
32
quarkus-native           pmlopes            Quarkus.io native image template
33
perl-alpine              tmiklas            Perl language template based on Alpine image
34
node10-express-service   openfaas-incubator Node.js 10 express.js microservice template
35
crystal-http             koffeinfrei        Crystal HTTP template
36
rust-http                openfaas-incubator Rust HTTP template
37
bash-streaming           openfaas-incubator Bash Streaming template



☞ Note that you can specify an alternative store for templates. The following example command lists the templates from a repository named andreipope: 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli template store list -u https://raw.githubusercontent.com/andreipope/my-custom-store/master/templates.json


2. Download the official templates locally: 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli template pull


Shell
 




xxxxxxxxxx
1


 
1
Fetch templates from repository: https://github.com/openfaas/templates.git at master
2
2020/03/11 20:51:22 Attempting to expand templates from https://github.com/openfaas/templates.git
3
2020/03/11 20:51:25 Fetched 19 template(s) : [csharp csharp-armhf dockerfile go go-armhf java11 java11-vert-x java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf python3-debian ruby] from https://github.com/openfaas/templates.git



☞ By default, the above command downloads the templates from the OpenFaaS official GitHub repository. If you want to use a custom repository, then you should specify the URL of your repository. The following example command pulls the templates from a repository named andreipope: 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli template pull https://github.com/andreipope/my-custom-store/



  1. To create a new serverless function, run the faas-cli new command specifying:
  • The name of your new function (appfleet-hello-world)
  • The lang parameter followed by the programming language template (node).
Shell
 




xxxxxxxxxx
1


 
1
faas-cli new appfleet-hello-world --lang node


Shell
 




xxxxxxxxxx
1
21


 
1
Folder: appfleet-hello-world created.
2
  ___                   _____           ____
3
 / _ \ _ __   ___ _ __ |  ___|_ _  __ _/ ___|
4
| | | | '_ \ / _ \ '_ \| |_ / _` |/ _` \___ \
5
| |_| | |_) |  __/ | | |  _| (_| | (_| |___) |
6
 \___/| .__/ \___|_| |_|_|  \__,_|\__,_|____/
7
      |_|
8

          
9

          
10
Function created in folder: appfleet-hello-world
11
Stack file written: appfleet-hello-world.yml
12

          
13
Notes:
14
You have created a new function which uses Node.js 12.13.0 and the OpenFaaS
15
Classic Watchdog.
16

          
17
npm i --save can be used to add third-party packages like request or cheerio
18
npm documentation: https://docs.npmjs.com/
19

          
20
For high-throughput services, we recommend you use the node12 template which
21
uses a different version of the OpenFaaS watchdog.



At this point, your directory structure should look like the following:

Shell
 




xxxxxxxxxx
1


 
1
tree . -L 2



Shell
 




xxxxxxxxxx
1
27


 
1
.
2
├── appfleet-hello-world
3
│   ├── handler.js
4
│   └── package.json
5
├── appfleet-hello-world.yml
6
└── template
7
    ├── csharp
8
    ├── csharp-armhf
9
    ├── dockerfile
10
    ├── go
11
    ├── go-armhf
12
    ├── java11
13
    ├── java11-vert-x
14
    ├── java8
15
    ├── node
16
    ├── node-arm64
17
    ├── node-armhf
18
    ├── node12
19
    ├── php7
20
    ├── python
21
    ├── python-armhf
22
    ├── python3
23
    ├── python3-armhf
24
    ├── python3-debian
25
    └── ruby
26

          
27
21 directories, 3 files



Things to note:

  • The appfleet-hello-world/handler.js file contains the code of your serverless function. You can use the echo command to list the contents of this file:
Shell
 




xxxxxxxxxx
1


 
1
cat appfleet-hello-world/handler.js


JavaScript
 




xxxxxxxxxx
1


 
1
"use strict"
2

          
3
module.exports = async (context, callback) => {
4
    return {status: "done"}
5
}



  • You can specify the dependencies required by your serverless function in the package.json file. The automatically generated file is just an empty shell:
Shell
 




xxxxxxxxxx
1


 
1
cat appfleet-hello-world/package.json



JSON
 




xxxxxxxxxx
1
12


 
1
{
2
  "name": "function",
3
  "version": "1.0.0",
4
  "description": "",
5
  "main": "handler.js",
6
  "scripts": {
7
    "test": "echo \"Error: no test specified\" && exit 1"
8
  },
9
  "keywords": [],
10
  "author": "",
11
  "license": "ISC"
12
}


  • The spec of the appfleet-hello-world function is stored in the appfleet-hello-world.yml file:
Shell
 




xxxxxxxxxx
1


 
1
cat appfleet-hello-world.yml



Shell
 




xxxxxxxxxx
1


 
1
version: 1.0
2
provider:
3
  name: openfaas
4
  gateway: http://127.0.0.1:8080
5
functions:
6
  appfleet-hello-world:
7
    lang: node
8
    handler: ./appfleet-hello-world
9
    image: appfleet-hello-world:latest



Build Your Serverless Function

  1. Open the appfleet-hello-world.yml file in a plain-text editor, and update the image field by prepending your Docker Hub user name to it. The following example prepends my username (andrepopescu12) to the image field:
Shell
 




xxxxxxxxxx
1


 
1
image: andrepopescu12/appfleet-hello-world:latest



Once you've made this change, the appfleet-hello-world.yml file should look similar to the following: 

Shell
 




xxxxxxxxxx
1


 
1
version: 1.0
2
provider:
3
  name: openfaas
4
  gateway: http://127.0.0.1:8080
5
functions:
6
  appfleet-hello-world:
7
    lang: node
8
    handler: ./appfleet-hello-world
9
    image: <YOUR-DOCKER-HUB-ACCOUNT>/appfleet-hello-world:latest


2. Build the function. Enter the faas-cli build command specifying the -f argument with the name of the YAML file you edited in the previous step (appfleet-hello-world.yml): 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli build -f appfleet-hello-world.yml



Shell
 




xxxxxxxxxx
1
82


 
1
[0] > Building appfleet-hello-world.
2
Clearing temporary build folder: ./build/appfleet-hello-world/
3
Preparing: ./appfleet-hello-world/ build/appfleet-hello-world/function
4
Building: andreipopescu12/appfleet-hello-world:latest with node template. Please wait..
5
Sending build context to Docker daemon  10.24kB
6
Step 1/24 : FROM openfaas/classic-watchdog:0.18.1 as watchdog
7
 ---> 94b5e0bef891
8
Step 2/24 : FROM node:12.13.0-alpine as ship
9
 ---> 69c8cc9212ec
10
Step 3/24 : COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog
11
 ---> Using cache
12
 ---> ebab4b723c16
13
Step 4/24 : RUN chmod +x /usr/bin/fwatchdog
14
 ---> Using cache
15
 ---> 7952724b5872
16
Step 5/24 : RUN addgroup -S app && adduser app -S -G app
17
 ---> Using cache
18
 ---> 33c7f04595d2
19
Step 6/24 : WORKDIR /root/
20
 ---> Using cache
21
 ---> 77b9dee16c79
22
Step 7/24 : ENV NPM_CONFIG_LOGLEVEL warn
23
 ---> Using cache
24
 ---> a3d3c0bb4480
25
Step 8/24 : RUN mkdir -p /home/app
26
 ---> Using cache
27
 ---> 65457e03fcb1
28
Step 9/24 : WORKDIR /home/app
29
 ---> Using cache
30
 ---> 50ab672e5660
31
Step 10/24 : COPY package.json ./
32
 ---> Using cache
33
 ---> 6143e79de873
34
Step 11/24 : RUN npm i --production
35
 ---> Using cache
36
 ---> a41566487c6e
37
Step 12/24 : COPY index.js ./
38
 ---> Using cache
39
 ---> 566633e78d2c
40
Step 13/24 : WORKDIR /home/app/function
41
 ---> Using cache
42
 ---> 04c9de75f170
43
Step 14/24 : COPY function/*.json ./
44
 ---> Using cache
45
 ---> 85cf909b646a
46
Step 15/24 : RUN npm i --production || :
47
 ---> Using cache
48
 ---> c088cbcad583
49
Step 16/24 : COPY --chown=app:app function/ .
50
 ---> Using cache
51
 ---> 192db89e5941
52
Step 17/24 : WORKDIR /home/app/
53
 ---> Using cache
54
 ---> ee2b7d7e8bd4
55
Step 18/24 : RUN chmod +rx -R ./function     && chown app:app -R /home/app     && chmod 777 /tmp
56
 ---> Using cache
57
 ---> 81831389293e
58
Step 19/24 : USER app
59
 ---> Using cache
60
 ---> ca0cade453f5
61
Step 20/24 : ENV cgi_headers="true"
62
 ---> Using cache
63
 ---> afe8d7413349
64
Step 21/24 : ENV fprocess="node index.js"
65
 ---> Using cache
66
 ---> 5471cfe85461
67
Step 22/24 : EXPOSE 8080
68
 ---> Using cache
69
 ---> caaa8ae11dc7
70
Step 23/24 : HEALTHCHECK --interval=3s CMD [ -e /tmp/.lock ] || exit 1
71
 ---> Using cache
72
 ---> 881b4d2adb92
73
Step 24/24 : CMD ["fwatchdog"]
74
 ---> Using cache
75
 ---> 82b586f039df
76
Successfully built 82b586f039df
77
Successfully tagged andreipopescu12/appfleet-hello-world:latest
78
Image: andreipopescu12/appfleet-hello-world:latest built.
79
[0] < Building appfleet-hello-world done in 2.25s.
80
[0] Worker done.
81

          
82
Total build time: 2.25s


3. You can list your Docker images with: 

Shell
 




xxxxxxxxxx
1


 
1
docker images



Shell
 




xxxxxxxxxx
1


 
1
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
2
andreipopescu12/appfleet-hello-world   latest              82b586f039df        25 minutes ago      96MB



Push Your Image to Docker Hub

  1. Log in to Docker Hub. Run the docker login command with the --username flag followed by your Docker Hub user name. The following example command logs you in as andreipopescu12:
Shell
 




xxxxxxxxxx
1


 
1
docker login --username andreipopescu12



Next, you will be prompted to enter your Docker Hub password:

Shell
 




xxxxxxxxxx
1


 
1
Password:
2
Login Succeeded


2. Use the faas-cli push command to push your serverless function to Docker Hub: 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli push -f appfleet-hello-world.yml


Shell
 




xxxxxxxxxx
1
18


 
1
The push refers to repository [docker.io/andreipopescu12/appfleet-hello-world]
2
073c41b18852: Pushed
3
a5c05e98c215: Pushed
4
f749ad113dce: Pushed
5
e4f29400b370: Pushed
6
b7d0eb42e645: Pushed
7
84fba0eb2756: Pushed
8
cf2a3f2bc398: Pushed
9
942d3272b7d4: Pushed
10
037b653b7d4e: Pushed
11
966655dc62be: Pushed
12
08d8e0925a73: Pushed
13
6ce16b164ed0: Pushed
14
d76ecd300100: Pushed
15
77cae8ab23bf: Pushed
16
latest: digest: sha256:4150d4cf32e7e5ffc8fd15efeed16179bbf166536f1cc7a8c4105d01a4042928 size: 3447
17
[0] < Pushing appfleet-hello-world [andreipopescu12/appfleet-hello-world:latest] done.
18
[0] Worker done.



Deploy Your Function Using the CLI

  1. With your serverless function pushed to Docker Hub, log in to your local instance of the OpenFaaS gateway by entering the following command:
Shell
 




xxxxxxxxxx
1


 
1
echo -n $PASSWORD | faas-cli login --username admin --password-stdin



2. Run the faas-cli deploy command to deploy your serverless function: 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli deploy -f appfleet-hello-world.yml


Shell
 




xxxxxxxxxx
1


 
1
Deploying: appfleet-hello-world.
2
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.
3
Handling connection for 8080
4
Handling connection for 8080
5

          
6
Deployed. 202 Accepted.
7
URL: http://127.0.0.1:8080/function/appfleet-hello-world



☞ OpenFaaS provides an auto-scaling mechanism based on the number of requests per second, which is read from Prometheus. For the sake of simplicity, we won't cover auto-scaling in this tutorial. To further your knowledge, you can refer the Auto-scaling page.

  1. Use the faas-cli list command to list the functions deployed to your local OpenFaaS gateway:
Shell
 




xxxxxxxxxx
1


 
1
faas-cli list


Shell
 




xxxxxxxxxx
1


 
1
Function                        Invocations     Replicas
2
appfleet-hello-world            0               1



☞ Note that you can also list the functions deployed to a different gateway by providing the URL of the gateway as follows:

Shell
 




xxxxxxxxxx
1


 
1
faas-cli list --gateway https://<YOUR-GATEWAT-URL>:<YOUR-GATEWAY-PORT>


4. You can use the faas-cli describe method to retrieve more details about the appfleet-hello-world function: 

Shell
 




xxxxxxxxxx
1


 
1
faas-cli describe appfleet-hello-world


Shell
 




xxxxxxxxxx
1
11


 
1
Name:                appfleet-hello-world
2
Status:              Ready
3
Replicas:            1
4
Available replicas:  1
5
Invocations:         1
6
Image:               andreipopescu12/appfleet-hello-world:latest
7
Function process:    node index.js
8
URL:                 http://127.0.0.1:8080/function/appfleet-hello-world
9
Async URL:           http://127.0.0.1:8080/async-function/appfleet-hello-world
10
Labels:              faas_function : appfleet-hello-world
11
Annotations:         prometheus.io.scrape : false



Invoke Your Serverless Function Using the CLI

  1. To see your serverless function in action, issue the faas-cli invoke command, specifying:
  • The -f flag with the name of the YAML file that describes your function (appfleet-hello-world.yml)
  • The name of your function (appfleet-hello-world)
Shell
 




xxxxxxxxxx
1


 
1
faas-cli invoke -f appfleet-hello-world.yml appfleet-hello-world



Shell
 




xxxxxxxxxx
1


 
1
Reading from STDIN - hit (Control + D) to stop.



2. Type CTRL+D. The following example output shows that your serverless function works as expected: 

Shell
 




xxxxxxxxxx
1


 
1
appfleet
2
Handling connection for 8080
3
{"status":"done"}


Update Your Function

The function you created, deployed, and then invoked in the previous sections is just an empty shell. In this section, we'll update it to:

  • Read the name of a city from stdin
  • Fetch the weather forecast from the openweathermap.org
  • Print to the console the weather forecast
  1. Create an OpenWeatherMap account by following the instructions from the Sign Up page.
  2. Log in to OpenWeatherMap and then select API KEYS:

  1. From here, you can either copy the value of the default key or create a new API key, and then copy its value:

  1. Now that you have an OpenWeatherMap API key, you must use npm to install a few dependencies. The following command moves into the appfleet-hello-world directory and then installs the get-stdin and request packages:
Shell
 




xxxxxxxxxx
1


 
1
cd appfleet-hello-world && npm i --save get-stdin request



5. Replace the content of the handler.js file with: 

JavaScript
 




xxxxxxxxxx
1
19


 
1
"use strict"
2
const getStdin = require('get-stdin')
3
const request = require('request');
4

          
5
let handler = (req) => {
6
  request(`http://api.openweathermap.org/data/2.5/weather?q=${req}&?units=metric&APPID=<YOUR-OPENWEATHERMAP-APP-KEY>`, function (error, response, body) {
7
    console.error('error:', error)
8
    console.log('statusCode:', response && response.statusCode)
9
    console.log('body:', JSON.stringify(body))
10
  })
11
};
12

          
13
getStdin().then(val => {
14
   handler(val);
15
}).catch(e => {
16
  console.error(e.stack);
17
});
18

          
19
module.exports = handler



☞ To try this function, replace <YOUR-OPENWEATHERMAP-API-KEY> with your OpenWeatherMap API KEY.

  1. You can use the faas-cli remove command to remove the function you've deployed earlier in this tutorial:
Shell
 




xxxxxxxxxx
1


 
1
faas-cli remove appfleet-hello-world


Shell
 




xxxxxxxxxx
1


 
1
Deleting: appfleet-hello-world.
2
Handling connection for 8080
3
Removing old function.


7. Now that the old function has been removed, you must rebuild, push, and deploy your modified function. Instead of issuing three separate commands, you can use the openfaas-cli up command as in the following example: 

Shell
xxxxxxxxxx
1
 
1
faas-cli up -f appfleet-hello-world.yml


Shell
xxxxxxxxxx
1
117
 
1
[0] > Building appfleet-hello-world.
2
Clearing temporary build folder: ./build/appfleet-hello-world/
3
Preparing: ./appfleet-hello-world/ build/appfleet-hello-world/function
4
Building: andreipopescu12/appfleet-hello-world:latest with node template. Please wait..
5
Sending build context to Docker daemon  43.01kB
6
Step 1/24 : FROM openfaas/classic-watchdog:0.18.1 as watchdog
7
 ---> 94b5e0bef891
8
Step 2/24 : FROM node:12.13.0-alpine as ship
9
 ---> 69c8cc9212ec
10
Step 3/24 : COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog
11
 ---> Using cache
12
 ---> ebab4b723c16
13
Step 4/24 : RUN chmod +x /usr/bin/fwatchdog
14
 ---> Using cache
15
 ---> 7952724b5872
16
Step 5/24 : RUN addgroup -S app && adduser app -S -G app
17
 ---> Using cache
18
 ---> 33c7f04595d2
19
Step 6/24 : WORKDIR /root/
20
 ---> Using cache
21
 ---> 77b9dee16c79
22
Step 7/24 : ENV NPM_CONFIG_LOGLEVEL warn
23
 ---> Using cache
24
 ---> a3d3c0bb4480
25
Step 8/24 : RUN mkdir -p /home/app
26
 ---> Using cache
27
 ---> 65457e03fcb1
28
Step 9/24 : WORKDIR /home/app
29
 ---> Using cache
30
 ---> 50ab672e5660
31
Step 10/24 : COPY package.json ./
32
 ---> Using cache
33
 ---> 6143e79de873
34
Step 11/24 : RUN npm i --production
35
 ---> Using cache
36
 ---> a41566487c6e
37
Step 12/24 : COPY index.js ./
38
 ---> Using cache
39
 ---> 566633e78d2c
40
Step 13/24 : WORKDIR /home/app/function
41
 ---> Using cache
42
 ---> 04c9de75f170
43
Step 14/24 : COPY function/*.json ./
44
 ---> Using cache
45
 ---> f5765914bd05
46
Step 15/24 : RUN npm i --production || :
47
 ---> Using cache
48
 ---> a300be28c096
49
Step 16/24 : COPY --chown=app:app function/ .
50
 ---> 91cd72d8ad7a
51
Step 17/24 : WORKDIR /home/app/
52
 ---> Running in fce50a76475a
53
Removing intermediate container fce50a76475a
54
 ---> 0ff17b0a9faf
55
Step 18/24 : RUN chmod +rx -R ./function     && chown app:app -R /home/app     && chmod 777 /tmp
56
 ---> Running in 6d0c4c92fac1
57
Removing intermediate container 6d0c4c92fac1
58
 ---> 1e543bfbf6b0
59
Step 19/24 : USER app
60
 ---> Running in 6d33f5ec237d
61
Removing intermediate container 6d33f5ec237d
62
 ---> cb7cf5dfab12
63
Step 20/24 : ENV cgi_headers="true"
64
 ---> Running in 972c23374934
65
Removing intermediate container 972c23374934
66
 ---> 21c6e8198b21
67
Step 21/24 : ENV fprocess="node index.js"
68
 ---> Running in 3be91f9d5228
69
Removing intermediate container 3be91f9d5228
70
 ---> aafb7a756d38
71
Step 22/24 : EXPOSE 8080
72
 ---> Running in da3183bd88c5
73
Removing intermediate container da3183bd88c5
74
 ---> 5f6fd7e66a95
75
Step 23/24 : HEALTHCHECK --interval=3s CMD [ -e /tmp/.lock ] || exit 1
76
 ---> Running in a590c91037ae
77
Removing intermediate container a590c91037ae
78
 ---> fbe20c32941f
79
Step 24/24 : CMD ["fwatchdog"]
80
 ---> Running in 59cd231f0576
81
Removing intermediate container 59cd231f0576
82
 ---> 88cd8ac65ade
83
Successfully built 88cd8ac65ade
84
Successfully tagged andreipopescu12/appfleet-hello-world:latest
85
Image: andreipopescu12/appfleet-hello-world:latest built.
86
[0] < Building appfleet-hello-world done in 13.95s.
87
[0] Worker done.
88
89
Total build time: 13.95s
90
91
[0] > Pushing appfleet-hello-world [andreipopescu12/appfleet-hello-world:latest].
92
The push refers to repository [docker.io/andreipopescu12/appfleet-hello-world]
93
04643e0c999f: Pushed
94
db3ccc4403b8: Pushed
95
24d1d5a62262: Layer already exists
96
adfa28db7666: Layer already exists
97
b7d0eb42e645: Layer already exists
98
84fba0eb2756: Layer already exists
99
cf2a3f2bc398: Layer already exists
100
942d3272b7d4: Layer already exists
101
037b653b7d4e: Layer already exists
102
966655dc62be: Layer already exists
103
08d8e0925a73: Layer already exists
104
6ce16b164ed0: Layer already exists
105
d76ecd300100: Layer already exists
106
77cae8ab23bf: Layer already exists
107
latest: digest: sha256:818d92b10d276d32bcc459e2918cb537051a14025e694eb59a9b3caa0bb4e41c size: 3456
108
[0] < Pushing appfleet-hello-world [andreipopescu12/appfleet-hello-world:latest] done.
109
[0] Worker done.
110
111
Deploying: appfleet-hello-world.
112
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.
113
Handling connection for 8080
114
Handling connection for 8080
115
116
Deployed. 202 Accepted.
117
URL: http://127.0.0.1:8080/function/appfleet-hello-world


☞ Note that you can skip the push or the deploy steps:

  • The following example command skips the push step:
Shell
xxxxxxxxxx
1
 
1
faas-cli up -f appfleet-hello-world.yml --skip-push


  • The following example command skips the deploy step:
Shell
xxxxxxxxxx
1
 
1
faas-cli up -f appfleet-hello-world.yml --skip-deploy

8. To verify that the updated serverless function works as expected, invoke it as follows: 

Shell
xxxxxxxxxx
1
 
1
faas-cli invoke -f appfleet-hello-world.yml appfleet-hello-world


Shell
xxxxxxxxxx
1
 
1
Reading from STDIN - hit (Control + D) to stop.
2
Berlin
3
Handling connection for 8080
4
Hello, you are currently in Berlin
5
statusCode: 200
6
body: "{\"coord\":{\"lon\":13.41,\"lat\":52.52},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"base\":\"stations\",\"main\":{\"temp\":282.25,\"feels_like\":270.84,\"temp_min\":280.93,\"temp_max\":283.15,\"pressure\":1008,\"humidity\":61},\"visibility\":10000,\"wind\":{\"speed\":13.9,\"deg\":260,\"gust\":19},\"clouds\":{\"all\":40},\"dt\":1584107132,\"sys\":{\"type\":1,\"id\":1275,\"country\":\"DE\",\"sunrise\":1584077086,\"sunset\":1584119213},\"timezone\":3600,\"id\":2950159,\"name\":\"Berlin\",\"cod\":200}"

9. To clean-up, run the faas-cli remove command with the name of your serverless function (appfleet-hello-world as an argument): 

Shell
xxxxxxxxxx
1
 
1
faas-cli remove appfleet-hello-world
Shell
xxxxxxxxxx
1
 
1
Deleting: appfleet-hello-world.
2
Handling connection for 8080
3
Removing old function.

Deploy Serverless Functions Using the Web Interface

OpenFaaS provides a web-based user interface. In this section, you'll learn how you can use it to deploy a serverless function.

  1. First, you must use the echo command to retrieve your password:
Shell
xxxxxxxxxx
1
 
1
echo $PASSWORD


Shell
xxxxxxxxxx
1
 
1
49IoP28G8247MZcj6a1FWUYUx


2. Open a browser and visit http://localhost:8080. To log in, use the admin username and the password you retrieved in the previous step. You will be redirected to the OpenFaaS home page. Select the DEPLOY NEW FUNCTION button.

  1. A new window will be displayed. Select the Custom tab, and then type:
  • docker.io/andreipopescu12/appfleet-hello-world in the Docker Image input box
  • appfleet-hello-world in the Function name input box.
  1. Once you've filled in the Docker image and Function name input boxes, select the DEPLOY button:
  1. Your new function will be visible in the left navigation bar. Click on it:

You'll be redirected to the invoke function page:

  1. In the Request body input box, type in the name of the city you want to retrieve the weather forecast for, and then select the INVOKE button:

If everything works well, the weather forecast will be displayed in the Response Body field:

Monitor Your Serverless Functions with Prometheus and Grafana

The OpenFaaS gateway exposes the following metrics:

Retrieved from https://docs.openfaas.com/architecture/metrics/

In this section, you will learn how to set up Prometheus and Grafana to track the health of your serverless functions.

  1. Use the following command to list your deployments:
Shell
xxxxxxxxxx
1
 
1
kubectl get deployments -n openfaas -l "release=openfaas, app=openfaas"
Shell
xxxxxxxxxx
1
 
1
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
2
alertmanager        1/1     1            1           15m
3
basic-auth-plugin   1/1     1            1           15m
4
faas-idler          1/1     1            1           15m
5
gateway             1/1     1            1           15m
6
nats                1/1     1            1           15m
7
prometheus          1/1     1            1           15m
8
queue-worker        1/1     1            1           15m


2. To expose the prometheus deployment, create a service object named prometheus-ui: 

Shell
xxxxxxxxxx
1
 
1
kubectl expose deployment prometheus -n openfaas --type=NodePort --name=prometheus-ui
Shell
xxxxxxxxxx
1
 
1
service/prometheus-ui exposed


☞ The --type=NodePort flag exposes the prometheus-ui service on each of the node's IP addresses. Also, a ClusterIP service is created. You'll use this to connect to the prometheus-ui service from outside of the cluster. 

3. To inspect the prometheus-ui service, enter the following command: 

Shell
xxxxxxxxxx
1
 
1
kubectl get svc prometheus-ui -n openfaas
Shell
xxxxxxxxxx
1
 
1
NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
2
prometheus-ui   NodePort   10.96.129.204   <none>        9090:31369/TCP   8m1s


4. Forward all requests made to http://localhost:9090 to the pod running the prometheus-ui service: 

Shell
xxxxxxxxxx
1
 
1
kubectl port-forward -n openfaas svc/prometheus-ui 9090:9090 &


5. Now, you can point your browser to http://localhost:9090, and you should see a page similar to the following screenshot: 


  1. To deploy Grafana, you'll the stefanprodan/faas-grafana:4.6.3 image. Run the following command:
Shell
xxxxxxxxxx
1
 
1
kubectl run grafana -n openfaas --image=stefanprodan/faas-grafana:4.6.3 --port=3000
Shell
xxxxxxxxxx
1
 
1
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
2
deployment.apps/grafana created


7. Now, you can list your deployments with: 

Shell
xxxxxxxxxx
1
 
1
kubectl get deployments -n openfaas
Shell
xxxxxxxxxx
1
 
1
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
2
alertmanager        1/1     1            1           46m
3
basic-auth-plugin   1/1     1            1           46m
4
faas-idler          1/1     1            1           46m
5
gateway             1/1     1            1           46m
6
grafana             1/1     1            1           107s
7
nats                1/1     1            1           46m
8
prometheus          1/1     1            1           46m
9
queue-worker        1/1     1            1           46m


8. Use the following kubectl expose deployment command to create a service object that exposes the grafana deployment: 

Shell
xxxxxxxxxx
1
 
1
kubectl expose deployment grafana -n openfaas --type=NodePort --name=grafana
Shell
xxxxxxxxxx
1
 
1
service/grafana exposed


9. Retrieve details about your new service with: 

Shell
xxxxxxxxxx
1
 
1
kubectl get service grafana -n openfaas
Shell
xxxxxxxxxx
1
 
1
NAME      TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
2
grafana   NodePort   10.96.194.59   <none>        3000:32464/TCP   60s


10. Forward all requests made to http://localhost:3030 to the pod running the grafana service: 

Shell
xxxxxxxxxx
1
 
1
kubectl port-forward -n openfaas svc/grafana 3000:3000 &
Shell
x
 
1
[3] 3973
2
Forwarding from 127.0.0.1:3000 -> 3000
3
Forwarding from [::1]:3000 -> 3000


11. Now that you set up the port forwarding, you can access Grafana by pointing your browser to http://localhost:3000: 


  1. Log into Grafana using the username admin and password admin. The Home Dashboard page will be displayed:

  1. From the left menu, select Dashboards --> Import:

  1. Type https://grafana.com/grafana/dashboards/3434 in the Grafana.com Dashboard input box. Then, select the Load button:

  1. In the Import Dashboard dialog box, set the Prometheus data source to faas, and then select Import:

An empty dashboard will be displayed:


  1. Now, you can invoke your function a couple of times using the faas-cli invoke command as follows:
Shell
 




xxxxxxxxxx
1


 
1
faas-cli invoke -f appfleet-hello-world.yml appfleet-hello-world



16. Switch back to the browser window that opened Grafana. Your dashboard should be automatically updated and look similar to the following screenshot: 


We hope this tutorial was useful for learning the basics of deploying serverless functions with OpenFaaS. For more great tutorials about Docker and Kubernetes, we recommend you visit our blog.

Thanks for reading!

shell Docker (software) Command (computing) Kubernetes Template Web Service

Published at DZone with permission of Sudip Sengupta. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Create a Kubernetes Cluster With Centos
  • Running SpringBoot Application On OpenShift
  • 13-Step Guide to Performance Testing in Kubernetes
  • Zero to Hero on Kubernetes With Devtron

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!