OpenLiberty / guide-cloud-ibm

A guide on how to deploy microservices to IBM Cloud Kubernetes Service (IKS) and IBM Cloud Private (ICP): https://openliberty.io/guides/cloud-ibm.html
Other
3 stars 4 forks source link

// Copyright (c) 2018, 2024 IBM Corporation and others. // Licensed under Creative Commons Attribution-NoDerivatives // 4.0 International (CC BY-ND 4.0) // https://creativecommons.org/licenses/by-nd/4.0/ // // Contributors: // IBM Corporation // :projectid: cloud-ibm :page-layout: guide-multipane :page-duration: 1 hour :page-releasedate: 2019-05-29 :page-majorupdateddate: 2024-06-06 :page-description: Explore how to deploy microservices to IBM Cloud Kubernetes Service. :page-tags: ['kubernetes', 'docker', 'cloud'] :page-permalink: /guides/{projectid} :page-related-guides: ['kubernetes-intro', 'kubernetes-microprofile-config', 'kubernetes-microprofile-health', 'istio-intro'] :common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod :source-highlighter: prettify :page-seo-title: Deploying Java microservices to IBM Cloud Kubernetes Service :page-seo-description: A getting started tutorial with examples on how to deploy Java microservices to IBM Cloud Kubernetes Service using IBM Cloud Container Registry. :guide-author: Open Liberty = Deploying microservices to IBM Cloud Kubernetes Service

[.hidden] NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website^].

Explore how to deploy microservices to IBM Cloud Kubernetes Service.

:minikube-ip: 192.168.99.100 :kube: Kubernetes :hashtag: # :win: WINDOWS :mac: MAC :linux: LINUX :system-api: http://[hostname]:[system-node-port]/system/properties :inventory-api: http://[hostname]:[inventory-node-port]/inventory/systems

// ================================================================================================= // Introduction // =================================================================================================

== What you'll learn

You will learn how to deploy two microservices in Open Liberty containers to a {kube} cluster on IBM Cloud.

Kubernetes is an open source container orchestrator that automates many tasks involved in deploying, managing, and scaling containerized applications. If you would like to learn more about Kubernetes, check out the https://openliberty.io/guides/kubernetes-intro.html[Deploying microservices to Kubernetes^] guide.

Different cloud-based solutions are available to run your Kubernetes workloads. A cloud-based infrastructure enables you to focus on developing your microservices without worrying about low-level infrastructure details for deployment. Using a cloud helps you to easily scale and manage your microservices in a high-availability setup.

The IBM Cloud Kubernetes Service is an IBM public cloud offering. It provides a hosted Kubernetes cluster where you can deploy your microservices. In this guide, you will use it with the IBM Cloud Container Registry, which is a private registry that is used to store and distribute your container images.

Note: Because the IBM Cloud Container Registry is hosted on IBM Cloud Platform, fees might be associated with running this guide. For more information, see link:https://cloud.ibm.com/docs/account?topic=account-accounts[IBM Cloud account type].

The two microservices you will deploy are called system and inventory. The system microservice returns the JVM system properties of the running container. It also returns the pod’s name in the HTTP header, making replicas easy to distinguish from each other. The inventory microservice adds the properties from the system microservice to the inventory. This configuration demonstrates how to establish communication between pods inside a cluster.

// ================================================================================================= // Prerequisites // =================================================================================================

== Additional prerequisites

Before you begin, the following additional tools need to be installed:

include::{common-includes}/os-tabs.adoc[]

[.tab_content.windows_section]

Open command prompt as an administrator and run the following command.

[role=command]

powershell -command "Set-ExecutionPolicy Unrestricted; iex(New-Object Net.WebClient).DownloadString('https://clis.cloud.ibm.com/install/powershell')"

--

[.tab_content.mac_section]

[role=command]

curl -fsSL https://clis.cloud.ibm.com/install/osx | sh

--

[.tab_content.linux_section]

[role=command]

curl -fsSL https://clis.cloud.ibm.com/install/linux | sh

--

// ================================================================================================= // Getting Started // =================================================================================================

[role=command] include::{common-includes}/gitclone.adoc[]

// no "try what you'll build" section in this guide because it would be too long due to all setup the user will have to do.

// ================================================================================================= // Creating a Kubernetes cluster on IBM Cloud // =================================================================================================

== Creating a Kubernetes cluster on IBM Cloud

