Google Cloud Platform offers a “pre-emptible” option for it’s virtual machines. This means that google will shut your instance(s) down within a 24-hour period. This gets you an 80% discount (see: https://cloud.google.com/preemptible-vms).

What if we want to auto-magically start our instances back up? I have the solution. We will create a CronJob on Kubernetes which will run every 15-minutes and will automatically start our stopped instances.

The ConfigMap

First we need to create a ConfigMap to hold our values:

configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: gcloud-config
data:
  PROJECT: <your google cloud project name>
  ZONE: <the zone of the instance>
  INSTANCE_NAME: <name of the instance>

Now we need to install it with:

$ kubectl apply -f configmap.yaml

The Secret

We need to store our Google Cloud Platform Service Account in a Kubernetes Secret. This will be mounted by our Pod and will be available on the file system:

$ kubectl create secret generic gcloud-service-account \
                    --from-file=<path to your .json key>

The CronJob

The meat of the puzzle is the CronJob. This will run every minute (or you can change it to your liking) and will start our instance:

cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob

metadata:
  name: gcloud-preemptible-starter
spec:
  schedule: "* * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: gcloud-preemptible-starter
              image: google/cloud-sdk:183.0.0-alpine
              resources:
                requests:
                  cpu: 0.1
                  memory: 128M
                limits:
                  memory: 512M
              args:
                - /bin/sh
                - -c
                - gcloud auth activate-service-account --key-file /config/*.json && gcloud compute instances start $(INSTANCE_NAME) --project $(PROJECT) --zone $(ZONE)
              env:
                - name: PROJECT
                  valueFrom:
                    configMapKeyRef:
                      name: gcloud-config
                      key: PROJECT
                - name: ZONE
                  valueFrom:
                    configMapKeyRef:
                      name: gcloud-config
                      key: ZONE
                - name: INSTANCE_NAME
                  valueFrom:
                    configMapKeyRef:
                      name: gcloud-config
                      key: INSTANCE_NAME
              volumeMounts:
                - name: gcloud-service-account
                  mountPath: /config
                  readOnly: true
          restartPolicy: Never
          volumes:
            - name: gcloud-config
              configMap:
                name: gcloud-config
            - name: gcloud-service-account
              secret:
                secretName: gcloud-service-account

Now we can install it with:

$ kubectl apply -f cronjob.yaml

You should now be able to see your cronjob:

$ kubectl get cronjob

NAME                                  SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
gcloud-preemptible-starter            * * * * *     False     0        20s             7m33s

To get the logs out of our cronjob run:

$ kubectl logs pod/gcloud-preemptible-starter-1560486060-hcnmh

Activated service account credentials for: [[email protected]account.com]
Starting instance(s) centos-1...
.done.
Updated [https://www.googleapis.com/compute/v1/projects/streaming-platform-production/zones/us-east1-b/instances/centos-1].

See Also

Have questions, comments or concerns? Contact Me!

This tutorial also has a complimentary repository where you can simply make install,
See https://github.com/mateothegreat/k8-byexamples-gcloud-preemptible-starter.