--- tags: feature author: Oliver.W --- # Serverless Application Template Owner: Oliver Stakeholders: 3rd part Applicaiton developers, Tencent, Serverless China, Serverless Currently Tencent is working with 3rd part company publish their own application template for end users to easy set up and deploy their own apllications. As the sametime, we like the 3rd part developers can using serverless to build the template while the end user will just need simple configure to start using their own application. eg: Record service to record and replay the stream content in a short period of time (near realtime.) * Using Components Solution: Developers cant benefit from exist components and get benefits of serverless. * Using Templates Solution: No way to manage the template version and validation rules, also can't publish to registry, and hard to deploy through console. ### Current Template Implementation 当前 全景录制应用 需要配置的我内容 ```md * app: * region: * vpc: * vpcId: * subnetId: * bucket: * cfs: * redis: * host * port * password * index ``` The currently serverless.yml for record service. ```yml component: multi-scf name: web_record app: ${env:NAME} inputs: src: src: ./ exclude: - .env - record/** - node_modules/** - transcode/** - docker/** - dist/** - scripts/** region: '${env:REGION}' runtime: Nodejs12.16 role: SCF_QcsRole memorySize: 256 isAutoPublish: true timeout: 90 msgTTL: 21600 retryNum: 0 vpc: vpcId: '${env:VPC_ID}' subnetId: '${env:SUBNET_ID}' environments: - key: SLS_APP_NAME value: '${app}' - key: ENV value: '${env:ENV}' - key: APP_VERSION value: '${env:APP_VERSION}' - key: VPC_ID value: '${env:VPC_ID}' - key: SUBNET_ID value: '${env:SUBNET_ID}' - key: REGION value: '${env:REGION}' - key: COS_BUCKET value: '${env:COS_BUCKET}' - key: CDN_DOMAIN value: '${env:CDN_DOMAIN}' - key: REDIS_HOST value: '${env:REDIS_HOST}' - key: REDIS_PORT value: '${env:REDIS_PORT}' - key: REDIS_AUTH value: '${env:REDIS_AUTH}' - key: REDIS_INDEX value: '${env:REDIS_INDEX}' - key: CFS_ID value: '${env:CFS_ID}' - key: MOUNT_ID value: '${env:MOUNT_ID}' - key: RECORD_IMAGE_URL value: '${env:RECORD_IMAGE_URL}' - key: REGISTRY_ID value: '${env:REGISTRY_ID}' - key: TRANSCODE_IMAGE_URL value: '${env:TRANSCODE_IMAGE_URL}' functions: - name: '${app}-callback' src: ./callback handler: index.main_handler memorySize: 512 asyncRunEnable: true traceEnable: true - name: '${app}-upload' src: ./upload handler: index.main_handler memorySize: 512 timeout: 7200 asyncRunEnable: true traceEnable: true cfs: - cfsId: '${env:CFS_ID}' mountInsId: '${env:MOUNT_ID}' localMountDir: /mnt/ remoteMountDir: / - name: '${app}-transcode' memorySize: 3072 timeout: 7200 asyncRunEnable: true traceEnable: true image: imageUrl: '${env:TRANSCODE_IMAGE_URL}' imageType: public registryId: '${env:REGISTRY_ID}' cfs: - cfsId: '${env:CFS_ID}' mountInsId: '${env:MOUNT_ID}' localMountDir: /mnt/ remoteMountDir: / - name: '${app}-record' memorySize: 3072 timeout: 86400 asyncRunEnable: true traceEnable: true image: imageUrl: '${env:RECORD_IMAGE_URL}' imageType: public registryId: '${env:REGISTRY_ID}' cfs: - cfsId: '${env:CFS_ID}' mountInsId: '${env:MOUNT_ID}' localMountDir: /mnt/ remoteMountDir: / - name: '${app}-dispatch' memorySize: 256 src: ./dispatch handler: index.main_handler - name: '${app}-diagnose' memorySize: 256 timeout: 150 src: ./diagnose handler: index.main_handler triggers: - type: timer function: '${app}-dispatch' parameters: name: dispatch_timer cronExpression: 0 */10 * * * * * enable: true argument: Active - type: timer function: '${app}-diagnose' parameters: name: diagnose_timer cronExpression: '*/30 * * * * * *' enable: true argument: argument - type: timer function: '${app}-record' parameters: name: record_timer cronExpression: 0 */10 * * * * * enable: true argument: Active - type: apigw parameters: name: web_record protocols: - http - https description: Serverless web-record API GW environment: release apis: - path: /record apiName: dispatch_api method: POST description: Serverless REST API enableCORS: true responseType: JSON serviceTimeout: 90 authType: APP function: '${app}-dispatch' ``` * The validation rules will still using the multi-scf rules. * No way to manage the version of the template. * It is hard for 3rd part developers build template and manage env configs. ## Objectives & Key Results * 3rd part developer can use components to build Application Template and get benefits of Serverless. * Application Template should have way to validte the config before deploy. * Application Template should have way to define the version of it. ## Proposed Solution * Add new application template for this use case. * Similar to components config but can extend exist components * End user can use application level config (serverless.yml) to deploy an applicaiton. 修改应用模板使用 组件模板 方式进行开发。如 创建新的 应用模板 `panorama-record` 后, 应用用户 通过 serverless.yml 进行实例配置, 应用开发者使用 serverless.components.yml 中的base 进行模板配置 ### 使用 serverless.yml 进行配置 ``` SDK. image: node12lts image: tencent-scf-node12lts. api.get('blogs') => { .... } ``` ```yml component: multi-scf name: web_record app: ${APP:app} inputs: src: src: ./ exclude: - .env - record/** - node_modules/** - transcode/** - docker/** - dist/** - scripts/** runtime: Nodejs12.16 role: SCF_QcsRole variable: default: xxx type: string rules: - regex: '^[a-zA-Z][a-zA-Z0-9(_)]{0,48}[a-zA-Z0-9]?$' message: "字符不接受" - min: 2 message: "长度过短" - max: 60 message: "长度过长" memorySize: 256 isAutoPublish: true timeout: 90 msgTTL: 21600 retryNum: 0 functions: triggers: ``` 使用 新的[组件校验规则](https://hackmd.io/@serverless-cn/Sy-SRaU0d)完成 serverless.yml 的配置校验。 * 可以进行多个规则的校验 * 通过接口可以直接对配置信息进行校验。 * 在部署前进行校验 ### 使用 serverless.application.yml 配置应用模板 ```yml name: panorama-record version: 0.1.1 author: Tencent Cloud, Inc. org: Tencent Cloud, Inc. description: Deploy a serverless cloud function on Tencent Cloud. keywords: tencent, serverless, SCF repo: https://github.com/serverless-components/tencent-scf readme: https://github.com/serverless-components/tencent-scf/tree/master/README.md license: MIT main: ./src webDeployable: true # 变量名称,变量类型,变量默认值。 template: will use as default value for end users when they init. serverless.yml app: my-panorama-record-app component: panorama-record inputs: region:ap-guangzhou type: string default: allow: - event - web ... vpc: vpcId: ${output:${stage}:${app}:sls-demo-msn-vpc.vpcId} subnetId: ${output:${stage}:${app}:sls-demo-msn-vpc.subnetId} bucket: my-bucket cfs: cfsId: my-cfs mountId: 1 redis: host: my-cfs.host.com port: 3022 password: ${env: RedisPassword} index: 1 images: transcodeUrl: mytrans.host.com recordUrl: myrecord.host.com registryId: 1 ``` With this solution, The benefits are * Easier for developer to config * Set up each application config validation rules by reuse [components-types](https://github.com/serverless-components/tencent-types) * Able to publish to registry and init through CLI. ## The future Serverless Architecture * The application templates will be used like templates. * End User can not modify the application template code beside make PR. * End User need to config application app with `serverless.yml` as usual. * Application Template config example defineds in `serverless.application.yml` ![](https://i.imgur.com/IfHiEpF.png) ### 3rd pard developers UX 1. develop app as normal with `serverless.yml` ```yml component: multi-scf name: web_record app: ${base:app} inputs: src: src: ./ runtime: Nodejs12.16 role: SCF_QcsRole memorySize: 256 isAutoPublish: true timeout: 90 msgTTL: 21600 retryNum: 0 functions: - name: '${app}-callback' src: ./callback handler: index.main_handler memorySize: 512 asyncRunEnable: true ... ``` 2. add `serverless.applicaiton.yml` to the application template. * Application name, version etc info. * Confing file(serverless.yml) template. ```yml name: panorama-record version: 0.1.1 author: Tencent Cloud, Inc. org: Tencent Cloud, Inc. description: Deploy a serverless cloud function on Tencent Cloud. keywords: tencent, serverless, SCF repo: https://github.com/serverless-components/tencent-scf readme: https://github.com/serverless-components/tencent-scf/tree/master/README.md license: MIT main: ./src webDeployable: true default: # will use as default value for end users when they init. app: my-panorama-record-app component: panorama-record inputs: region:ap-guangzhou vpc: vpcId: ${output:${stage}:${app}:sls-demo-msn-vpc.vpcId} subnetId: ${output:${stage}:${app}:sls-demo-msn-vpc.subnetId} bucket: my-bucket cfs: cfsId: my-cfs mountId: 1 redis: host: my-cfs.host.com port: 3022 password: ${env: RedisPassword} index: 1 images: transcodeUrl: mytrans.host.com recordUrl: myrecord.host.com registryId: 1 ``` 3. publish as serverless applicaiton template. 4. [optional]upload config validation into [components-types](https://github.com/serverless-components/tencent-types) ### end-user UX 1. init application with name registred * through CLI `sls init panorama-record --name my-record-service` * through Tencetn Console 2. fill the config file (serverless.yml) ```yml # serverless.yml app: my-panorama-record-app component: panorama-record inputs: region:ap-guangzhou # 应用部署地区 vpc: vpcId: ${output:${stage}:${app}:sls-demo-msn-vpc.vpcId} subnetId: ${output:${stage}:${app}:sls-demo-msn-vpc.subnetId} bucket: my-bucket cfs: cfsId: my-cfs mountId: 1 redis: host: my-cfs.host.com port: 3022 password: ${env: RedisPassword} index: 1 images: transcodeUrl: mytrans.host.com recordUrl: myrecord.host.com registryId: 1 ``` 3. deploy the applicaiton. * through CLI `sls deploy` * through Tencent Console