Yixin Open Source | Hands-on Instruction for Installing the First LAIN Application

Expand reading:Yixin Open Source | Explain the Function and Architecture of LAIN, PaaS Platform

Yixin Open Source | An Example Analysis of Nine Killer Functions of LAIN, PaaS Platform

I. installation of LAIN cluster

This section contains three scenarios for installing LAIN clusters

  • Local startup virtual machine installs LAIN cluster for local test development.
  • Physical Server/Virtual Machine Installation LAIN Cluster
  • Cloud Server Installs LAIN Cluster

All three need to obtain the released LAIN version source code from GitHub:
https://github.com/laincloud/ …

Download the source code and decompress it on the target machine.

tar xf lain-VERSION.tar.gz

1. Locally install LAIN cluster

1) Environmental Dependence

  • Linux / MacOS
  • Ability to connect to the Internet
  • VirtualBox 5.1.22 r115126 (Qt5.6.2)
  • Vagrant 1.9.4
  • Minimum 2G of remaining memory (minimum 3G if multiple nodes need to be pulled)

2) initialization

Start and initialize the first node

cd lain-VERSION
vagrant up --provision

The startup time depends on the download time of vagrant box. vagrant will automatically execute bootstrap to initialize after startup. Initialization takes at least 20 minutes, depending on the network speed. The initialization process configures vip= for the cluster by default

If the following error occurs:

Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

mount -t vboxsf -o uid=1000,gid=1000 vagrant /vagrant

The error output from the command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device

This error is caused by the inconsistency between the Guest Additions of the Virtual Box hosting the host and the installed Guest Additions version of laincoud/centos-lainbox, which makes it impossible to create the synchronization directory /vagrant. Please modify Vagrantfile under the root directory of the project to prohibit the host from forcibly installing the new version of Guest Additions, i.e. add the following configuration:

config.vbguest.auto_update = false

3) Add more nodes

vagrant up node2

# 待 node2 启动后
[vagrant@node1 ~]$ cd /vagrant
[vagrant@node1 ~]$ sudo lainctl node add -p playbooks node2:
# root 密码为 vagrant

4) the same can be addednode3

2. Installation of LAIN Cluster for Physical Server/Virtual Machine

1) Environmental Dependence

  • CentOS 7.2
  • NTP service guarantees consistent time between nodes
  • Access to available yum sources (including epel) is required
  • Ability to connect to the Internet
  • Each node can ssh to each other
  • Hostname of each node is different.
  • Each node is located in the same router

2) initialization

First node

cd lain-VERSION
# 选择一个同网段的未被使用的 IP 地址作为 VIP
sudo ./bootstrap -r docker.io/laincloud --vip={{ vip }}

Domestic users suggest using aliyun’s accelerator to download the image through the -m parameter in the following ways

sudo ./bootstrap -m https://l2ohopf9.mirror.aliyuncs.com \
-r docker.io/laincloud --vip=

Add more nodes

# 需要输入 root 密码
sudo lainctl node add -p playbooks {{ hostname }}:{{ ip }}

3. Install LAIN Cluster for Cloud Server

1) Environmental Dependence

  • CentOS 7.2
  • NTP service guarantees consistent time between nodes
  • Access to available yum sources (including epel) is required
  • Ability to connect to the Internet
  • Each node can ssh to each other
  • Hostname of each node is different.
  • Each node is located within the same VPC (or virtual router)

3) initialization

First node

cd lain-VERSION

# 如果 VPC 不对数据包进行来源 IP 限制(如青云)
sudo ./bootstrap -r docker.io/laincloud

# 如果 VPC 限制了数据包的来源 IP(如阿里云)
sudo ./bootstrap -r docker.io/laincloud --ipip

Add more nodes

# 需要输入 root 密码
sudo lainctl node add -p playbooks {{ hostname }}:{{ ip }}

4. Configure domain name resolution for LAIN Console

