avatarAlex Ellis

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

6112

Abstract

ions on how to get started, follow each step:</p><div id="585f"><pre><span class="hljs-comment"># Forward the gateway to your machine</span> <span class="hljs-attribute">kubectl</span> rollout status -n openfaas deploy/gateway <span class="hljs-attribute">kubectl</span> port-forward -n openfaas svc/gateway <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span> &</pre></div><div id="e0dc"><pre><span class="hljs-comment"># Now log in using the CLI</span> <span class="hljs-attribute">PASSWORD</span>=(kubectl <span class="hljs-built_in">get</span><span class="hljs-built_in"> secret </span>-n openfaas basic-auth -o <span class="hljs-attribute">jsonpath</span>=<span class="hljs-string">"{.data.basic-auth-password}"</span> | base64 --decode; echo) echo -n <span class="hljs-variable">PASSWORD</span> | faas-cli login --username admin --password-stdin</pre></div><p id="ca53">Check that the CLI is authenticated by deploying a sample function from the store:</p><div id="3a2b"><pre>faas-<span class="hljs-keyword">cli</span> store deploy nodeinfo</pre></div><div id="9553"><pre># Check to see <span class="hljs-string">"Ready"</span> <span class="hljs-built_in">status</span> faas-cli <span class="hljs-built_in">describe</span> nodeinfo</pre></div><div id="e64c"><pre><span class="hljs-comment"># Invoke</span> echo | faas-cli<span class="hljs-built_in"> invoke </span>nodeinfo echo | faas-cli<span class="hljs-built_in"> invoke </span>nodeinfo --async</pre></div><div id="03b0"><pre><span class="hljs-comment"># You should see two invocations</span> <span class="hljs-attribute">faas</span>-cli list <span class="hljs-attribute">Function</span> Invocations Replicas <span class="hljs-attribute">nodeinfo</span> <span class="hljs-number">2</span> <span class="hljs-number">1</span></pre></div><p id="4aaa">You can open the OpenFaaS UI dashboard too at <a href="http://localhost:8080,">http://localhost:8080,</a> the username is “admin”.</p><div id="1cf8"><pre><span class="hljs-comment"># Get the password so you can open the UI</span> <span class="hljs-built_in">echo</span> <span class="hljs-variable">$PASSWORD</span></pre></div><figure id="17df"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*luFkwMzN401UAENAL6Q_IA.png"><figcaption>OpenFaaS UI portal</figcaption></figure><h2 id="c2af">Build a new Python function</h2><p id="815a">You can build a new function using the python3 template, or search for others using the Template Store (<code>faas-cli template store list</code>).</p><p id="f4e3">OpenFaaS is a cloud native Serverless platform which means it uses a Docker image for each build of your function. That means it works natively with Kubernetes.</p><p id="dbea">Sign up for a <a href="https://hub.docker.com/">Docker Hub account</a>, so that you can store your functions for free.</p><div id="660a"><pre><span class="hljs-built_in">export</span> <span class="hljs-attribute">OPENFAAS_PREFIX</span>=<span class="hljs-string">"DOCKER_HUB_USERNAME"</span></pre></div><div id="4b74"><pre>faas-cli <span class="hljs-keyword">new</span> <span class="hljs-comment">--lang python3 serverless</span></pre></div><p id="9fac">Now you’ll see three important files:</p><div id="92e9"><pre>├── serverless │ ├── init<span class="hljs-selector-class">.py</span> │ ├── handler<span class="hljs-selector-class">.py</span> │ └── requirements<span class="hljs-selector-class">.txt</span> └── serverless.yml</pre></div><p id="c862">The YAML file contains info about your function, how to build and deploy it. The serverless folder contains your function’s handler and a requirements.txt file which can be used to set up pip modules that you need.</p><p id="b4e0">Let’s edit the handler.py file:</p><div id="4979"><pre><span class="hljs-keyword">def</span> <span class="hljs-title function_">handle</span>(<span class="hljs-params">req</span>): <span class="hljs-keyword">return</span> <span class="hljs-string">"serverless"</span></pre></div><h2 id="9539">Deploy your function</h2><p id="0c5d">To deploy your function simply run:</p><div id="e1bd"><pre>faas-<span class="hljs-keyword">cli</span> <span class="hljs-meta">up</span> -f serverless<span class="hljs-number">.</span>yml</pre></div><p id="799d">In a few moments you’ll receive your URL, and can then invoke the function or check its status on the OpenFaaS UI / CLI:</p><div id="3613"><pre>faas-<span class="hljs-keyword">cli</span> <span class="hljs-keyword">describe</span> -f serverless.yml serverless</pre></div><div id="2230"><pre><span class="hljs-attribute">Name</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> serverless</span> <span class="hljs-attribute">Status</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> Ready</span> <span class="hljs-attribute">Replicas</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> 1</span> <span class="hljs-attribute">Available replicas</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> 1</span> <span class="hljs-attribute">Invocations</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> 10</span> <span class="hljs-attribute">Image</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> alexellis2/serverless:latest</span> <span class="hljs-attribute">Function process</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> python3 index.py</span> <span class="hljs-attribute">URL</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> http://127.0.0.1:8080/function/serverless</span> <span class="hljs-attribute">Async URL</span><span class="hljs-punctuation">:</span> <span class="hljs-string"> http://127.0.0.1:8080/async-function/serverless</span></pre></div><p id="30d7">Try to invoke the function:</p><div id="13c5"><pre>echo | faas-cli<span class="hljs-built_in"> invoke </span>serverless</pre></div><div id="302b"><pre><span class

