Rolling App Deployments

Page last updated:

This topic describes how developers use Cloud Foundry Command Line Interface (cf CLI) commands or the Cloud Foundry API (CAPI) to push their apps using a rolling deployment.

For information about the traditional method for addressing app downtime while pushing app updates, see Using Blue-Green Deployment to Reduce Downtime and Risk.

For more information about CAPI, see the Cloud Foundry API (CAPI) documentation.

Prerequisites

The procedures in this topic require one of the following:

  • cf CLI v7: Install cf CLI v7.

  • cf CLI v6: If you use cf CLI v6:

    • You must install cf CLI v6.40 or later.
    • The rolling deployment feature must be enabled for your deployment. Use capi-release v0.168.0 or later and deploy the cc_deployment_updater. For this ops file, there are also external-db and postgres variants.
  • CAPI V3: If you use CAPI V3, you must install the cf CLI.

Commands

This section describes the commands for working with rolling app deployments.

Deploy an App

To deploy an app without incurring downtime:

  • cf CLI v7:
  1. Run:

    cf push APP-NAME --strategy rolling
    

    Where APP-NAME is the name that you want to give your app.

    Note: cf CLI v7 exits when one instance of each process is healthy. It also includes a --no-wait flag on push for users who do not want to wait for the operation to complete. cf push used with the --no-wait flag exits as soon as one instance is healthy.

  • cf CLI v6:
  1. Run:

    cf v3-zdt-push APP-NAME
    

    Where APP-NAME is the name that you want to give your app.

    Note: This command is experimental and unsupported. Consider upgrading to cf CLI v7 to use a supported version of this command. To upgrade to cf CLI v7, see Install cf CLI v7 in Upgrading to cf CLI v7.

  • CAPI V3:
  1. Log in to the cf CLI.

    cf login
    
  2. Create an empty app by running the following curl command with POST /v3/apps. Record the app GUID from the output.

    cf curl /v3/apps \
      -X POST \
      -H "Content-type: application/json" \
      -d '{
        "name": "APP-NAME",
        "relationships": {
          "space": {
            "data": {
              "guid": "SPACE-GUID"
            }
          }
        }
      }'
    

    Where:

    • APP-NAME is the name that you want to give your app.
    • SPACE-GUID is the space identifier that you want to associate with your app.
  3. Create a package with the following curl command with POST /v3/packages. Record the package GUID from the output.

    cf curl /v3/packages \
      -X POST \
      -H "Content-type: application/json" \
      -d '{
        "type": "bits",
        "relationships": {
          "app": {
            "data": {
              "guid": APP-GUID"
            }
          }
        }
      }'
    

    Where APP-GUID is the app GUID that you recorded in the previous step. This app GUID is a unique identifier for your app.

  4. Upload the package bits by running the following curl command with POST /v3/packages/PACKAGE-GUID/upload.

    cf curl /v3/packages/PACKAGE-GUID/upload \
    -X POST \
    -F bits=@"PACKAGED-APP" \
    

    Where:

    • PACKAGE-GUID is the package GUID that you recorded in the previous step.
    • PACKAGED-APP is your app packaged in a file such as .zip.
  5. Create the build by running the following curl command with POST /v3/builds. Record the droplet GUID from the output.

    cf curl /v3/builds \
      -X POST \
      -H "Content-type: application/json" \
      -d '{
        "package": {
           "guid": PACKAGE-GUID"
        }
      }'
    

    Where PACKAGE-GUID is the package GUID that you recorded in a previous step.

  6. Deploy your app by running the following curl command with POST /v3/deployments. To verify the status of the deployment or take action on the deployment, record the deployment GUID from the output.

    cf curl /v3/deployments \
    -X POST \
    -H "Content-type: application/json" \
    -d '{
      "droplet": {
        "guid": "DROPLET-GUID"
      },
      "strategy": "rolling",
      "relationships": {
        "app": {
          "data": {
            "guid": "APP-GUID"
          }
        }
      }
    }'
    

    Where DROPLET-GUID and APP-GUID are the GUIDs that you recorded in previous steps.

Warning: Ensure that you understand the limitations of this feature before running the command. For more information, see Limitations below.

For more information about this command, see How It Works below.

Cancel a Deployment

To stop the deployment of an app that you pushed:

  • cf CLI v7:
  1. Run:

    cf cancel-deployment APP-NAME
    

    Where APP-NAME is the name of the app.

  • cf CLI v6:
  1. Run:

    cf v3-cancel-zdt-push APP-NAME
    

    Where APP-NAME is the name of the app.

    Note: This command is experimental and unsupported. Consider upgrading to cf CLI v7 to use a supported version of this command. To upgrade to cf CLI v7, see Install cf CLI v7 in Upgrading to cf CLI v7.

  • CAPI V3:
  1. Run:

    cf curl /v3/deployments/DEPLOYMENT-GUID/actions/cancel" -X POST
    

    Where DEPLOYMENT-GUID is the GUID of the deployment that you recorded after following the CAPI procedure in Deploy an App above.

This reverts the app to its state from before the deployment started by doing the following:

  • Scaling up the original web process
  • Removing any deployment artifacts
  • Resetting the current_droplet on the app

Note: The cancel command is designed to revert the app to its original state as quickly as possible and does not guarantee zero downtime.

Restart an App

