# Deployments in OpenShift
## Overview
In OpenShift, deployment is an update to a single replication controller's pod template based on triggered events. The deployment subsystem provides:
* [Declarative definition](#defining-a-deploymentconfig) of a desired deployment configuration which drives automated deployments by the system
* [Triggers](#triggers) which drive new deployments in response to events
* [Rollbacks](#rollbacks) to a previous deployment
* [Strategies](#strategies) for deployment rollout behavior which are user-customizable
* Audit history of deployed pod template configurations
#### Concepts
An OpenShift `deploymentConfig` describes a single `template` and a set of `triggers` for when a new `deployment` should be created. A `deployment` is simply a specially annotated `replicationController`. A `strategy` is responsible for making a `deployment` live in the cluster.
Each time a new deployment is created, the `latestVersion` field of `deploymentConfig` is incremented, and a `deploymentCause` is added to the `deploymentConfig` describing the change that led to the latest deployment.
## Defining a deploymentConfig
A `deploymentConfig` in OpenShift is a REST object which can be POSTed to the API server to create a new instance. Consider a simple configuration which should result in a new `deployment` every time a Docker image tag changes.
```
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "frontend"
},
"spec": {
"strategy": {
"type": "Recreate",
"resources": {}
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"helloworld"
],
"from": {},
"lastTriggeredImage": ""
}
}
],
"replicas": 1,
"selector": {
"name": "frontend"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"name": "frontend"
}
},
"spec": {
"containers": [
{
"name": "helloworld",
"image": "openshift/openshift/origin-ruby-sample",
"ports": [
{
"containerPort": 8080,
"protocol": "TCP"
}
],
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"capabilities": {},
"securityContext": {
"capabilities": {},
"privileged": false
}
}
],
"restartPolicy": "Always",
"dnsPolicy": "ClusterFirst"
}
}
}
}
```
This specification will create a new `deploymentConfig` named `frontend`. A single ImageChange `trigger` is defined, which causes a new `deployment` to be created each time the `openshift/origin-ruby-sample:latest` tag value changes. The Recreate `strategy` makes the `deployment` live by removing any prior `deployment` and increasing the replica count of the new `deployment`.
## Triggers
A `deploymentConfig` contains `triggers` which drive the creation of new deployments in response to events (both inside and outside OpenShift). The following trigger types are supported:
##### Image change triggers
The ImageChange `trigger` will result in a new deployment whenever the value of a Docker `imageRepository` tag value changes. Consider an example trigger.
```
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"helloworld"
],
"repositoryName": "openshift/origin-ruby-sample",
"tag": "latest"
}
}
```
In this example, when the `latest` tag value for the `imageRepository` named `openshift/origin-ruby-sample` changes, the containers specified in `containerNames` for the `deploymentConfig` will be updated with the new tag value, and a new `deployment` will be created.
If the `automatic` option is set to `false`, the trigger is effectively disabled.
##### Config change triggers
The ConfigChange `trigger` will result in a new deployment whenever changes are detected to the `template` of the `deploymentConfig`. Suppose the REST API is used to modify an environment variable in a container within the `template`.
```
{
"type": "ConfigChange"
}
```
This `trigger` will cause a new `deployment` to be created in response to the `template` modification.
## Strategies
A `deploymentConfig` has a `strategy` which is responsible for making new deployments live in the cluster. Each application has different requirements for availability (and other considerations) during deployments. OpenShift provides out-of-the-box strategies to support a variety of deployment scenarios:
##### Recreate strategy
The Recreate `strategy` has very basic behavior.
```
{
"type": "Recreate"
}
```
The algorithm for this `strategy` is:
1. Find and destroy any existing `deployment` (by reducing its `replicationController` replica count to 0, and finally deleting it)
2. Ensure that the old `replicationController` and `pods` are actually destroyed
3. Set the replica count of the new `replicationController` to 1
4. Ensure that pods defined by the new `replicationController` are created
##### Custom strategy
The Custom `strategy` allows users of OpenShift to provide their own deployment behavior.
```
{
"type": "Custom",
"customParams": {
"image": "organization/strategy",
"command": ["command", "arg1"],
"environment": [
{
"name": "ENV_1",
"value": "VALUE_1"
}
]
}
}
```
With this specification, the `organization/strategy` Docker image will carry out the `strategy` behavior. The optional `command` array overrides any `CMD` directive specified in the image's Dockerfile. The optional `environment` variables provided will be added to the execution environment of the `strategy` process.
Additionally, the following environment variables are provided by OpenShift to the `strategy` process:
* `OPENSHIFT_DEPLOYMENT_NAME` - the name of the `replicationController` representing the new `deployment`
* `OPENSHIFT_DEPLOYMENT_NAMESPACE` - the namespace of the `replicationController` representing the new `deployment`
The replica count of the `replicationController` for the new deployment will be 0 initially. The responsibility of the `strategy` is to make the new `deployment` live using whatever logic best serves the needs of the user.
## Rollbacks
Rolling a deployment back to a previous state is a two step process accomplished by:
1. POSTing a `rollback` API object to a special endpoint, which generates and returns a new `deploymentConfig` representing the rollback state
2. POSTing the new `deploymentConfig` to the API server
The `rollback` API object configures the generation process and provides the scope of the rollback. For example, given a previous deployment `deployment-1` and the current deployment `deployment-2`:
```
{
"kind": "DeploymentConfigRollback",
"apiVersion": "v1",
"spec": {
"from": {
"name": "deployment-1"
},
"includeTriggers": false,
"includeTemplate": true,
"includeReplicationMeta": false,
"includeStrategy": true
}
}
```
With this rollback specification, a new `deploymentConfig` named `deployment-3` will be generated, containing the details of `deployment-2` with the specified portions of `deployment-1` overlayed. The generation options are:
* `includeTemplate` - whether to roll back `podTemplate` of the `deploymentConfig`
* `includeTriggers` - whether to roll back `triggers` of the `deploymentConfig`
* `includeReplicationMeta` - whether to roll back `replicas` and `selector` of the `deploymentConfig`
* `includeStrategy` - whether to roll back the `strategy` of the `deploymentConfig`
Note that `namespace` is specified on the `rollback` itself, and will be used as the namespace from which to obtain the `deployment` specified in `from`.