Liberty InstantOn on Amazon EKS
This article was published when Liberty InstantOn was still beta. Liberty InstantOn moved out of beta as of the Liberty 23.0.0.6 release. For the latest information about Liberty InstantOn, see Faster startup for containerized applications with Open Liberty InstantOn in the Open Liberty docs.
Liberty InstantOn beta dramatically improves the startup time of Liberty applications. In this post, we will deploy a simple Liberty application to Amazon Elastic Kubernetes Service (Amazon EKS) and use InstantOn to quickly spin up application containers.
First, we will build an InstantOn container image and push it to Amazon Elastic Container Registry (Amazon ECR). Next, we will create a new Amazon EKS cluster, deploy the Liberty application to the cluster, and scale the application up.
To complete the steps outlined in this post, you need the following resources:
-
Maven to build the Liberty application
-
Podman to build the InstantOn image
-
An Amazon AWS Account
-
The AWS CLI to create and manage AWS services
-
The Amazon EKS CLI (v0.120.0 or higher) to create and manage EKS clusters
-
The kubectl command-line tool to interact with a Kubernetes cluster
Build the InstantOn image
First, clone the repository of the sample Liberty application. We are checking out the instanton
branch, which contains the InstantOn modifications.
git clone -b instanton https://github.com/OpenLiberty/sample-getting-started.git
cd sample-getting-started
Next, build the application code using Maven:
mvn install
Once the code is compiled, we can build the InstantOn container image. This process creates two container images:
-
The base image, which contains only the application
-
The InstantOn image, which extends the base image and adds the checkpoint data needed for a quick startup.
A small set of elevated Linux permissions are required to build the InstantOn container image. However, to simplify the example, the next few commands are run as the root user using the sudo command.
|
To build the base image, run:
sudo ./build-og.sh
The script runs a simple podman build
command and creates the dev.local/getting-started
container image.
To build the InstantOn image, run:
sudo ./build-instanton.sh
The scripts runs a sequence of podman
commands that create the checkpoint data and save that data in a new dev.local/getting-started-instanton
container image.
Push the image to ECR
At this point, the InstantOn image on exists on a local machine. We need to push it to a container registry to make it available to the EKS cluster. One option is to make the image available in a public registry, such as DockerHub or Quay. Another option is to use Amazon ECR.
In this post, we will use Amazon ECR for a couple of reasons. First, a default private Amazon ECR is provided with each AWS account, so we don’t have to set up and configure a separate registry elsewhere. Second, Amazon ECR can seamlessly integrate with EKS and other similar AWS services such as Amazon ECS. Therefore, we do not have to configure any image pull secrets in our EKS cluster to pull down images from the private container registry.
To use the private Amazon ECR registry, first create a repository for the InstantOn image:
aws ecr create-repository --repository-name getting-started-instanton
In the output of this command, note the repositoryUri
value. It should match the <aws_account_id>.dkr.ecr.<region>.amazonaws.com/getting-started-instanton
pattern. For example: 1234567890.dkr.ecr.us-east-1.amazonaws.com/getting-started-instanton
. You will need this value when you create the deployment.yaml
file to deploy the InstantOn application.
Next, authenticate to the registry using the following command so you can push or pull images using Podman:
aws ecr get-login-password | sudo podman login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com
After you are authenticated, you can tag and push the InstantOn image to the private ECR registry:
sudo podman tag dev.local/getting-started-instanton <aws_account_id>.dkr.ecr.<region>.amazonaws.com/getting-started-instanton
sudo podman push <aws_account_id>.dkr.ecr.<region>.amazonaws.com/getting-started-instanton
Provision the EKS cluster
We are ready to provision an EKS cluster now. The first step is to create a cluster.yaml
file with the following contents.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: instanton
region: us-east-1
version: "1.24"
managedNodeGroups:
- name: ng-instanton
instanceType: t3.micro
desiredCapacity: 3
iam:
attachPolicyARNs:
- arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
- arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
The initial cluster.yaml
file requests a Kuberentes v1.24 cluster to be provisioned with three managed EC2 nodes. The cluster is just big enough to handle the sample application. If you are planning to deploy other applications to the cluster, adjust the instanceType
and/or the desiredCapacity
parameters. Also, make sure that the region
parameter matches your region. See the config file schema for additional settings that can be configured when provisioning a cluster.
With this configuration, the cluster nodes are created using the default Amazon Machine Image (AMI) running the Amazon Linux 2 operating system. The latest Amazon Linux AMI is running a Linux kernel version that supports InstantOn. The other EKS-optimized AMIs, such as Bottlerocket or Ubuntu 20, also support InstantOn. You can use a custom AMI for your cluster as long as it is running Linux kernel 5.9 or higher. |
After making updates to the cluster.yaml
, run the following command to provision the EKS cluster:
eksctl create cluster -f cluster.yaml
After about 15 minutes, the cluster should be provisioned and ready to use. Double check by running the following command to see the cluster nodes:
kubectl get node -o wide
Look for output similar to the following example:
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-xxx-xxx-xx-xxx.ec2.internal Ready <none> 2m44s v1.24.6-eks-4360b32 xxx.xxx.xx.xxx xx.xxx.xxx.xxx Amazon Linux 2 5.10.165-143.735.amzn2.x86_64 containerd://1.6.6
ip-xxx-xxx-xx-xxx.ec2.internal Ready <none> 2m42s v1.24.6-eks-4360b32 xxx.xxx.xx.xxx xx.xx.xx.xx Amazon Linux 2 5.10.165-143.735.amzn2.x86_64 containerd://1.6.6
Deploy the InstantOn application
After the cluster is up and running, we can deploy the Liberty InstantOn application.
First, create a deployment.yaml
file with the following contents. Update the image
value to match the repositoryUri
from the create-repository
command output.
apiVersion: apps/v1
kind: Deployment
metadata:
name: open-liberty-instanton
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: open-liberty-instanton
template:
metadata:
labels:
app.kubernetes.io/name: open-liberty-instanton
spec:
containers:
- image: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/getting-started-instanton
imagePullPolicy: IfNotPresent
name: app
ports:
- containerPort: 9080
name: 9080-tcp
protocol: TCP
resources:
limits:
cpu: 1
memory: 512Mi
requests:
cpu: 500m
memory: 256Mi
securityContext:
runAsNonRoot: true
privileged: false
capabilities:
add:
- CHECKPOINT_RESTORE
- SETPCAP
drop:
- ALL
Next, deploy the application by running the following command:
kubectl apply -f deployment.yaml
Check the logs to see if the application started up successfully. Keep in mind that it might take a few extra seconds for the pod to start for very first time as the cluster nodes must pull down the container image from ECR:
kubectl logs -l app.kubernetes.io/name=open-liberty-instanton --tail=-1
Look for the following output to confirm that the application started successfully with InstantOn:
[AUDIT ] CWWKZ0001I: Application io.openliberty.sample.getting.started started in 0.331 seconds.
[AUDIT ] CWWKC0452I: The Liberty server process resumed operation from a checkpoint in 0.464 seconds.
[AUDIT ] CWWKF0012I: The server installed the following features: [cdi-2.0, checkpoint-1.0, distributedMap-1.0, jaxrs-2.1, jaxrsClient-2.1, jndi-1.0, json-1.0, jsonp-1.1, monitor-1.0, mpConfig-2.0, mpHealth-3.1, mpMetrics-3.0, servlet-4.0, ssl-1.0].
[AUDIT ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 0.510 seconds.
[AUDIT ] CWWKS4104A: LTPA keys created in 0.919 seconds. LTPA key file: /opt/ol/wlp/output/defaultServer/resources/security/ltpa.keys
[AUDIT ] CWPKI0803A: SSL certificate created in 3.290 seconds. SSL key file: /opt/ol/wlp/output/defaultServer/resources/security/key.p12
Now, you can scale the application up to see how quickly the new pod instances are coming up! Results may vary but you should see up to 90% improvement in the startup time over the same application without InstantOn.
kubectl scale deployment/open-liberty-instanton --replicas=3
In a follow on blog post, we will combine InstantOn with Knative and explore the scale-to-zero scenario.
Clean up
If you no longer need the EKS cluster, make sure to delete it by running the following command:
eksctl delete cluster -f cluster.yaml
Similarly, if you no longer need the ECR repository, delete it using the following command:
aws ecr delete-repository --repository-name getting-started-instanton --force