docs/proposals/image-promotion.md
This proposal describes the best practices and defines patterns for promoting Docker images between different stages (e.g. from development to production). This proposal also describes a way how to configure OpenShift to serve as a Continuous Delivery tool.
This document describes the following ways to promote images:
oc and docker commands manuallycontainer images can be promoted (and the use-cases are valid for):
The container image promotion can be done using the Docker image tags or container image labels. OpenShift also provides more features to add metadata, such as annotations or labels. Using them might allow users to develop complex conditional promotion scenarios, but this document does not describe them.
In some cases, promoting just container images might not be enough and you want to promote the entire deployment or a project as a single unit of promotion. These scenarios are also not covered by this document.
oc tag command. For
example:
oc tag application/image:@sha256:02c104b application/image:qa-ready
This will tag the application/image with SHA256 tag 02c104b as qa-ready.oc import-image application --from=external:application
This will import the external:application image available in 'external'
registry to the application image stream.oc export is -l name=application | oc create -n stage -f -docker tag application/image qa-registry:application/image:qa-readydocker push qa-registry:application/image:qa-readyoc tag command. This means that the cron
job is using polling mechanism to determine if a new version of the image
is available in the internal registry.oc tag as a post-deployment
step.docker tag and docker pushdocker tag and docker pushoc import commandoc tag but have DeploymentConfig independent of
the image change (require manual intervention to roll out a new deployment)oc tag but require human to start a new deploymentAs a developer of Rails application, when I update the source code and push it to a remote source code repository, I want to have my changes tested before deploying them to production. I also want to have the container image that contains applications with my changes to be promoted based on the verification results.
As a user I have a Jenkins server running in my project by following the instructions from the Jenkins example. Then I create the frontend-production DeploymentConfig in my Prod project.
This DeploymentConfig has the ImageChangeTrigger set to watch changes in the "prod-ready" ImageStreamTag:
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"from": {
"kind": "ImageStreamTag",
"name": "origin-ruby-example:prod-ready"
},
"containerNames": [
"frontend"
]
}
}
I also have a BuildConfig defined for my application image that does not specify any triggers.
When a change is detected in remote source code repository, the Jenkins job will connect to OpenShift and start a new build. Based on the build status, Jenkins job then tag the updated application image as prod-ready. When a new image with this tag is available, the frontend-production manages to roll out a new deployment.
As a user I create two DeploymentConfig's, both as part of my "Prod" project:
The "frontend-test" DeploymentConfig has the ImageChangeTrigger set to watch changes in the qa-ready ImageStreamTag. This DeploymentConfig also defines the post lifecycle hook that executes a script in the container deployed and performs additional verification and tests.
Example of DeploymentConfig post-lifecycle hook:
"strategy": {
"type": "Rolling",
"rollingParams": {
"post": {
"failurePolicy": "Abort",
"execNewPod": {
"containerName": "test-container",
"command": [
"/opt/app-root/bin/verify-deployment"
],
}
}
}
}
Based on the result of the verify-deployment command, which runs in the container based on the
application image, the command will promote the image by tagging it as production-ready (e.g. using
the oc tag command). The command might also notify me about the verification failure.
The frontend-production DeploymentConfig has the ImageChangeTrigger set to watch changes in the prod-ready ImageStreamTag. When a new container image with this tag is available, it can automatically roll out a new production deployment. In case you don't want to roll out the frontend-production automatically, you can avoid specifying the ImageChangeTrigger and roll out the new deployment by hand.
As a user I create two projects: 'stage' and 'prod'. Then I create following resources inside these projects:
stage:
prod:
Now I start the 'sample-app-build' using:
$ oc start-build sample-app-build -n stage
This build will produce the 'sample-app:latest' image. This build can be automated by GitHub or generic triggers to build after every commit.
The "sample-app" DeploymentConfig that I created in the "stage" project is configured to trigger a new deployment when the "sample-app:stable" ImageStreamTag is updated. The reason why I use "sample-app:stable" over "sample-app:latest" is that I don't want every commit cause automatic redeployment of the "stage".
To tag the "latest" image, we can run the following command, which will result in the current "sample-app:latest" being automatically deployed in "stage":
$ oc tag stage/sample-app:latest stage/sample-app:stable
Tag sample-app:stable set to stage/sample-app@sha256:<sha>
Now we have our application deployed in the "stage" project and we can perform verification of this deployment, or notify the testers to do it. Once we are happy with this image, we want to promote it for production:
First, we have to allow the the "prod" service account to pull the image from the "stage" repository in container image registry:
$ oc policy add-role-to-user edit system:serviceaccount:stage:default -n prod
Then we can tag the image to the "prod" project:
$ oc tag stage/sample-app:stable prod/sample-app:v0.0.1
$ oc tag prod/sample-app:v0.0.1 prod/sample-app:latest
Since the DeploymentConfig "sample-app" in "prod" is configured to redeploy when the ImageStreamTag "sample-app:latest" is updated, this will cause the image to be deployed in the "prod" project. Also we are making sure that the image we deploy in "prod" is the same image as we tested in "stage".
As a developer of a Rails application, when I update the source code and OpenShift build my image I want to promote the image by passing it through QA and operation teams.
As a platform operator, I want to be able to promote the S2I builder image(s) when a new version is available in Red Hat container image registry. I want to perform additional verifications (iow. deploy to "stage" first) before rolling a new image out to production which causes rebuild of a thousand applications.
openshift/ruby-22-rhel7 image to internal CI registry
oc import-image openshift/ruby-22-rhel7As a developer of the S2I image, I want to make sure that the changes I propose won't break the applications that are based on this image, when they will be rebuilt. For that I want to promote the image as "ok-to-merge", only when the sample application that use this image pass the verification checks.
openshift/ruby-22-rhel7 imageopenshift/ruby-22-rhel7 repositoryThe first use-case describes a typical Continuous Delivery example, where the developer uses both the Jenkins server and the OpenShift to deliver updates to the application.
oc export-image)oc import-image)