Deploy

Workflow for deployment of an environment

The deployment workflow is the most complex in Bunnyshell. We will go through each stage of the workflow, and explain both the order of stages, as well as what is being ran in each step.

Deployment Flow

When a deploy is triggered, the following stages are ran, sequentially.

  1. The deployment is Queued, meaning it is waiting for a background worker to free up or be created and start the process. Some validations are taking place before anything gets started.

  2. Next, image builds are being ran in parallel in a single stage: both DockerImage components, as well as images needed by the Docker-compose components

  3. The needed checks are performed on the cluster, to see if the cluster meets the requirements imposed by the environment (being able to expose URLs, for example). If it does not, Bunnyshell will try to install the needed resources within your cluster.

  4. Component cleanup refers to Components which have been marked for deletion. These will have all their resources deleted from Kubernetes.
    Note: If the cleanup fails for whatever reason, the deployment is allowed to continue.
    Note: there is a 25 minute wait timeout on the cleanup jobs, but the jobs are not killed immediately. So, please be advised, even if the Component disappears from the Environment, cleanup jobs may run even after the deployment has marked it as timed out; this may cause interferences in next deployments.
    Note: the Volumes may be deleted later, as they are deleted only when no Pod actually used them anymore.

📘

The destroy scripts which will be executed are the ones last deployed, so if you change the destroy script and immediately delete the Component (without deploying first) the latest version of scripts will NOT be ran, but the previous one, which was deployed before deleting.

  1. Afterwards, all components of kind Helm, KubernetesManifest, Terraform GenericComponent are deployed by running their defined scripts / commands from the deploy attribute of each. They are ran sequentially, so the output from one can be used as input for others which follow.

  2. Next, all Docker-compose components of kind Application, Database and Service are bundled into one single Kubernetes manifest, generated with kompose.io and applied in one go.
    Important: The manifest containing all Docker-compose components is applied into a new namespace, created specifically for this Environment, also called the Environment's default namespace.

  3. The resource cleanup is performed, which involves deleting resources which are not part of this deployment from Kubernetes namespaces involved in the Environment.
    Please note this is different from Step 4, where entire Components get deleted. Here, only extra resources are deleted.
    Note: only resources which are part of this environment are selected, meaning they were previously deployed by Bunnyshell; this means that if you have resources which were created separately from Bunnyshell, they will not be deleted.

  4. Bunnyshell waits for all the resources to be created, and for the Pods to be up-and-running before moving the Environment into the Running status and finalizing the deployment (eg. sending notifications).

Below, a graphical representation is also listed, so it is easier to follow through.

📘

DNS Records

The DNS records for Ingresses are created after each component's manifest has been applied.

Deployment Strategy

Depending on the needs of the application, as well as the available capacity within the cluster and the target time for the deployment, you may choose between 2 strategies for deploying:

RollingUpdate

This will ensure an uninterrupted service, but take more time to complete and need more resources in the cluster, as new Pods are created before old Pods are removed.

This is also Kubernetes' default deployment strategy.

There are 2 additional parameters which need to be configured:

  • maxUnavailable: defines the maximum number of Pods which can be unavailable at any time during the deployment - optional, can be integer or percent
  • maxSurge: defines the maximum number of Pods which can be created on top of the desisred number of Pods at any time during the deployment - optional, can be integer or percent

Percentages are expressed out of the (future) total number of Pods requested (replicas).

deployment:
  strategy:
    type: RollingUpdate
    maxSurge: 50% # optional, default value is 25%
    maxUnavailable: 2 # optional, default value is 25%

📘

Use only numeric values (integers or percents) for maxUnavailable and maxSurge.
Example: do not write it as "3", but as 3 instead.

🚧

We enforce the defaults for maxUnavailable and maxSurge in the Deployment, if not specified in Bunnyshell. If you have set values for these outside Bunnyshell, they will be overwritten.

❗️

Important

Regardless of the chosen deployment strategy, if the Deployment uses Persistent Volume Claims (PVCs), Bunnyshell enforces the strategy to Recreate.

This is to prevent failures caused by RollingUpdate and volumes combination.

Example: the Old Pod is still running, and New Pod is scheduled on a different node; the PVC is mounted into the node which hosts the Old Pod, so it cannot be mounted simultaneously into the New Pod's node too. So the new Pod would wait for the PVC to be available, and this never happens, therefore the Deployment will remain forever in the Progressing status).

Recreate

This will be faster and consume less resources in the cluster, but with service interruptions, as old Pods are simply deleted, then new Pods are created.

No other parameters are configurable.

deployment:
  strategy:
    type: Recreate