There is an iron gallery app that the Nautilus DevOps team was developing. They have recently customized the app and are going to deploy the same on the Kubernetes cluster. Below you can find more details:
- Create a namespace
iron-namespace-devops Create a deployment
iron-gallery-deployment-devopsforiron galleryunder the same namespace you created.
:- Labelsrunshould beiron-gallery.
:- Replicas count should be1.
:- Selector's matchLabelsrunshould beiron-gallery.
:- Template labelsrunshould beiron-galleryunder metadata.
:- The container should be named asiron-gallery-container-devops, usekodekloud/irongallery:2.0image ( use exact image name / tag ).
:- Resources limits for memory should be100Miand for CPU should be50m.
:- First volumeMount name should beconfig, its mountPath should be/usr/share/nginx/html/data.
:- Second volumeMount name should beimages, its mountPath should be/usr/share/nginx/html/uploads.
:- First volume name should beconfigand give itemptyDirand second volume name should beimages, also give itemptyDir.Create a deployment
iron-db-deployment-devopsforiron dbunder the same namespace.
:- Labelsdbshould bemariadb.
:- Replicas count should be1.
:- Selector's matchLabelsdbshould bemariadb.
:- Template labelsdbshould bemariadbunder metadata.
:- The container name should beiron-db-container-devops, usekodekloud/irondb:2.0image ( use exact image name / tag ).
:- Define environment, setMYSQL_DATABASEits value should bedatabase_host, setMYSQL_ROOT_PASSWORDandMYSQL_PASSWORDvalue should be with some complex passwords for DB connections, andMYSQL_USERvalue should be any custom user ( except root ).
:- Volume mount name should bedband its mountPath should be/var/lib/mysql. Volume name should bedband give it anemptyDir.Create a service for
iron dbwhich should be namediron-db-service-devopsunder the same namespace. Configure spec as selector's db should bemariadb. Protocol should beTCP, port and targetPort should be3306and its type should beClusterIP.Create a service for
iron gallerywhich should be namediron-gallery-service-devopsunder the same namespace. Configure spec as selector's run should beiron-gallery. Protocol should beTCP, port and targetPort should be80, nodePort should be32678and its type should beNodePort.
Note:
- We don't need to make connection b/w database and front-end now, if the installation page is coming up it should be enough for now.
- The
kubectlutility on thejump-hosthas been configured to work with the Kubernetes cluster.
Understanding the Application Architecture
Application Components
The Iron Gallery application consists of two main components:
| Component | Description | Image |
|---|---|---|
| Gallery Frontend | Web server displaying the gallery | kodekloud/irongallery:2.0 |
| Database Backend | MariaDB database for storing data | kodekloud/irondb:2.0 |
Architecture Diagram
┌─────────────────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ Namespace: iron-namespace-devops │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Gallery Pod │ │ │
│ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ Container: iron-gallery-container-devops │ │ │ │
│ │ │ │ Image: kodekloud/irongallery:2.0 │ │ │ │
│ │ │ │ Port: 80 │ │ │ │
│ │ │ │ Resources: 100Mi memory, 50m CPU │ │ │ │
│ │ │ │ Volumes: │ │ │ │
│ │ │ │ - config → /usr/share/nginx/html/data │ │ │ │
│ │ │ │ - images → /usr/share/nginx/html/uploads │ │ │ │
│ │ │ └────────────────────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Gallery Service │ │ │
│ │ │ - Type: NodePort │ │ │
│ │ │ - NodePort: 32678 │ │ │
│ │ │ - Target: Port 80 │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ http://<node-ip>:32678 │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Database Pod │ │ │
│ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ Container: iron-db-container-devops │ │ │ │
│ │ │ │ Image: kodekloud/irondb:2.0 │ │ │ │
│ │ │ │ Port: 3306 │ │ │ │
│ │ │ │ Environment: │ │ │ │
│ │ │ │ - MYSQL_DATABASE: database_host │ │ │ │
│ │ │ │ - MYSQL_ROOT_PASSWORD: RootPass123! │ │ │ │
│ │ │ │ - MYSQL_PASSWORD: UserPass456! │ │ │ │
│ │ │ │ - MYSQL_USER: dbuser │ │ │ │
│ │ │ │ Volume: db → /var/lib/mysql │ │ │ │
│ │ │ └────────────────────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Database Service │ │ │
│ │ │ - Type: ClusterIP │ │ │
│ │ │ - Port: 3306 │ │ │
│ │ │ - Target: Port 3306 │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Step-by-Step Implementation
Step 1: Create the Namespace
Namespaces provide isolation for resources within a Kubernetes cluster.
kubectl create namespace iron-namespace-devops
Output:
namespace/iron-namespace-devops created
Step 2: Create the Gallery Deployment
Create the YAML file for the Gallery deployment:
cat > iron-gallery-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: iron-gallery-deployment-devops
namespace: iron-namespace-devops
labels:
run: iron-gallery
spec:
replicas: 1
selector:
matchLabels:
run: iron-gallery
template:
metadata:
labels:
run: iron-gallery
spec:
containers:
- name: iron-gallery-container-devops
image: kodekloud/irongallery:2.0
resources:
limits:
memory: 100Mi
cpu: 50m
volumeMounts:
- name: config
mountPath: /usr/share/nginx/html/data
- name: images
mountPath: /usr/share/nginx/html/uploads
volumes:
- name: config
emptyDir: {}
- name: images
emptyDir: {}
EOF
Key Configuration Points:
| Element | Value | Purpose |
|---|---|---|
namespace |
iron-namespace-devops |
Isolates resources |
labels.run |
iron-gallery |
Identifies the deployment |
replicas |
1 |
Single instance for testing |
image |
kodekloud/irongallery:2.0 |
Gallery application image |
memory |
100Mi |
Memory limit |
cpu |
50m |
CPU limit |
Step 3: Create the Database Deployment
Create the YAML file for the Database deployment:
cat > iron-db-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: iron-db-deployment-devops
namespace: iron-namespace-devops
labels:
db: mariadb
spec:
replicas: 1
selector:
matchLabels:
db: mariadb
template:
metadata:
labels:
db: mariadb
spec:
containers:
- name: iron-db-container-devops
image: kodekloud/irondb:2.0
env:
- name: MYSQL_DATABASE
value: database_host
- name: MYSQL_ROOT_PASSWORD
value: "RootPass123!"
- name: MYSQL_PASSWORD
value: "UserPass456!"
- name: MYSQL_USER
value: "dbuser"
volumeMounts:
- name: db
mountPath: /var/lib/mysql
volumes:
- name: db
emptyDir: {}
EOF
Key Configuration Points:
| Element | Value | Purpose |
|---|---|---|
labels.db |
mariadb |
Identifies the database deployment |
image |
kodekloud/irondb:2.0 |
Database application image |
MYSQL_DATABASE |
database_host |
Database name |
MYSQL_ROOT_PASSWORD |
RootPass123! |
Root password |
MYSQL_PASSWORD |
UserPass456! |
User password |
MYSQL_USER |
dbuser |
Database user |
Step 4: Create the Database Service
Create the YAML file for the Database service:
cat > iron-db-service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
name: iron-db-service-devops
namespace: iron-namespace-devops
spec:
type: ClusterIP
selector:
db: mariadb
ports:
- protocol: TCP
port: 3306
targetPort: 3306
EOF
Key Configuration Points:
| Element | Value | Purpose |
|---|---|---|
type |
ClusterIP |
Internal service only |
selector.db |
mariadb |
Routes to database pods |
port |
3306 |
Service port |
targetPort |
3306 |
Container port |
Step 5: Create the Gallery Service
Create the YAML file for the Gallery service:
cat > iron-gallery-service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
name: iron-gallery-service-devops
namespace: iron-namespace-devops
spec:
type: NodePort
selector:
run: iron-gallery
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 32678
EOF
Key Configuration Points:
| Element | Value | Purpose |
|---|---|---|
type |
NodePort |
External access |
selector.run |
iron-gallery |
Routes to gallery pods |
port |
80 |
Service port |
targetPort |
80 |
Container port |
nodePort |
32678 |
Node port for external access |
Step 6: Apply All Configurations
kubectl apply -f iron-gallery-deployment.yaml
kubectl apply -f iron-db-deployment.yaml
kubectl apply -f iron-db-service.yaml
kubectl apply -f iron-gallery-service.yaml
Output:
deployment.apps/iron-gallery-deployment-devops created
deployment.apps/iron-db-deployment-devops created
service/iron-db-service-devops created
service/iron-gallery-service-devops created
Step 7: Verify All Resources
kubectl get namespaces
Output:
NAME STATUS AGE
default Active 27m
iron-namespace-devops Active 3m44s
kube-node-lease Active 27m
kube-public Active 27m
kube-system Active 27m
kubectl get all -n iron-namespace-devops
Output:
NAME READY STATUS RESTARTS AGE
pod/iron-db-deployment-devops-5dc5645559-nbv8x 1/1 Running 0 3m36s
pod/iron-gallery-deployment-devops-7b59878ffd-bt4mk 1/1 Running 0 3m36s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/iron-db-service-devops ClusterIP 10.43.83.150 <none> 3306/TCP 3m36s
service/iron-gallery-service-devops NodePort 10.43.14.63 <none> 80:32678/TCP 3m36s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/iron-db-deployment-devops 1/1 1 1 3m36s
deployment.apps/iron-gallery-deployment-devops 1/1 1 1 3m37s
Accessing the Application
Via NodePort
The application can be accessed using the NodePort service:
http://<node-ip>:32678
Via Port Forwarding
For local testing, you can use port forwarding:
kubectl port-forward -n iron-namespace-devops service/iron-gallery-service-devops 8080:80
Then access: http://localhost:8080
Understanding the Configuration
Resource Management
Resource limits ensure the application does not consume excessive cluster resources:
resources:
limits:
memory: 100Mi
cpu: 50m
Volume Mounts
EmptyDir volumes provide temporary storage for the application:
volumeMounts:
- name: config
mountPath: /usr/share/nginx/html/data
- name: images
mountPath: /usr/share/nginx/html/uploads
Environment Variables
Environment variables configure the database connection:
env:
- name: MYSQL_DATABASE
value: database_host
- name: MYSQL_ROOT_PASSWORD
value: "RootPass123!"
- name: MYSQL_PASSWORD
value: "UserPass456!"
- name: MYSQL_USER
value: "dbuser"
Troubleshooting
Pod Not Starting
# Check pod status
kubectl get pods -n iron-namespace-devops
# Check pod details
kubectl describe pod <pod-name> -n iron-namespace-devops
# Check pod logs
kubectl logs <pod-name> -n iron-namespace-devops
Service Not Accessible
# Check service status
kubectl get services -n iron-namespace-devops
# Check endpoints
kubectl get endpoints -n iron-namespace-devops
# Check service details
kubectl describe service <service-name> -n iron-namespace-devops
Namespace Issues
# Verify namespace exists
kubectl get namespaces
# Check resources in namespace
kubectl get all -n iron-namespace-devops
Key Concepts
Namespaces
Namespaces provide:
- Resource isolation
- Naming scope
- Access control boundaries
- Organizational separation
Deployments
Deployments provide:
- Declarative updates
- Rolling updates
- Rollback capabilities
- Self-healing
Services
Services provide:
- Stable network endpoints
- Load balancing
- Service discovery
- External access
Environment Variables
Environment variables provide:
- Configuration management
- Separation of config from code
- Secure credential handling
- Runtime flexibility
Summary
In this challenge, we successfully:
- Created a dedicated namespace for the application
- Deployed the Gallery front-end with resource limits and volume mounts
- Deployed the Database backend with environment variables
- Exposed the database internally using a ClusterIP service
- Exposed the front-end externally using a NodePort service
This deployment pattern demonstrates a complete multi-tier application setup in Kubernetes, following best practices for resource management, service exposure, and configuration management.
Useful Commands Reference
| Command | Purpose |
|---|---|
kubectl create namespace <name> |
Create a namespace |
kubectl get namespaces |
List namespaces |
kubectl get all -n <namespace> |
List all resources in a namespace |
kubectl get deployments -n <namespace> |
List deployments in a namespace |
kubectl get pods -n <namespace> |
List pods in a namespace |
kubectl get services -n <namespace> |
List services in a namespace |
kubectl describe deployment <name> -n <namespace> |
Detailed deployment info |
kubectl describe pod <name> -n <namespace> |
Detailed pod info |
kubectl describe service <name> -n <namespace> |
Detailed service info |
kubectl logs <pod-name> -n <namespace> |
View pod logs |
kubectl apply -f <file> |
Apply configuration from file |
kubectl delete namespace <name> |
Delete a namespace |
Top comments (0)