Before you can deploy your microservices, you must create a {kube} cluster on IBM Cloud.

// ================================================================================================= // Configuring IBM Cloud CLI // =================================================================================================

=== Configuring IBM Cloud CLI

Log in to IBM Cloud by using the ibmcloud command line. When you are prompted to select a region, for example, choose us-south. This allows you to create a free cluster, which is limited to specific regions. Note that if you are using a federated user ID, you will have to use the --sso flag to get a one-time code for single sign-on.

[role=command]

ibmcloud login

// ================================================================================================= // Provisioning a cluster // =================================================================================================

=== Provisioning a cluster

To create a {kube} cluster on IBM Cloud, you need Administrator access to IBM Cloud Kubernetes Service. To verify your Administrator access, log in to the https://cloud.ibm.com/[IBM Cloud Dashboard^]. Then, navigate to Manage > Access (IAM) > Users > [Your Username] > Access > Access Policies. Alternatively, if you are part of an access group, you also can check Manage > Access (IAM) > Access groups > [Your Access Group] > Access. Using these steps, you can confirm that Administrator is listed as a policy for all resources in the account or for the Kubernetes service.

Once you confirm that you have appropriate permissions, use the following commands to provision a cluster.

Retrieve the list of available Kubernetes zones for deploying the cluster within the https://cloud.ibm.com/docs/containers?topic=containers-regions-and-zones#zones-sz[IBM Cloud classic infrastructure] [role=command]

ibmcloud ks zone ls --provider classic

Use the following command to retrieve a list of the available flavors of Kubernetes worker nodes for a zone. Replace the [available_zone] value with a zone selected from the list you generated with previous command.

[role=command]

ibmcloud ks flavor ls  --provider classic --zone [available_zone]

Look for the following output: [role="no_copy"]

For more information about these flavors, see 'https://ibm.biz/flavors' Name Cores Memory Network Speed OS Server Type Storage Secondary Storage Flavor Class Provider b3c.16x64 16 64GB 1000Mbps UBUNTU_20_64 virtual 25GB 100GB - classic b3c.16x64.300gb 16 64GB 1000Mbps UBUNTU_20_64 virtual 25GB 300GB - classic ...

Use the following command to create a Kubernetes cluster. Replacing the [selected_flavor] value with a flavor selected from the output of the previous command and the [available_zone] with the previously used zone.

[role=command]

ibmcloud ks cluster create classic --name guide-cluster --flavor [selected_flavor] --zone [available_zone]

Look for the following output: [source, role="no_copy"]

Number of workers was not specified. Using default: 1 Creating cluster... OK Cluster created with ID [cluster-id]

Check the current status of your cluster.

[role=command]

ibmcloud ks clusters

Wait until your cluster is in the normal state before proceeding. It will start off in the deploying state.

[role="no_copy"]

Name ID State Created Workers Location Version Resource Group Name Provider
guide-cluster bpp5ge4f0ck66fue46vg deploying 4 minutes ago 1 par01 1.16.8_1526 Default classic

Next, it will transition to the pending state.

[role="no_copy"]

Name ID State Created Workers Location Version Resource Group Name Provider
guide-cluster bpp5ge4f0ck66fue46vg pending 16 minutes ago 1 par01 1.16.8_1526 Default classic

Finally, it will transition to the normal state. It may take a while for the IBM Cloud Kubernetes Service to prepare your cluster.

[role="no_copy"]

Name ID State Created Workers Location Version Resource Group Name Provider
guide-cluster bpp5ge4f0ck66fue46vg normal 1 hour ago 1 par01 1.16.8_1526 Default classic

Once your cluster is ready, connect kubectl to the cluster.

[role=command]

ibmcloud ks cluster config --cluster guide-cluster

Verify that you're connected to the cluster by checking the cluster's nodes.

[role=command]

kubectl get nodes

[source, role="no_copy"]

NAME STATUS ROLES AGE VERSION 10.70.200.73 Ready 1h v1.16.8+IKS

// ================================================================================================= // Deploying microservices to IBM Cloud Kubernetes Service // =================================================================================================

== Deploying microservices to IBM Cloud Kubernetes Service

In this section, you will learn how to deploy two microservices in Open Liberty containers to a {kube} cluster on IBM Cloud. You will build and containerize the system and inventory microservices, push them to a container registry, and then deploy them to your {kube} cluster.

