Caution
All material provides only an introduction to containerization & K8s. It is not intended for production use and does not cover all best practices. Please dig especially into security topics before deploying anything to production.
This workshop is intended for developers who want to learn how to deploy applications to Kubernetes.
Tip
Check if your local environment is setup correctly by running the following command:
git clone [email protected]:l3montree-dev/kubernetes-developer-workshop.git
cd kubernetes-developer-workshop
./check_env.sh
If the script notifies you of any missing dependencies, please install them before proceeding.
Table of Contents
- Prerequisites
- Color-Application Architecture Overview
- Section 1 Containerize the Application
- Section 2 Kubernetes Deployment
- Part 2.1 Installing and Starting Minikube
- Part 2.2 Create the "workshop" Namespace in Minikube
- Part 2.3 PostgreSQL Installation Using Helm
- Part 2.4 Creating Kubernetes Deployment Files
- Part 2.5 Deploy the Entire Application
- Section 3: Helm Charts
flowchart TD
A[React Frontend] -->|Fetches Color| B[Spring-Boot Color-API]
B -->|Returns| A
B-->|Logs Request| C[PostgreSQL]
-
Explore the example Spring Boot application in the color-api directory. It provides an endpoint that returns a random hex color.
-
Review the Dockerfile.
-
Build the container image with the following command:
docker build -t spring-boot-demo:latest color-api
-
Inspect the image, which is essentially a tar archive:
docker save spring-boot-demo:latest -o spring-boot-demo.tar
-
Run the
inspect_layers.sh
script:- It extracts the tar archive into the extracted_image folder.
- It extracts each layer tar archive in the extracted_image/blobs folder into the layers folder.
- It merges the layers into a single file system in the merged_layers folder, resolving conflicts by replacing files as needed.
-
Examine the merged_layers folder to see the file system of the container image.
- Modify the Dockerfile as instructed in the comments to create a multi-stage build. Rebuild and inspect the image again.
- Explore the example Next.js application in the nextjs-frontend directory. It fetches the randomly generated color from the color-api and displays it.
- Build and run the container:
docker build -t nextjs-frontend:latest nextjs-frontend docker run -p 3000:3000 nextjs-frontend:latest
- Open http://localhost:3000 in your browser.
- Review the docker-compose.yaml file.
- Note that it adds PostgreSQL to the deployment and configures the
COLOR_API_URL
environment variable. - Build and start the containers using the following command. Use the image references from GitHub to avoid building the images yourself:
docker compose up
- Open http://localhost:3000 in your browser. It should now return a color from the color-api.
Follow the instructions at Minikube Start.
brew install minikube && minikube start
Enable the storage provisioner and ingress controller:
minikube addons enable storage-provisioner
minikube addons enable ingress
Set the kubectl alias to the Minikube cluster:
alias kubectl="minikube kubectl --"
Create the namespace:
kubectl create namespace workshop
Alternatively, install kubectl
by following the official documentation.
Add the Bitnami repository:
helm repo add bitnami https://charts.bitnami.com/bitnami
Install PostgreSQL:
helm install -n workshop postgresql bitnami/postgresql
# or
helm install postgresql -n workshop oci://registry-1.docker.io/bitnamicharts/postgresql
Inspect the running deployment to ensure it started successfully:
kubectl get pods -n workshop
NAME READY STATUS RESTARTS AGE
postgresql-0 1/1 Running 1 (2m5s ago) 15m
-
Deploy the COLOR-API
The Next.js frontend deployment files are already provided as an example in the kube/nextjs-frontend directory.
kubectl apply -n workshop -f kube/nextjs-frontend
Create the
color-api
deployment files and apply them to the cluster:kubectl apply -n workshop -f kube/color-api
Hints:
- You need a deployment and a service.
- Use the image
ghcr.io/l3montree-dev/kubernetes-developer-workshop/color-api:latest
. - The application runs on port 8080.
- Required environment variables:
DB_URL
: jdbc:postgresql://postgresql:5432/postgresDB_USER
: postgresDB_PASS
: ? (check the secret created by the PostgreSQL Helm chart)
-
Configure the connection between the frontend and the color-api using the
COLOR_API_URL
environment variable.
Kubernetes is idempotent, so you can apply the entire configuration:
kubectl apply -n workshop -R -f kube
Check the running pods:
kubectl get pods -n workshop
NAME READY STATUS RESTARTS AGE
color-api-5c8bc7f9d6-2t7df 1/1 Running 0 23m
color-api-5c8bc7f9d6-72qnw 1/1 Running 0 23m
frontend-68bcf87ffd-n7wtp 1/1 Running 0 39m
postgresql-0 1/1 Running 1 (49m ago) 63m
Use Minikube to view the frontend:
minikube tunnel
The frontend should be available at http://127.0.0.1.
Create a new Helm chart:
helm create color-application
Remove everything except Chart.yaml
and values.yaml
:
rm -rf color-application/templates/* color-application/charts
Clear the values.yaml
file:
echo "" > color-application/values.yaml
Copy the contents of the kube
folder into the templates
folder of the Helm chart:
cp -r kube/* color-application/templates/
Modify the color-application/nextjs-frontend/ingress.yaml
file to use the path prefix /helm
.
Install the Helm chart:
helm upgrade --install -n workshop-helm --create-namespace color-application color-application
Check the running pods in the workshop-helm
namespace:
kubectl get pods -n workshop-helm
NAME READY STATUS RESTARTS AGE
color-api-564cf76456-nchc7 0/1 CreateContainerConfigError 0 9m56s
color-api-564cf76456-w2dkr 0/1 CreateContainerConfigError 0 9m56s
frontend-68bcf87ffd-6pkz9 1/1 Running 0 9m56s
The color-api pods are not starting because the database is missing. Add the PostgreSQL dependency to Chart.yaml
:
dependencies:
- name: postgresql
version: 16.4.9
repository: https://charts.bitnami.com/bitnami
Install the Helm chart again:
helm upgrade --install -n workshop-helm --create-namespace color-application color-application
If it fails, install the dependencies first:
helm dependency update color-application
Apply the Helm chart again:
helm upgrade --install -n workshop-helm --create-namespace color-application color-application
Check the running pods:
kubectl get pods -n workshop-helm
NAME READY STATUS RESTARTS AGE
color-api-564cf76456-khh2s 0/1 CreateContainerConfigError 0 52s
color-api-564cf76456-w2dkr 0/1 CreateContainerConfigError 0 16m
color-application-postgresql-0 1/1 Running 0 108s
frontend-68bcf87ffd-6pkz9 1/1 Running 0 16m
The color-api pods are still not starting. Configure the environment variables correctly:
env:
- name: DB_PASS
valueFrom:
secretKeyRef:
name: color-application-postgresql
key: postgres-password
Check if the DB_URL
is correctly configured. Find the service name with:
kubectl get services -n workshop-helm
Apply the Helm chart again:
helm upgrade --install -n workshop-helm --create-namespace color-application color-application
Check the running pods and visit the frontend.
Set the number of replicas in values.yaml
:
# values.yaml
replicaCount: 2
Use the replicaCount
value in the color-application/color-api/deployment.yaml
:
spec:
replicas: {{ .Values.replicaCount }}
Apply the Helm chart again:
helm upgrade --install -n workshop-helm --create-namespace color-application color-application
Check the running pods:
kubectl get pods -n workshop-helm
NAME READY STATUS RESTARTS AGE
color-api-86f8b7bb7d-29mt7 1/1 Running 0 8m48s
color-api-86f8b7bb7d-2lzql 1/1 Running 0 8m46s
color-api-86f8b7bb7d-rl78x 1/1 Running 0 15s
color-application-postgresql-0 1/1 Running 0 10m
frontend-68bcf87ffd-vvv5v 1/1 Running 0 10m
Visit the frontend. You should see three different colors after reloading a few times.
Package the Helm chart:
helm package color-application
The packaged Helm chart is in the color-application-0.1.0.tgz
file. Install the packaged Helm chart:
helm install -n workshop-helm-packaged --create-namespace color-application color-application-0.1.0.tgz --set replicaCount=1
The installation fails due to a conflicting path in the ingress. Maybe this can be made configurable as well?
Build and push the Docker images:
docker buildx build --push --platform linux/arm64/v8,linux/amd64 -t ghcr.io/l3montree-dev/kubernetes-developer-workshop/nextjs-frontend:latest nextjs-frontend
docker buildx build --push --platform linux/arm64/v8,linux/amd64 -t ghcr.io/l3montree-dev/kubernetes-developer-workshop/color-api:latest color-api