Skip to content

Instantly share code, notes, and snippets.

@smarterclayton
Created November 16, 2016 18:55
Show Gist options
  • Save smarterclayton/a85d705fb1b2942a7560114d4b16d218 to your computer and use it in GitHub Desktop.
Save smarterclayton/a85d705fb1b2942a7560114d4b16d218 to your computer and use it in GitHub Desktop.
Blue Green OpenShift Jenkins example from a pipeline
{
"kind": "Template",
"apiVersion": "v1",
"metadata": {
"name": "jenkins-pipeline-example",
"creationTimestamp": null,
"annotations": {
"description": "This example showcases the new Jenkins Pipeline integration in OpenShift, which performs continuous integration and deployment right on the platform. The template contains a Jenkinsfile - a definition of a multi-stage CI/CD process - that leverages the underlying OpenShift platform for dynamic and scalable builds. OpenShift integrates the status of your pipeline builds into the web console allowing you to see your entire application lifecycle in a single view.",
"iconClass": "icon-jenkins",
"tags": "instant-app,jenkins"
}
},
"message": "A Jenkins server will be automatically instantiated in this project to manage the Pipeline BuildConfig created by this template. You will be able to log in to it using your OpenShift user credentials.",
"objects": [
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "sample-pipeline",
"creationTimestamp": null,
"labels": {
"name": "sample-pipeline"
},
"annotations": {
"pipeline.alpha.openshift.io/uses": "[{\"name\": \"${NAME}\", \"namespace\": \"\", \"kind\": \"DeploymentConfig\"}]"
}
},
"spec": {
"triggers": [
{
"type": "GitHub",
"github": {
"secret": "secret101"
}
},
{
"type": "Generic",
"generic": {
"secret": "secret101"
}
}
],
"strategy": {
"type": "JenkinsPipeline",
"jenkinsPipelineStrategy": {
"jenkinsfile": "node('nodejs') {\nstage 'build'\nopenshiftBuild(buildConfig: '${NAME}', showBuildLogs: 'true')\nstage 'deploy'\nopenshiftDeploy(deploymentConfig: '${NAME}')\n}"
}
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "blue-${NAME}"
},
"spec": {
"to": {
"kind": "Service",
"name": "${NAME}-blue"
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "green-${NAME}"
},
"spec": {
"to": {
"kind": "Service",
"name": "${NAME}-green"
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}"
},
"spec": {
"to": {
"kind": "Service",
"name": "${NAME}-blue",
"weight": "100"
},
"alternateBackends": [{"name":"${NAME}-green", "weight": "0"}]
}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}",
"annotations": {
"description": "Keeps track of changes in the application image"
}
}
},
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}",
"annotations": {
"description": "Defines how to build the application"
}
},
"spec": {
"source": {
"type": "Git",
"git": {
"uri": "${SOURCE_REPOSITORY_URL}",
"ref": "${SOURCE_REPOSITORY_REF}"
},
"contextDir": "${CONTEXT_DIR}"
},
"strategy": {
"type": "Source",
"sourceStrategy": {
"from": {
"kind": "ImageStreamTag",
"namespace": "${NAMESPACE}",
"name": "nodejs:4"
},
"env": [
{
"name": "NPM_MIRROR",
"value": "${NPM_MIRROR}"
}
]
}
},
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "${NAME}:latest"
}
},
"triggers": [
{
"type": "GitHub",
"github": {
"secret": "${GITHUB_WEBHOOK_SECRET}"
}
},
{
"type": "Generic",
"generic": {
"secret": "${GENERIC_WEBHOOK_SECRET}"
}
}
],
"postCommit": {
"script": "npm test"
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}-blue",
"annotations": {
"service.alpha.openshift.io/dependencies": "[{\"name\": \"${DATABASE_SERVICE_NAME}\", \"namespace\": \"\", \"kind\": \"Service\"}]"
}
},
"spec": {
"ports": [
{
"name": "web",
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"name": "${NAME}-blue"
}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}-blue",
"annotations": {
"description": "Defines how to deploy the application server"
}
},
"spec": {
"strategy": {
"type": "Rolling"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": false,
"containerNames": [
"nodejs-mongodb-example"
],
"from": {
"kind": "ImageStreamTag",
"name": "${NAME}:blue"
}
}
},
{
"type": "ConfigChange"
}
],
"replicas": 1,
"selector": {
"name": "${NAME}-blue"
},
"template": {
"metadata": {
"name": "${NAME}-blue",
"labels": {
"name": "${NAME}-blue"
}
},
"spec": {
"containers": [
{
"name": "nodejs-mongodb-example",
"image": " ",
"ports": [
{
"containerPort": 8080
}
],
"env": [
{
"name": "DATABASE_SERVICE_NAME",
"value": "${DATABASE_SERVICE_NAME}"
},
{
"name": "MONGODB_USER",
"value": "${DATABASE_USER}"
},
{
"name": "MONGODB_PASSWORD",
"value": "${DATABASE_PASSWORD}"
},
{
"name": "MONGODB_DATABASE",
"value": "${DATABASE_NAME}"
},
{
"name": "MONGODB_ADMIN_PASSWORD",
"value": "${DATABASE_ADMIN_PASSWORD}"
}
],
"readinessProbe": {
"timeoutSeconds": 3,
"initialDelaySeconds": 3,
"httpGet": {
"path": "/pagecount",
"port": 8080
}
},
"livenessProbe": {
"timeoutSeconds": 3,
"initialDelaySeconds": 30,
"httpGet": {
"path": "/pagecount",
"port": 8080
}
},
"resources": {
"limits": {
"memory": "${MEMORY_LIMIT}"
}
}
}
]
}
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}-green",
"annotations": {
"service.alpha.openshift.io/dependencies": "[{\"name\": \"${DATABASE_SERVICE_NAME}\", \"namespace\": \"\", \"kind\": \"Service\"}]"
}
},
"spec": {
"ports": [
{
"name": "web",
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"name": "${NAME}-green"
}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${NAME}-green",
"annotations": {
"description": "Defines how to deploy the application server"
}
},
"spec": {
"strategy": {
"type": "Rolling"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": false,
"containerNames": [
"nodejs-mongodb-example"
],
"from": {
"kind": "ImageStreamTag",
"name": "${NAME}:green"
}
}
},
{
"type": "ConfigChange"
}
],
"replicas": 1,
"selector": {
"name": "${NAME}-green"
},
"template": {
"metadata": {
"name": "${NAME}-green",
"labels": {
"name": "${NAME}-green"
}
},
"spec": {
"containers": [
{
"name": "nodejs-mongodb-example",
"image": " ",
"ports": [
{
"containerPort": 8080
}
],
"env": [
{
"name": "DATABASE_SERVICE_NAME",
"value": "${DATABASE_SERVICE_NAME}"
},
{
"name": "MONGODB_USER",
"value": "${DATABASE_USER}"
},
{
"name": "MONGODB_PASSWORD",
"value": "${DATABASE_PASSWORD}"
},
{
"name": "MONGODB_DATABASE",
"value": "${DATABASE_NAME}"
},
{
"name": "MONGODB_ADMIN_PASSWORD",
"value": "${DATABASE_ADMIN_PASSWORD}"
}
],
"readinessProbe": {
"timeoutSeconds": 3,
"initialDelaySeconds": 3,
"httpGet": {
"path": "/pagecount",
"port": 8080
}
},
"livenessProbe": {
"timeoutSeconds": 3,
"initialDelaySeconds": 30,
"httpGet": {
"path": "/pagecount",
"port": 8080
}
},
"resources": {
"limits": {
"memory": "${MEMORY_LIMIT}"
}
}
}
]
}
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
"annotations": {
"description": "Exposes the database server"
}
},
"spec": {
"ports": [
{
"name": "mongodb",
"port": 27017,
"targetPort": 27017
}
],
"selector": {
"name": "${DATABASE_SERVICE_NAME}"
}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
"annotations": {
"description": "Defines how to deploy the database"
}
},
"spec": {
"strategy": {
"type": "Recreate"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"mongodb"
],
"from": {
"kind": "ImageStreamTag",
"namespace": "${NAMESPACE}",
"name": "mongodb:3.2"
}
}
},
{
"type": "ConfigChange"
}
],
"replicas": 1,
"selector": {
"name": "${DATABASE_SERVICE_NAME}"
},
"template": {
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
},
"spec": {
"containers": [
{
"name": "mongodb",
"image": " ",
"ports": [
{
"containerPort": 27017
}
],
"env": [
{
"name": "MONGODB_USER",
"value": "${DATABASE_USER}"
},
{
"name": "MONGODB_PASSWORD",
"value": "${DATABASE_PASSWORD}"
},
{
"name": "MONGODB_DATABASE",
"value": "${DATABASE_NAME}"
},
{
"name": "MONGODB_ADMIN_PASSWORD",
"value": "${DATABASE_ADMIN_PASSWORD}"
}
],
"readinessProbe": {
"timeoutSeconds": 1,
"initialDelaySeconds": 3,
"exec": {
"command": [ "/bin/sh", "-i", "-c", "mongo 127.0.0.1:27017/$MONGODB_DATABASE -u $MONGODB_USER -p $MONGODB_PASSWORD --eval=\"quit()\""]
}
},
"livenessProbe": {
"timeoutSeconds": 1,
"initialDelaySeconds": 30,
"tcpSocket": {
"port": 27017
}
},
"resources": {
"limits": {
"memory": "${MEMORY_MONGODB_LIMIT}"
}
},
"volumeMounts": [
{
"name": "${DATABASE_SERVICE_NAME}-data",
"mountPath": "/var/lib/mongodb/data"
}
]
}
],
"volumes": [
{
"name": "${DATABASE_SERVICE_NAME}-data",
"emptyDir": {
"medium": ""
}
}
]
}
}
}
}
],
"parameters": [
{
"name": "NAME",
"displayName": "Name",
"description": "The name assigned to all of the frontend objects defined in this template.",
"required": true,
"value": "nodejs-mongodb-example"
},
{
"name": "APPLICATION_DOMAIN",
"displayName": "Application Hostname",
"description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted.",
"value": ""
},
{
"name": "SOURCE_REPOSITORY_URL",
"displayName": "Git Repository URL",
"description": "The URL of the repository with your application source code.",
"required": true,
"value": "https://github.com/openshift/nodejs-ex.git"
},
{
"name": "DATABASE_NAME",
"displayName": "Database Name",
"required": true,
"value": "sampledb"
},
{
"name": "DATABASE_USER",
"displayName": "MongoDB Username",
"description": "Username for MongoDB user that will be used for accessing the database.",
"generate": "expression",
"from": "user[A-Z0-9]{3}"
},
{
"name": "DATABASE_PASSWORD",
"displayName": "MongoDB Password",
"description": "Password for the MongoDB user.",
"generate": "expression",
"from": "[a-zA-Z0-9]{16}"
},
{
"name": "MEMORY_LIMIT",
"displayName": "Memory Limit",
"description": "Maximum amount of memory the Node.js container can use.",
"required": true,
"value": "512Mi"
},
{
"name": "MEMORY_MONGODB_LIMIT",
"displayName": "Memory Limit (MongoDB)",
"description": "Maximum amount of memory the MongoDB container can use.",
"required": true,
"value": "512Mi"
},
{
"name": "DATABASE_SERVICE_NAME",
"displayName": "Database Service Name",
"required": true,
"value": "mongodb"
},
{
"name": "DATABASE_ADMIN_PASSWORD",
"displayName": "Database Administrator Password",
"description": "Password for the database admin user.",
"generate": "expression",
"from": "[a-zA-Z0-9]{16}"
},
{
"name": "SOURCE_REPOSITORY_REF",
"displayName": "Git Reference",
"description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch."
},
{
"name": "CONTEXT_DIR",
"displayName": "Context Directory",
"description": "Set this to the relative path to your project if it is not in the root of your repository."
},
{
"name": "GITHUB_WEBHOOK_SECRET",
"displayName": "GitHub Webhook Secret",
"description": "A secret string used to configure the GitHub webhook.",
"generate": "expression",
"from": "[a-zA-Z0-9]{40}"
},
{
"name": "GENERIC_WEBHOOK_SECRET",
"displayName": "Generic Webhook Secret",
"description": "A secret string used to configure the Generic webhook.",
"generate": "expression",
"from": "[a-zA-Z0-9]{40}"
},
{
"name": "NPM_MIRROR",
"displayName": "Custom NPM Mirror URL",
"description": "The custom NPM mirror URL",
"value": ""
},
{
"name": "NAMESPACE",
"displayName": "Namespace",
"description": "The OpenShift Namespace where the NodeJS and MongoDB ImageStreams reside.",
"required": true,
"value": "openshift"
}
],
"labels": {
"template": "application-template-sample-pipeline"
}
}
@smarterclayton
Copy link
Author

@smarterclayton
Copy link
Author

smarterclayton commented Nov 16, 2016

Deploy pseudo code:

# stage deploy
# active='$(oc get route foo -o jsonpath='{ .spec.to.name }')'
# figure out which one is active from the route (get backend with 100)
# tag nodejs-mongodb-example:latest -> nodejs-mongodb-example:<inactive>
# deploy <inactive>
# wait
# stage confirm
# human confirm / auto confirm
# stage swap
# swap oc set route-backends <routename> <active>=100 <inactive>=0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment