Deployments

A deployment describes how a Docker image is going to be deployed:

  1. The desired number of replicas that should be running

  2. The allowed number of unavailable replicas - used during rolling updates

  3. The strategy for updating container images

  4. Labels to identify the deployment - used by service to attach to the right pods.

  5. Lists environment variables.

Note that this gets the Docker image deployed, but you’ll need to create a service that becomes the single endpoint that ties the multiple pods together, and an ingress to route requests based on the URL that the request came in on.

This is an example YAML file for a deployment, which is the suggested way to create a deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-dev                      # Name of this deployment
spec:
  replicas: 1                           # Desired number of replicas
  selector:                             # The selector specifies the labels of the
    matchLabels:                        # pods for this replication set
      app: tomcat
      env: dev
  strategy:                             # Indicates the strategy for rolling updates
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1                       # Max extra nodes while creating updates
      maxUnavailable: 1                 # Max number of nodes that can be down while updating
  minReadySeconds: 5                    # Number of seconds before pod is considered ready
  template:                             # This section describes the pod that will be replicated
    metadata:
      labels:                           # Labels assigned to the pod.  This is useful to find pods by label.
        app: tomcat
        env: dev
    spec:
      containers:
      - name: tomcat                    # A name you give the container for the image.
        image: tomcat:7                 # The Docker image for the container
        ports:
          - containerPort: 8080
        env:                            # Environment variables provided to the container
          - name: DS_URL
            valueFrom:
              secretKeyRef:             # Here the value is being extracted from secrets.
                name: tomcat-dev
                key: url
          - name: DS_USR
            valueFrom:
              secretKeyRef:
                name: tomcat-dev
                key: username
          - name: DS_PWD
            valueFrom:
              secretKeyRef:
                name: tomcat-dev
                key: password

Note: The first part of the spec: describes the replication strategy. The second part, template: describes the pod the Docker image will be deployed to. These two parts are associated to each other with the matchLabels and labels section.

Here is an example of a deployment:

from k9.helper import (
    set_default_namespace,
    create_namespace,
    delete_namespace,
    create_secret,
    delete_secret,
    create_deployment,
    update_deployment_image,
    scale_deployment,
    delete_deployment
)

def test_deployments(self):
    try:
        # Create namespace
        set_default_namespace("deployment-unit-test")
        create_namespace()

        # Create secret - you really should query user rather than embed real
        # secrets in your source code.
        secret_name = "tomcat-dev"
        secrets = {
            'url': 'https://some/url',
            'password': 'My1SecretPassword',
            'username': 'postgres'
        }
        create_secret(secret_name, secrets)

        # Create Deployment
        deploy_name = 'tomcat-dev'
        body = read_yaml('../test/tomcat-deploy-dev.yml')
        create_deployment(body)

        # This is an example of updating the deployment to a a later version of
        # Tomcat.  For example, you would run this from Jenkins when building an
        # updated version of your app.
        update_deployment_image(deploy_name, 'tomcat', 'tomcat:8')

        # This is an example of scaling your deployment from 2 to 3 replicas
        spec = {
            'replicas': 3
        }
        scale_deployment(deploy_name, spec)


    finally:
        # This is here to document how you delete these items.
        # Typically, you would not delete this unless you are writing
        # a unit test.
        delete_deployment(deploy_name)
        delete_secret(secret_name)
        delete_namespace()
k9.apps.list_deployments(namespace: Optional[str] = None)[source]

Lists deployments in a given namespace.

Parameters

namespace – Namespace you want to search. If None, the default namespace is used.

Returns

A list of deployment names.

k9.apps.deployment_exists(name: str, namespace: Optional[str] = None)[source]

Returns True if the specified deployment exists.

Parameters
  • name – The name of the deployment

  • namespace – The namespace to search in. If none, we use the default namespace.

Returns

True if the deployment exists in the specified namespace (or default if not provided).

k9.apps.get_deployment(name: str, namespace: Optional[str] = None)[source]

Get a specific deployment by name.

Parameters
  • name – Name of deployment to retrieve.

  • namespace – Namespace to search. If None, the default namespace is used.

Returns

V1Deployment

k9.apps.create_deployment(body: dict, namespace: Optional[str] = None)[source]

Create a deployment from a definition file:

Parameters
Returns

V1Deployment

You’ll most likely create a deployment configuration file and import that in as follows:

Sample YAML file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat
      env: dev
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: tomcat
        env: dev
    spec:
      containers:
      - name: tomcat
        image: tomcat:7
        ports:
          - containerPort: 8080
        env:
          - name: DS_URL
            valueFrom:
              secretKeyRef:
                name: tomcat-dev
                key: ds-url
          - name: DS_USR
            valueFrom:
              secretKeyRef:
                name: tomcat-dev
                key: username
          - name: DS_PWD
            valueFrom:
              secretKeyRef:
                name: tomcat-dev
                key: password

Example:

import k9.helper as k9

body = k9.read_yaml('tomcat-deploy-dev.yml')
k9.create_deployment(body)
k9.apps.delete_deployment(name: str, namespace: Optional[str] = None)[source]

Delete the specified deployment.

Parameters
  • name – Name of deployment to remove.

  • namespace – Namespace to remove deployment from. If None, the default namespace is used.

Returns

None if deployment did not exist, otherwise V1Status

k9.apps.update_deployment_image(name: str, container: str, image: str, namespace: Optional[str] = None)[source]

Updates the specified deployment name with a new image tag for the container. The container name must match the container name specified in the original deployment.

This will perform a rolling update if max_unavailable replicas is less than the total number of replicas for the cluster.

Parameters
  • name – Name of the deployment to update

  • container – Name of the container within the deployment to update.

  • image – The image and tag of the image to update the container to.

  • namespace – The namespace to find the deployment in. If None, the default namespace is used.

Returns

V1Deployment

The following example results in a rolling update to to Tomcat 8:

update_deployment_image(deploy_name, 'tomcat', 'tomcat:8')

Note that the container name matches the specification of the deployment YAML shown above and changes the version of Tomcat from version 7 to version 8.

k9.apps.scale_deployment(name: str, spec: str, namespace: Optional[str] = None)[source]

Updates the scaling specification for this deployment.

Parameters
  • name – Name of deployment to update.

  • spec – The updated specification of the scaling parameters.

  • namespace – The namespace to update the deployment in. If namespace is None, the default namespace is used.

Returns

V1Scale

Other useful references: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#scaling-a-deployment

Example to scale up the deployment to 3 replicas:

spec = {
    'replicas': 3
}
scale_deployment(deploy_name, spec)