// ================================================================================================= // Building and containerizing the microservices // =================================================================================================

=== Building and containerizing the microservices

The first step of deploying to {kube} is to build and containerize your microservices.

The starting Java project, which you can find in the start directory, is a multi-module Maven project. It's made up of the system and inventory microservices. Each microservice resides in its own directory, start/system and start/inventory. Each of these directories also contains a Dockerfile, which is necessary for building Docker images. If you're unfamiliar with Dockerfiles, check out the https://openliberty.io/guides/containerize.html[Containerizing Microservices^] guide.

To build these microservices, navigate to the start directory and run the following command:

[role=command]

mvn package

Next, run the docker build commands to build container images for your application: [role='command']

docker build --platform linux/amd64 -t system:1.0-SNAPSHOT system/.
docker build --platform linux/amd64 -t inventory:1.0-SNAPSHOT inventory/.

The --platform flag in the docker build command specifies the target platform for the build output. Because IBM Cloud Kubernetes service supports both x86_64 and s390x architectures, the target platform is linux/amd64. Also, the -t flag in the command allows the Docker image to be labeled (tagged) in the name[:tag] format. The tag for an image describes the specific image version. If the optional [:tag] tag is not specified, the latest tag is created by default.

During the build, you'll see various Docker messages describing what images are being downloaded and built. When the build finishes, run the following command to list all local Docker images:

[role=command]

docker images

Verify that the system:1.0-SNAPSHOT and inventory:1.0-SNAPSHOT images are listed among them, for example:

[source, role="no_copy"]

REPOSITORY TAG system 1.0-SNAPSHOT inventory 1.0-SNAPSHOT icr.io/appcafe/open-liberty kernel-slim-java11-openj9-ubi

If you don't see the system:1.0-SNAPSHOT and inventory:1.0-SNAPSHOT images, then check the Maven build log for any potential errors.

// ================================================================================================= // Pushing the images to a container registry // =================================================================================================

=== Pushing the images to a container registry

Pushing the images to a registry enables the cluster to create pods by using your container images. It's a private repository so only users with access to your IBM Cloud account will have access to these images.

The registry you will use is called IBM Cloud Container Registry. Use the container registry plug-in to create a namespace for your container images.

To create, assign, and remove namespaces, you must have the Manager role in the Container Registry service at the account level. For more information, see link:https://cloud.ibm.com/docs/Registry?topic=Registry-registry_setup_cli_namespace#registry_setup_cli_namespace_plan_perm[User permissions for working with namespaces].

The namespace must be unique within IBM Cloud for the region you selected, so choose something relevant that you'll remember for the duration of the guide.

[role=command]

ibmcloud cr namespace-add [your-namespace]

Use the plug-in again to log in to the container registry and find out your registry name, for example, us.icr.io.

[role=command]

ibmcloud cr login

[source, role="no_copy"]

Logging 'docker' in to 'us.icr.io'... Logged in to 'us.icr.io'.

// Tagging images Next, tag your container images with the relevant data about your registry. Remember to replace us.icr.io to your registry and [your-namespace] with the namespace you created earlier in the guide.

[role=command]

docker tag system:1.0-SNAPSHOT us.icr.io/[your-namespace]/system:1.0-SNAPSHOT
docker tag inventory:1.0-SNAPSHOT us.icr.io/[your-namespace]/inventory:1.0-SNAPSHOT

// Pushing images Finally, push your images to the registry. Remember to replace us.icr.io to your registry and [your-namespace] with the namespace you created earlier in the guide.

[role=command]

docker push us.icr.io/[your-namespace]/system:1.0-SNAPSHOT
docker push us.icr.io/[your-namespace]/inventory:1.0-SNAPSHOT

// ================================================================================================= // Deploying the microservices // =================================================================================================

// ================================================================================================= // Deploying the microservices // =================================================================================================

=== Deploying the microservices

Now that your container images are built, deploy them using a Kubernetes resource definition.

A Kubernetes resource definition is a YAML file that contains a description of all your deployments, services, or any other resources that you want to deploy. All resources can also be deleted from the cluster by using the same YAML file that you used to deploy them. For this guide, the kubernetes.yaml resource definition file is provided for you. If you are interested in learning more about the Kubernetes resource definition, check out the https://openliberty.io/guides/kubernetes-intro.html[Deploying microservices to Kubernetes^] guide.