The LAIN Console component is the console of the LAIN cluster and can be accessed in the browser after domain name resolution is configured.http://console.lain.local

echo "IP/VIP  console.lain.local" >> /etc/hosts

5. Frequently Asked Questions

Add-nodesh-copy-id failed

If ssh-copy-id fails, you may need tonode1:/root/.ssh/lain.pubContent innode2:/root/.ssh/authorized_keys, add a new line. Of course, the reasons may be various, most likely lain-02/root/.sshThe directory or the file permissions in the directory are incorrect

II. Installation of LAIN Client

When developing LAIN applications, LAIN clients need to be installed. LAIN clients rely on:

  • docker
  • python

LAIN clients, such as Linux and macOS, can be used as long as the system supports docker and python.

The following assume that the domain of LAIN cluster is lain.local. For other domains, replace LAIN.local below.

1. Installing and Configuring docker

1) installation

Please refer tohttps://docs.docker.com/engin …Install doc > = 1.12.

2) Configuration

Insecure Registries

After installation, please refer tohttps://docs.docker.com/regis …willregistry.lain.localAdded to docker daemoninsecure-registriesOptions.

For example, on Linux, the following/etc/docker/daemon.jsonIndicates that willregistry.lain.localJoinedinsecure-registries

  "insecure-registries" : ["registry.lain.local"]

The configuration of insecure registries on macOS is shown in the following figure:

Configurationinsecure-registriesThe reason is that the mirror warehouse of LAIN cluster only provides HTTP service, not HTTPS service.

2. Installation and Configuration of lain-cli

pip install lain-cli

Virtualenv is recommended to install this python package, namely:

pip install virtualenv  # 安装 virtualenv
virtualenv lain  # lain 是虚拟环境的名字,也可以取其他名字
source lain/bin/activate  # 激活 lain 虚拟环境
pip install lain-cli
deactivate  # 退出 lain 虚拟环境

When you need to use lain-cli in the future, usesource ${lain-virtualenv-path}/bin/activateActivate lain virtual environment; When not using lain-cli, usedeactivateExit lain Virtual Environment

After installation, lain-cli needs to be configured to let lain-cli know the Domain and other information of LAIN cluster:

lain config show  # 显示当前配置
lain config save-global private_docker_registry registry.lain.local # 配置 docker 私有仓库
lain config save local domain lain.local  # 保存 lain.local 集群,并取名为 local

If sso authentication is enabled for LAIN cluster (not enabled by default), configure sso:

lain config save local sso_url https://sso.lain.local

3. Configure domain name resolution of LAIN component

If the LAIN cluster cannot be resolved on the public network (such as a locally started cluster), configure /etc/hosts.

If the cluster was started using thevipMode, even if used/vagrant/bootstrap -r docker.io/laincloud --vip=, please execute:

echo "  registry.lain.local console.lain.local entry.lain.local lvault.lain.local ipaddr-client.lain.local ipaddr-service.lain.local ipaddr-client.ipaddr-resource.resource.lain.local" >> /etc/hosts the vip parameter when starting the cluster

If you do not use when starting the clustervipMode, even if used/vagrant/bootstrap -r docker.io/laincloudStart, please execute:

echo "  registry.lain.local console.lain.local entry.lain.local lvault.lain.local ipaddr-client.lain.local ipaddr-service.lain.local ipaddr-client.ipaddr-resource.resource.lain.local" >> /etc/hosts the IP of the master node of the cluster, that is, the IP of the node that started the cluster.

Third, the first LAIN application

This section will demonstrate how to create a LAIN application based on LAIN cluster, which provides HTTP service when users access/When, returnHello, LAIN..

1. Prerequisites

  • First, a LAIN cluster is needed, and it is suggested to be composed of 2 nodes.
  • Secondly, we need a local development environment. For specific steps, see Installing LAIN Client.

LAIN is a PaaS system based on docker. It is suggested to understand the basic concept of docker first:

2. Business Code

