Ease Stack

1. Production Principles

The Ease Stack is designed for the whole backend services management.

We introduce a term - Stack. A Stack is grouped by a number of service, all of them together serve the users. Such as a classical web stack which has Nginx, Tomcat, Redis and Mysql. Every service is very critical and without one of them the whole stack will be running improperly.

So, we need two-layer services orchestration solution, which can schedule the whole stack’s services, so that can provide the real SLA to customer.

  • Integral Stack Management. Need to manage the whole lifecycle of the Stack.

  • Simple to Use. Need be simple and easy to use, it’s lightweight and only provide the important features.

  • Base on Mainstream Technology. Must be base on the mainstream orchestration technology, such as Docker Swarm, Kubernetes or Mesos.

  • Support Both Web and Batch application. Need to support online Web application and Big data batch job application.

  • Not a Platform. The Ease Stack is not a PaaS platform, it’s a kind of framework or service which provide a number of APIs, client can invoke them.

2. Design Principles

The Ease Stack is a kind of Two-layer Service Orchestration. The lower layer is services, the upper layer is stack. And the lower layer is delegate to current mature solution in industry, such as Kubernetes and Mesos. The upper layer is try to make the lower layer be transparent and focus on the whole stack scheduling.

The Ease Stack has the following design principles:

  • Lifecycle Management. A stack lifecycle could includes these states - Provision, Ready, Scale, Failed and Destroy. Those states must be managed integrally, and the state can be synced up back from the production.

  • Stateful Node Scheduling. As we know, the stateless is very easy to management, but the Stateful node is hard. But the Stateful node is very critical, if we cannot manage it, then this is meaningless.

  • Automation enables Scale. The automation operation is the key. So, the failover, scaling in/out, and deployment must be automated.

  • Easy to Use and Integrate. Must be easy to integrate with the current user’s current system. so, we need provide a number of management API to use.

  • No Side-Affects. The Ease Stack has no side affects, even if it’s down, the whole stack can still run properly without any impacts.

Actually, we try to leverage the following platform.

Services Orchestration Platform

Note:

  • The Ease Gateway can be used for the API Gateway.
  • The Ease Monitor can be used for the Application Monitor.

3. Architecture

The Ease Stack has three stages as blow:

  • Stack Manifest. This is used for Stack Definition, it is the stack formation.
  • Stack Instance. This is the Stack running controller or running management.
  • Physcal Platform. This is underly platform, currently, we uses Kurbernetes as this layer.

Stack Definition

The Ease Stack is quite simple and lightweight. The following flow chart show how it works.

  1. The command is accepted by restful API, which handled by Command component.
  2. The command will send to Profile component, this component just is an Event Emitter.
  3. The event will send to the Controller, this is the component control the underlying platform - Kurbernetes
  4. The service scheduling needs time. So, we need a Watchdog to sync back the state.

Stack Definition

4. Features

The Ease Stack is not a platform, it is a framework or service which allow other systems manipulate it by calling its APIs.

It has the following features:

  • Services Architecture Formation. By providing a manifest of stack - the definition of the service architecture with the service-oriented docker image. we can bootstrap the whole architecture/stack with one simple API call.

  • Elegant Configuration Update. There two types of configurations need be updated during the service running

    1. Static Configuration - The configuration for service startup. e.g. tomcat’s JVM startup paremeters.
    2. Dynamic Configuration - the configuration need to know during the running. e.g. zookeeper’s peer IP address.

The Ease Stack provides a framework help you construct the Service-Oriented Docker Images easily. And which can

  • Maintain the Service Minimal Instances. If a service need 3 instances at least, then the Ease Stack can maintain this forcibly - if some instances down, the Ease Stack will boot the instances to meet the minimal instances requirement.

  • Scaling the Stack. The Ease Stack can scale the whole stack with one API call.

  • Batch Job Support. The Ease Stack also can schedule the data analysis batch job - the resource will be allocated on demands.

5. Details

5.1 How to Integrate with Ease Stack

To integrate with the Ease Stack, we need the following prerequisites.

  • Stack Manifest File. A manifest file to describe the details how to architect a Stack .
  • Service-Oriented Docker Image. All services must be Dockerized with some scripts used to start, stop, update the component. (We provide a framework to make this easy to write)
  • Underlying Cluster. Currently, we only support Kurbernetes cluster environment as the underlying platform.

