本节介绍 lain.yaml 如何编写以及 lain-cli 在编译 lain.yaml 时的 image 产物
在 LAIN 中创建一个 app 时,最重要的就是在应用的根目录下定义好一个正确的 lain.yaml。一个完整的 lain.yaml 可以包含以下内容:
appname: {APP_NAME} # 全局唯一的应用名
giturl: {GIT_URL} # 将app绑定到一个具体的远程giturl,防止appname命名冲突,代码版本比较
build: # 描述如何构建应用 build image
base: {BASE_IMAGE} # 一个已存在的 docker image ,包含编译环境和默认的配置
prepare: # 描述如何构建应用 prepare image
version: {PREPARE_VERSION} # prepare 版本号,字符串类型
script: # 定义构建 prepare image 时需要的 script
- {PREPARE_SCRIPT}
script: # 定义构建 build image 时需要的 script
- {BUILD_SCRIPT}
build_arg: # 为 docker build 添加参数
- ARG1=arg1
release: # 描述如何构建应用 release image,可选
dest_base: {DEST_BASE_IMAGE} # release image 基于的 base image
copy: # 定义将哪些内容 copy 到 release 镜像中
- src: {SRC_FILE/SRC_FOLDER}
dest: {DEST_FILE/DEST_FOLDER}
test: # 描述如何构建应用 test image
script: # 定义构建 test image 时需要的 script
- {TEST_SCRIPT}
proc.{PROC_NAME}: # 定义一个 proc, 定义 web 时,可以只用 web 表示 web.web
user: root # 默认为 root,还可以定义一些 release image 中存在的 user,比如 nobody 等
type: worker # 默认为 worker,还包括 web, portal(web 类型的 proc 会由 webrouter 导入 HTTP 流量)
image: {PROC_IMAGE} # 默认为 app image,也可以进行自定义
entrypoint: {PROC_ENTRYPOINT} # 启动 proc 时的入口点,支持类似于 Dockerfile
# 中 ENTRYPOINT 的两种格式:
# - entrypoint: ["executable","param1","param2"] (exec form)
# - entrypoint: command param1 param2 (shell form)
# **注意**:默认值为 []
cmd: {PROC_CMD} # 启动 proc 时定义的命令,支持类似于 Dockerfile 中
# CMD 的三种格式:
# - cmd: ["executable","param1","param2"] (exec form)
# - cmd: ["param1","param2"] (as default parameters to entrypoint)
# - cmd: command param1 param2 (shell form)
# **注意**:cmd 与 entrypoint 两者至少需要定义一个
port: {PROC_PORT} # proc 中服务所监听的端口
ports: # 集群端口与(tcp/udp)应用的映射关系,由于以后可能扩展healthcheck,所以保留map结构,源端口范围:[9500:10000]
9506:8000/tcp: # 源端口:目的端口(不填与源端口一致)/协议类型(默认tcp)
9504: #
labels: # 给容器打标签
- proctype:router
filters: # 容器部署规则过滤
- affinity:proctype!=~router #不与proctype为router的容器部署在同一节点
memory: {PROC_MEMORY} # 容器所用内存,默认为 32M
num_instances: 1 # 部署时 proc 的个数,默认为 1
https_only: true # 针对 web 类型,默认为false, 是否只允许 https 访问
container_healthcheck: # docker1.12.1 or later 容器状态监测,容器滚动升级时等到上一个容器health后才升级下一个
cmd: curl http://localhost/ # required 监测容器状态的命令
options: # optional
timeout: 5 # 超时时间
interval: 30 # 检查间隔时间
retries: 3 # 重试次数
healthcheck: '/url' # 针对 web 类型,提供该 url 给 tengine 进行健康检查,如果没有设置container_healthcheck,则该属性会继承container_healthcheck cmd为curl http://localhost/url,超时时间及间隔为10s,重试次数为3
portal: # 如果 app 作为 service,提供服务的 proc 需要定义 portal
allow_clients: "**" # portal 允许的 client,默认提供给所有
cmd: ./proxy # 启动 portal 时的命令
port: 4321 # portal 端口
env: # 定义 proc 运行时需要使用的环境变量
- ENVA=a
- ENVB=b
logs: # 声明应用需要落地的日志文件,被强制位于 /lain/logs 目录之下
- {LOG_FILENAME} # 对应 /lain/logs/{LOG_FILENAME}
cloud_volumes:
type: {CLOUDVOLUME-TYPE} # 支持 single, multi 两种类型,默认为 multi 类型
dirs: # 容器中需要进行写入的目录
- /cloud
volumes: # volume 文件,proc 被删时数据也不会移出,和 persistent_dirs 等效
# lain run的时候,在/tmp/lain/run/;lain deploy时,在/data/lain/volumes/
- /var/log
- /etc/nginx/nginx.conf:
backup: # 定义备份策略
schedule: "0 23 * * *"# 依次为 分,时,日,月,周,同 crontab
expire: "10d" # 过期时间,数字+单位, 如10d表示10天, 10h表示10小时, 3m表示3分钟
pre_run: {PRE_HOOK} # pre hook, 备份执行前调用
post_run: {POST_HOOK} # post hook, 备份结束后调用
mountpoint: # 只支持 ProcType==web 的 proc(默认已分配 ${appname}.${LAIN-domain} 的域名)
- a.external.domain1/b/c # 响应 a.external.domain1 这个外网域名 b/c 段 location 的请求,转发到 lain 内网 upstream
secret_files: # 定义 secret file 作为配置文件
- /secrets/hello # 定义文件路径,为相对路径时前面会加上 `/lain/app/`
- secret.dat
secret_files_bypass: True # 若为 True, 则当 console 拿不到 secret files 时会忽略该错误,默认为 False, 除了 layer1 应用不建议使用
stateful: true # 默认为 false, 表示 proc 挂掉时,并不会在另外一个节点重新启动容器
setup_time: 0 # 单位为秒,proc 多 instance 滚动升级时,设置升级前一个 proc 后隔多少秒升级后一个应用,用于保障服务不中断(当设置了healthcheck或者container_healthcheck时,则该参数可作为滚动升级时健康检查间隔时间)
kill_timeout: 10 # 单位为秒,下线 proc 容器时强制删除的时间,即 docker stop timeout 时间\
use_services: # 指出需要使用 service
{SERVICE_NAME}: # 标明 service app name
- {PROC_NAME} # 指出要使用的 service proc,这个 proc 已经定义了相应的 portal
use_resources: # 指出需要使用 resource
{RESOURCE_NAME}: # 依赖的 resource app name
memory: 32M # 给一系列可自定义的参数赋值,也可以使用 resource 的默认值
services: # 定义一系列依赖的 resource proc, proc 已经定义了相应的 portal
- {PROC_NAME}
用户在使用 lain-cli 命令时,lain.yaml 在各阶段的 image 的编译与转换过程如下图所示:
LAIN 中默认使用域名 lain.local
进行内部访问,除此之外也可以通过设置 extra_domain
来支持其它域名,但是这些都应该是对内服务能够访问的域名。
对于需要对外网提供服务的 web 类型的 proc,lain.yaml 可支持 mountpoint
这个属性,根据这个属性 LAIN 中的 webrouter 会将对应 server_name 的对应 location 代理到这个 proc,这个域名才应该是 proc 提供给外网访问的域名。
procType==web && procName==web
web.web:
cmd: {PROC_CMD} # 默认为 image 定义的 CMD
mountpoint: # `可选项`,系统会对 web.web 这个特殊的 proc 自动追加 {APPNAME}.{DOMAIN} 的请求响应
- a.external.domain1/b/c # 响应 a.external.domain1 这个外网域名 b/c 段 location 的请求,转发到 lain 内网这个 proc 对应 upstream
- d.external.domain2/e # 响应 d.external.domain2 这个外网域名 e 段 location 的请求,转发到 lain 内网这个 proc 对应 upstream
- /m # 响应 {APPNAME}.{DOMAIN} 这个内部域名 `m` 段 localtion 的请求,转发到 lain 内网这个 proc 对应 upstream
procType==web && procName!=web
web.admin:
cmd: {PROC_CMD} # 默认为 image 定义的 CMD
mountpoint: # `必填项`,web 类型但是名字不是 web 的 proc 必须填写一个以上的 mountpoint
- a.external.domain1/b/c # 响应 a.external.domain1 这个外网域名 b/c 段 location 的请求,转发到 lain 内网这个 proc 对应 upstream
- d.external.domain2/e # 响应 d.external.domain2 这个外网域名 e 段 location 的请求,转发到 lain 内网这个 proc 对应 upstream
- /admin # 响应 {APPNAME}.{DOMAIN} 这个内部域名 `admin` 段 localtion 的请求,转发到 lain 内网这个 proc 对应 upstream
使用 cloud_volumes 之前需要跟管理员确认 LAIN 中已经在相关目录挂载了提供 POSIX 兼容接口的分布式文件系统,如 MooseFS、CephFS 等。
如果集群中某些应用需要占用大量的磁盘空间,使用 volume 机制挂载宿主机的磁盘可能会出现空间不够的情况,这个时候可以考虑使用 cloud-volumes。此时在往 cloud_volumes 配置的文件夹中写入数据时会相应的存储到分布式文件系统中。
如果需要 proc 的多个 instance 同时共享一个目录,可以配置 cloud-volume 为 single 属性,此时所有 instance 在宿主机中对应的文件夹均默认位于 /data/lain/cloud-volumes/{APP_NAME}/{APP_NAME}.{PROC_TYPE}.{PROC_NAME}/ 目录下。
配置为 multi 属性则表示每个 instance 有个单独的文件夹可供写入,默认位于 /data/lain/cloud-volumes/{APP_NAME}/{APP_NAME}.{PROC_TYPE}.{PROC_NAME}/{INSTANCE_NO}/ 目录下。
在编写对应的 lain.yaml 时,有一些点需要注意:
-
在编译 prepare image 时,如果 base, script 或者 keep 发生变化,请变更这个版本号,否则不用变动
-
各阶段的 script 语句均在 /lain/app/ 路径下执行,所以上一行的
cd
等操作不会对下面行的工作目录产生影响 -
release 阶段可以不写,如果不写,lain-cli 会把 build 阶段生成的 image 打上 release 的标签
-
relese 中的 copy 指定把 script 运行结束后的中间结果 image 的路径 src 拷贝到 dest_base 中的 dest 中, src 可以是绝对路径或者是相对于 /lain/app 的路径
-
在编写 proc 时,支持几种简写形式:在定义 web 类型的 proc 时,可以直接用 web 代替 proc.{PROC_NAME};定义 service 时,可以简单的将 portal 定义在 proc 下面,也可以单独定义一个 proctype 为 portal 的 proc
-
proc 中定义的
user
变量必须为 release image 中已经存在的 user(可以通过cat /etc/passwd
查看),如果不存在,容器启动会出现问题 -
volumes 定义的文件默认位于 /data/lain/volume/{APP_NAME}/{APP_NAME}.{PROC_TYPE}.{PROC_NAME}/{INSTANCE_NO}/ 目录下
-
定义 volumes/persistent_dirs 与 stateful 选项都能使得 proc 在升级的时候不移动到其它节点,但是 statefule 定义为 true 时可以使得某个节点宕机后,集群不会在另外的节点拉起 proc,主要为了防止某些应用需要历史数据
-
由于 LAIN 中暂时不支持 proc 的别名定义机制,因此在定义
use_services
或use_resources
时,使用的 services 和 resources 的 proc 不能存在相同的 procname,否则使用 lain-cli 进行 build 时会报错,部署后 portal 的访问也有可能出现问题。