package main

import (

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, LAIN."))

    http.ListenAndServe(":8080", nil)

The logic of the code is:

  • Monitor0.0.0.0:8080Port
  • Received/Return when requesting HTTP fromHello, LAIN.


lain.yamlIs the configuration file of LAIN application, as shown in the following example:

appname: hello-world  # 应用名,在集群内唯一,由小写字母、数字和 `-` 组成,且开头不能为数字,不能有连续的 `-`

build:  # 描述如何构建 hello-world:build-${git-committer-date}-${git-commit-hash} 镜像
  base: golang:1.8  # 基础镜像,类似于 Dockerfile 里的 FROM
    - go build -o hello-world  # 编译指令,类似于 Dockerfile 里的 RUN,WORKDIR 为 /lain/app

proc.web:  # 定义一个 proc,名字为 web
  type: web  # proc 类型为 web(LAIN 会为 web 类型的 proc 配置 ${appname}.${LAIN-domain} 的域名,对外提供 HTTP 服务)
  cmd: /lain/app/hello-world  # 因为 WORKDIR 为 /lain/app,所以编译好的程序在 /lain/app 目录下
  port: 8080  # hello-world 监听的端口

Because we need to provide HTTP services, define awebProc of type, LAIN cluster will automatically assign domain name of ${appname}.${LAIN-domain} to proc of web type.

Proc.type isweb, its name must also be web, that is, an app can have only one proc of web type and its name is web.

The complete code for laincoud/hello-world @ basic is here:https://github.com/laincloud/ …

4. Local Operation

[vagrant@lain ~]$ cd ${hello-world-project}  # 进入工程目录

[vagrant@lain hello-world]$ lain build  # 构建 hello-world:build-${git-committer-date}-${git-commit-hash} 镜像,生成编译结果
>>> Building meta and release images ...
>>> found shared prepare image at remote and local, sync ...
>>> generating dockerfile to /Users/bibaijin/Projects/go/src/github.com/laincloud/hello-world/Dockerfile
>>> building image hello-world:build-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 ...
Sending build context to Docker daemon 6.656 kB
Step 1/4 : FROM registry.lain.local/hello-world:prepare-0-1494908044
 ---> 7406706a7f21
Step 2/4 : COPY . /lain/app/
 ---> 45f6215362ad
Removing intermediate container 41e822d3b086
Step 3/4 : WORKDIR /lain/app/
 ---> 75c0f3094b6e
Removing intermediate container 24065cf1d7de
Step 4/4 : RUN ( go build -o hello-world )
 ---> Running in 43cefd489608
 ---> 644f596f83c8
Removing intermediate container 43cefd489608
Successfully built 644f596f83c8
>>> build succeeded: hello-world:build-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> tag hello-world:build-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 as hello-world:release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> generating dockerfile to /Users/bibaijin/Projects/go/src/github.com/laincloud/hello-world/Dockerfile
>>> building image hello-world:meta-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 ...
Sending build context to Docker daemon 6.656 kB
Step 1/2 : FROM scratch
Step 2/2 : COPY lain.yaml /lain.yaml
 ---> cfdb9c518f0d
Removing intermediate container ab94a3603b8a
Successfully built cfdb9c518f0d
>>> build succeeded: hello-world:meta-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> Done lain build.

[vagrant@lain hello-world]$ lain run web  # 在本地运行
>>> run proc hello-world.web.web with image hello-world:release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> container name: hello-world.web.web
>>> port mapping:
>>> 8080/tcp ->
  • All lain-cli commands need to be run in a directory that contains lain.yaml files.
  • Lain-cli depends on the git management version, so git must be installed first and`lain

buildBeforegit commit`

docker ps, you can see:

CONTAINER ID        IMAGE                                                                     COMMAND                  CREATED             STATUS              PORTS                     NAMES
59f7fe4b1a7c        hello-world:release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005   "/lain/app/hello-w..."   27 seconds ago      Up 31 seconds>8080/tcp   hello-world.web.web

The above output indicates that lain mapped port 8080 in the hello-world.web.web container to 32769 of the host through docker, so it can be accessed on the host:

[vagrant@lain hello-world]$ curl http://localhost:32769
Hello, LAIN.

The expected results have been obtained.

5. Deploy to LAIN Cluster

As can be seen from the previous section, there is no problem with local operation and it can now be deployed to LAIN cluster:

[vagrant@lain ~]$ cd ${hello-world-project}  # 进入工程目录

[vagrant@lain hello-world]$ lain build  # 构建 hello-world:build-${git-committer-date}-${git-commit-hash} 镜像,生成编译结果

[vagrant@lain hello-world]$ lain tag local  # 类似于 docker tag,为 hello-world:(meta/release)-${git-committer-date}-${git-commit-hash} 镜像添加仓库前缀
>>> Taging meta and relese image ...
>>> tag hello-world:meta-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 as registry.lain.local/hello-world:meta-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> tag hello-world:release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 as registry.lain.local/hello-world:release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> Done lain tag.

[vagrant@lain hello-world]$ lain push local  # 类似于 docker push,将镜像推送到 LAIN 集群
>>> Pushing meta and release images ...
>>> pushing image registry.lain.local/hello-world:meta-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 ...
The push refers to a repository [registry.lain.local/hello-world]
1a4886bd9611: Layer already exists
meta-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005: digest: sha256:daed70190af5fa980d6963fd3a6350591708c1568e180fe85e7eb6cfdd12d998 size: 524
>>> pushing image registry.lain.local/hello-world:release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005 ...
The push refers to a repository [registry.lain.local/hello-world]
1a2245680fe1: Layer already exists
dfe083dd50ba: Layer already exists
edac683c8e67: Layer already exists
0372f18510d4: Layer already exists
c0b53d6ac422: Layer already exists
bcf20a0a17f3: Layer already exists
9d039e60afe3: Layer already exists
a172d29265f3: Layer already exists
e6562eb04a92: Layer already exists
596280599f68: Layer already exists
5d6cbe0dbcf9: Layer already exists
release-1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005: digest: sha256:1cea69b6ed882fcc16f1f5661b3830a8b3f20263264c51d0610b8ec09e72a439 size: 2626
>>> Done lain push.

[vagrant@lain hello-world]$ lain deploy local  # 将应用部署到 LAIN 集群
>>> Begin deploy app hello-world to local ...
upgrading... Done.
>>> app hello-world deploy operation:
>>>     last version: 1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>>     this version: 1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
>>> if shit happened, rollback your app by:
>>>     lain deploy -v 1496631978-a46ef7afcbbc18c1c1248bcbb84fa770d0758005
  • Local is the name of LAIN cluster, please refer to the settings in Installing LAIN Client
  • lain tagAdd a warehouse prefix to the mirror before proceedinglain push
  • releaseMirrors contain compilation results and will be used to run containers in the future.
  • metaMirror includeslain.yamlFile, used for LAIN cluster analysis, users do not need to care about
  • The deployment process is an asynchronous process, which is implemented inlain deploy localCan be used laterlain ps localQuery deployment results.

At this point, you can access through the following commandhello-world

[vagrant@lain hello-world]$ curl -H "Host: hello-world.lain.local"
Hello, LAIN.

Or you can change it first./etc/hostsFile, and then directly use the domain name to access:

[vagrant@lain hello-world]$ echo " hello-world.lain.local" >> /etc/hosts
[vagrant@lain hello-world]$ curl http://hello-world.lain.local
Hello, LAIN.

Above192.168.77.201It is the virtual IP of the local LAIN cluster and does not usevipMethod to start, please use192.168.77.21

GotHello, LAIN.The response was in line with our expectations.

GitHub addresshttps://github.com/laincloud

White paperhttps://laincloud.gitbooks.io …