Standard Deployment¶
-
class
shpkpr.deployment.
StandardDeployment
(marathon_client, timeout, app_definitions, **kw)¶ StandardDeployment implements Marathon’s basic deployment workflow and uses the primitives provided by the Marathon API to perform a standard rolling deploy according to application settings.
This deployment strategy is best suited for non-web-facing applications or those that can tolerate minor downtime during deployment e.g. consumer or worker applications.
-
execute
(force=False)¶ Execute standard Marathon deployment.
-
Standard default template¶
shpkpr includes a set of default templates which are used when a custom template is not supplied by the user at runtime. The default template used for standard deployments is included below for reference purposes.
{#
Built-In Standard Template
This file contains the default template used by shpkpr when performing a
standard Marathon deployment if no custom template is provided. The goal of
this template is to provide a comprehensive application definition that
works in a wide variety of usecases.
With sensible defaults for most options, it should be possible to deploy a
new or updated application with very minimal configuration.
This template makes some assumptions about your application:
- It is configured via environment variables (12-factor style).
- It runs in a Docker container.
- It exposes at most one TCP port.
Only 2 values are required to deploy an application using this template:
- MARATHON_APP_ID: The name of the deployed application on Marathon
- DOCKER_REPOTAG: The repotag of the Docker image to be deployed
If the application being deployed exposes services via HTTP, it is
recommended that a health check is also configured using the
`MARATHON_HEALTH_CHECK_PATH` variable.
#}
{
{#
Unique identifier for the app consisting of a series of names separated
by slashes. Each name must be at least 1 character and may only contain
digits (0-9), dashes (-), dots (.), and lowercase letters (a-z). The
name may not begin or end with a dash.
When choosing an ID for your application it should meet the following
criteria:
- Be descriptive: A good ID should easily identify what is running. If
in doubt, the GitHub repo name is a good starting point.
- Good: `authentication-service`, `godoc`, `core-documentation`
- Bad: `incongruous-elderberries`, `banana-for-scale`, `so-service-much-http-wow`
- Use a common prefix: Where an application has more than one type of
service to run, all instances should use a common prefix to enable
easy categorization and sorting.
- Good: `some-service/consumer`, `some-service/web`
- Bad: `consumer-some-service`, `web-some-service`
#}
"id": "{{MARATHON_APP_ID}}",
{#
The command that is executed on task startup. This is optional, if not
defined it defaults to the CMD configured in the Docker container at
build time.
#}
{% if MARATHON_CMD is defined %}"cmd": "{{MARATHON_CMD}}",{% endif %}
{#
The number of CPU shares this application needs per instance.
The `cpus` parameter is used for two different purposes in two different
contexts, by Mesos when scheduling tasks across the cluster, and by the
Linux Kernel when scheduling processes on a single machine.
Mesos uses the `cpus` value when deciding on which slave a task should
be scheduled. Mesos treats `cpus` values as absolute, e.g. A box with 4
available CPUs would never be assigned a set of tasks whose `cpus`
values total more than 4. Mesos does not (yet) support oversubscription
of resources at the cluster level.
When a task has been scheduled to a given slave, Linux's scheduler takes
over. An application's `cpus` value is used by CFS (Linux's Completely
Fair Scheduler) to assign a *minimum* relative share of all CPU
resources on the slave, e.g. If a slave is running 3 CPU-bound tasks,
each with a `cpus` value of `0.1`, each will be allocated
*approximately* 33% of the available CPU time. If not all of the tasks
on a given slave are CPU-bound, CFS will allow the spare CPU resource to
be consumed by any task that requires it.
To summarize:
- Marathon’s cpu setting is used for 2 distinct purposes.
- Mesos treats the value as absolute and uses it to schedule a task to a
specific slave with the available resources.
- Linux treats the value as a relative weight, ensuring that an
application has access to a *minimum* share of CPU time (equivalent to
`task.cpus / sum([t.cpus for t in tasks])`).
When choosing a value for `cpus` you should take care not to request
more resources than your application needs:
- Is my application typically CPU bound?
- No: `0.1` is a good default value for `cpus`.
- Yes: `0.5` is a good starting value from which the application can
be monitored and adjusted up/down as necessary.
#}
"cpus": {{MARATHON_CPUS|default(0.1)|require_float(min=0.1)}},
{#
The amount of memory in MB that is needed for the application per
instance. If an application exceeds the amount of memory it has been
allocated, Marathon will kill and restart the task to reclaim the RAM.
#}
"mem": {{MARATHON_MEM|default(128)|require_int(min=0)}},
{# The number of instances of this application to start. #}
"instances": {{MARATHON_INSTANCES|default(1)|require_int(min=0)}},
"container": {
"type": "DOCKER",
"docker": {
{# The name/tag of the Docker image to use. #}
"image": "{{DOCKER_REPOTAG}}",
{% block docker_port_mappings %}
{% if DOCKER_EXPOSED_PORT is defined %}
"portMappings": [
{
{#
Port number within the container that should be exposed
to the host.
#}
"containerPort": {{DOCKER_EXPOSED_PORT|require_int}},
{#
Setting `hostPort` to `0` allows Marathon to dynamically
allocate a port on the host to map.
#}
"hostPort": {{DOCKER_HOST_PORT|default(0)}},
"protocol": "tcp"
}
],
{% endif %}
{% endblock %}
"parameters": [
{#
Passes `--init` to the `docker run` command.
#}
{"key": "init", "value": "{{DOCKER_INIT|default("false")}}"}{% if _all_env|filter_items("LABEL_") %},{% endif %}
{% block docker_labels %}
{% for key, value in _all_env|filter_items("LABEL_", strip_prefix=True) %}
{"key": "label", "value": "{{key|slugify}}={{value}}"}{% if not loop.last %},{% endif %}
{% endfor %}
{% endblock %}
],
"network": "BRIDGE"
}
},
{#
Key value pairs that get added to the environment variables of each task
that is started by Marathon.
#}
"env": {
{% for key, value in _all_env|filter_items("ENV_", strip_prefix=True) %}
"{{key}}": "{{value}}"{% if not loop.last %},{% endif %}
{% endfor %}
},
{#
Attaching metadata to apps can be useful to expose additional
information to other services, so Marathon has the ability to place
labels on apps (for example, you could label apps “staging” and
“production” to mark services by their position in the pipeline).
#}
{% block labels %}
"labels": {
{% for key, value in _all_env|filter_items("LABEL_", strip_prefix=True) %}
"{{key}}": "{{value}}"{% if not loop.last %},{% endif %}
{% endfor %}
},
{% endblock %}
{#
Secrets allow Marathon to retrieve secret data from configured "secret
stores" at application startup time. This allows decoupling of how
secrets are provisioned from the how applications make use of those
secrets at runtime.
Secrets functionality requires the use of a custom Marathon plugin, none
is enabled by default. The exact mechanism by which secrets are made
available to the application at runtime depends on the plugin being
used.
Docs: https://mesosphere.github.io/marathon/docs/plugin.html
#}
"secrets": {
{% for key, value in _all_env|filter_items("SECRET_", strip_prefix=True) %}
"{{key}}": {"source": "{{value}}"}{% if not loop.last %},{% endif %}
{% endfor %}
},
{#
Constraints control where apps run to allow optimizing for either fault
tolerance (by spreading a task out on multiple nodes) or locality (by
running all of an applications tasks on the same node). Constraints have
three parts: a field name, an operator, and an optional parameter. The
field can be the hostname of the agent node or any attribute of the
agent node.
Docs: https://mesosphere.github.io/marathon/docs/constraints.html
#}
"constraints": [
["hostname", "MAX_PER", "{{MARATHON_GROUP_BY|default(2)|require_int(min=1)}}"]
],
{#
During an upgrade all instances of an application get replaced by a new
version. The upgradeStrategy controls how Marathon stops old versions
and launches new versions.
Docs: https://mesosphere.github.io/marathon/docs/deployments.html#rolling-restarts
#}
"upgradeStrategy": {
{#
A number between 0 and 1 that is multiplied with the instance count.
This is the minimum number of healthy nodes that do not sacrifice
overall application purpose. Marathon will make sure, during the
upgrade process, that at any point of time this number of healthy
instances are up.
#}
"minimumHealthCapacity": {{MARATHON_MIN_HEALTH_CAPACITY|default(0)|require_float(min=0, max=1)}},
{#
A number between 0 and 1 which is multiplied with the instance
count. This is the maximum number of additional instances launched
at any point of time during the upgrade process.
#}
"maximumOverCapacity": {{MARATHON_MAX_OVER_CAPACITY|default(0)|require_float(min=0, max=1)}}
},
{#
An array of checks to be performed on running tasks to determine if they
are operating as expected. Health checks begin immediately upon task
launch.
An HTTP health check is considered passing if (1) its HTTP response code
is between 200 and 399, inclusive, and (2) its response is received
within the `timeoutSeconds` period.
If a task fails more than `maxConsecutiveFailures` health checks
consecutively, that task is killed causing Marathon to start more
instances.
#}
{% block healthchecks %}
{% if MARATHON_HEALTH_CHECK_PATH is defined and MARATHON_HEALTH_CHECK_PATH %}
"healthChecks": [
{
{#
Path to endpoint exposed by the task that will provide health
status. Example: “/path/to/health”.
#}
"path": "{{MARATHON_HEALTH_CHECK_PATH}}",
{#
Protocol of the requests to be performed. One of “MESOS_HTTP”,
“MESOS_HTTPS”, “MESOS_TCP”, or “Command”.
#}
"protocol": "{{MARATHON_HEALTH_CHECK_PROTOCOL|default("MESOS_HTTP")}}",
{#
A port index of `0` tells Marathon to make requests to the
application on the first exposed port. In this case, since the
template can only ever expose a single port
(`DOCKER_EXPOSED_PORT` above) it's safe to hardcode this value.
#}
"portIndex": 0,
{#
Health check failures are ignored within this number of
seconds of the task being started or until the task becomes
healthy for the first time.
#}
"gracePeriodSeconds": {{MARATHON_HEALTH_CHECK_GRACE_PERIOD_SECONDS|default(300)|require_int(min=0)}},
{# Number of seconds to wait between health checks. #}
"intervalSeconds": {{MARATHON_HEALTH_CHECK_INTERVAL_SECONDS|default(10)|require_int(min=0)}},
{#
Number of seconds after which a health check is considered a
failure regardless of the response.
#}
"timeoutSeconds": {{MARATHON_HEALTH_CHECK_TIMEOUT_SECONDS|default(5)|require_int(min=0)}},
{#
Number of consecutive health check failures after which the
unhealthy task should be killed.
#}
"maxConsecutiveFailures": {{MARATHON_HEALTH_CHECK_MAX_CONSECUTIVE_FAILURES|default(3)|require_int(min=0)}}
}
],
{% endif %}
{% endblock %}
{#
Configures the termination signal escalation behavior of executors when
stopping tasks. Sets the number of seconds between the executor sending
SIGTERM to a task it is about to stop and then finally sending SIGKILL
to enforce the matter.
Using this grace period, tasks should perform orderly shutdown
immediately upon receiving SIGTERM.
#}
"taskKillGracePeriodSeconds": {{MARATHON_TASK_KILL_GRACE_PERIOD_SECONDS|default(10)|require_int(min=0)}}
}