5.1.1 Stack Manifest File

The stack manifest is json format file which describe detail of the stack, the Ease Stack makes use of it to know how to deploy component in stack and how to manage the stack. The manifest file is consist of two parts:

  • Base Information. Including stack name, stack control information and some global information shared in all components in stack.

  • Component Information. Including, the component’s Docker image name, image version, deployment information and component’s own configuration etc.

For example:

{
    "name": "some-app",
    "description": "description",
    "namespace": "default",
    "env": {
        "name": "local",
        "description": "the nodes of local environments",
        "nodes": [],
        "storages": []
    },
    "healthcheck_retry_times": 10,
    "healthcheck_interval": 10,
    "stack_provision_timeout": 1200000000000,
    "stack_destroy_timeout": 1200000000000,
    "stack_update_timeout": 1200000000000,
    "stack_scale_timeout": 1200000000000,
    "env_variables": [
        {
            "name": "INFRASTRUCTURE_PROVIDER",
            "value": "aws"
        },
        {
            "name": "SCRIPT_LOG_LEVEL",
            "value": "WARNING"
        }
    ],

   "deployments": [
        {
            "name": "backend-server",
            "image": "172.31.13.51/megaese/tomcat-server",
            "image_version": "1.8",
            "type": "Stateless",
            "description": "the backend-server component deployment information",
            "instance_count": 3,
            "require_resource": {
                "cpu": "300m",
                "memory": "512Mi"
            },
            "limit_resource": {
                "cpu": "500m",
                "memory": "1Gi"
            },
            "storage_mounts": [],
            "coloring_nodes": [
                "ip-172-31-10-103",
                "ip-172-31-9-252",
                "ip-172-31-14-200"
            ],
            "configurations": [
                "{\n\"httpPort\": 9527,\n\"stage\": \"test\"\n}"
            ],
            "initial_delay_seconds": 90,
            "healthcheck_retry_times": 30,
            "named_ports": [
                {
                    "name": "httpPort",
                    "port": 8080,
                    "is_host_port": false
                }
            ],
            "is_node_port": false,
            "node_port_policy": "default",
            "env_variables": []
        },

        {
            "name": "fontend-server",
            "image": "172.31.13.51/megaease/reactjs-web",
            "image_version": "1.8",
            "type": "Stateless",
            "description": "the reactjs-web component deployment information ",
            "instance_count": 1,
            "require_resource": {
                "cpu": "200m",
                "memory": "128Mi"
            },
            "limit_resource": {
                "cpu": "500m",
                "memory": "1Gi"
            },
            "storage_mounts": [],
            "coloring_nodes": [
                "ip-172-31-2-1"
            ],
            "configurations": [
                "{\n\"httpPort\": 8080,\n\"stage\": \"test\"\n}"
            ],
            "initial_delay_seconds": 60,
            "named_ports": [
                {
                    "name": "httpPort",
                    "port": 80,
                    "is_host_port": true
                }
            ],
            "is_node_port": true,
            "node_port_policy": "default",
            "env_variables": []
        }
    ],
    "healthchecker_image": "172.31.13.51/megaease/cmdagent",
    "healthchecker_image_version": "1.1"
}

The above example describe a stack named some-app. It’s a typical web application and has two components, one is tomcat service tomcat-server and another is react based front end sevice react-web.

We may notice, in the deployments arrays, we defined component informations include image information, resource quota allocated to component, static configs in configurations, component docker container number specified by instance_count and deployed node information.

5.1.2 Service-Oriented Docker Images

The Ease Stack not only uses Docker Image to do the service deployment. Furthermore, the service related operational function also need be provide by the Docker image, which including how to start/stop the service, and how to update the service configuration etc.

The following sections help to understand how to build a Service-Oriented Docker Image. And we provide a framework to help make them easier.

5.1.2.1 Entrypoint

