Deploying a Stateful Web Application on Kubernetes: A Hands-On Guide
Introduction
Kubernetes is a powerful container orchestration platform that allows developers to deploy, manage, and scale applications seamlessly. In this blog, we will walk through deploying a stateful web application on Kubernetes, covering essential concepts such as namespaces, ConfigMaps, Secrets, and StatefulSets. By the end of this guide, you'll have a practical understanding of how to use these features to manage and deploy your applications.
Table of Contents
Namespaces
Namespaces in Kubernetes provide a way to partition cluster resources between multiple users. They are particularly useful for organizing environments like development, staging, and production within a single cluster. By using namespaces, you can apply policies and allocate resources in an isolated manner.
Example: Creating a Namespace
apiVersion: v1
kind: Namespace
metadata:
name: webapp-namespace
To create the namespace, apply the configuration:
kubectl apply -f namespace.yaml
ConfigMaps and Secrets
ConfigMaps and Secrets are Kubernetes objects that allow you to decouple configuration and sensitive data from your application code.
- ConfigMaps store non-confidential data in key-value pairs, such as configuration settings or environment variables.
Example: Creating a ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: webapp-namespace
data:
MYSQL_DATABASE: webappdb
MYSQL_USER: webappuser
Apply the ConfigMap:
kubectl apply -f mysql-configmap.yaml
- Secrets store sensitive data like passwords, tokens, and SSH keys. Secrets ensure that sensitive information is stored securely, typically in base64 encoding.
Example: Creating a Secret
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: webapp-namespace
type: Opaque
data:
MYSQL_ROOT_PASSWORD: dG9wU2VjcmV0Cg==
MYSQL_PASSWORD: c2VjcmV0Cg==
Apply the Secret:
kubectl apply -f mysql-secret.yaml
StatefulSets
StatefulSets manage the deployment and scaling of a set of pods, providing guarantees about the ordering and uniqueness of these pods. They are particularly useful for stateful applications that require stable, persistent storage and consistent network identities, such as databases.
Key features of StatefulSets:
Stable, unique network identifiers
Stable, persistent storage
Ordered, graceful deployment and scaling
Example: Creating a StatefulSet for MySQL
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: webapp-namespace
spec:
selector:
matchLabels:
app: mysql
serviceName: "mysql"
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_DATABASE
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_PASSWORD
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
Apply the StatefulSet:
kubectl apply -f mysql-statefulset.yaml
Practice Project: Deploying a Stateful Web Application
Let's put everything together and deploy a simple web application with a MySQL backend.
- Set Up Kubernetes Namespace
apiVersion: v1
kind: Namespace
metadata:
name: webapp-namespace
Apply the namespace:
kubectl apply -f namespace.yaml
- Create ConfigMaps and Secrets
ConfigMap for MySQL Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: webapp-namespace
data:
MYSQL_DATABASE: webappdb
MYSQL_USER: webappuser
Apply the ConfigMap:
kubectl apply -f mysql-configmap.yaml
Secret for MySQL Password
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: webapp-namespace
type: Opaque
data:
MYSQL_ROOT_PASSWORD: dG9wU2VjcmV0Cg== # base64 encoded "topSecret"
MYSQL_PASSWORD: c2VjcmV0Cg== # base64 encoded "secret"
Apply the Secret:
kubectl apply -f mysql-secret.yaml
- Deploy a MySQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: webapp-namespace
spec:
selector:
matchLabels:
app: mysql
serviceName: "mysql"
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_DATABASE
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_PASSWORD
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
Apply the StatefulSet:
kubectl apply -f mysql-statefulset.yaml
- Deploy a Web Application using Deployment
We will use the nginx
image to simulate our web application.
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: webapp-namespace
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:latest # Using the official Nginx image
ports:
- containerPort: 80
Apply the deployment:
kubectl apply -f webapp-deployment.yaml
Verify the Setup
- Check Namespaces
kubectl get namespaces
- Check ConfigMaps and Secrets
kubectl get configmaps -n webapp-namespace
kubectl get secrets -n webapp-namespace
- Check StatefulSet and Pods
kubectl get statefulsets -n webapp-namespace
kubectl get pods -n webapp-namespace
- Check Deployment and Pods
kubectl get deployments -n webapp-namespace
kubectl get pods -n webapp-namespace
- Check Services
kubectl get services -n webapp-namespace
By following this guide, you have deployed a stateful web application using Kubernetes, leveraging namespaces for resource isolation, ConfigMaps and Secrets for configuration management, and StatefulSets for stable storage and network identities.
Conclusion
In this blog, we explored how to deploy a stateful web application on Kubernetes. We covered essential concepts such as namespaces, ConfigMaps, Secrets, and StatefulSets, and applied them in a practical project. By mastering these concepts, you can efficiently manage and deploy complex applications on Kubernetes.
Subscribe to my newsletter
Read articles from Mohammed Yunus Shaikh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Mohammed Yunus Shaikh
Mohammed Yunus Shaikh
I love to explore new technologies, excited to learn and grow everyday.