Kubernetes: Deploy a Node Express Application

In this tutorial, you use an Oracle Cloud Infrastructure account to set up a Kubernetes cluster. Then, you deploy a Node Express application to your cluster. Key tasks include how to:

  • Set up OpenSSL API encryption keys to access your cluster.
  • Set up an authentication token.
  • Set up a Kubernetes cluster on OCI.
  • Set up OCI CLI to access your cluster.
  • Build a Node Express application and Docker Image.
  • Push your image to OCIR.
  • Deploy your Docker application to your cluster.
  • Connect to your application from the internet.
A diagram of the components needed to run a NodeJS Express application on Oracle Cloud Infrastructure Container Engine

For additional information, see:

1. Gather Required Information

Prepare the information you need from the Oracle Cloud Infrastructure Console.

  1. Check your service limits:
    • Regions: minimum 2

      In the top navigation bar, expand <region>. Example: US East (Ashburn) and US West (Phoenix).

    • Compute instances: minimum 3

      Click your profile avatar. Select Tenancy. Go to Service Limits and expand Compute.

    • Block Volume: minimum 50 GBs

      In the Service Limits section, expand Block Volume.

    • Load Balancer: available

      In the Service Limits section, expand Networking.

  2. Have a compartment for your cluster.
  3. Create an authorization token:
    • In the top navigation bar, click your user avatar.
    • Select your username.
    • Click Auth Tokens.
    • Click Generate Token.
    • Give it a description.
    • Click Generate Token.
    • Copy the token and save it.
    Note

    Make sure you save your token right after you create it. You will not have access to it later.
  4. Find your region identifier and region key from Regions and Availability Domains. Example: us-ashburn-1 and iad for Ashburn.
  5. Collect the following information and copy them into your notepad.
    • Auth Token: <auth-token> from step 3.
    • Region: <region-identifier> from step 4. Example: us-ahburn-1.
    • Region Key: <region-key> from step 4. Example: iad.
    • Tenancy name: <tenancy-name> from your user avatar.
    • Tenancy OCID: <tenancy-ocid> from your user avatar, go to Tenancy:<your-tenancy> and copy OCID.
    • Username: <user-name> from your user avatar.
    • User OCID: <user-ocid> from your user avatar, go to User Settings and copy OCID.

2. Create SSH Encryption Keys

Create ssh encryption keys you can use to log into your VM.

  1. Open a terminal window:
    • MacOS or Linux: Open a terminal window in the directory where you want to store your keys.
    • Windows: Right click on the directory where you want to store your keys and select Git Bash Here.
  2. Issue the following OpenSSH command:
    ssh-keygen -t rsa -N "" -b 2048 -C <my-key> -f <my-key>

    The command generates some random text art used to generate the keys. When complete, you should have two files:

    • The private key file: <my-key>
    • The public key file: <my-key>.pub

    You use these files to connect to your Compute instance.

You have generated the required encryption keys.

See Creating a Key Pair for more detailed information on generating ssh encryption keys.

3. Create a Virtual Cloud Network (VCN)