The entry point of Docker image is a standalone executable provided by the Ease Stack, we named it as ease-controller. The ease-controller main responsibilities are:

  1. Retrieving information related to application in container, these informations include endpoint of component with which the current application related, the static configuration of current application configured in manifest file. The ease-controller will detect changes of the stack by periodical checking.

  2. Running specific scripts at the proper time. As mentioned before, when the ease-controller detects configuration is being changed, it will automatically run the apply-config.sh to notify application to change the configuration, after successfully run the apply-config.sh, the ease-controller would run the stop-instance.sh to to stop the service in container and run the start-instance.sh to restart it.

5.1.2.2 Specific Scripts

The specific scripts are provided by the vender of application in Docker image. There are three kinds of scripts and the responsibilities are:

  • start-instance.sh. It is dedicated to boot main application of component in docker container

  • stop-instance.sh. It is used to stop main application in docker container.

  • apply-config.sh. It takes the responsibility for generating application related config with dynamic configuration and static configuration.

start-instance.sh

This script is used to start the service.

Most of time, to start a service, it needs some dynamic configurations, such as: JVM’s arguments need be inputed by outside instead of hard coding in this script.

The Ease Stack provide a mechanism to achieve this - by defined some Environment Variables in the manifest file.

stop-instance.sh

This script is used to stop the service by elegant way.

apply-config.sh

When the configuration changes, either from dynamic configurations or the dependent components changes. the ease-controller would run apply-config.sh to re-generate configuration.

Five arguments would be passed to apply-config.sh:

  1. instance_id: The identify of the component instance.
  2. namespace: The kubernetes namespace in which component are deployed.
  3. component_name: The name of component.
  4. static_configuration_file: The absolute path of the static configuration file whoese content comes from the stack manifest.
  5. dynamic_configuration_file: The absolute path of the dynamic configuration file generated by the ease-controller.

Note

The dynamic configuration is a JSON format file, in general, apply-config.sh would use tool like jq to parse interested information from it. The dynamic configuration contains the component and dependent components’ information, e.g., listen address and port. If the component want to expose its port, it needs to define a named port in stack manifest, with which, the ease-controller knows they’re requisite, and load them from DNS svc records.

The JSON schema of dynamic_configuration as below.

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Dynamic configuration schema file",
  "description": "Dynamic configuration schema file",
  "type": "array",
  "minItems": 0,
  "items": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "name": {
        "type": "string",
        "descritpion": "The name of component",
        "pattern": "^[a-zA-Z0-9_\\-]*$"
      },
      "namedports": {
        "type": "array",
        "descrpiton": "The named port list of component",
        "items": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "name": {
              "description": "The name of named port",
              "type": "string",
              "pattern": "^[a-zA-Z0-9_\\-]*$"
            },
            "endpoints": {
              "type": "array",
              "description": "the endpoint of named point list",
              "items": {
                "type": "string",
                "description": "the item like `zookeeper-0.zookeeper.default.svc.cluster.local:2188`"
              }
            }
          },
          "required": [
            "name",
            "endpoints"
          ]
        }
      }
    },
    "required": [
      "name",
      "namedports"
    ]
  },
  "definitions": {}
}

5.2 How to Start the Stack

5.3 How to Update the Stack

5.4 How to Scale the Stack

6. Reference

6.1 Restful APIs

6.1.1 /stackManifests


POST

Summary: Create new stack manifest

Description:

Parameters

NameLocated inDescriptionRequiredSchema
bodybodyStackManifest object which needs to be save to the the EaseStack’s inventoryYesstack.json

Responses

CodeDescription
200Successful operation
400Invalid input
406The stack manifest already exist and stack instance is not exist or stack instance status is not destroyed
500Server internal error

6.1.2 /stackManifests/{stackName}


GET

Summary: Query stack manifest by stack’s name

Description: Returns a complete stack’s manifest information

Parameters

NameLocated inDescriptionRequiredSchema
stackNamepathStatus values that need to be considered for filterYesstring
bodybodyYesquery_stack.json

Responses

CodeDescriptionSchema
200successful operationstack.json
400Bad request, Payload data could not be validated by json schema.
404The stack manifest information could not be found
500Server internal error
DELETE

Summary: Delete stack manifest by stack’s name

Description:

Parameters

NameLocated inDescriptionRequiredSchema
stackNamepathStatus values that need to be considered for filterYesstring
bodybodyYesquery_stack.json

