<p>I am playing with <code>Docker</code>, <code>Kubernetes</code>, <code>Google Cloud Platform(GCP)</code> and <code>Gitlab</code> recently to achieve <code>CI/CD</code> from <code>commit</code> to <code>staging</code>. 
So far I have succeeded <code>testing</code>, <code>building</code> and <code>pushing</code> the image to <code>Container registry of Gitlab</code>. </p>

<p>I have a small node and docker application which output <code>'Hello world'</code>. Also, I have built my docker image in <code>Container registry of Gitlab</code>. At this moment the process is docker-in-docker.  I want to push my image from <code>Gitlab container registry</code> to <code>Kubernetes engine</code> in GCP. I have installed both <code>kubectl</code> and <code>gcloud sdk</code>. The <a href="https://docs.gitlab.com/ee/topics/autodevops/#auto-devops" rel="nofollow noreferrer">Auto DevOps</a> seems to be promising but I want to implement my own <code>.gitlab-ci.yml</code> file.</p>

<p>Here is my <code>.gitlab-ci.yml</code> below:</p>

<pre><code>stages:
  - testing
  - build
  - staging

variables:
  CONTAINER_TEST_IMAGE: registry.gitlab.com/surajneupane55/node-app-
  testing
 CONTAINER_RELEASE_IMAGE: registry.gitlab.com/surajneupane55/node-
 app-testing:latest


test:
  stage: testing
  image: node:boron
  script:
  - npm install
  - npm test


build_image:
  stage: build
  only: [master]
  image: docker:git
  services:
    - docker:dind
  script:
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN 
      registry.gitlab.com/surajneupane55
    - docker build -t $CONTAINER_TEST_IMAGE .
    - docker push $CONTAINER_TEST_IMAGE


staging_site:

//I need help here!!!
//For staging my project in Kubernetes cluster in GCP
//Already created node-app Kubernetes cluster
</code></pre>

<p>Please, let me know if my approach is wrong since this is my first learning project with CI/CD.  </p>

<p>A simple <code>gitlab-ci.yml</code> file to build and deploy in GKE with <code>Google Container Registry(GCR)</code>. First, we build image and push it to GCR. With valid credentials, we can easily connect the GKE with GCR and deploy.  </p>

<pre><code>stages:
  - build
  - deploy

variables:
  CONTAINER_TEST_IMAGE: gcr.io/node-testing-189614/node-testing:latest




build_image:
  stage: build
  only: [master]
  image: google/cloud-sdk
  services:
    - docker:dind

  script:
    - echo "$GOOGLE_KEY_SECRET" &gt; key.json # Google Cloud service accounts
    - gcloud auth activate-service-account --key-file key.json
    - gcloud config set project node-testing-189614
    - gcloud container builds submit -t $CONTAINER_TEST_IMAGE .




deploy_staging:
  image: google/cloud-sdk
  stage: deploy
  script:
    - echo "$GOOGLE_KEY_SECRET" &gt; key.json # Google Cloud service accounts
    - gcloud auth activate-service-account --key-file key.json
    - gcloud config set project node-testing-189614
    - gcloud config set compute/zone europe-west1-b
    - gcloud config set container/use_client_certificate True
    - gcloud container clusters get-credentials node-testing
    - kubectl delete pods --all
    - kubectl apply -f staging.yml

  environment:
    name: staging
    url: http://***.***.**.***:****/ //External IP from Kubernetes
  only:
  - master
</code></pre>

<p>Above we delete pods in GKE because we always want to update the image with the latest tag. The best possible solution available so far is to delete the pods and let the <code>staging.yml</code> file creates new one if not available.</p>

<p>Finally <code>staging.yml</code> looks like this:</p>

<pre><code>apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: node-testing
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: node-testing
    spec:
      containers:
      - name: node-testing
        image: gcr.io/node-testing-189614/node-testing:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
      imagePullSecrets:
        - name: gcr.io/node-testing-189614/node-testing
</code></pre>