Setup a VCN to connect your Linux instance to the internet. You configure all the components needed to create your virtual network.

  1. From the main landing page, select Set up a network with a wizard. Quick action menu from the main Free Tier landing page
  2. In the Start VCN Wizard workflow, select VCN with Internet Connectivity and then click Start VCN Wizard .
  3. In the configuration dialog, fill in the VCN Name for your VCN. Your Compartment is already set to its default value of <your-tenancy> (root).
  4. In the Configure VCN and Subnets section, keep the default values for the CIDR blocks:
    • VCN CIDR BLOCK: 10.0.0.0/16
    • PUBLIC SUBNET CIDR BLOCK: 10.0.0.0/24
    • PRIVATE SUBNET CIDR BLOCK: 10.0.1.0/24
    Note

    Notice the public and private subnets have different network addresses.
  5. For DNS RESOLUTION uncheck USE DNS HOSTNAMES IN THIS VCN.Picture shows the USE DNS HOSTNAMES IN THIS VCN option is unchecked.
  6. Click Next.

    The Create a VCN with Internet Connectivity configuration dialog is displayed (not shown here) confirming all the values you just entered.

  7. Click Create to create your VCN.

    The Creating Resources dialog is displayed (not shown here) showing all VCN components being created.

  8. Click View Virtual Cloud Network to view your new VCN.

    Your new VCN is displayed. Now you need to add a security rule to allow HTTP connections on port 3000, the default port for your application.

  9. With your new VCN displayed, click your Public subnet link.

    The public subnet information is displayed with the Security Lists at the bottom of the page. There should be a link to the Default Security List for your VCN.

  10. Click on the Default Security List link.

    The default Ingress Rules for your VCN are displayed.

  11. Click Add Ingress Rules.

    An Add Ingress Rules dialog is displayed.

  12. Fill in the ingress rule with the following information. Once all the data is entered, click Add Ingress Rules.

    Fill in the ingress rule as follows:

    • Stateless: Checked
    • Source Type: CIDR
    • Source CIDR: 0.0.0.0/0
    • IP Protocol: TCP
    • Source port range: (leave-blank)
    • Destination Port Range: 3000
    • Description: VCN for applications

    Once you click Add Ingress Rule, HTTP connections are allowed to your public subnet.

Note

To open a different port, replace 3000 in the last step with the port number.
You have successfully created a VCN that will make your applications available from the internet.

4. Install an Ubuntu VM

Install an Ubuntu VM to host your applications. This is a Free Tier VM and using it is free, no cost forever.

  1. From the Oracle Cloud Infrastructure main menu, select Compute, then Instances.
  2. From the list of instances screen, click Create Instance.

    The Create Compute Instance dialog is displayed. Notice the Show Shape, Network and Storage Options should be expanded to configure the virtual machine.

  3. Fill in the fields for the Create Compute Instance dialog with the following data:

    Initial Options

    • Name of your Instance: <name-for-the-instance>
    • Image or Operating System (Click Change Image): Canonical Ubuntu 18.04
    • Availability Domain: <Select-an-always-free-eligible-domain>
    • Instance Shape: VM.Standard.E2.1.Micro: Virtual Machine, 1 core OCPU, 1 GB Memory, 0.48 Gbps network bandwidth
    Note

    If you select an Always Free Eligible availability domain, the shape should default to VM.Standard.E2.1.Micro. However, if the shape is not automatically selected, click Change Shape. From the Shape Series select Specialty and Legacy and then VM.Standard.E2.1.Micro.

    If you plan to use this VM for other applications, make sure that the 1 GB of memory is adequate for your applications.

    Configure Networking

    • VIRTUAL CLOUD NETWORK COMPARTMENT: <your-compartment>
    • VIRTUAL CLOUD NETWORK: <VCN-you-created>
    • SUBNET COMPARTMENT: <your-subnet-compartment>
    • SUBNET: <public-subnet-you-created>
    • USE NETWORK SECURITY GROUPS TO CONTROL TRAFFIC: Unchecked
    • ASSIGN A PUBLIC IP ADDRESS: Selected/Checked

    Additional Options

    • Boot Volume: All options Unchecked
    • Add SSH Keys: Add the public key file (.pub) you created in the beginning of this tutorial.
  4. Click Create to create the instance.

    Provisioning the system may take several minutes.

You have successfully created an Ubuntu Linux VM to build and test your applications.

5. Create a Local Node Express Application

Next, set up an Express framework on your Ubuntu Linux VM and then create and run a NodeJS application.

