×
Community Blog Installing IronFunctions Serverless Framework on Alibaba Cloud

Installing IronFunctions Serverless Framework on Alibaba Cloud

In this tutorial, you will learn how to install Iron Functions on an Alibaba Cloud ECS instance with Ubuntu 18.04 installed.

By Sai Sarath Chandra, Alibaba Cloud Community Blog author.

IronFunctions is an open-source serverless computing platform that is written in the Go programming Language. IronFunctions was designed for developers to Function as a Service (FaaS), having an infrastructure that allows for easy integration and advance job processing that can significantly reduce task time.

IronFunctions is one of the framework currently used in support of many on-premises deployments in the industry, especially those using AWS Lambda. IronFunctions has the major advantage of allowing people not to be locked in with a certain cloud provider since IronFunctions is open source and can work with any cloud provider. In other words, you can deploy existing AWS format function to other cloud providers, including Alibaba Cloud, if you're using IronFunctions.

In this tutorial, we will discuss how we can install IronFunctions on an Alibaba Cloud Elastic Compute Service (ECS) instance with Ubuntu 18.04. You'll need to create an Alibaba Cloud ECS Instance. Next, you'll also need Docker installed, and you'll have to also install IronFunctions.

Setting up Your ECS Instance

When it comes to creating the ECS instance, there are several basic steps which you should pay attention to:

  • Basic Configurations:

1.Billing method

Make sure you choose Pay-As-You-Go as the billing method if you are prototyping the application

2.Image

You need to select the Ubuntu 18.04 (64-bit)

1

  • Networking

1.Make sure you select the proper security group here. Of course, though, we can open the ports while we are working on this.

  • System Configurations

1.For this tutorial, I chose password-based authentication.

  • Grouping
  • Preview

1.The complete information for the selected configuration that you choose. Note that you can also save it as a template so that in the future when creating an ECS instance you can do so in a single click.

2.If you wish to release the instance at the later point in time, select the Auto-Release schedule option.

Also, make sure that your instance is up and running like the one below:

2

Getting Your ECS Instance All Ready

Now, let's get your ECS instance ready for the later steps of this tutorial. Open your command line interface and let's do some coding. First, let's connect to the instance using SHH, as shown below:

ssh root@<IP ADDRESS>
The authenticity of host 'AAA.CCC.BBB.DDD' can't be established.
ECDSA key fingerprint is SHA256:/il4fRYvgAake/ENoBgJSZvdO8DxY7H99oeIuye8AEo.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ' AAA.CCC.BBB.DDD ' (ECDSA) to the list of known hosts.

root@<IP ADDRESS>'s password: 
Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-23-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

Welcome to Alibaba Cloud Elastic Compute Service !

You can update the package entries by running the following command:

sudo apt-get update

Once that's done, we will upgrade any obsolete packages. Next, we will know what packages are to be updated and removed by running the below command:

sudo apt-get upgrade

You will see a similar message as the one below, where it asks for your consent to upgrade:

The following packages were automatically installed and are no longer required:
  libopts25 sntp
Use 'sudo apt autoremove' to remove them.
The following packages have been kept back:
  linux-generic linux-headers-generic linux-image-generic
The following packages will be upgraded:
  amd64-microcode apparmor apt apt-utils base-files bind9-host binutils binutils-common binutils-x86-64-linux-gnu
  bsdutils chrony console-setup console-setup-linux cpp cpp-7 cups-bsd cups-client cups-common curl
  distro-info-data dnsutils dpkg dpkg-dev fdisk friendly-recovery g++ g++-7 gcc gcc-7 gcc-7-base gcc-8-base
  grub-common grub-pc grub-pc-bin grub2-common guile-2.0-libs initramfs-tools initramfs-tools-bin
  initramfs-tools-core intel-microcode iperf keyboard-configuration kmod language-pack-en language-pack-en-base
  language-pack-gnome-en language-pack-gnome-en-base libapparmor1 libapt-inst2.0 libapt-pkg5.0
  libarchive-zip-perl libarchive13 libasan4 libatomic1 libavahi-client3 libavahi-common-data libavahi-common3
  libbind9-160 libbinutils libblkid1 libcc1-0 libcilkrts5 libcryptsetup12 libcups2 libcupsimage2 libcurl4
  libdns-export1100 libdns1100 libdpkg-perl libfdisk1 libgcc-7-dev libgcc1 libglib2.0-0 libglib2.0-data libgomp1
  libirs160 libisc-export169 libisc169 libisccc160 libisccfg160 libitm1 libjpeg-turbo8 libkmod2 liblsan0
  liblwres160 libmount1 libmpx2 libmysqlclient20 libnss-systemd libpam-systemd libparted2 libperl5.26
  libplymouth4 libpng16-16 libpolkit-gobject-1-0 libpython3-stdlib libpython3.6 libpython3.6-minimal
  libpython3.6-stdlib libquadmath0 librados2 librbd1 libsmartcols1 libstdc++-7-dev libstdc++6 libsystemd0
  libtsan0 libubsan0 libudev1 libuuid1 libx11-6 libx11-data libxml2 linux-libc-dev lshw man-db mount netplan.io
  networkd-dispatcher nplan openssh-client openssh-server openssh-sftp-server parted perl perl-base
  perl-modules-5.26 plymouth plymouth-theme-ubuntu-text python-apt-common python3 python3-apt python3-distupgrade
  python3-minimal python3-requests python3-update-manager python3.6 python3.6-minimal sntp ssh systemd
  systemd-sysv tzdata ubuntu-release-upgrader-core udev update-manager-core util-linux uuid-runtime