Options

="hljs-attribute">serverless</span></pre></div><h2 id="0794">Consume an environment variable</h2><p id="59be">Environment variables are useful for non-confidential configuration and are set in the YAML file.</p><div id="a37c"><pre><span class="hljs-symbol">functions:</span> <span class="hljs-symbol"> serverless:</span> <span class="hljs-symbol"> lang:</span> python3 <span class="hljs-symbol"> handler:</span> ./serverless <span class="hljs-symbol"> image:</span> alexellis2/serverless:latest <span class="hljs-symbol"> environment:</span> <span class="hljs-symbol"> MESSAGE:</span> kubernetes</pre></div><p id="1d91">Let’s edit the handler.py file:</p><div id="bfba"><pre>import <span class="hljs-built_in">os</span> def handle(req): <span class="hljs-keyword">return</span> <span class="hljs-string">"serverless "</span> + <span class="hljs-built_in">os</span>.<span class="hljs-built_in">getenv</span>(<span class="hljs-string">"MESSAGE"</span>)</pre></div><p id="0019">Deploy the function again and invoke it, you should see “serverless kubernetes”</p><h2 id="5413">Consume a secret</h2><p id="8238">You should use secrets for things like API tokens and callback URLs.</p><div id="37f8"><pre><span class="hljs-built_in">export</span> <span class="hljs-attribute">SECRET</span>=<span class="hljs-string">"secure"</span></pre></div><div id="6352"><pre>faas-cli secret <span class="hljs-built_in">create</span> api-<span class="hljs-keyword">token</span> <span class="hljs-comment">--from-literal $SECRET</span></pre></div><p id="77ba">Now to consume the secret, add it to your YAML file:</p><div id="5a51"><pre><span class="hljs-attribute">functions</span><span class="hljs-punctuation">:</span> <span class="hljs-attribute">serverless</span><span class="hljs-punctuation">:</span> <span class="hljs-attribute">lang</span><span class="hljs-punctuation">:</span> <span class="hljs-string">python3</span> <span class="hljs-attribute">handler</span><span class="hljs-punctuation">:</span> <span class="hljs-string">./serverless</span> <span class="hljs-attribute">image</span><span class="hljs-punctuation">:</span> <span class="hljs-string">alexellis2/serverless:latest</span> <span class="hljs-attribute">environment</span><span class="hljs-punctuation">:</span> <span class="hljs-attribute">MESSAGE</span><span class="hljs-punctuation">:</span> <span class="hljs-string">kubernetes</span> <span class="hljs-attribute">secrets</span><span class="hljs-punctuation">:</span> <span class="hljs-bullet">-</span> <span class="hljs-string">api-token</span></pre></div><p id="9a87">Edit the handler and read the secret from <code>/var/openfaas/secrets/</code></p><div id="37c9"><pre><span class="hljs-keyword">import</span> os</pre></div><div id="d26d"><pre>def read_secret(name)<span class="hljs-operator">:</span> <span class="hljs-keyword">val</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span> <span class="hljs-keyword">with</span> <span class="hljs-keyword">open</span>(<span class="hljs-string">"/var/openfaas/secrets/api-token"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> f<span class="hljs-operator">:</span>
<span class="hljs-keyword">val</span> <span class="hljs-operator">=</span> f.read() <span class="hljs-keyword">return</span> <span class="hljs-keyword">val</span></pre></div><div id="9f1e"><pre>def <span class="hljs-built_in">handle</span>(req): if req.<span class="hljs-built_in">strip</span>() == <span class="hljs-built_in">read_secret</span>(<span class="hljs-string">"api-token"</span>).<span class="hljs-built_in">strip</span>(): return <span class="hljs-string">"authenticated"</span> return <span class="hljs-string">"invalid api-token"</span></pre></div><p id="41e5">Let’s try it?</p><div id="c22d"><pre>faas-<span class="hljs-keyword">cli</span> <span class="hljs-meta">up</span> -f serverless<span class="hljs-number">.</span>yml</pre></div><div id="cfc8"><pre>curl -d <span class="hljs-string">"hi"</span> <span class="hljs-keyword">http</span>://<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>:<span class="hljs-number">8080</span>/<span class="hljs-function"><span class="hljs-keyword">function</span>/<span class="hljs-title">serverless</span></span> invalid api-<span class="hljs-keyword">token</span></pre></div><div id="c733"><pre>curl -d <span class="hljs-string">"secure"</span> http:<span class="hljs-regexp">//</span><span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>:<span class="hljs-number">8080</span><span class="hljs-regexp">/function/</span>serverless authenticated</pre></div><div id="b4db"><pre>echo -n <span class="hljs-string">"secure"</span> | faas-cli<span class="hljs-built_in"> invoke </span>serverless authenticated</pre></div><h2 id="9fcf">Over to you</h2><p id="1e20">We’ve deployed Kubernetes to our laptop using a lightweight option, ideal for local development. We then went on to deploy a popular serverless platform for Kubernetes and built out a function in Python3 to consume both configuration and confidential secrets.</p><figure id="5695"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*UD7BLmO3p0Apn1wrSKv58Q.png"><figcaption>OpenFaaS — Serverless Functions Made Simple</figcaption></figure><blockquote id="7f76"><p>You can deploy functions and microservices to <a href="https://www.openfaas.com/">OpenFaaS</a> using any programming language, binary, or even a custom Dockerfile.</p></blockquote><p id="b072">If you’d like to learn more, try the <a href="https://github.com/openfaas/workshop/">OpenFaaS workshop</a> where you’ll learn how to put all of this together to scale and monitor your code.</p><ul><li>Join <a href="https://slack.openfaas.io/">us on Slack</a></li><li><a href="https://www.openfaas.com/blog/birthday-teamserverless/">OpenFaaS 3rd Birthday Celebrations</a></li><li>Follow <a href="https://twitter.com/openfaas">OpenFaaS on Twitter</a></li></ul></article></body>

Deploy your first Serverless Function to Kubernetes

In this tutorial I want to show you how to deploy your first Serverless Function to Kubernetes. From there I’ll show you how to access confidential secrets such as API keys and how that differs from using environment variables for configuration. Then it’s over to you, to build something awesome that you can run on any cloud.

Why Kubernetes?

Kubernetes provides a portable way to run containers, and containers we know solve the packaging and deployment problem of “works on my machine” (tm).

All the major cloud players have built their own managed Kubernetes services, meaning that you can have a “serverless” experience where you only deal with what you want to deploy, and nothing else. You can also deploy Kubernetes to bare-metal, your laptop, or to a low-powered Raspberry Pi using k3s from Rancher Labs.

Get Kubernetes on your laptop

If you already have Kubernetes set up, then you can skip this section.

The easiest and fastest way to get Kubernetes on your laptop is by first installing Docker, that then gives us two main options:

KinD — from the Kubernetes community. KinD stands for Kubernetes in Docker and roughly equivalent to installing Kubernetes the vanilla way, however that also means it can be slower, larger and needs more RAM. I should say that KinD is a great option for testing your patches on the Kubernetes codebase.

k3d — from the Rancher community. k3d installs k3s, which is a lightweight version of Kubernetes which passes the CNCF’s suite of compliance tests. With k3d you can start a single-node cluster in about 5 seconds. It’s my tool of choice right now and I wish I had started using it sooner.

Get k3d, and create a cluster (make sure Docker is running first)

curl -s https://raw.githubusercontent.com/rancher/k3d/master/install.sh | bash
k3d create

Now after creating the cluster, you need to tell the Kubernetes CLI to point at that cluster. This is an important step and you can, if not careful, point at the wrong cluster and destroy something important.

export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
kubectl get node
NAME                     STATUS     ROLES    AGE   VERSION
k3d-k3s-default-server   Ready      master   4s    v1.17.2+k3s1

Install a Serverless Platform for Kubernetes

You cannot install a cloud Serverless platform on a Kubernetes cluster, however you can find some emulation tools and local testers. These are not the same thing.

There are several options for installing a serverless platform to Kubernetes, as listed on the CNCF landscape.

OpenFaaS — Serverless Made Simple

Today we’ll use OpenFaaS which aims to be developer-friendly, operationally simple and community-centric. It is also lightweight (can run on a 1GB Raspberry Pi or VPS) and simple to use.

OpenFaaS is used in production by companies using Kubernetes and has a large, active community of open source contributors. You can read more about the project and its users on its homepage and blog.

OpenFaaS can be installed with helm 2 or 3 and has its own installer called arkade that automates everything from downloading helm, to adding the chart path, to configuring the system.

First install the OpenFaaS CLI:

curl -sSLf https://cli.openfaas.com | sudo sh

Now install arkade:

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

Next, use arkade to install OpenFaaS:

arkade install openfaas

You can see install options via --help, such as adding additional replicas of core services or using cloud LoadBalancer.

After the installation you will be given a help message, you can get back this at any time via arkade info openfaas

Log into the API

After the deployment you’ll receive instructions on how to get started, follow each step:

# Forward the gateway to your machine
kubectl rollout status -n openfaas deploy/gateway
kubectl port-forward -n openfaas svc/gateway 8080:8080 &
# Now log in using the CLI
PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

Check that the CLI is authenticated by deploying a sample function from the store:

faas-cli store deploy nodeinfo
# Check to see "Ready" status
faas-cli describe nodeinfo
# Invoke
echo | faas-cli invoke nodeinfo
echo | faas-cli invoke nodeinfo --async
# You should see two invocations
faas-cli list
Function                       Invocations     Replicas
nodeinfo                       2               1

You can open the OpenFaaS UI dashboard too at http://localhost:8080, the username is “admin”.

# Get the password so you can open the UI
echo $PASSWORD
OpenFaaS UI portal

Build a new Python function

You can build a new function using the python3 template, or search for others using the Template Store (faas-cli template store list).

OpenFaaS is a cloud native Serverless platform which means it uses a Docker image for each build of your function. That means it works natively with Kubernetes.

Sign up for a Docker Hub account, so that you can store your functions for free.

export OPENFAAS_PREFIX="DOCKER_HUB_USERNAME"
faas-cli new --lang python3 serverless

Now you’ll see three important files:

├── serverless
│   ├── __init__.py
│   ├── handler.py
│   └── requirements.txt
└── serverless.yml

The YAML file contains info about your function, how to build and deploy it. The serverless folder contains your function’s handler and a requirements.txt file which can be used to set up pip modules that you need.

Let’s edit the handler.py file:

def handle(req):
    return "serverless"

Deploy your function

To deploy your function simply run:

faas-cli up -f serverless.yml

In a few moments you’ll receive your URL, and can then invoke the function or check its status on the OpenFaaS UI / CLI:

faas-cli describe -f serverless.yml serverless
Name:                serverless
Status:              Ready
Replicas:            1
Available replicas:  1
Invocations:         10
Image:               alexellis2/serverless:latest
Function process:    python3 index.py
URL:                 http://127.0.0.1:8080/function/serverless
Async URL:           http://127.0.0.1:8080/async-function/serverless

Try to invoke the function:

echo | faas-cli invoke serverless
serverless

Consume an environment variable

Environment variables are useful for non-confidential configuration and are set in the YAML file.

functions:
  serverless:
    lang: python3
    handler: ./serverless
    image: alexellis2/serverless:latest
    environment:
      MESSAGE: kubernetes

Let’s edit the handler.py file:

import os
def handle(req):
    return "serverless " + os.getenv("MESSAGE")

Deploy the function again and invoke it, you should see “serverless kubernetes”

Consume a secret

You should use secrets for things like API tokens and callback URLs.

export SECRET="secure"
faas-cli secret create api-token --from-literal $SECRET

Now to consume the secret, add it to your YAML file:

functions:
  serverless:
    lang: python3
    handler: ./serverless
    image: alexellis2/serverless:latest
    environment:
      MESSAGE: kubernetes
    secrets:
    - api-token

Edit the handler and read the secret from /var/openfaas/secrets/

import os
def read_secret(name):
    val = ""
    with open("/var/openfaas/secrets/api-token", "r") as f:  
        val = f.read()
    return val
def handle(req):
    if req.strip() == read_secret("api-token").strip():
       return "authenticated"
    return "invalid api-token"

Let’s try it?

faas-cli up -f serverless.yml
curl -d "hi" http://127.0.0.1:8080/function/serverless
invalid api-token
curl -d "secure" http://127.0.0.1:8080/function/serverless
authenticated
echo -n "secure" | faas-cli invoke serverless
authenticated

Over to you

We’ve deployed Kubernetes to our laptop using a lightweight option, ideal for local development. We then went on to deploy a popular serverless platform for Kubernetes and built out a function in Python3 to consume both configuration and confidential secrets.

OpenFaaS — Serverless Functions Made Simple

You can deploy functions and microservices to OpenFaaS using any programming language, binary, or even a custom Dockerfile.

If you’d like to learn more, try the OpenFaaS workshop where you’ll learn how to put all of this together to scale and monitor your code.

Kubernetes
Cloud
Serverless
Python3
Docker
Recommended from ReadMedium