By default, Ubuntu 18.04 does not come with NodeJS, Express, Docker, Kubernetes or virtualenv. To create your application with Express, perform the following steps:

  1. From the main menu select Compute, then Instances.
  2. Click the link to the instance you created in the previous step.

    From the Instance Details page look in the Instance Access section. Copy the public IP address the system created for you. You will use this IP address to connect to your instance.

  3. Open a Terminal or Command Prompt window.
  4. Change into the directory where you stored the ssh encryption keys you created for this tutorial.
  5. Connect to your VM with this ssh command
    ssh -i <your-private-key-file> ubuntu@<x.x.x.x>

    Since you identified your public key when you created the VM, this command should log you into your VM. You can now issue sudo commands to install and start your server.

  6. Update firewall settings.
    The Ubuntu firewall is disabled by default. However, it is still necessary to update your iptables configuration to allow HTTP traffic. Execute the following commands to update iptables.
    sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 3000 -j ACCEPT
    sudo netfilter-persistent save

    The commands add a rule to allow HTTP traffic through port 3000 and saves the changes to the iptables configuration files.

  7. Install NodeJS version 8.10+.
    sudo apt update
    sudo apt install nodejs
    Note

    You may need to type "y" a few times to accept the packages that are installed to the VM.
    node --version
  8. Install Express version 4.0+.
    sudo apt install node-express-generator
    express --version
  9. Create a directory for your application.
    mkdir node-hello-app
  10. Change to the node-hello-app directory.
    cd node-hello-app
  11. Create a "Hello, World!" application.

    Create the file:

    vi app.js

    In the file, input the following text and save the file:

    const express = require('express')
    const app = express()
    
    app.get('/', function (req, res) {
      res.send('Hello World!')
    })
    
    app.listen(3000, function() {
      console.log('Hello World app listening on port 3000!');
    })
    
  12. Run the NodeJS program:
    node app.js
  13. Test the application using the command line or a browser:
    • To test with curl, from a new terminal, connect to your Ubuntu VM with your SSH keys, and then in the command line enter: curl -X GET http://localhost:3000
    • From a browser, connect to the public IP address assigned to your VM: http://<x.x.x.x>:3000
    You should see Hello World! on your VM, or in your browser.

You have successfully created a local NodeJS application in an Express framework, on your Oracle Cloud Infrastructure VM.

References:

For more information on Express, see Getting Started with Express.

6. Build and Push the Node Express Docker Image

Next, create a Docker image on your Ubuntu Linux VM and then push it to Oracle Cloud Infrastructure Registry.

Package the Application

Package your application and then point to the package in your Dockerfile.

  1. First, make sure you are in the node-hello-app directory.
  2. Install Node Package Manager (npm) 3.5.2+.
    sudo apt install npm
    npm --version
  3. Create a package.json file:

    Create the file:

    vi package.json

    In the file, input the following text, update the optional author and repository fields and then save the file:

    {
      "name": "node-hello-app",
      "version": "1.0.0",
      "description": "Node Express Hello application",
      "author": "Example User <username@example.com>",
      "main": "app.js",
      "scripts": {
        "start": "node app.js"
      },
      "repository": {
      "type": "git",
      "url": "git://github.com/username/repository.git"
      },
      "dependencies": {
        "express": "^4.0.0"
      },
      "license": "UPL-1.0"
    }
    
  4. Install the package with npm.
    npm install

Install Docker

Install Docker on your Oracle Linux VM.

  1. Install Docker 18.0.6+ on your VM:
    sudo snap install docker
    docker --version
Note

This snap build requires all files that Docker uses, such as Dockerfile, to be in $HOME or a sub-directory of it. Keep the files there, for commands such as docker build, docker save and docker load.

Build a Docker Image

