Skip to content

5. Deploy to IBM Cloud Private

Containerize the app and deploy to IBM Cloud Private

Create a Docker container

Use provided Dockerfile to build the application container:

cd ~/b2m-nodejs/src
docker build -t b2m-nodejs .

Test container locally (make sure you stopped the local Node.js server and removed previous version of this docker container).

docker stop b2m-nodejs
docker rm b2m-nodejs
docker run --name btm-nodejs -d -p 3001:3001 b2m-nodejs

Access http://localhost:3001 to verify the application is running.

Now, our Node.js application container can be deployed on ICP cluster. Make sure the kubectl client is configured to connect to your ICP cluster. More information here.

The b2m-nodejs application container image has been uploaded to public Docker Hub: rszypulka/b2m-nodejs. You can also upload it to the local ICP Container Registry.

Deploy b2m-nodejs application to the ICP cluster

Review provided YAML file b2m-nodejs-icp.yml and use it to deploy the application to IBM Cloud Private cluster. b2m-nodejs deployment object will pull application image container rszypulka/b2m-nodejs from Docker Hub.

kubectl apply -f b2m-nodejs-icp.yml

Verify deployment status.

$ kubectl get deploy b2m-nodejs -n default
b2m-nodejs   1         1         1            1           4h

Get the application URL by running these commands:

export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services b2m-nodejs)
export NODE_IP=$(kubectl get nodes -l proxy=true -o jsonpath="{.items[0].status.addresses[?(@.type==\"Hostname\")].address}")
echo http://$NODE_IP:$NODE_PORT

Use the browser to access the application URL: http://<node_external_ip>:<external_nodeport>

Enable monitoring using ICP Prometheus and Grafana

Add the following configuration in the monitoring-prometheus ConfigMap, scrape_configs: section.

      - job_name: 'b2m-nodejs'
        scrape_interval: 20s
          - targets:
            - b2m-nodejs.default.svc:80
              service: 'my-service'
              group: 'production'

Make sure the indentation is correct.

Import provided Grafana dashboard grafana-dashboard.json.

Generate ICP application traffic using provided script:

./ <application_url>

Use the <application_url> collected in previous chapter.

Access the ICP Grafana console and verify it properly shows metrics.

Define the kubernetes liveness probe for use with built-in application health check

The provided b2m-nodejs-icp.yml deployment YAML file define liveness probe that uses the implemented /healthz route.

       path: /healthz
       port: 3001
     initialDelaySeconds: 3
     periodSeconds: 10

Check the URL: http://<node_external_ip>:<external_nodeport>/healthz to verify current health status.

Expected output: {"status":"ok"}

Simulate an application problem by setting "bad health" status: http://<node_external_ip>:<external_nodeport>/bad-health

Expected output: {"status":"App health set to 'false'"}

Quickly check the health URL again: http://<node_external_ip>:<external_nodeport>/healthz

Expected output: {"error":"Application unhealthy"}

After up to 10s the application pod should be automatically restarted by kubernetes and health set back to {"status":"ok"}

Expected output: {"status":"ok"}

Verify the pod has been restarted.

kubectl describe pod b2m-nodejs

in the Events section you should see events similar to the following:

  Type     Reason     Age               From                     Message
  ----     ------     ----              ----                     -------
  Warning  Unhealthy  3m (x9 over 58m)  kubelet,  Liveness probe failed: HTTP probe failed with statuscode: 500
  Normal   Pulling    2m (x4 over 1h)   kubelet,  pulling image "rszypulka/b2m-nodejs"
  Normal   Killing    2m (x3 over 58m)  kubelet,  Killing container with id docker://node-prom:Container failed liveness probe.. Container will be killed and recreated.
  Normal   Pulled     2m (x4 over 1h)   kubelet,  Successfully pulled image "rszypulka/b2m-nodejs"
  Normal   Created    2m (x4 over 1h)   kubelet,  Created container
  Normal   Started    2m (x4 over 1h)   kubelet,  Started container