[role="code_command hotspot", subs="quotes"]

Update the kubernetes.yaml file in the start directory.

kubernetes.yaml

kubernetes.yaml [source, yaml, linenums, role='code_column']

include::finish/kubernetes.yaml[]

[role="edit_command_text"] The [hotspot=18 hotspot=39]image is the name and tag of the container image that you want to use for the container. Update the system [hotspot=18]image and the inventory [hotspot=39]image fields to point to your system and inventory container images. Remember to replace us.icr.io with your registry and [your-namespace] with the namespace you created earlier in the guide.

Run the following commands to deploy the resources as defined in the kubernetes.yaml file: [role='command']

kubectl apply -f kubernetes.yaml

When the apps are deployed, run the following command to check the status of your pods: [role='command']

kubectl get pods

If all the pods are healthy and running, you see an output similar to the following: [source, role="no_copy"]

NAME READY STATUS RESTARTS AGE system-deployment-6bd97d9bf6-4ccds 1/1 Running 0 15s inventory-deployment-645767664f-nbtd9 1/1 Running 0 15s

=== Finding the microservice's IP address and ports

The service used to expose your deployments has a type of NodePort service that enables you to access these services from outside of your cluster through a specific port. In this case, nodePort is not specified and the ports are randomized so you must obtain the ports before you make requests to the services. You must also obtain the public IP address of your cluster. Other ways to expose your services are available, such as by using a LoadBalancer service type or an Ingress resource. In production, you typically use an Ingress resource.

First, find the public IP address of your cluster.

[role=command]

ibmcloud ks workers --cluster guide-cluster

Take note of the Public IP in the command's output. You will substitute this value as the hostname into commands later in this guide.

[role="no_copy"]

OK ID Public IP Private IP Flavor State Status Zone Version
kube-bpp5ge4f0ck66fue46vg-guidecluste-default-00000048 159.122.179.207 10.144.188.209 free normal Ready mil01 1.16.8_1526

Get the node port of the system microservice.

[role=command]

kubectl get service system-service -o jsonpath="{.spec.ports[0].nodePort}{'\n'}"

Get the node port of the inventory microservice.

[role=command]

kubectl get service inventory-service -o jsonpath="{.spec.ports[0].nodePort}{'\n'}"

Take note of the IP address and ports. They are required to make the HTTP requests.

=== Making requests to the microservices

To make a request to the system and inventory microservices, curl or visit the following URLs to access your microservices, substituting the appropriate hostname and node ports:

The first URL returns system properties and the name of the pod in an HTTP header called X-Pod-Name. To view the header, you can use the -I option in the curl when making a request to the {system-api} URL. The second URL adds properties from system-service to the inventory.

// ================================================================================================= // Testing microservices that are running on IBM Cloud // =================================================================================================

== Testing microservices that are running on IBM Cloud

A few tests are included for you to test the basic functionality of the microservices. If a test fails, then you might have introduced a bug into the code. To run the tests, wait until all pods are in the ready state before proceeding further. The default properties that are defined in the pom.xml file are:

[cols="15, 100", options="header"] |=== | Property | Description | cluster.ip | IP or hostname for your cluster | system.kube.service | Name of the {kube} Service wrapping the system pods, system-service by default. | system.node.port | The NodePort of the {kube} Service system-service, 31000 by default. | inventory.node.port | The NodePort of the {kube} Service inventory-service, 32000 by default. |===

Use the following command to run the integration tests against your cluster. Substitute [hostname], [system-node-port] and [inventory-node-port] with the appropriate values.

[role=command]

mvn failsafe:integration-test -Dcluster.ip=[hostname] -Dsystem.node.port=[system-node-port] -Dinventory.node.port=[inventory-node-port]

If the tests pass, you'll see an output similar to the following for each service respectively:

[source, role="no_copy"]


T E S T S

Running it.io.openliberty.guides.system.SystemEndpointIT Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.673 sec - in it.io.openliberty.guides.system.SystemEndpointIT

Results:

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[source, role="no_copy"]


T E S T S

Running it.io.openliberty.guides.inventory.InventoryEndpointIT Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.222 sec - in it.io.openliberty.guides.inventory.InventoryEndpointIT

Results:

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

== Deploying a new version of system microservice

