Skip to content

Getting started with cdk8s for Java

In this guide, we’ll walk you through the process of building a basic Kubernetes application using cdk8s for Java.

Prerequisites

  1. To install the cdk8s CLI, you need the Node Package Manager (npm) installed on your local machine.
  2. cdk8s for Java supports Java Development Kit (JDK) versions 8+. Check your Java version:
    java --version
    

Set up an environment

Initial setup

To get setup, follow these general steps:

  1. To begin, you’ll need Maven 3.6.3+ installed. If you’re not familiar with this setup, use these instructions to setup Apache Maven.

Install the CLI

To initialize a cdk8s project and auto-generate Kubernetes manifests based on our code, we need the cdk8s CLI:

  1. Run the following command to install the CLI using npm. For more installation methods, see Install the cdk8s CLI.
    npm install -g cdk8s-cli
    

Create a project

Next, we’ll initialize a project to create the directory structure and install the necessary dependencies using the init command.

  1. In a terminal window, run the following command in an empty directory:

    cdk8s init java-app
    

  2. In your preferred code editor, open the Main.java file.

    package com.mycompany.app;
    
    import software.constructs.Construct;
    
    import org.cdk8s.App;
    import org.cdk8s.Chart;
    import org.cdk8s.ChartProps;
    
    public class Main extends Chart 
    {
    
        public Main(final Construct scope, final String id) {
            this(scope, id, null);
        }
    
        public Main(final Construct scope, final String id, final ChartProps options) {
            super(scope, id, options);
    
            // define resources here
        }
    
        public static void main(String[] args) {
            final App app = new App();
            new Main(app, "java");
            app.synth();
        }
    }
    

This sample shows the basic structure of a cdk8s application with the essential libraries: constructs and cdk8s. These libraries supply the foundational classes and methods required for working with cdk8s. It includes the following components:

  • A custom Main class inherits from the Chart base class provided by the cdk8s library, serving as a representation of the Kubernetes resources to be generated and managed.
  • The Main constructor method is responsible for initializing the base class (Chart) and specifying the Kubernetes resources. This method is invoked when creating an instance of the class.
  • An instance of the App class is created in the main function, which acts the primary entry point of the cdk8s application and oversees the application’s lifecycle and resources.
  • An instance of the Main class is created by passing the app instance and a string identifier, “java”, as arguments. This action generates and registers the Kubernetes resources defined in the Main class within the application. Note that in this example, the “java” string identifier is autogenerated based on the current directory name.
  • The synth method is called on the app instance, which produces the required Kubernetes YAML manifest files based on the defined resources. Note that in this example, we haven’t defined any resources within the Main constructor, so running the “cdk8s synth” command in the CLI would generate a blank Kubernetes manifest.

Define Kubernetes resources

Now, we are ready to define Kubernetes resources for our application. In this sample, we define a basic Kubernetes Deployment for a sample application. We start by importing the imports.k8s sub-directory, which contains all the cdk8s Kubernetes classes and functions we’ll need.

Copy the code sample

  1. Copy and paste the following code sample into the existing Main.java file of your project.
    package com.mycompany.app;
    
    import software.constructs.Construct;
    import org.cdk8s.App;
    import org.cdk8s.Chart;
    import org.cdk8s.ChartProps;
    import imports.k8s.Container;
    import imports.k8s.ContainerPort;
    import imports.k8s.DeploymentSpec;
    import imports.k8s.KubeDeployment;
    import imports.k8s.KubeDeploymentProps;
    import imports.k8s.LabelSelector;
    import imports.k8s.ObjectMeta;
    import imports.k8s.PodSpec;
    import imports.k8s.PodTemplateSpec;
    
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    
    public class Main extends Chart {
    
        public Main(final Construct scope, final String id, final String appLabel) {
            this(scope, id, null, appLabel);
        }
    
        public Main(final Construct scope, final String id, final ChartProps props, final String appLabel) {
            super(scope, id, props);
    
            Map<String, String> label = Collections.singletonMap("app", appLabel);
    
            new KubeDeployment(this, "my-deployment", KubeDeploymentProps.builder()
                    .spec(DeploymentSpec.builder()
                            .replicas(3)
                            .selector(LabelSelector.builder()
                                    .matchLabels(label)
                                    .build())
                            .template(PodTemplateSpec.builder()
                                    .metadata(ObjectMeta.builder().labels(label)
                                            .build())
                                    .spec(PodSpec.builder()
                                            .containers(List.of(Container.builder()
                                                    .name("app-container-test")
                                                    .image("nginx:1.19.10")
                                                    .ports(List.of(ContainerPort.builder()
                                                            .containerPort(80)
                                                            .build()))
                                                    .build()))
                                            .build())
                                    .build())
                            .build())
                    .build());
        }
    
        public static void main(String[] args) {
            final App app = new App();
            new Main(app, "getting-started", "my-app");
            app.synth();
        }
    }
    

A few things worth noting about this sample:

  • The constructor in the custom Main class leverages Java’s object-oriented programming features to construct a Kubernetes Deployment. The Deployment is defined with specific parameters, including the number of replicas, label selectors, and pod specifications. This constructor employs Java’s strong typing and encapsulation to dynamically set the “app” key in label selectors and metadata labels for our Kubernetes resources, creating a clear and concise way to set key configuration details.

Generate Kubernetes manifests

After you have defined the Kubernetes resources for your application, you are ready to generate the Kubernetes manifest that will define your Deployment resource.

Run the synth command

  1. Open a terminal and navigate to your project directory.
  2. Run the synth command. This command generates a Kubernetes manifest file in the dist folder of your project directory. The manifest file contains all the resources you defined inside the MyChart class.
    cdk8s synth
    

View the manifest

  1. Open the dist/getting-started.k8s.yaml file. You should see a Kubernetes manifest similar to the following:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: getting-started-my-deployment-c85252a6
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          containers:
            - image: nginx:1.19.10
              name: app-container
              ports:
                - containerPort: 80
    

Conclusion

Throughout this guide, we introduced you to the cdk8s Java library and guided you through the process of creating a cdk8s Java application. We initiated a simple project and constructed a Kubernetes Deployment using cdk8s code. This included leveraging Java-specific programming language conventions to dynamically set the “app” key in “label” selectors and “metadata” labels for Kubernetes resources using Java’s versatile strong typing and encapsulation features.

Next up

  • To run a complete code sample, we recommend diving into the Kubernetes Deployment and Service using the cdk8s-core sample application.