To restart your app without downtime, run the appropriate command below. Restart an app to apply configuration updates that require a restart, such as environment variables or service bindings.

  • cf CLI v7:
  1. Run:

    cf restart APP-NAME --strategy rolling
    

    Where APP-NAME is the name of the app.

  • cf CLI v6:
  1. Run:

    cf v3-zdt-restart APP-NAME
    

    Where APP-NAME is the name of the app.

    Note: This command is experimental and unsupported. Consider upgrading to cf CLI v7 to use a supported version of this command. To upgrade to cf CLI v7, see Install cf CLI v7 in Upgrading to cf CLI v7.

  • CAPI V3:
  1. Run:

    cf curl /v3/deployments \
    -X POST \
    -H "Content-type: application/json" \
    -d '{
      "droplet": {
        "guid": "DROPLET-GUID"
      },
      "strategy": "rolling",
      "relationships": {
        "app": {
          "data": {
            "guid": "APP-GUID"
          }
        }
      }
    }'
    

    Where DROPLET-GUID and APP-NAME are the GUIDs that you recorded in previous steps.

How It Works

This section describes the rolling deployments and their limitations.

Rolling Deployment Process

This section describes the process of pushing an app with a rolling deployment strategy.

  1. The cf push APP-NAME --strategy rolling command does the following:

    1. Stages the updated app package.
    2. Creates a droplet with the updated app package.
    3. Creates a deployment with the new droplet and any new configuration.
      • This starts a new process with one instance that shares the route with the old process.
      • At this point, if you run cf app on your app, you see multiple web processes.
        For more information about the deployment object, see the Deployments section of the CAPI V3 documentation.
  2. After the command creates the deployment, the cc_deployment_updater BOSH job runs in the background, updating deployments as follows:

    1. Adds another instance of the new web process and removes an instance from the old web process.

      Note: This only happens if all instances of the new web process are currently running.

    2. Repeats the above step until the new web process reaches the desired number of instances.
    3. Removes the old web process. The new web process now fully replaces the old web process.
    4. Restarts all non-web processes of the app.
    5. Sets the deployment to DEPLOYED.

Limitations

The following table describes the limitations of when using rolling deployments.

Limitation Description
App Manifests The cf v3-zdt-push command does not support providing an app manifest with the -f flag. If you have a manifest.yml file in your app directory, it is ignored.

Note: This limitation only applies to cf CLI v6.

SSH to app instances Pushing updates to your app with a cf v3-zdt-push command causes the new web process and app GUID to mismatch. cf ssh does not handle this scenario. You must use the cf v3-ssh command instead.

Note: This limitation only applies to cf CLI v6.

Multiple app versions During a deployment, Cloud Foundry serves both the old and new version of your app at the same route. This could lead to user issues if you push backwards-incompatible API changes.
Database migrations Deployments do not handle database migrations. Migrating an app database when the existing app is not compatible with the migration can result in downtime.
Non-web processes Rolling deployments only run web processes through the rolling update sequence described above. The commands restart worker and other non-web processes in bulk after updating all web processes.

The CAPI V3 API introduces the concept of processes as runnable units of an app. Each app has a web process by default. You can specify additional processes with a Procfile, and in some cases buildpacks create additional processes. For more information about processes, see Processes in the CAPI V3 documentation.
Quotas Pushing updates to your app using a rolling deployment strategy creates an extra instance of your app. If you lack sufficient quota, the deployment fails. Admins might need to increase quotas to accommodate rolling deployments.
Simultaneous apps when interrupting a push If you push app before your previous push command for the same app has completed, your first push gets interrupted. Until the last deployment completes, there might be many versions of the app running at the same time. Eventually, the app runs the code from your most recent push.

View the Status of Rolling Deployments

You can use CAPI to view the status of rolling deployments.

To view the status of a rolling deployment:

  1. Log in to the cf CLI:

    cf login
    
  2. Find the GUID of your app by running:

    cf app APP-NAME --guid
    

    Where APP-NAME is the name of the app.

  3. Find the deployment for that app by running:

    cf curl GET /v3/deployments?app_guids=APP-GUID&status_values=ACTIVE
    

    Where APP-GUID is the GUID of the app. Deployments are listed in chronological order, with the latest deployment displayed as the last in a list.

  4. Run:

    cf curl GET /v3/deployments/DEPLOYMENT-GUID
    

    Where DEPLOYMENT-GUID is the GUID of the rolling deployment.

cf curl GET /v3/deployments/DEPLOYMENT-GUID returns the following properties about the status of rolling deployments:

  • status.value: Indicates if the deployment is ACTIVE or FINALIZED.

  • status.reason: Provides detail about the deployment status.

  • status.details: Provides the timestamp for the most recent successful health check. The value of the status.details property can be nil if there is no successful health check for the deployment. For example, there might be no successful health check if the deployment was cancelled.

The following table describes the possible values for the status.value and status.reason properties:

status.value status.reason Description
ACTIVE DEPLOYING The deployment is deploying.
ACTIVE CANCELLING The deployment is cancelling.
FINALIZED DEPLOYED The deployment was deployed.
FINALIZED CANCELLED The deployment was cancelled.
FINALIZED SUPERSEDED The deployment was stopped and did not finish deploying because there was another deployment created for the app.
FINALIZED DEGENERATE The deployment was created incorrectly by the system.
View the source for this page in GitHub