148 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
Need to get 79.6 MB of archives.
After this operation, 312 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y

Input Y and also if you wish to remove the unused packages, removal can be done by running the following command

sudo apt autoremove

This command will also give the similar prompt asking for the same thing as above. The upgrade will take some time. There might be some warning while it is installing like the one I gave below.

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
  LANGUAGE = (unset),
  LC_ALL = (unset),
  LC_CTYPE = "UTF-8",
  LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").

One fix to the warning give above is to do the following. You can run the locale command. You will see the following output:

locale
LANGUAGE=
LC_CTYPE=C.UTF-8
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=

From this you can figure out that you need to set the LC_ALL and Language settings by running the following commands:

export LANGUAGE="en_US.UTF-8"
export LC_ALL="en_US.UTF-8"

Before we proceed anything else, we need to point the pip registry to the global site, this can be done by running the following command:

~root@iZa2d4spx9n9e90jofcyxoZ:~# sudo nano /root/.pip/pip.conf

Next, you'll want to replace the output with the below text:

## Note, this file is written by cloud-init on first boot of an instance
## modifications made here will not survive a re-bundle.
###[m
[global]
## index-url=http://ap-south-1.mirrors.cloud.aliyuncs.com/pypi/simple/
index-url=https://pypi.python.org/simple/
[install]
## trusted-host=ap-south-1.mirrors.cloud.aliyuncs.com
trusted-host=pypi.python.org

We need to install all the required tools and other packages using the following command:

sudo apt-get install git python-pip python-setuptools build-essential libssl-dev libffi-dev python-dev software-properties-common

Setting up Docker

Before you install Docker, you will need to first install Ansible. You can do so with the following command:

sudo pip install ansible==2.1.2.0

If the installation is complete, you will get the following message:

Successfully installed ansible-2.1.2.0 bcrypt-3.1.4 cffi-1.11.5 paramiko-2.4.2 pyasn1-0.4.4 pycparser-2.19 pynacl-1.3.0
You are using pip version 10.0.1, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Now we will install Docker. To do so, first the key and the repository:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
OK

Next, enter the following:

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"

Then, update the repository with this command:

~root@iZa2d4spx9n9e90jofcyxoZ:~# sudo apt update

We will set and make sure that the version from the Docker repository is stable. We can also verify that using the Docker command.

~root@iZa2d4spx9n9e90jofcyxoZ:~# apt-cache policy docker-ce

The output will be the following:

docker-ce:
  Installed: (none)
  Candidate: 5:18.09.0~3-0~ubuntu-bionic
  Version table:
     5:18.09.0~3-0~ubuntu-bionic 500
        500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
     18.06.1~ce~3-0~ubuntu 500
        500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
     18.06.0~ce~3-0~ubuntu 500
        500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
     18.03.1~ce~3-0~ubuntu 500
        500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages

We will install Docker by running the install command:

sudo apt install docker-ce

You can verify the installation by running the following command:

sudo systemctl status docker

The output will show that it is in the running status:

docker.service - Docker Application Container Engine[m
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat CST; 4s ago
     Docs: https://docs.docker.com[m
 Main PID: 25119 (dockerd)
    Tasks: 9
   CGroup: /system.slice/docker.service
           └─25119 /usr/bin/dockerd -H unix://

Now, we need to make some changes to the configuration file, edit the config file using the command below:

sudo vi /lib/systemd/system/docker.service

Then, update the "ExecStart" with the line below:

/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

We will reload the docker daemon and restart the docker service:

sudo systemctl daemon-reload
sudo systemctl restart docker.service

After we see the status as running, we can check the other environment details by running the following command:

curl http://localhost:2375/version
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"18.09.0","Details":{"ApiVersion":"1.39","Arch":"amd64","BuildTime":"ABCD","Experimental":"false","GitCommit":"4d60db4","GoVersion":"go1.10.4","KernelVersion":"4.15.0-23-generic","MinAPIVersion":"1.12","Os":"linux"}}],"Version":"18.09.0","ApiVersion":"1.39","MinAPIVersion":"1.12","GitCommit":"4d60db4","GoVersion":"go1.10.4","Os":"linux","Arch":"amd64","KernelVersion":"4.15.0-23-generic","BuildTime":"ABCD"}

Setting up IronFunctions

Now it's about time that you install and configure IronFunctions. Before we install IronFunctions we need to install screen, which will help us to run multiple processes in linux. To install screen run the following command:

apt install screen

Also, login to docker hub by running the following command:

docker login

Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: <your username>
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Then, start a new process "screen":

docker run --rm -it --name functions -v ${PWD}/data:/app/data -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 iron/functions
Unable to find image 'iron/functions:latest' locally
latest: Pulling from iron/functions
+ eval dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 --storage-driver=overlay2
+ dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 --storage-driver=overlay2
can't create unix socket /var/run/docker.sock: device or resource busy
+ echo Docker crashed with exit code 1.  Respawning..
Docker crashed with exit code 1.  Respawning..
+ pidfile=/var/run/docker/libcontainerd/docker-containerd.pid
+ cat /var/run/docker/libcontainerd/docker-containerd.pid
cat: can't open '/var/run/docker/libcontainerd/docker-containerd.pid': No such file or directory
+ kill -9
sh: you need to specify whom to kill
+ exec ./functions
INFO Serving Functions API on address `:8080`     
INFO Halting...

If successful, you will see the cli version as below:

curl -LSs git.io/ironfn | sh
fn version 0.2.72

Now, that that's finished we can go ahead to install IronFunctions. To do so, create a directory and a function:

sudo nano func.go

Then, copy the function definition to the file:

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Person struct {
    Name string
}

func main() {
    p := &Person{Name: "World"}
    json.NewDecoder(os.Stdin).Decode(p)
    fmt.Printf("Hello %v!", p.Name)
}

Run the following commands in the same folder

# create func.yaml file, replace $USERNAME with your Docker Hub username.
fn init <docker username>/hello
# build the function
fn build
# test it - you can pass data into it too by piping it in, eg: `cat hello.payload.json | fn run`
fn run
Hello World!
# Once it's ready, build and push it to Docker Hub
fn build && fn push

Running prebuild command: docker run --rm -v /root/test:/go/src/github.com/x/y -w /go/src/github.com/x/y iron/go:dev go build -o func
Building image saichandu415/hello:0.0.1
Sending build context to Docker daemon  557.1kB
Sending build context to Docker daemon  2.333MB
Step 1/4 : FROM iron/go
 ---> ed7df0451f6c
Step 2/4 : WORKDIR /function
 ---> Using cache
 ---> 9de3968aa402
Step 3/4 : ADD . /function/
 ---> Using cache
 ---> 3136a9e9ae54
Step 4/4 : ENTRYPOINT ["./func"]
 ---> Using cache
 ---> 6235a1829834
Successfully built 6235a1829834
Successfully tagged saichandu415/hello:0.0.1
Function saichandu415/hello:0.0.1 built successfully.
# create an app - you only do this once per app
fn apps create myapp
myapp created
# create a route that maps /hello to your new function
fn routes create myapp /hello
/hello created with saichandu415/hello:0.0.1

You can test the functions here by running the following command:

curl http://localhost:8080/r/myapp/hello
Hello World!

We can also achieve the same result by using the functions UI, which can be installed by running the following command:

docker run --rm -it --link functions:api -p 4000:4000 -e "API_URL=http://api:8080" iron/functions-ui:0.0.2
Unable to find image 'iron/functions-ui:0.0.2' locally
0.0.2: Pulling from iron/functions-ui

> FunctionsUI@0.0.2 start /app
> node server

Using API url: api:8080
Server running on port 4000

We have the function running at port 4000 on the public IP of ECS instance:

3

You can create an app by clicking the Create App button and enter a name and config information if you have it:

4

Once you create the application, we can create a function by choosing Add Route and fill in all the corresponding information.

5

6

You can test the function directly from the IronFunctions UI.

7

8

0 0 0
Share on

Alibaba Clouder

2,110 posts | 487 followers

You may also like

Comments