Optionally, you might want to make changes to your microservice and redeploy the updated version. In this section, you will bump the version of the system microservice to 2.0-SNAPSHOT and redeploy the new version of the microservice.

Use Maven to repackage your microservice: [role=command]

mvn package

Next, build the new version of the container image as 2.0-SNAPSHOT: [role=command]

docker build --platform linux/amd64 -t system:2.0-SNAPSHOT system/.

Since you built a new image, you need to push it to the repository again. In the following docker and kubectl commands, remember to replace us.icr.io with your registry and [your-namespace] with the namespace you created earlier in the guide.

// Tagging images Tag your container image with the relevant data about your registry.

[role=command]

docker tag system:2.0-SNAPSHOT us.icr.io/[your-namespace]/system:2.0-SNAPSHOT

// Pushing images Push your image to the registry.

[role=command]

docker push us.icr.io/[your-namespace]/system:2.0-SNAPSHOT

Update the system-deployment deployment to use the new container image that you just pushed to the registry:

[role=command]

kubectl set image deployment/system-deployment system-container=us.icr.io/[your-namespace]/system:2.0-SNAPSHOT

Use the following command to find the name of the pod that is running the system microservice.

[role=command]

kubectl get pods

[source, role="no_copy"]

NAME READY STATUS RESTARTS AGE inventory-app-ibm-open-l-994778cf7-fdkb5 1/1 Running 0 5m system-app-ibm-open-libe-85c85949c-lb49d 1/1 Running 0 23s

In this case, the system microservice is running in the pod called system-app-ibm-open-libe-85c85949c-lb49d. Substitute the name of your pod into the following command to see more details about the pod.

[role=command]

kubectl describe pod [pod-name]

Substitute the [pod-name] to your pod name into the following command. Run the command to view your pod events. Observe that the pod is using the new container image system:2.0-SNAPSHOT.

[role=command]

kubectl get event --field-selector involvedObject.name=[pod-name]

[source, role="no_copy"]


LAST SEEN TYPE REASON OBJECT MESSAGE 12m Normal Scheduled pod/system-app-ibm-open-libe-85c85949c-lb49d Successfully assigned default/system-app-ibm-open-libe-85c85949c-lb49d to 10.144.182.122 12m Normal Pulling pod/system-app-ibm-open-libe-85c85949c-lb49d Pulling image "us.icr.io/[your-namespace]/system:2.0-SNAPSHOT" 12m Normal Pulled pod/system-app-ibm-open-libe-85c85949c-lb49d Successfully pulled image "us.icr.io/[your-namespace]/system:2.0-SNAPSHOT" in 6.8103423s 12m Normal Created pod/system-app-ibm-open-libe-85c85949c-lb49d Created container ibm-open-liberty 12m Normal Started pod/system-app-ibm-open-libe-85c85949c-lb49d Started container ibm-open-liberty

// ================================================================================================= // Tear Down // =================================================================================================

== Tearing down the environment

When you no longer need your deployed microservices, you can delete all {kube} resources by running the kubectl delete command: [role='command']

kubectl delete -f kubernetes.yaml

Remove your images from your container registry. Remember to replace us.icr.io to your registry and [your-namespace] with the namespace you created earlier in the guide.

[role=command]

ibmcloud cr image-rm us.icr.io/[your-namespace]/system:1.0-SNAPSHOT
ibmcloud cr image-rm us.icr.io/[your-namespace]/system:2.0-SNAPSHOT
ibmcloud cr image-rm us.icr.io/[your-namespace]/inventory:1.0-SNAPSHOT

Remove the namespace you created in your container registry.

[role=command]

ibmcloud cr namespace-rm [your-namespace]

Log out of your container registry. Remember to replace us.icr.io to your registry.

[role=command]

docker logout us.icr.io
docker logout registry.ng.bluemix.net

Remove your IKS cluster.

[role=command]

ibmcloud ks cluster rm --cluster guide-cluster

Log out of the ibmcloud command line tool.

[role=command]

ibmcloud logout

// ================================================================================================= // finish // =================================================================================================

== Great work! You're done!

You just deployed two microservices to IBM Cloud. You also learned how to use the kubectl command to deploy your microservices on a {kube} cluster.

// Multipane include::{common-includes}/attribution.adoc[subs="attributes"]

// DO NO CREATE ANYMORE SECTIONS AT THIS POINT // Related guides will be added in automatically here if you included them in ":page-related-guides"