Build a Docker image for your application.

  1. Create a file named Dockerfile:

    Create the file:

    vi Dockerfile

    In the file, input the following text and save the file:

    FROM node:12.18.1
    WORKDIR /app
    COPY app.js .
    COPY package.json .
    RUN npm install
    EXPOSE 3000
    CMD [ "node", "app.js" ]
    
  2. Build a Docker image:
    sudo docker build -t node-hello-app .

    You should get a message of success.

    [INFO] BUILD SUCCESS
    Successfully tagged node-hello-app:latest
  3. Run the Docker image: sudo docker run --rm -p 3000:3000 node-hello-app:latest
  4. Test the application using the command line or a browser:
    • To test with curl, in a terminal, enter curl localhost:3000
    • From a browser, connect to the public IP address assigned to your VM: http://<x.x.x.x>:3000.
    If you get Hello World!, then the Docker image is running.
  5. Stop the Hello world application.
    From another terminal, run sudo docker ps. Find the container id for your application and then run sudo docker stop <node-hello-app-container-id>.

    Now you can push the image to Oracle Cloud Infrastructure Registry (OCIR).

Push your Docker image to OCIR

With your Docker image created, now you need to push it to OCIR.

  1. Open a terminal window.
  2. Use <region-key> from the gather information section to log Docker into OCIR:
    sudo docker login <region-key>.ocir.io

    You are prompted for your login name and password.

    • Username: <tenancy-name>/<user-name>
    • Password: <auth-token>
  3. List your local Docker images.
    sudo docker images

    The Docker images on your system are displayed. Identify the image you created in the last section: node-hello-app

  4. Before you push your local image to OCIR, you must reference it with a new name that includes the path to OCIR. Then you can push the image with the new name to OCIR. Use the Docker tag command to create a shortcut to your image using the new name:
    sudo docker tag <your-local-image> <registry-image>

    The registry image consists of: <region-key>.ocir.io/<tenancy-name>/<image-folder>/<image-name>

    Example: sudo docker tag node-hello-app iad.ocir.io/<tenancy-name>/<image-folder>/node-hello-app

    Note

    The <image-folder> is a string of your choosing that is used to group your images. For example, a short version of your username is often used. "John Doe" might use: sudo docker tag node-hello-app iad.ocir.io/<tenancy-name>/johnd/node-hello-app.
  5. Check your Docker images to see if the reference has been created.
    sudo docker images
    Note

    The new image has the same image ID as your local image.
  6. Push the image to OCIR.
    sudo docker push <registry-image>:latest

    Example: sudo docker push iad.ocir.io/<tenancy-name>/<image-folder>/node-hello-app:latest

    You should see your image in OCIR after the push command is complete.

View the OCIR Repository you Created

  1. In the Console, from the main menu select Developer Services, then Registry (OCIR).
  2. In the list of registries, expand your registry: <image-folder>/node-hello-app. You may need to scroll to the right, to get a second scrollbar, to find your registry. By default, your repository is created with private access.
    You should see:

    Access: Private

  3. Click latest.
    You should see:

    Full Path: <region-key>.ocir.io/<tenancy-name>/<image-folder>/node-hello-app

Congratulations! You created a Node Express Docker image. Now you can create a Kubernetes cluster and deploy this image to the cluster.

7. Create a Kubernetes Cluster

Set up the Kubernetes cluster you will deploy your application to. You will use a wizard to set up your first cluster.

  1. From the OCI main menu select Developer Services then Container Clusters.
  2. Click Create Cluster.
  3. Select Quick Create.
  4. Click Launch Workflow.

    The Cluster Creation dialog is displayed.

  5. Fill in the following information:
    • Name: <your-cluster-name>
    • Compartment: <your-compartment-name>
    • Kubernetes Version: <take-default>
    • Visibility Type: <Private>
    • Shape: VM.Standard.E2.1
    • Number of Nodes: 3
    • Add Ons: <none-selected>
  6. Click Next.

    All your choices are displayed. Review them to make sure everything is configurated correctly.

  7. Click Create Cluster.

    The services set up for your cluster are displayed.

  8. Click Close.
  9. Get a cup of coffee. It may take a few minutes for the cluster to be created.
You have successfully created a Kubernetes cluster.

8. Set up OCI Command Line Interface

