Thursday, November 29, 2018

Scalable web application on Kubernetes

Scalable web application on Kubernetes

This tutorial walks you through how to scaffold a web application, run it locally in a container, and then deploy it to a Kubernetes cluster created with Kubernetes Service. Additionally, you will learn how to bind a custom domain, monitor the health of the environment, and scale the application.
Containers are a standard way to package apps and all their dependencies so that you can seamlessly move the apps between environments. Unlike virtual machines, containers do not bundle the operating system. Only the app code, run time, system tools, libraries, and settings are packaged inside containers. Containers are more lightweight, portable, and efficient than virtual machines.
For developers looking to kickstart their projects, the IBM Cloud Developer Tools CLI enables rapid application development and deployment by generating template applications that you can run immediately or customize as the starter for your own solutions. In addition to generating starter application code, Docker container image and CloudFoundry assets, the code generators used by the dev CLI and web console generate files to aid deployment into Kubernetes environments. The templates generate Helm charts that describe the application’s initial Kubernetes deployment configuration, and are easily extended to create multi-image or complex deployments as needed.

Objectives

  • Scaffold a starter application.
  • Deploy the application to the Kubernetes cluster.
  • Bind a custom domain.
  • Monitor the logs and health of the cluster.
  • Scale Kubernetes pods.

Services used

This tutorial uses the following runtimes and services:
This tutorial may incur costs. Use the Pricing Calculator to generate a cost estimate based on your projected usage.

Architecture

Architecture
  1. A developer generates a starter application with IBM Cloud Developer Tools.
  2. Building the application produces a Docker container image.
  3. The image is pushed to a namespace in Kubernetes Service.
  4. The application is deployed to a Kubernetes cluster.
  5. Users access the application.

Before you begin

Create a Kubernetes cluster

Kubernetes Service delivers powerful tools by combining Docker and Kubernetes technologies, an intuitive user experience, and built-in security and isolation to automate the deployment, operation, scaling, and monitoring of containerized apps in a cluster of compute hosts.
The major portion of this tutorial can be accomplished with a Free cluster. Two optional sections relating to Kubernetes Ingress and custom domain require a Paid cluster of type Standard.
  1. Create a Kubernetes cluster from the IBM® Cloud catalog.
    For ease of use, check the configuration details like the number of CPUs, memory and the number of worker nodes you get with Lite and Standard plans.
    Kubernetes Cluster Creation on IBM Cloud
  2. Select the Cluster type and click Create Cluster to provision a Kubernetes cluster.
  3. Check the status of your Cluster and Worker Nodes and wait for them to be ready.

Configure kubectl

In this step, you'll configure kubectl to point to your newly created cluster going forward. kubectl is a command line tool that you use to interact with a Kubernetes cluster.
  1. Use ibmcloud login to log in interactively. Provide the organization (org), location and space under which the cluster is created. You can reconfirm the details by running ibmcloud target command.
  2. When the cluster is ready, retrieve the cluster configuration by setting MYCLUSTER environment variable to your cluster name:
    export MYCLUSTER= ibmcloud cs cluster-config ${MYCLUSTER}
  3. Copy and paste the export command to set the KUBECONFIG environment variable as directed. To verify whether the KUBECONFIG environment variable is set properly or not, run the following command: echo $KUBECONFIG
  4. Check that the kubectl command is correctly configured
    kubectl cluster-info

Create a starter application

The ibmcloud dev tooling greatly cuts down on development time by generating application starters with all the necessary boilerplate, build and configuration code so that you can start coding business logic faster.
  1. Start the ibmcloud dev wizard.
    ibmcloud dev create
  2. Select Backend Service / Web App > Java - MicroProfile / JavaEE > Java Web App with Eclipse MicroProfile and Java EE (Web App) to create a Java starter. (To create a Node.js starter instead, use Backend Service / Web App > NodeNode.js Web App with Express.js (Web App) )
  3. Enter a name for your application.
  4. Select the resource group where to deploy this application.
  5. Do not add additional services.
  6. Do not add a DevOps toolchain, select manual deployment.
This generates a starter application complete with the code and all the necessary configuration files for local development and deployment to cloud on Cloud Foundry or Kubernetes. For an overview of the files generated, see Project Contents Documentation.

Build the application

You can build and run the application as you normally would using mvn for java local development or npm for node development. You can also build a docker image and run the application in a container to ensure consistent execution locally and on the cloud. Use the following steps to build your docker image.
  1. Ensure your local Docker engine is started.
    docker ps
  2. Change to the generated project directory.
    cd
  3. Build the application.
    ibmcloud dev build
    This might take a few minutes to run as all the application dependencies are downloaded and a Docker image, which contains your application and all the required environment, is built.

Run the application locally

  1. Run the container.
    ibmcloud dev run
    This uses your local Docker engine to run the docker image that you built in the previous step.
  2. After your container starts, go to http://localhost:9080/. If you created a Node.js application, go to http://localhost:3000/.

Deploy application to cluster using helm chart