Responses

CodeDescription
200successful operation
400Bad request, Payload data could not be validated by json schema.
404The stack manifest which need to be deleted could not be found
405The status of stack instance correspond with the stack’s manifest is alive
500Server internal error

6.1.3 /stacks/_bootstrap


POST

Summary: Initialize stack instance with stack manifest

Description: Bootstrap all components which is defined in stack manifest information the components in request payload could be omitted. The EaseStack would bootstrap whole stack completely when components is omitted, otherwise API server would bootstrap stack partially. The order in components need be guaranteed in correct way by api user

Parameters

NameLocated inDescriptionRequiredSchema
bodybodySpecify which stack need to be initializedYesstack_base_request.json

Responses

CodeDescription
200Success. Stack’s status is in bootstrap processing, the latest status of stack instance could be queried by status interface.
400Bad Request! The payload data could not be validated by json schema.
404Not found! The stack definition or stack instance could not be found.
406Status not acceptable! The operation is not acceptable because of current status of stack instance.
500Internal server error.

6.1.4 /stacks/_scale


POST

Summary: Scale instance count or coloring nodes of component in stack.

Description:

Parameters

NameLocated inDescriptionRequiredSchema
bodybodySpecify which stack need to be destroyedYesstack_scale.json

Responses

CodeDescription
200Success. Stack’s status is in scaling, the latest status of stack instance could be queried by status interface.
304Status not modified. No component(s) in stack need to be scaled
400Bad Request! The payload data could not be validated by json schema.
404Not found! The stack definition or stack instance could not be found.
406Status not acceptable! The operation is not acceptable because of current status of stack instance.
500Internal server error.

6.1.5 /stacks/_update


POST

Summary: Update configuration or image information of component in stack

Description:

Parameters

NameLocated inDescriptionRequiredSchema
bodybodyThe informations of component in stack need to be updated, including docker image, version of docker image and configuration of component relevantYesstack_update.json

Responses

CodeDescription
200Success. Stack is in updating, the latest status of stack instance need be queried by status interface.
304Status not modified. No component(s) in stack need to be updated.
400Bad Request! The payload data could not be validated by json schema.
404Not found! The stack definition or stack instance could not be found
406Status not acceptable! The operation is not acceptable because of stack instance status
500Internal server error

6.1.6 /stacks/_destroy


POST

Summary: Destroy stack instance which’s status is ready or provisioned

Description: Destroy components of stack, the components in request payload could be omitted. The EaseStack would destroy whole stack completely when components is omitted, otherwise API server would destroy stack partially. The order in components need be guaranteed in correct way by api user

Parameters

NameLocated inDescriptionRequiredSchema
bodybodySpecify which stack need to be destroyedYesstack_base_request.json

Responses

CodeDescription
200Success. Stack’s status is in destroying, the latest status of stack instance could be queried by status interface.
400Bad Request! The payload data could not be validated by json schema.
404Not found! The stack definition or stack instance could not be found.
406Status not acceptable! The operation is not acceptable because of current status of stack instance.
500Internal server error.

6.2 JSON Schema