You can use the OCI Command Line Interface (CLI) to push your application to Registry and then pull and deploy it with Container Engine for Kubernetes. In this step, you install and set up the CLI to run on the VM that you are using as your local machine.

Note

This tutorial covers the installation of the OCI CLI on your local machine. As an alternative, OCI provides a Cloud Shell with the CLI installed, that can be accessed from the OCI Console. For more information see: Interact with an OKE cluster from Cloud Shell.
  1. Install virtualenv:

    With a virtual environment, you can manage dependencies for your project. Every project can be in its own virtual environment to host independent groups of Python libraries. You will use virtualenv for the CLI.

    From a terminal, enter:
    sudo apt install python3-venv
  2. Install a virtual environment wrapper.

    The virtualenvwrapper is an extension to virtualenv. It provides a set of commands, which makes working with virtual environments much more pleasant. It also places all your virtual environments in one place. The virtualenvwrapper provides tab-completion on environment names.

    sudo apt install python3-pip
    sudo pip3 install virtualenvwrapper
  3. Set up your virtual environment wrapper in .bashrc.

    Update the file:

    sudo vi .bashrc

    In the file, append the following text and save the file:

    # set up Python env
    export WORKON_HOME=~/envs
    export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
    export VIRTUALENVWRAPPER_VIRTUALENV_ARGS=' -p /usr/bin/python3 '
    source /usr/local/bin/virtualenvwrapper.sh

    Activate the above commands in the current window.

    source ~/.bashrc
  4. Start a virtual environment.
    mkvirtualenv cli-app
    You should see something like: (cli-app) ubuntu@<ubuntu-instance-name>:~$
  5. Install OCI CLI .
    pip3 install oci-cli
  6. Test the installation:
    oci -v

    You should get the CLI version, if it is set up correctly.

  7. Set up the OCI CLI config file.
    oci setup config

    Enter basic information: (Get the answers from "Gather Required Information" step.)

    • Location for your config [$HOME/.oci/config]: <take-default>
    • User OCID: <user-ocid>
    • Tenancy OCID: <tenancy-ocid>
    • Region (e.g. us-ashburn-1): <region-identifier>

    Set up your OpenSSL API encryption keys:

    • Generate a new API Signing RSA key pair? [Y/n]: Y
    • Directory for your keys [$HOME/.oci]: <take-default>
    • Name for your key [oci_api_key] <take-default>
    Note

    Your private key is oci_api_key.pem and your public key is oci_api_key_public.pem. This key is different than the one to access your VM.
  8. Deactivate the virtual environment:
    deactivate

    The (cli-app) prefix in your environment should not be displayed anymore.

    Note

    • Whenever you want to use the OCI CLI, activate it with: workon cli-app
    • workon deactivates the environment you are currently in, if you change project names. This way, you can quickly switch between environments.
  9. Activate the cli-app environment:
    workon cli-app
  10. Copy the public key.
    In the terminal enter:
    cat $HOME/.oci/oci_api_key_public.pem
  11. Add the public key to your user account.
    • From your user avatar, go to User Settings.
    • Click Add Public Key.
    • Select Paste Public Keys.
    • Paste value from previous step, including the lines with BEGIN PUBLIC KEY and END PUBLIC KEY
    • Click Add.
    You have now set up the Oracle Cloud Infrastructure CLI to connect to your tenancy with your user account.

9. Manage the Kubernetes Cluster (Local)