In this section, you first push the Docker image to the IBM Cloud private container registry, and then create a Kubernetes deployment pointing to that image.
  1. Find your namespace by listing all the namespace in the registry.
    ibmcloud cr namespaces
    If you have a namespace, make note of the name for use later. If you don't have one, create it.
    ibmcloud cr namespace-add
  2. Set MYNAMESPACE and MYPROJECT environment variables to your namespace and project name respectively
    export MYNAMESPACE=
    export MYPROJECT=
  3. Identify your Container Registry (e.g. registry.ng.bluemix.net) by running ibmcloud cr info
  4. Set MYREGISTRY env var to your registry.
    export MYREGISTRY=
  5. Build and tag (-t)the docker image
    docker build . -t ${MYREGISTRY}/${MYNAMESPACE}/${MYPROJECT}:v1.0.0
  6. Push the docker image to your container registry on IBM Cloud
    docker push ${MYREGISTRY}/${MYNAMESPACE}/${MYPROJECT}:v1.0.0
  7. On an IDE, navigate to values.yaml under chart\YOUR PROJECT NAME and update the image repositoryvalue pointing to your image on IBM Cloud container registry. Save the file.
    For image repository details, run echo ${MYREGISTRY}/${MYNAMESPACE}/${MYPROJECT}
  8. Helm helps you manage Kubernetes applications through Helm Charts, which helps define, install, and upgrade even the most complex Kubernetes application. Initialize Helm by navigating to chart\YOUR PROJECT NAMEand running the below command in your cluster
    helm init
    To upgrade helm, run this command helm init --upgrade
  9. To install a Helm chart, change to the chart\YOUR PROJECT NAME directory and run the below command
    helm install . --name ${MYPROJECT}
  10. Use kubectl get service ${MYPROJECT}-service for your Java application and kubectl get service ${MYPROJECT}-application-service for your Node.js application to identify the public port the service is listening on. The port is a 5-digit number(e.g., 31569) under PORT(S).
  11. For the public IP of worker node, run the below command
    ibmcloud cs workers ${MYCLUSTER}
  12. Access the Java application at http://worker-ip-address:portnumber/nameofproject and Node.js application at http://worker-ip-address:portnumber

Use the IBM-provided domain for your cluster

In the previous step, the application was accessed with a not standard port. The service was exposed by way of Kubernetes NodePort feature.
Paid clusters come with an IBM-provided domain. This gives you a better option to expose applications with a proper URL and on standard HTTP/S ports.
Use Ingress to set up the cluster inbound connection to the service.
Ingress
  1. Identify your IBM-provided Ingress domain
    ibmcloud cs cluster-get ${MYCLUSTER}
    to find
    Ingress subdomain:    mycluster.us-south.containers.appdomain.cloud
    Ingress secret:        mycluster
    
  2. Create an Ingress file ingress-ibmdomain.yml pointing to your domain with support for HTTP and HTTPS. Use the following file as a template, replacing all the values wrapped in <> with the appropriate values from the above output.service-name is the name under ==> v1/Service in the above step or run kubectl get svc to find the service name of type NodePort.
    apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-for-ibmdomain-http-and-https spec: tls: - hosts: - secretName: rules: - host: http: paths: - path: / backend: serviceName: servicePort: 9080
  3. Deploy the Ingress
    kubectl apply -f ingress-ibmdomain.yml
  4. Access your application at https:///

Use your own custom domain

To use your custom domain, you need to update your DNS records with either a CNAME record pointing to your IBM-provided domain or an A record pointing to the portable public IP address of the IBM-provided Ingress. Given a paid cluster comes with fixed IP addresses, an A record is a good option.

with HTTP

  1. Create an Ingress file ingress-customdomain-http.yml pointing to your domain:
    apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-for-customdomain-http spec: rules: - host: http: paths: - path: / backend: serviceName: servicePort: 9080
  2. Deploy the Ingress
    kubectl apply -f ingress-customdomain-http.yml
  3. Access your application at http:///

with HTTPS

If you were to try to access your application with HTTPS at this time https:///, you will likely get a security warning from your web browser telling you the connection is not private. You would also get a 404 as the Ingress just configured would not know how to direct HTTPS traffic.
  1. Obtain a trusted SSL certificate for your domain. You'll need the certificate and the key:https://console.bluemix.net/docs/containers/cs_apps.html#custom_domain_cert You can use Let's Encrypt to generate trusted certificate.
  2. Save the cert and the key in base64 ascii format files.
  3. Create a TLS secret to store the cert and the key:
    kubectl create secret tls my-custom-domain-secret-name --cert= --key=
  4. Create an Ingress file ingress-customdomain-https.yml pointing to your domain:
    apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-customdomain-https spec: tls: - hosts: - secretName: rules: - host: http: paths: - path: / backend: serviceName: servicePort: 9080
  5. Deploy the Ingress:
    kubectl apply -f ingress-customdomain-https.yml
  6. Access your application at https:///.

Monitor application health

  1. To check the health of your application, navigate to clusters to see a list of clusters and click on the cluster you created above.
  2. Click Kubernetes Dashboard to launch the dashboard in a new tab.
  3. Select Nodes on the left pane, click the Name of the nodes and see the Allocation Resources to see the health of your nodes.
  4. To review the application logs from the container, select Podspod-name and Logs.
  5. To ssh into the container, identify your pod name from the previous step and run
    kubectl exec -it -- bash

Scale Kubernetes pods

As load increases on your application, you can manually increase the number of pod replicas in your deployment. Replicas are managed by a ReplicaSet. To scale the application to two replicas, run the following command:
kubectl scale deployment -deployment --replicas=2
After a shortwhile, you will see two pods for your application in the Kubernetes dashboard (or with kubectl get pods). The Ingress controller in the cluster will handles the load balancing between the two replicas. Horizontal scaling can also be made automatic.

No comments:

Post-Incident Analysis: AWS US-EAST-1

  Post-Incident Analysis: AWS US-EAST-1 Outage (October 20, 2025) 1. Incident Overview and Scope of Impact The major AWS service disruption ...