6.2.1 manifest_update.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "The stack orchestration inventory.",
  "description": "The stack orchestration inventory.",
  "properties": {
    "env": {
      "type": "string",
      "title": "Name schema.",
      "description": "The stack prototype name, must be unique.",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "namespace": {
      "type": "string",
      "title": "Namespace schema.",
      "description": "The namespace of Kubernetes .",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "update_requests": {
      "type": "array",
      "title": "The stack deployments schema.",
      "description": "The stack deployment informations about environment specified.",
      "items": {
        "type": "object",
        "title": "Deployments schema.",
        "description": "The deployment list information.",
        "properties": {
          "name": {
            "type": "string",
            "title": "Name schema.",
            "description": "The deployed component resource name",
            "pattern": "^[a-zA-Z0-9_\\-]*$"
          },
          "description": {
            "type": "string",
            "title": "Description schema.",
            "description": "The component deployment description."
          },
          "image": {
            "type": "string",
            "title": "Component image schema.",
            "description": "The image name of component used in docker."
          },
          "image_version": {
            "type": "string",
            "title": "Component image version schema.",
            "description": "The image version of component used in docker."
          },
          "coloring_nodes": {
            "type": "array",
            "title": "Coloring_nodes schema.",
            "description": "The node list which the component could be deployed.",
            "items": {
              "type": "string",
              "title": "1 schema.",
              "description": "The name referenced to nodes."
            }
          },
          "instance_count": {
            "type": "integer",
            "title": "Instance_count schema.",
            "description": "The component instance count."
          }
        },
        "required": [
          "name"
        ]
      }
    }
  },
  "required": [
    "namespace",
    "env",
    "update_requests"
  ]
}

6.2.2 query_stack.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "The stack orchestration inventory.",
  "description": "The stack orchestration inventory.",
  "properties": {
    "env": {
      "type": "string",
      "title": "Name schema.",
      "description": "The stack prototype name, must be unique.",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "namespace": {
      "type": "string",
      "title": "Namespace schema.",
      "description": "The namespace of Kubernetes .",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    }
  },
  "required": [ "env", "namespace" ]
}

6.2.3 stack.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "The stack orchestration inventory.",
  "description": "The stack orchestration inventory.",
  "properties": {
    "name": {
      "type": "string",
      "title": "Name schema.",
      "description": "The stack prototype name, must be unique.",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "description": {
      "type": "string",
      "description": "The description of the manifest file",
      "pattern": "\\w+"
    },
    "namespace": {
      "type": "string",
      "title": "Namespace schema.",
      "description": "The namespace of Kubernetes .",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "env_variables": {
      "description": "This is environment variables shared in whole stack.",
      "type": "array",
      "items": {
        "type": "object",
        "oneOf": [
          {
            "$ref": "#/definitions/env_variable"
          }
        ]
      }
    },
    "healthcheck_retry_times": {
      "type": "integer",
      "description": "The retry number when component's healthcheck failed. default is 10 times",
      "minimum": 1
    },
    "healthcheck_interval": {
      "type": "integer",
      "description": "The interval (in second) between two healthcheck execution, default is 10 seconds",
      "minimum": 1
    },
    "stack_provision_timeout": {
      "type": "integer",
      "description": "The maximum time allowed in provisioning status of stack, default is 30 mintues",
      "minimum": 1
    },
    "stack_update_timeout": {
      "type": "integer",
      "description": "The maximum time allowed in updating status of stack, default is 20 mintues",
      "minimum": 1
    },
    "stack_scale_timeout": {
      "type": "integer",
      "description": "The maximum time allowed in scaling status of stack, default is 20 mintues",
      "minimum": 1
    },
    "stack_destroy_timeout": {
      "type": "integer",
      "description": "The maximum time allowed in destroying status of stack, default is 20 mintues",
      "minimum": 1
    },
    "healthchecker_image": {
      "type": "string",
      "description": "The healthchecker image name, default is gcr.io/google_containers/exechealthz-amd64",
      "minLength": 1
    },
    "healthchecker_image_version": {
      "type": "string",
      "description": "The healthchecker image name, default is 1.2",
      "minLength": 1
    },
    "env": {
      "type": "object",
      "title": "The environment which the stack would be deployed schema.",
      "description": "The environment which the stack would be deployed.",
      "properties": {
        "name": {
          "type": "string",
          "title": "Environment name schema.",
          "description": "The environment name must be unique.",
          "pattern": "^[a-zA-Z0-9_\\-]*$"
        },
        "description": {
          "type": "string",
          "title": "envirmont description schema.",
          "description": "A short description of environment."
        },
        "nodes": {
          "type": "array",
          "title": "Environment node list schema",
          "description": "The complete node list in the environment.",
          "items": {
            "type": "object",
            "title": "Node item schema.",
            "description": "An explanation about the purpose of this instance.",
            "properties": {
              "node": {
                "type": "string",
                "title": "Node name schema.",
                "description": "The node name must be equal one of k8s cluster node name"
              },
              "description": {
                "type": "string",
                "title": "Node description schema.",
                "description": "A short description of node."
              },
              "address": {
                "type": "string",
                "title": "node address schema.",
                "description": "The ipv4 address."
              }
            },
            "required": [
              "node",
              "address"
            ],
            "additionalProperties": false
          }
        },
        "storages": {
          "type": "array",
          "title": "Storages schema.",
          "description": "The storage informations in the environment.",
          "items": {
            "type": "object",
            "title": "The storage information list.",
            "description": "The list of storage information.",
            "properties": {
              "name": {
                "type": "string",
                "title": "Name schema.",
                "description": "The storage item name could be referenced in deployment."
              },
              "description": {
                "type": "string",
                "title": "Description schema.",
                "description": "The storage item description."
              },
              "host": {
                "type": "string",
                "title": "Host schema.",
                "description": "The host name or ip address of nfs server."
              },
              "path": {
                "type": "string",
                "title": "Path schema.",
                "description": "The path of nfs server."
              },
              "awsebs_volume_id": {
                "type": "string",
                "descritpion": "The volume id of aws ebs"
              },
              "awsebs_fs_type": {
                "type": "string",
                "enums": [
                  "ext4"
                ]
              },
              "type": {
                "type": "string",
                "title": "Type schema.",
                "description": "An explanation about the purpose of this instance.",
                "enums": [
                  "NFS",
                  "CEPHFS",
                  "EBS"
                ]
              }
            },
            "anyOf": [
              {
                "properties": {
                  "type": {
                    "enum": [
                      "NFS"
                    ]
                  }
                },
                "required": [
                  "name",
                  "description",
                  "type",
                  "host",
                  "path"
                ]
              },
              {
                "properties": {
                  "type": {
                    "enum": [
                      "EBS"
                    ]
                  }
                },
                "required": [
                  "name",
                  "description",
                  "type",
                  "awsebs_fs_type",
                  "awsebs_volume_id"
                ]
              }
            ]
          }
        }
      },
      "required": [
        "name",
        "description",
        "storages"
      ],
      "additionalProperties": false
    },
    "deployments": {
      "type": "array",
      "title": "The stack deployments schema.",
      "description": "The stack deployment informations about environment specified.",
      "items": {
        "type": "object",
        "title": "Deployments schema.",
        "description": "The deployment list information.",
        "properties": {
          "name": {
            "type": "string",
            "title": "Name schema.",
            "description": "The deployed component resource name",
            "pattern": "^[a-zA-Z0-9_\\-]*$"
          },
          "component_name": {
            "type": "string",
            "title": "Component Name schema",
            "description": "The  component name referenced to components.",
            "pattern": "^[a-zA-Z0-9_\\-]*$"
          },
          "description": {
            "type": "string",
            "title": "Description schema.",
            "description": "The component deployment description."
          },
          "dependency_components": {
            "type": "array",
            "title": "Dependency components list",
            "description": "The dependency component(deployment) name list, it could be empty list, if the list is empty,  it implicted that current component depend on all component(deployment) defined before, it also could be a list which contains one empty string element, it means that current component do not depended any component(deployment), otherwise  it defined current component dependent component list.",
            "items": {
              "type": "string",
              "title": "dependency components item",
              "description": "The item of current component depdendency. "
            }
          },
          "env_variables": {
            "description": "This is environment variables shared in whole stack.",
            "type": "array",
            "items": {
              "type": "object",
              "oneOf": [
                {
                  "$ref": "#/definitions/env_variable"
                }
              ]
            }
          },
          "image": {
            "type": "string",
            "title": "Component image schema.",
            "description": "The image name of component used in docker."
          },
          "image_version": {
            "type": "string",
            "title": "Component image version schema.",
            "description": "The image version of component used in docker."
          },
          "type": {
            "type": "string",
            "title": "Component type schema.",
            "description": "The type of component which value is one of stateful or stateless",
            "enum": [
              "Stateful",
              "Stateless"
            ]
          },
          "instance_count": {
            "type": "integer",
            "title": "Instance_count schema.",
            "description": "The component instance count."
          },
          "require_resource": {
            "type": "object",
            "title": "Require_resource schema.",
            "description": "The component required resource",
            "properties": {
              "cpu": {
                "type": "string",
                "title": "Cpu schema.",
                "description": "The component required resource of CPU.",
                "minLength": 2
              },
              "memory": {
                "type": "string",
                "title": "Memory schema.",
                "description": "The component required resource of Memory.",
                "minLength": 2
              }
            },
            "required": [
              "cpu",
              "memory"
            ],
            "additionalProperties": false
          },
          "limit_resource": {
            "type": "object",
            "title": "Limit_resource schema.",
            "description": "The maximum resource owned by the component.",
            "properties": {
              "cpu": {
                "type": "string",
                "title": "Cpu schema.",
                "description": "The maximum CPU resource owned by the component.",
                "minLength": 2
              },
              "memory": {
                "type": "string",
                "title": "Memory schema.",
                "description": "The maximum memory resource owned by the component.",
                "minLength": 2
              }
            },
            "required": [
              "cpu",
              "memory"
            ],
            "additionalProperties": false
          },
          "storage_mounts": {
            "type": "array",
            "title": "Storage_mounts schema.",
            "description": "An explanation about the purpose of this instance.",
            "items": {
              "type": "object",
              "title": "0 schema.",
              "description": "An explanation about the purpose of this instance.",
              "properties": {
                "storage_name": {
                  "type": "string",
                  "title": "Storage_name schema.",
                  "description": "The storage name reference to storages."
                },
                "mount_point": {
                  "type": "string",
                  "title": "Mount_point schema.",
                  "description": "The path which mounted in component."
                }
              },
              "required": [
                "storage_name",
                "mount_point"
              ],
              "additionalProperties": false
            }
          },
          "coloring_nodes": {
            "type": "array",
            "title": "Coloring_nodes schema.",
            "description": "The node list which the component could be deployed.",
            "items": {
              "type": "string",
              "title": "1 schema.",
              "description": "The name referenced to nodes."
            }
          },
          "configurations": {
            "type": "array",
            "title": "Configurations schema.",
            "description": "An explanation about the purpose of this instance.",
            "items": {
              "type": "string",
              "title": "0 schema.",
              "description": "The configuration which is used by specified component."
            }
          },
          "initial_delay_seconds": {
            "type": "number",
            "minimum": 0,
            "maximum": 180000,
            "title": "Initial delay seconds schema",
            "description": "Wait seconds before performing the first healthcheck probe"
          },
          "is_node_port": {
            "type": "boolean",
            "description": "The requests outside of cluster can be delivered to inside of cluster from named port of cluster node. Once the requests were delivered into cluster through node port, it could load balance in cluster by orchestrator platform. The field's default value is false"
          },
          "node_port_policy": {
            "type": "string",
            "enum": [
              "random",
              "default"
            ],
            "description": "node port policy"
          },
          "healthcheck_retry_times": {
            "type": "integer",
            "description": "The retry number when component's healthcheck failed. default is 10 times",
            "minimum": 1
          },
          "healthcheck_interval": {
            "type": "integer",
            "description": "The interval (in second) between two healthcheck execution, default is 10 seconds",
            "minimum": 1
          },
          "named_ports": {
            "type": "array",
            "minItems": 0,
            "items": {
              "type": "object",
              "description": "named port object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "The name of port which reference to component name port"
                },
                "port": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 65535,
                  "description": "The port which component would listen"
                },
                "is_host_port": {
                  "type": "boolean",
                  "description": "The listen port is exposed to machine in which container hosted. The field's default value is false"
                }
              },
              "required": [
                "name",
                "port"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "name",
          "description",
          "instance_count",
          "image",
          "image_version",
          "type",
          "require_resource",
          "limit_resource",
          "storage_mounts",
          "coloring_nodes",
          "configurations",
          "initial_delay_seconds",
          "named_ports"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "name",
    "namespace",
    "env",
    "deployments"
  ],
  "additionalProperties": false,
  "definitions": {
    "env_variable": {
      "properties": {
        "name": {
          "type": "string",
          "pattern": "[a-zA-Z_][a-zA-Z0-9_]"
        },
        "value": {
          "type": "string"
        }
      },
      "required": [
        "name",
        "value"
      ],
      "additionalProperties": false
    }
  }
}

6.2.4 stack_base_request.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "The stack orchestration inventory.",
  "description": "The stack orchestration inventory.",
  "properties": {
    "env": {
      "type": "string",
      "title": "Name schema.",
      "description": "The stack prototype name, must be unique.",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "namespace": {
      "type": "string",
      "title": "Namespace schema.",
      "description": "The namespace of Kubernetes .",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "components": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "The compnoent's name which need to be bootstrapped",
        "pattern": "^[a-zA-Z0-9_\\-]*$"
      }
    }
  },
  "required": [ "env", "namespace" ]
}

6.2.5 stack_scale.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "The stack orchestration inventory.",
  "description": "The stack orchestration inventory.",
  "properties": {
    "env": {
      "type": "string",
      "title": "Name schema.",
      "description": "The stack prototype name, must be unique.",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "namespace": {
      "type": "string",
      "title": "Namespace schema.",
      "description": "The namespace of Kubernetes .",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "components": {
      "type": "array",
      "items": {
        "type": "object",
        "title": "components schema.",
        "description": "The component lists in which need to be updated.",
        "properties": {
          "name": {
            "type": "string",
            "descritpion": "The name of component which need to updated.",
            "pattern": "^[a-zA-Z0-9_\\-]*$"
          },
          "instance_count": {
            "type": "integer",
            "title": "Instance_count schema.",
            "description": "The component instance count."
          },
          "coloring_nodes": {
            "type": "array",
            "title": "Coloring_nodes schema.",
            "description": "The node list which the component could be deployed.",
            "items": {
              "type": "string",
              "description": "The name referenced to nodes."
            }
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "namespace",
    "env",
    "components"
  ],
  "additionalProperties": false
}

6.2.6 stack_update.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "The stack orchestration inventory.",
  "description": "The stack orchestration inventory.",
  "properties": {
    "env": {
      "type": "string",
      "title": "Name schema.",
      "description": "The stack prototype name, must be unique.",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "namespace": {
      "type": "string",
      "title": "Namespace schema.",
      "description": "The namespace of Kubernetes .",
      "pattern": "^[a-zA-Z0-9_\\-]*$"
    },
    "components": {
      "type": "array",
      "items": {
        "type": "object",
        "title": "components schema.",
        "description": "The component lists in which need to be updated.",
        "properties": {
          "name": {
            "type": "string",
            "descritpion": "The name of component which need to updated.",
            "pattern": "^[a-zA-Z0-9_\\-]*$"
          },
          "image": {
            "type": "string",
            "description": "The image name of component"
          },
          "image_version": {
            "type": "string",
            "description": "The image version of component"
          },
          "configurations": {
            "type": "array",
            "title": "Configurations schema.",
            "description": "",
            "items": {
              "type": "string",
              "description": "The configuration which is used by specified component."
            }
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "namespace",
    "env",
    "components"
  ],
  "additionalProperties": false
}

6.2.7 watchdog.json



{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Destroy inventory",
  "description": "Easemonitor destroy inventory.",
  "type": "object",
  "properties": {
    "profile_server_endpoint": {
      "description": "Specify endpoint of profile server.",
      "type": "string",
      "minLength": 7
    },
    "k8s-envs": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of k8s cluster.",
            "pattern": "^[a-zA-Z0-9_\\-]*$"
          },
          "kubernetes_cluster": {
            "description": "Kubernetes cluster and account infomation.",
            "type": "object",
            "properties": {
              "server": {
                "type": "string"
              },
              "username": {
                "type": "string"
              },
              "password": {
                "type": "string"
              },
              "cert_file_path": {
                "type": "string"
              },
              "cert_key_file_path": {
                "type": "string"
              },
              "ca_file_path": {
                "type": "string"
              }
            },
            "required": [
              "server"
            ]
          },
          "namespace": {
            "description": "The namespace to deploy stack in the kubernetes cluster.",
            "type": "string"
          },
          "deployment_env_name": {
            "description": "Specify deployment enviornment name.",
            "type": "string",
            "minLength": 1
          },
          "health_checker_port": {
            "description": "Specify listen port of health checker.",
            "type": "number"
          },
          "aws_test": {
            "description": "only for test, NEVER SET THIS AS TRUE",
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "kubernetes_cluster"
        ]
      }
    }
  },
  "required": [
    "k8s-envs",
    "profile_server_endpoint"
  ],
  "definitions": {}
}