DEV Community

Janak Shrestha
Janak Shrestha

Posted on

Day 67: Deploy Guest Book App on Kubernetes

The Nautilus Application development team has finished development of one of the applications and it is ready for deployment. It is a guestbook application that will be used to manage entries for guests/visitors. As per discussion with the DevOps team, they have finalized the infrastructure that will be deployed on Kubernetes cluster. Below you can find more details about it.

BACK-END TIER

  1. Create a deployment named redis-master for Redis master.
    a.) Replicas count should be 1.
    b.) Container name should be master-redis-nautilus and it should use image redis.
    c.) Request resources as CPU should be 100m and Memory should be 100Mi.
    d.) Container port should be redis default port i.e 6379.

  2. Create a service named redis-master for Redis master. Port and targetPort should be Redis default port i.e 6379.

  3. Create another deployment named redis-slave for Redis slave.
    a.) Replicas count should be 2.
    b.) Container name should be slave-redis-nautilus and it should use gcr.io/google_samples/gb-redisslave:v3 image.
    c.) Requests resources as CPU should be 100m and Memory should be 100Mi.
    d.) Define an environment variable named GET_HOSTS_FROM and its value should be dns.
    e.) Container port should be Redis default port i.e 6379.

  4. Create another service named redis-slave. It should use Redis default port i.e 6379.

  5. Create another service named redis-follower. Port and targetPort should be Redis default port i.e 6379. Its selector app should be redis-slave.

FRONT END TIER

  1. Create a deployment named frontend.
    a.) Replicas count should be 3.
    b.) Container name should be php-redis-nautilus and it should use gcr.io/google-samples/gb-frontend@sha256:a908df8486ff66f2c4daa0d3d8a2fa09846a1fc8efd65649c0109695c7c5cbff image.
    c.) Request resources as CPU should be 100m and Memory should be 100Mi.
    d.) Define an environment variable named as GET_HOSTS_FROM and its value should be dns.
    e.) Container port should be 80.

  2. Create a service named frontend. Its type should be NodePort, port should be 80 and its nodePort should be 30009.

Finally, you can check the guestbook app by clicking on App button.

You can use any labels as per your choice.

Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.


Day 67: Deploy Guest Book App on Kubernetes – A Complete Guide

Introduction

Welcome to Day 67 of my 100 Days of DevOps journey. Today, we are deploying a complete multi-tier Guest Book application on Kubernetes. This application demonstrates a typical three-tier architecture with a frontend web layer, a Redis master for write operations, and Redis slaves for read operations.

The Guest Book application allows users to leave messages that are stored in Redis. This architecture is common in real-world applications where scalability and high availability are important considerations.


Understanding the Application Architecture

Components Overview

Tier Component Replicas Purpose
Backend Redis Master 1 Handles write operations
Backend Redis Slave 2 Handles read operations
Frontend PHP Frontend 3 Web interface for users

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Kubernetes Cluster                                 │
│                                                                              │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Frontend Tier                                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐ │ │
│  │  │  Deployment: frontend (3 replicas)                              │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  Container: php-redis-nautilus                            │ │ │ │
│  │  │  │  Image: gcr.io/google-samples/gb-frontend                  │ │ │ │
│  │  │  │  Port: 80                                                  │ │ │ │
│  │  │  │  Env: GET_HOSTS_FROM=dns                                  │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────┘ │ │ │
│  │  └──────────────────────────────────────────────────────────────────┘ │ │
│  │                                    │                                   │ │
│  │                                    ▼                                   │ │
│  │  Service: frontend (NodePort 30009)                                   │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                    │                                         │
│                                    ▼                                         │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Backend Tier                                                         │ │
│  │                                                                       │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐ │ │
│  │  │  Redis Master                                                    │ │ │
│  │  │  Deployment: redis-master (1 replica)                            │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  Container: master-redis-nautilus                         │ │ │ │
│  │  │  │  Image: redis                                              │ │ │ │
│  │  │  │  Port: 6379                                               │ │ │ │
│  │  │  │  Resources: 100m CPU, 100Mi Memory                       │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────┘ │ │ │
│  │  │  Service: redis-master (6379)                                  │ │ │
│  │  └──────────────────────────────────────────────────────────────────┘ │ │
│  │                                    │                                   │ │
│  │                                    ▼                                   │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐ │ │
│  │  │  Redis Slave                                                    │ │ │
│  │  │  Deployment: redis-slave (2 replicas)                           │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  Container: slave-redis-nautilus                          │ │ │ │
│  │  │  │  Image: gcr.io/google_samples/gb-redisslave:v3           │ │ │ │
│  │  │  │  Port: 6379                                               │ │ │ │
│  │  │  │  Env: GET_HOSTS_FROM=dns                                  │ │ │ │
│  │  │  │  Resources: 100m CPU, 100Mi Memory                       │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────┘ │ │ │
│  │  │  Services: redis-slave (6379), redis-follower (6379)           │ │ │
│  │  └──────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Implementation

Step 1: Create Redis Master Deployment

The Redis Master handles all write operations for the Guest Book application.

cat > redis-master-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-master
  labels:
    app: redis-master
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-master
  template:
    metadata:
      labels:
        app: redis-master
        role: master
    spec:
      containers:
      - name: master-redis-nautilus
        image: redis
        ports:
        - containerPort: 6379
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
EOF
Enter fullscreen mode Exit fullscreen mode

Key Configuration Points:

Element Value Purpose
replicas 1 Single master instance
image redis Official Redis image
containerPort 6379 Redis default port
cpu 100m 0.1 CPU request
memory 100Mi 100 MB memory request

Step 2: Create Redis Master Service

The Redis Master service exposes the master for internal cluster communication.

cat > redis-master-service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels:
    app: redis-master
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis-master
    role: master
EOF
Enter fullscreen mode Exit fullscreen mode

Step 3: Create Redis Slave Deployment

Redis slaves handle read operations, distributing the load from the frontend.

cat > redis-slave-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-slave
  labels:
    app: redis-slave
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis-slave
  template:
    metadata:
      labels:
        app: redis-slave
        role: slave
    spec:
      containers:
      - name: slave-redis-nautilus
        image: gcr.io/google_samples/gb-redisslave:v3
        ports:
        - containerPort: 6379
        env:
        - name: GET_HOSTS_FROM
          value: dns
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
EOF
Enter fullscreen mode Exit fullscreen mode

Key Configuration Points:

Element Value Purpose
replicas 2 Two slave instances for high availability
image gcr.io/google_samples/gb-redisslave:v3 Redis slave image
GET_HOSTS_FROM dns Service discovery using DNS
cpu 100m 0.1 CPU request
memory 100Mi 100 MB memory request

Step 4: Create Redis Slave Service

cat > redis-slave-service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  labels:
    app: redis-slave
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis-slave
    role: slave
EOF
Enter fullscreen mode Exit fullscreen mode

Step 5: Create Redis Follower Service

The follower service provides an alternative endpoint name for Redis slaves.

cat > redis-follower-service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: redis-follower
  labels:
    app: redis-follower
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis-slave
EOF
Enter fullscreen mode Exit fullscreen mode

Step 6: Create Frontend Deployment

The frontend provides the web interface for users to view and add guest book entries.

cat > frontend-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: php-redis-nautilus
        image: gcr.io/google-samples/gb-frontend@sha256:a908df8486ff66f2c4daa0d3d8a2fa09846a1fc8efd65649c0109695c7c5cbff
        ports:
        - containerPort: 80
        env:
        - name: GET_HOSTS_FROM
          value: dns
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
EOF
Enter fullscreen mode Exit fullscreen mode

Key Configuration Points:

Element Value Purpose
replicas 3 Three frontend instances for scalability
image gcr.io/google-samples/gb-frontend@sha256:... Frontend image with specific SHA
containerPort 80 HTTP port
GET_HOSTS_FROM dns Service discovery using DNS
cpu 100m 0.1 CPU request
memory 100Mi 100 MB memory request

Step 7: Create Frontend Service

The frontend service exposes the application to external users.

cat > frontend-service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30009
  selector:
    app: frontend
EOF
Enter fullscreen mode Exit fullscreen mode

Step 8: Apply All Configurations

# Apply Backend
kubectl apply -f redis-master-deployment.yaml
kubectl apply -f redis-master-service.yaml
kubectl apply -f redis-slave-deployment.yaml
kubectl apply -f redis-slave-service.yaml
kubectl apply -f redis-follower-service.yaml

# Apply Frontend
kubectl apply -f frontend-deployment.yaml
kubectl apply -f frontend-service.yaml
Enter fullscreen mode Exit fullscreen mode

Output:

deployment.apps/redis-master created
service/redis-master created
deployment.apps/redis-slave created
service/redis-slave created
service/redis-follower created
deployment.apps/frontend created
service/frontend created
Enter fullscreen mode Exit fullscreen mode

Step 9: Verify All Resources

kubectl get deployments
Enter fullscreen mode Exit fullscreen mode

Output:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
frontend       3/3     3            3           30s
redis-master   1/1     1            1           30s
redis-slave    2/2     2            2           30s
Enter fullscreen mode Exit fullscreen mode
kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Output:

NAME                            READY   STATUS    RESTARTS   AGE
frontend-94bfbd46c-4895s        1/1     Running   0          30s
frontend-94bfbd46c-dpjmt        1/1     Running   0          30s
frontend-94bfbd46c-k8xqz        1/1     Running   0          30s
redis-master-6f677945d4-89rb4   1/1     Running   0          30s
redis-slave-65bfddc98d-jvc2g    1/1     Running   0          30s
redis-slave-65bfddc98d-l9x99    1/1     Running   0          30s
Enter fullscreen mode Exit fullscreen mode
kubectl get services
Enter fullscreen mode Exit fullscreen mode

Output:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
frontend         NodePort    10.43.123.118   <none>        80:30009/TCP     30s
kubernetes       ClusterIP   10.43.0.1       <none>        443/TCP          54m
redis-follower   ClusterIP   10.43.191.102   <none>        6379/TCP         30s
redis-master     ClusterIP   10.43.101.228   <none>        6379/TCP         30s
redis-slave      ClusterIP   10.43.65.228    <none>        6379/TCP         30s
Enter fullscreen mode Exit fullscreen mode

Understanding the Application Flow

1. User Interaction

  1. A user accesses the Guest Book application via the frontend service
  2. The frontend connects to Redis services for data operations

2. Data Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                    Data Flow Architecture                                  │
│                                                                              │
│  User → Frontend → Redis Slave (Read)                                      │
│                                                                              │
│  User → Frontend → Redis Master (Write)                                    │
│                                                                              │
│  Redis Master → Redis Slave (Replication)                                  │
└─────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

3. Service Discovery

The GET_HOSTS_FROM=dns environment variable instructs the application to use Kubernetes DNS for service discovery. This allows the frontend to find Redis services by their DNS names:

  • redis-master.default.svc.cluster.local
  • redis-slave.default.svc.cluster.local

Troubleshooting

Pod Not Starting

# Check pod status
kubectl get pods

# Check pod details
kubectl describe pod <pod-name>

# Check pod logs
kubectl logs <pod-name>
Enter fullscreen mode Exit fullscreen mode

Service Not Accessible

# Check service status
kubectl get services

# Check endpoints
kubectl get endpoints

# Check service details
kubectl describe service frontend
Enter fullscreen mode Exit fullscreen mode

Image Pull Issues

# Check if image exists
kubectl describe pod <pod-name> | grep -A 5 "Failed"

# Verify image name
kubectl get deployment frontend -o yaml | grep image
Enter fullscreen mode Exit fullscreen mode

Useful Commands Reference

Command Purpose
kubectl get deployments List deployments
kubectl get pods List pods
kubectl get services List services
kubectl describe pod <pod-name> Detailed pod information
kubectl logs <pod-name> View pod logs
kubectl get endpoints List service endpoints
kubectl delete deployment <name> Delete deployment
kubectl apply -f <file> Apply configuration
kubectl port-forward service/frontend 8080:80 Port forward for local testing

Summary

In this challenge, we successfully:

  1. Deployed a Redis master for write operations
  2. Deployed Redis slaves for read operations
  3. Configured services for internal communication
  4. Deployed the PHP frontend application
  5. Exposed the application using a NodePort service

This multi-tier application deployment demonstrates key Kubernetes concepts including:

  • Managing stateful and stateless components
  • Service discovery using DNS
  • Resource management with requests
  • Horizontal scaling of application tiers
  • Multi-container service communication

The Guest Book application architecture is a common pattern used in production environments for applications that require separate read and write capabilities, scalability, and high availability.

Top comments (0)