copyright | lastupdated | keywords | subcollection | ||
---|---|---|---|---|---|
|
2019-04-09 |
kubernetes, iks |
containers |
{:new_window: target="_blank"} {:shortdesc: .shortdesc} {:screen: .screen} {:pre: .pre} {:table: .aria-labeledby="caption"} {:codeblock: .codeblock} {:tip: .tip} {:note: .note} {:important: .important} {:deprecated: .deprecated} {:download: .download}
{: #cs_apps_tutorial}
You can learn how to use {{site.data.keyword.containerlong}} to deploy a containerized app that leverages {{site.data.keyword.watson}} {{site.data.keyword.toneanalyzershort}}. {: shortdesc}
In this scenario, a fictional PR firm uses the {{site.data.keyword.Bluemix_notm}} service to analyze their press releases and receive feedback on the tone of their messages.
Using the Kubernetes cluster that is created in the last tutorial, the PR firm's app developer deploys a Hello World version of the app. Building on each lesson in this tutorial, the app developer deploys progressively more complicated versions of the same app. The following diagram shows the components of each deployment by lesson.
As depicted in the diagram, Kubernetes uses several different types of resources to get your apps up and running in clusters. In Kubernetes, deployments and services work together. Deployments include the definitions for the app. For example, the image to use for the container and which port must be exposed for the app. When you create a deployment, a Kubernetes pod is created for each container that you defined in the deployment. To make your app more resilient, you can define multiple instances of the same app in your deployment and let Kubernetes automatically create a replica set for you. The replica set monitors the pods and assures that the specified number of pods are always up and running. If one of the pods becomes unresponsive, the pod is re-created automatically.
Services group a set of pods and provide network connection to these pods for other services in the cluster without exposing the actual private IP address of each pod. You can use Kubernetes services to make an app available to other pods inside the cluster or to expose an app to the internet. In this tutorial, you use a Kubernetes service to access your running app from the internet by using a public IP address that is automatically assigned to a worker node and a public port.
To make your app even more highly available, in standard clusters, you can create a worker pool that spans multiple zones with worker nodes in each zone to run even more replicas of your app. This task is not covered in this tutorial, but keep this concept in mind for future improvements to an app's availability.
Only one of the lessons includes the integration of an {{site.data.keyword.Bluemix_notm}} service into an app, but you can use them with as simple or complex of an app as you can imagine.
{: #apps_objectives}
- Understand basic Kubernetes terminology
- Push an image to your registry namespace in {{site.data.keyword.registryshort_notm}}
- Make an app publicly accessible
- Deploy a single instance of an app in a cluster by using a Kubernetes command and a script
- Deploy multiple instances of an app in containers that are re-created during health checks
- Deploy an app that uses functionality from an {{site.data.keyword.Bluemix_notm}} service
{: #apps_time}
40 minutes
{: #apps_audience}
Software developers and network administrators that are deploying an app into a Kubernetes cluster for the first time.
{: #apps_prereqs}
Tutorial: Creating Kubernetes clusters
{: #cs_apps_tutorial_lesson1}
In the previous tutorial, you created a cluster with one worker node. In this lesson, you configure a deployment and deploy a single instance of the app into a Kubernetes pod within the worker node. {:shortdesc}
The components that you deploy by completing this lesson are shown in the following diagram.
To deploy the app:
-
Clone the source code for the Hello world app
to your user home directory. The repository contains different versions of a similar app in folders that each start with
Lab
. Each version contains the following files:Dockerfile
: The build definitions for the image.app.js
: The Hello world app.package.json
: Metadata about the app.
git clone https://github.com/IBM/container-service-getting-started-wt.git
{: pre}
-
Navigate to the
Lab 1
directory.cd 'container-service-getting-started-wt/Lab 1'
{: pre}
-
Log in to the {{site.data.keyword.registryshort_notm}} CLI.
ibmcloud cr login
{: pre}
-
If you forgot your namespace in {{site.data.keyword.registryshort_notm}}, run the following command.
ibmcloud cr namespace-list
{: pre}
-
-
Build a Docker image that includes the app files of the
Lab 1
directory, and push the image to the {{site.data.keyword.registryshort_notm}} namespace that you created in the previous tutorial. If you need to make a change to the app in the future, repeat these steps to create another version of the image. Note: Learn more about securing your personal information when you work with container images.Use lowercase alphanumeric characters or underscores (
_
) only in the image name. Don't forget the period (.
) at the end of the command. The period tells Docker to look inside the current directory for the Dockerfile and build artifacts to build the image. To get the region prefix for the region that you are currently in, runibmcloud api
. For example, the Dallas location, US South region prefix isng
.ibmcloud cr build -t registry.<region>.bluemix.net/<namespace>/hello-world:1 .
{: pre}
When the build is complete, verify that you see the following success message:
Successfully built <image_ID> Successfully tagged registry.<region>.bluemix.net/<namespace>/hello-world:1 The push refers to a repository [registry.<region>.bluemix.net/<namespace>/hello-world] 29042bc0b00c: Pushed f31d9ee9db57: Pushed 33c64488a635: Pushed 0804854a4553: Layer already exists 6bd4a62f5178: Layer already exists 9dfa40a0da3b: Layer already exists 1: digest: sha256:f824e99435a29e55c25eea2ffcbb84be4b01345e0a3efbd7d9f238880d63d4a5 size: 1576
{: screen}
-
Deployments are used to manage pods, which include containerized instances of an app. The following command deploys the app in a single pod. For the purposes of this tutorial, the deployment is named hello-world-deployment, but you can give the deployment any name that you want.
kubectl run hello-world-deployment --image=registry.<region>.bluemix.net/<namespace>/hello-world:1
{: pre}
Example output:
deployment "hello-world-deployment" created
{: screen}
Learn more about securing your personal information when you work with Kubernetes resources.
-
Make the app accessible to the world by exposing the deployment as a NodePort service. Just as you might expose a port for a Cloud Foundry app, the NodePort that you expose is the port on which the worker node listens for traffic.
kubectl expose deployment/hello-world-deployment --type=NodePort --port=8080 --name=hello-world-service --target-port=8080
{: pre}
Example output:
service "hello-world-service" exposed
{: screen}
More about the expose parameters -
Now that all the deployment work is done, you can test your app in a browser. Get the details to form the URL.
-
Get information about the service to see which NodePort was assigned.
kubectl describe service hello-world-service
{: pre}
Example output:
Name: hello-world-service Namespace: default Labels: run=hello-world-deployment Selector: run=hello-world-deployment Type: NodePort IP: 10.xxx.xx.xxx Port: <unset> 8080/TCP NodePort: <unset> 30872/TCP Endpoints: 172.30.xxx.xxx:8080 Session Affinity: None No events.
{: screen}
The NodePorts are randomly assigned when they are generated with the
expose
command, but within 30000-32767. In this example, the NodePort is 30872. -
Get the public IP address for the worker node in the cluster.
ibmcloud ks workers --cluster <cluster_name_or_ID>
{: pre}
Example output:
ibmcloud ks workers --cluster pr_firm_cluster Listing cluster workers... OK ID Public IP Private IP Machine Type State Status Zone Version kube-mil01-pa10c8f571c84d4ac3b52acbf50fd11788-w1 169.xx.xxx.xxx 10.xxx.xx.xxx free normal Ready mil01 1.12.7
{: screen}
-
-
Open a browser and check out the app with the following URL:
http://<IP_address>:<NodePort>
. With the example values, the URL ishttp://169.xx.xxx.xxx:30872
. When you enter that URL in a browser, you can see the following text.Hello world! Your app is up and running in a cluster!
{: screen}
To see that the app is publicly available, try entering it into a browser on your cell phone. {: tip}
-
Launch the Kubernetes dashboard.
If you select your cluster in the {{site.data.keyword.Bluemix_notm}} console, you can use the Kubernetes Dashboard button to launch your dashboard with one click. {: tip}
-
In the Workloads tab, you can see the resources that you created.
Good job! You deployed your first version of the app.
Too many commands in this lesson? Agreed. How about using a configuration script to do some of the work for you? To use a configuration script for the second version of the app, and to create higher availability by deploying multiple instances of that app, continue to the next lesson.
{: #cs_apps_tutorial_lesson2}
In this lesson, you deploy three instances of the Hello World app into a cluster for higher availability than the first version of the app. {:shortdesc}
Higher availability means that user access is divided across the three instances. When too many users are trying to access the same app instance, they might notice slow response times. Multiple instances can mean faster response times for your users. In this lesson, you also learn how health checks and deployment updates can work with Kubernetes. The following diagram includes the components that you deploy by completing this lesson.
In the previous tutorial, you created your account and a cluster with one worker node. In this lesson, you configure a deployment and deploy three instances of the Hello World app. Each instance is deployed in a Kubernetes pod as part of a replica set in the worker node. To make it publicly available, you also create a Kubernetes service.
As defined in the configuration script, Kubernetes can use an availability check to see whether a container in a pod is running or not. For example, these checks might catch deadlocks, where an app is running, but it is unable to progress. Restarting a container that is in this condition can help to make the app more available despite bugs. Then, Kubernetes uses a readiness check to know when a container is ready to start accepting traffic again. A pod is considered ready when its container is ready. When the pod is ready, it is started again. In this version of the app, every 15 seconds it times out. With a health check configured in the configuration script, containers are re-created if the health check finds an issue with an app.
- In a CLI, navigate to the
Lab 2
directory.
cd 'container-service-getting-started-wt/Lab 2'
{: pre}
-
If you started a new CLI session, log in and set the cluster context.
-
Build, tag, and push the app as an image to your namespace in {{site.data.keyword.registryshort_notm}}. Again, don't forget the period (
.
) at the end of the command.ibmcloud cr build -t registry.<region>.bluemix.net/<namespace>/hello-world:2 .
{: pre}
Verify that you see the success message.
Successfully built <image_ID> Successfully tagged registry.<region>.bluemix.net/<namespace>/hello-world:1 The push refers to a repository [registry.<region>.bluemix.net/<namespace>/hello-world] 29042bc0b00c: Pushed f31d9ee9db57: Pushed 33c64488a635: Pushed 0804854a4553: Layer already exists 6bd4a62f5178: Layer already exists 9dfa40a0da3b: Layer already exists 1: digest: sha256:f824e99435a29e55c25eea2ffcbb84be4b01345e0a3efbd7d9f238880d63d4a5 size: 1576
{: screen}
-
Open the
healthcheck.yml
file, in theLab 2
directory, with a text editor. This configuration script combines a few steps from the previous lesson to create a deployment and a service at the same time. The PR firm's app developers can use these scripts when updates are made or to troubleshoot issues by re-creating the pods.-
Update the details for the image in your private registry namespace.
image: "registry.<region>.bluemix.net/<namespace>/hello-world:2"
{: codeblock}
-
In the Deployment section, note the
replicas
. Replicas are the number instances of your app. Running three instances makes the app more highly available than just one instance.replicas: 3
{: codeblock}
-
Note the HTTP liveness probe that checks the health of the container every 5 seconds.
livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 5
{: codeblock}
-
In the Service section, note the
NodePort
. Rather than generating a random NodePort like you did in the previous lesson, you can specify a port in the 30000 - 32767 range. This example uses 30072.
-
-
Switch back to the CLI that you used to set your cluster context and run the configuration script. When the deployment and the service are created, the app is available for the PR firm's users to see.
kubectl apply -f healthcheck.yml
{: pre}
Example output:
deployment "hw-demo-deployment" created
service "hw-demo-service" created
{: screen}
- Now that the deployment work is done you can open a browser and check out the app. To form the URL, take the same public IP address that you used in the previous lesson for your worker node and combine it with the NodePort that was specified in the configuration script. To get the public IP address for the worker node:
ibmcloud ks workers --cluster <cluster_name_or_ID>
{: pre}
With the example values, the URL is http://169.xx.xxx.xxx:30072
. In a browser, you might see the following text. If you do not see this text, don't worry. This app is designed to go up and down.
Hello world! Great job getting the second stage up and running!
{: screen}
You can also check http://169.xx.xxx.xxx:30072/healthz
for status.
For the first 10 - 15 seconds, a 200 message is returned, so you know that the app is running successfully. After those 15 seconds, a timeout message is displayed. This is an expected behavior.
{
"error": "Timeout, Health check error!"
}
{: screen}
-
Check your pod status to monitor the health of your app in Kubernetes. You can check the status from the CLI or in the Kubernetes dashboard.
-
From the CLI: Watch what is happening to your pods as they change status.
kubectl get pods -o wide -w
{: pre}
-
From the Kubernetes dashboard:
- Launch the Kubernetes dashboard.
- In the Workloads tab, you can see the resources that you created. From this tab, you can continually refresh and see that the health check is working. In the Pods section, you can see how many times the pods are restarted when the containers in them are re-created. If you happen to catch the following error in the dashboard, this message indicates that the health check caught a problem. Give it a few minutes and refresh again. You see the number of restarts changes for each pod.
Liveness probe failed: HTTP probe failed with statuscode: 500 Back-off restarting failed docker container Error syncing pod, skipping: failed to "StartContainer" for "hw-container" with CrashLoopBackOff: "Back-off 1m20s restarting failed container=hw-container pod=hw-demo-deployment-3090568676-3s8v1_default(458320e7-059b-11e7-8941-56171be20503)"
{: screen}
-
Good job! You deployed the second version of the app. You had to use fewer commands, learned how health checks work, and edited a deployment, which is great! The Hello world app passed the test for the PR firm. Now, you can deploy a more useful app for the PR firm to start analyzing press releases.
Ready to delete what you created before you continue? This time, you can use the same configuration script to delete both of the resources that you created.
kubectl delete -f healthcheck.yml
{: pre}
Example output:
deployment "hw-demo-deployment" deleted
service "hw-demo-service" deleted
{: screen}
{: #cs_apps_tutorial_lesson3}
In the previous lessons, the apps were deployed as single components in one worker node. In this lesson, you can deploy two components of an app into a cluster that use the {{site.data.keyword.watson}} {{site.data.keyword.toneanalyzershort}} service. {:shortdesc}
Separating components into different containers ensures that you can update one without affecting the others. Then, you update the app to scale it up with more replicas to make it more highly available. The following diagram includes the components that you deploy by completing this lesson.
From the previous tutorial, you have your account and a cluster with one worker node. In this lesson, you create an instance of {{site.data.keyword.watson}} {{site.data.keyword.toneanalyzershort}} service in your {{site.data.keyword.Bluemix_notm}} account and configure two deployments, one deployment for each component of the app. Each component is deployed in a Kubernetes pod in the worker node. To make both of those components publicly available, you also create a Kubernetes service for each component.
{: #lesson3a}
- In a CLI, navigate to the
Lab 3
directory.
cd 'container-service-getting-started-wt/Lab 3'
{: pre}
-
If you started a new CLI session, log in and set the cluster context.
-
Build the first {{site.data.keyword.watson}} image.
-
Navigate to the
watson
directory.cd watson
{: pre}
-
Build, tag, and push the
watson
app as an image to your namespace in {{site.data.keyword.registryshort_notm}}. Again, don't forget the period (.
) at the end of the command.ibmcloud cr build -t registry.<region>.bluemix.net/<namespace>/watson .
{: pre}
Verify that you see the success message.
Successfully built <image_id>
{: screen}
-
-
Build the {{site.data.keyword.watson}}-talk image.
-
Navigate to the
watson-talk
directory.cd 'container-service-getting-started-wt/Lab 3/watson-talk'
{: pre}
-
Build, tag, and push the
watson-talk
app as an image to your namespace in {{site.data.keyword.registryshort_notm}}. Again, don't forget the period (.
) at the end of the command.ibmcloud cr build -t registry.<region>.bluemix.net/<namespace>/watson-talk .
{: pre}
Verify that you see the success message.
Successfully built <image_id>
{: screen}
-
-
Verify that the images were successfully added to your registry namespace.
ibmcloud cr images
{: pre}
Example output:
Listing images... REPOSITORY NAMESPACE TAG DIGEST CREATED SIZE VULNERABILITY STATUS registry.ng.bluemix.net/namespace/hello-world namespace 1 0d90cb732881 40 minutes ago 264 MB OK registry.ng.bluemix.net/namespace/hello-world namespace 2 c3b506bdf33e 20 minutes ago 264 MB OK registry.ng.bluemix.net/namespace/watson namespace latest fedbe587e174 3 minutes ago 274 MB OK registry.ng.bluemix.net/namespace/watson-talk namespace latest fedbe587e174 2 minutes ago 274 MB OK
{: screen}
-
Open the
watson-deployment.yml
file, in theLab 3
directory, with a text editor. This configuration script includes a deployment and a service for both thewatson
andwatson-talk
components of the app.-
Update the details for the image in your registry namespace for both deployments.
watson:
image: "registry.<region>.bluemix.net/namespace/watson"
{: codeblock}
watson-talk:
image: "registry.<region>.bluemix.net/namespace/watson-talk"
{: codeblock}
-
In the volumes section of the
watson-pod
deployment, update the name of the {{site.data.keyword.watson}} {{site.data.keyword.toneanalyzershort}} secret that you created in the previous Creating Kubernetes cluster tutorial. By mounting the Kubernetes secret as a volume to your deployment, you make the {{site.data.keyword.Bluemix_notm}} Identity and Access Management (IAM) API key available to the container that is running in your pod. The {{site.data.keyword.watson}} app components in this tutorial are configured to look up the API key by using the volume mount path.volumes: - name: service-bind-volume secret: defaultMode: 420 secretName: binding-mytoneanalyzer
{: codeblock}
If you forgot what you named the secret, run the following command.
kubectl get secrets --namespace=default
{: pre}
-
In the watson-talk service section, note the value that is set for the
NodePort
. This example uses 30080.
-
-
Run the configuration script.
kubectl apply -f watson-deployment.yml
{: pre}
-
Optional: Verify that the {{site.data.keyword.watson}} {{site.data.keyword.toneanalyzershort}} secret is mounted as a volume to the pod.
-
To get the name of a watson pod, run the following command.
kubectl get pods
{: pre}
Example output:
NAME READY STATUS RESTARTS AGE watson-pod-4255222204-rdl2f 1/1 Running 0 13h watson-talk-pod-956939399-zlx5t 1/1 Running 0 13h
{: screen}
-
Get the details about the pod and look for the secret name.
kubectl describe pod <pod_name>
{: pre}
Example output:
Volumes: service-bind-volume: Type: Secret (a volume populated by a Secret) SecretName: binding-mytoneanalyzer default-token-j9mgd: Type: Secret (a volume populated by a Secret) SecretName: default-token-j9mgd
{: codeblock}
-
-
Open a browser and analyze some text. The format of the URL is
http://<worker_node_IP_address>:<watson-talk-nodeport>/analyze/"<text_to_analyze>"
.Example:
http://169.xx.xxx.xxx:30080/analyze/"Today is a beautiful day"
{: screen}
In a browser, you can see the JSON response for the text you entered.
-
In the Workloads tab, you can see the resources that you created.
{: #lesson3b}
While a deployment is running, you can edit the deployment to change values in the pod template. This lesson includes updating the image that is used. The PR firm wants to change the app in the deployment. {: shortdesc}
Change the name of the image:
-
Open the configuration details for the running deployment.
kubectl edit deployment/watson-talk-pod
{: pre}
Depending on your operating system, either a vi editor opens or a text editor opens.
-
Change the name of the image to the ibmliberty image.
spec: containers: - image: registry.<region>.bluemix.net/ibmliberty:latest
{: codeblock}
-
Save your changes and exit the editor.
-
Apply the changes to the running deployment.
kubectl rollout status deployment/watson-talk-pod
{: pre}
Wait for confirmation that the rollout is complete.
deployment "watson-talk-pod" successfully rolled out
{: screen}
When you roll out a change, another pod is created and tested by Kubernetes. When the test is successful, the old pod is removed.
Test your knowledge and take a quiz!
Good job! You deployed the {{site.data.keyword.watson}} {{site.data.keyword.toneanalyzershort}} app. The PR firm can start to use this deployment to start analyzing their press releases.
Ready to delete what you created? You can use the configuration script to delete the resources that you created.
kubectl delete -f watson-deployment.yml
{: pre}
Example output:
deployment "watson-pod" deleted
deployment "watson-talk-pod" deleted
service "watson-service" deleted
service "watson-talk-service" deleted
{: screen}
If you do not want to keep the cluster, you can delete that too.
ibmcloud ks cluster-rm --cluster <cluster_name_or_ID>
{: pre}
{: #apps_next}
Now that you conquered the basics, you can move to more advanced activities. Consider trying out one of the following:
- Complete a more complicated lab
in the repository
- Automatically scale your apps with {{site.data.keyword.containerlong_notm}}
- Explore the container orchestration code patterns on IBM Developer