<p>I am currently facing a situation where I need to deploy a small cluster (only 4 pods for now) which will be containing 4 different microservices. This cluster has to be duplicated so I can have one PRODUCTION cluster and one DEVELOPMENT cluster.</p>

<p>Even if it's not hard from my point of view (Creating a cluster and then uploading docker images to pods with parameters in order to use the right resources connection strings), I am stuck at the CD/CI part..</p>

<blockquote>
  <p>From a CloudBuild trigger, how to push the Docker image to the right "cluster's pod", I have absolutely no idea AT ALL how to achieve it...</p>
</blockquote>

<p>There is my cloudbuild.yaml</p>

<pre><code>steps:
  #step 1 - Getting the previous (current) image
  - name: 'gcr.io/cloud-builders/docker'
    entrypoint: 'bash'
    args: [
      '-c',
      'docker pull gcr.io/{PROJECT_ID}/{SERVICE_NAME}:latest || exit 0'
    ]
  #step 2 - Build the image and push it to gcr.io
  - name: 'gcr.io/cloud-builders/docker'
    args: [
      'build',
      '-t',
      'gcr.io/{PROJECT_ID}/{SERVICE_NAME}',
      '-t',
      'gcr.io/{PROJECT_ID}/{SERVICE_NAME}:latest',
      '.'
    ]
  #step 3 - Deploy our container to our cluster
  - name: 'gcr.io/cloud-builders/kubectl'
    args: ['apply', '-f', 'service.yaml', '--force']
    env:
      - 'CLOUDSDK_COMPUTE_ZONE={CLUSTER_ZONE}'
      - 'CLOUDSDK_CONTAINER_CLUSTER={CLUSTER_NAME}'
  #step 4 - Set the image
  - name: 'gcr.io/cloud-builders/kubectl'
    args: [
      'set',
      'image',
      'deployment',
      '{SERVICE_NAME}',
      '{SERVICE_NAME}=gcr.io/{PROJECT_ID}/{SERVICE_NAME}'
    ]
    env:
      - 'CLOUDSDK_COMPUTE_ZONE={CLUSTER_ZONE}'
      - 'CLOUDSDK_CONTAINER_CLUSTER={CLUSTER_NAME}'
# push images to Google Container Registry with tags
images: [
  'gcr.io/{PROJECT_ID}/{SERVICE_NAME}',
  'gcr.io/{PROJECT_ID}/{SERVICE_NAME}:latest'
]
</code></pre>

<p>Can anyone help me out? I don't really know in which direction to go to..</p>

<p>So my question is:</p>

<p>How are you triggering these builds? Manually? GitHub Trigger? HTTP Trigger using the REST API?</p>

<p>so you're almost there for the building/pushing part, you would need to use substitution variables <a href="https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values" rel="nofollow noreferrer">https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values</a></p>

<p>If you would be triggering the builds manually, you would edit the build trigger and change the sub variable for what you want it to be.
GitHub Trigger -- this is a little more complex as you might want to do releases or branches.
HTTP Trigger, same as manual, in your request you change the sub variable. </p>

<p>So here's part of one of our repo build files, as you will see there are different sub. variables we use, sometimes we want to build the image AND deploy to cluster, other times we just want to build or deploy.</p>

<pre><code>steps:
# pull docker image
- name: 'gcr.io/cloud-builders/docker'
  id: pull-docker-image
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    docker pull $${_TAG_DOCKER_IMAGE} || exit 0

# build docker image
- name: 'gcr.io/cloud-builders/docker'
  id: build-docker-image
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    if [[ "${_BUILD_IMAGE}" == "true" ]]; then
       docker build -t ${_DOCKER_IMAGE_TAG} --cache-from $${_TAG_DOCKER_IMAGE} .;
    else
       echo "skipping ... BUILD_IMAGE=${_BUILD_IMAGE}";
    fi

# push docker image
- name: 'gcr.io/cloud-builders/docker'
  id: push-docker-image
  entrypoint: 'bash'
  args:
  - '-c'
  - |
     if [[ "${_BUILD_IMAGE}" == "true" ]]; then
        docker push ${_DOCKER_IMAGE_TAG};
     else
        echo "skipping ... BUILD_IMAGE=${_BUILD_IMAGE}";
     fi

# tag docker image
- name: 'gcr.io/cloud-builders/gcloud'
  id: tag-docker-image
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    if [[ "${_BUILD_IMAGE}" == "true" ]]; then
       gcloud container images add-tag ${_DOCKER_IMAGE_TAG} $${_TAG_DOCKER_IMAGE} -q;
    else
       echo "skipping ... BUILD_IMAGE=${_BUILD_IMAGE}";
    fi


# update service image on environment
- name: 'gcr.io/cloud-builders/kubectl'
  id: update service deployment image
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    if [[ "${_UPDATE_CLUSTER}" == "true" ]]; then
       /builder/kubectl.bash set image deployment $REPO_NAME master=${_DOCKER_IMAGE_TAG} --namespace=${_DEFAULT_NAMESPACE};
    else
       echo "skipping ... UPDATE_CLUSTER=${_UPDATE_CLUSTER}";
    fi
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=${_CLOUDSDK_COMPUTE_ZONE}'
  - 'CLOUDSDK_CONTAINER_CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}'


# subs are needed because of our different ENVs
# _DOCKER_IMAGE_TAG = ['gcr.io/$PROJECT_ID/$REPO_NAME:gcb-${_COMPANY_ENV}-$SHORT_SHA', 'other']
# _COMPANY_ENV = ['dev', 'staging', 'prod']
# _DEFAULT_NAMESPACE = ['default'] or ['custom1', 'custom2']
# _CLOUDSDK_CONTAINER_CLUSTER = ['dev', 'prod']
# _CLOUDSDK_COMPUTE_ZONE = ['us-central1-a']
# _BUILD_IMAGE = ['true', 'false']
# _UPDATE_CLUSTER = ['true', 'false']
substitutions:
    _DOCKER_IMAGE_TAG: $DOCKER_IMAGE_TAG
    _COMPANY_ENV: dev
    _DEFAULT_NAMESPACE: default
    _CLOUDSDK_CONTAINER_CLUSTER: dev
    _CLOUDSDK_COMPUTE_ZONE: us-central1-a
    _BUILD_IMAGE: 'true'
    _UPDATE_CLUSTER: 'true'
options:
    substitution_option: 'ALLOW_LOOSE'
    env:
    - _TAG_DOCKER_IMAGE=gcr.io/$PROJECT_ID/$REPO_NAME:${_COMPANY_ENV}-latest
    - DOCKER_IMAGE_TAG=gcr.io/$PROJECT_ID/$REPO_NAME:gcb-${_COMPANY_ENV}-$SHORT_SHA
tags:
- '${_COMPANY_ENV}'
- 'build-${_BUILD_IMAGE}'
- 'update-${_UPDATE_CLUSTER}'
</code></pre>

<p>we have two workflows -- </p>

<ol>
<li>github trigger builds and deploys under the 'dev' environment. </li>
<li>we trigger via REST API <a href="https://cloud.google.com/cloud-build/docs/api/reference/rest/v1/projects.builds/create" rel="nofollow noreferrer">https://cloud.google.com/cloud-build/docs/api/reference/rest/v1/projects.builds/create</a> (we replace the variables via the request.json) -- this method also works using the <code>gcloud builds --substitutions</code> CLI.</li>
</ol>

<p>Hope that answers your question!</p>