In this section, you include the Kubernetes cluster information in a .kube/config file, so you can access the cluster and manage deployments. To do that, complete the following steps:

  1. From the OCI main menu select Developer Services then Container Clusters.
  2. Click the link to <your-cluster>.

    The information about your cluster is displayed.

  3. Click Access Cluster.
  4. Select Local Access.
  5. Follow the steps provided in the dialog. The steps for local access are reprinted here for your reference.
    Note

    If you are not in your virtual environment, enter: workon cli-app before you run kubectl commands.

    Activate your cli-app environment and test the oci connection.

    oci -v

    Make your .kube directory if it doesn't exist.

    mkdir -p $HOME/.kube

    Create kubeconfig file for your setup. Use the information from Access Your Cluster dialog.

    oci ce cluster create-kubeconfig <copy-data-from-dialog>

    Export the KUBECONFIG environment variable.

    export KUBECONFIG=$HOME/.kube/config
  6. Test your cluster configuration with the following command:

    List clusters:

    kubectl get service

    Note: If you have existing clusters, the new cluster information is merged with your $HOME/.kube/config file.

With your cluster configured, you are now ready to prepare your application for deployment.

10. Deploy the Docker Image to the Cluster

Now, create a manifest file to include information about the following resources and then create the resources with Kubernetes:
  • Deployment: Pull and deploy the image from registry.
  • Load Balancer Service: Make the application available with a public IP address.
Deploy your Image to the Cluster

With your image in OCIR, you can now deploy your application. Perform the following commands either in Cloud Shell or in a terminal connected to your VM.

  1. First, create a registry secret for your application. This will be used to authenticate your image when it is deployed to your cluster.

    Fill in the information in this template to create your secret with the name ocirsecret.

    
    kubectl create secret docker-registry ocirsecret --docker-server=<region-code>.ocir.io  --docker-username='<tenancy-name>/<user-name>' --docker-password='<auth-token>' --docker-email='<email-address>'

    After executing the command, you should get message similar to: secret/ocirsecret created.

  2. Verify the secret was created. Issue the following command.
    kubectl get secret ocirsecret --output=yaml

    The output includes information about your secret is shown in the yaml format.

  3. Determine the host URL to your registry image using the following template.
    
    <region-code>.ocir.io/<tenancy-name>/<repo-name>/<image-name>:<tag>

    Example: iad.ocir.io/<tenancy-name>/<repo-name>/node-hello-app:latest

  4. Create a file called app.yaml.
    
    vi app.yaml
  5. Copy the following information in your app.yaml.
    Note

    Your code must have the exact same indentation. The deployment and load balancer service are separated with ---.

    Here are some of the parameters that you will set for the deployment section:

    • replicas: 3
    • image: <your-image-url>
    • imagePullPolicy: Always
    • protocol: TCP
    • imagePullSecrets:
      • name: ocirsecret
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: node-hello-app
    spec:
      selector:
        matchLabels:
          app: node-hello-app
      replicas: 3
      template:
        metadata:
          labels:
            app: node-hello-app
            version: v1
        spec:
          containers:
          - name: node-hello-app
            image: <your-image-url>
            imagePullPolicy: Always
            ports:
            - containerPort: 3000
              protocol: TCP
          imagePullSecrets:
            - name: ocirsecret
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: node-hello-app-lb
      labels:
        app: node-hello-app
    spec:
      type: LoadBalancer
      ports:
      - port: 3000
      selector:
        app: node-hello-app
    
  6. Deploy your application with the following command:
    kubectl create -f app.yaml
Test your Application

Your load balancer may take a few seconds to load after issuing the command.

  1. Check for your load balancer to deploy.
    kubectl get service

    Repeat the command until the load balancer is assigned an external IP address.

  2. Using the IP address for the load balancer connect to your app in a browser, http://x.x.x.x:3000

Clean up the Application

After you are done, clean up and remove the services you created.

  1. Delete your application deployment and load balancer service:
    kubectl delete -f app.yaml
    The following messages are returned:
    service "node-hello-app-lb" deleted
    deployment.extensions "node-hello-app" deleted
  2. To check that the service is removed:
    kubectl get service
Congratulations! You installed and deployed a Node Express application to a Kubernetes cluster on Oracle Cloud Infrastructure.

What's Next

You have successfully created a Hello World application, deployed it to a Kubernetes cluster and made it accessible on the internet, using the Node Express framework.

To explore more information about development with Oracle products check out these sites: