DEV Community

Janak Shrestha
Janak Shrestha

Posted on

Day 65: Deploy Redis Deployment on Kubernetes

The Nautilus application development team observed some performance issues with one of the application that is deployed in Kubernetes cluster. After looking into number of factors, the team has suggested to use some in-memory caching utility for DB service. After number of discussions, they have decided to use Redis. Initially they would like to deploy Redis on kubernetes cluster for testing and later they will move it to production. Please find below more details about the task:

Create a redis deployment with following parameters:

  1. Create a config map called my-redis-config having maxmemory 2mb in redis-config.

  2. Name of the deployment should be redis-deployment, it should use

    redis:alpine image and container name should be redis-container. Also make sure it has only 1 replica.

  3. The container should request for 1 CPU.

  4. Mount 2 volumes:
    a. An Empty directory volume called data at path /redis-master-data.
    b. A configmap volume called redis-config at path /redis-master.
    c. The container should expose the port 6379.

  5. Finally, redis-deployment should be up and running.


Understanding Redis

What is Redis?

Redis (REmote DIctionary Server) is an open-source, in-memory data structure store. It supports various data structures including strings, hashes, lists, sets, and sorted sets. Redis is commonly used for:

  • Caching: Reducing database load by storing frequently accessed data
  • Session Management: Storing user session data
  • Real-time Analytics: Counting, ranking, and aggregation
  • Message Queuing: Pub/Sub messaging patterns
  • Rate Limiting: API request throttling

Why Use Redis on Kubernetes?

Deploying Redis on Kubernetes provides:

  • Scalability: Easy to scale horizontally with replicas
  • Resilience: Self-healing through Kubernetes pod management
  • Configuration Management: Using ConfigMaps for Redis configuration
  • Storage Management: Persistent volumes for data persistence
  • Service Discovery: Built-in service discovery through Kubernetes services

What We Will Build

Task Overview

Component Specification
ConfigMap my-redis-config with maxmemory 2mb
Deployment Name redis-deployment
Image redis:alpine
Container Name redis-container
Replicas 1
CPU Request 1
Volume 1 EmptyDir data at /redis-master-data
Volume 2 ConfigMap redis-config at /redis-master
Port 6379

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Kubernetes Cluster                                 │
│                                                                              │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  ConfigMap: my-redis-config                                           │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐ │ │
│  │  │  redis-config: |                                                │ │ │
│  │  │    maxmemory 2mb                                                │ │ │
│  │  └──────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                    │                                         │
│                                    ▼                                         │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Deployment: redis-deployment                                        │ │
│  │  ┌──────────────────────────────────────────────────────────────────┐ │ │
│  │  │  Pod: redis-deployment-xxxxxxxxxx-xxxxx                        │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  Container: redis-container                               │ │ │ │
│  │  │  │  Image: redis:alpine                                      │ │ │ │
│  │  │  │  Port: 6379                                               │ │ │ │
│  │  │  │  CPU Request: 1                                           │ │ │ │
│  │  │  │  VolumeMounts:                                            │ │ │ │
│  │  │  │  - data → /redis-master-data                             │ │ │ │
│  │  │  │  - redis-config → /redis-master                          │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────┘ │ │ │
│  │  │                                    │                             │ │
│  │  │                                    ▼                             │ │
│  │  │  Volumes:                                                       │ │
│  │  │  - data: emptyDir                                               │ │
│  │  │  - redis-config: ConfigMap (my-redis-config)                   │ │
│  │  └──────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                    │                                         │
│                                    ▼                                         │
│                    Redis Service (Optional)                                │
│                    Port: 6379                                              │
└─────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Implementation

Step 1: Create the ConfigMap

ConfigMaps store configuration data that can be consumed by pods. For Redis, we can store the maxmemory configuration.

cat > redis-configmap.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-redis-config
data:
  redis-config: |
    maxmemory 2mb
EOF
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • apiVersion: v1 – ConfigMap API version
  • kind: ConfigMap – Resource type
  • metadata.name: my-redis-config – ConfigMap name
  • data.redis-config – Configuration content for Redis

Step 2: Create the Deployment

The deployment defines the Redis pod specification, including volumes, volume mounts, and container configuration.

cat > redis-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis-container
        image: redis:alpine
        ports:
        - containerPort: 6379
        resources:
          requests:
            cpu: 1
        volumeMounts:
        - name: data
          mountPath: /redis-master-data
        - name: redis-config
          mountPath: /redis-master
      volumes:
      - name: data
        emptyDir: {}
      - name: redis-config
        configMap:
          name: my-redis-config
EOF
Enter fullscreen mode Exit fullscreen mode

YAML Breakdown

Deployment Metadata:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
Enter fullscreen mode Exit fullscreen mode

Pod Template:

template:
  metadata:
    labels:
      app: redis
  spec:
Enter fullscreen mode Exit fullscreen mode

Container Specification:

containers:
- name: redis-container
  image: redis:alpine
  ports:
  - containerPort: 6379
  resources:
    requests:
      cpu: 1
Enter fullscreen mode Exit fullscreen mode

Volume Mounts:

volumeMounts:
- name: data
  mountPath: /redis-master-data
- name: redis-config
  mountPath: /redis-master
Enter fullscreen mode Exit fullscreen mode

Volumes:

volumes:
- name: data
  emptyDir: {}
- name: redis-config
  configMap:
    name: my-redis-config
Enter fullscreen mode Exit fullscreen mode

Step 3: Apply the Configurations

kubectl apply -f redis-configmap.yaml
kubectl apply -f redis-deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Output:

configmap/my-redis-config created
deployment.apps/redis-deployment created
Enter fullscreen mode Exit fullscreen mode

Step 4: Verify the Deployment

kubectl get deployments
Enter fullscreen mode Exit fullscreen mode

Output:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
redis-deployment   1/1     1            1           10s
Enter fullscreen mode Exit fullscreen mode

Step 5: Verify the Pod

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Output:

NAME                               READY   STATUS    RESTARTS   AGE
redis-deployment-c795495f4-vjfpl   1/1     Running   0          10s
Enter fullscreen mode Exit fullscreen mode

Step 6: Verify the ConfigMap

kubectl describe configmap my-redis-config
Enter fullscreen mode Exit fullscreen mode

Output:

Name:         my-redis-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
redis-config:
----
maxmemory 2mb
Enter fullscreen mode Exit fullscreen mode

Step 7: Verify Volume Mounts

kubectl describe pod redis-deployment-c795495f4-vjfpl
Enter fullscreen mode Exit fullscreen mode

Key Output:

Containers:
  redis-container:
    Mounts:
      /redis-master from redis-config (rw)
      /redis-master-data from data (rw)
Volumes:
  data:
    Type:       EmptyDir
  redis-config:
    Type:      ConfigMap
    Name:      my-redis-config
Enter fullscreen mode Exit fullscreen mode

Step 8: Check Redis Configuration

kubectl exec -it redis-deployment-c795495f4-vjfpl -- redis-cli CONFIG GET maxmemory
Enter fullscreen mode Exit fullscreen mode

Output:

1) "maxmemory"
2) "0"
Enter fullscreen mode Exit fullscreen mode

Note: The ConfigMap is mounted as a file, but Redis does not automatically load the configuration from the mounted path. To load the configuration, Redis would need to be started with redis-server /redis-master/redis-config.

Step 9: Check Redis Memory Info

kubectl exec -it redis-deployment-c795495f4-vjfpl -- redis-cli INFO memory
Enter fullscreen mode Exit fullscreen mode

Output:

# Memory
used_memory:1419296
used_memory_human:1.35M
maxmemory:0
maxmemory_human:0B
Enter fullscreen mode Exit fullscreen mode

Step 10: Check Mounted Config File

kubectl exec -it redis-deployment-c795495f4-vjfpl -- cat /redis-master/redis-config
Enter fullscreen mode Exit fullscreen mode

Output:

maxmemory 2mb
Enter fullscreen mode Exit fullscreen mode

Redis Configuration Options

Common Redis Configuration Parameters

Parameter Description Example
maxmemory Maximum memory limit maxmemory 256mb
maxmemory-policy Eviction policy when memory limit is reached maxmemory-policy allkeys-lru
save Snapshotting intervals save 900 1
appendonly Enable AOF persistence appendonly yes
requirepass Password authentication requirepass mypassword

Redis Memory Policies

Policy Description
noeviction Return error when memory limit is reached
allkeys-lru Evict least recently used keys
volatile-lru Evict least recently used keys with expiration
allkeys-random Evict random keys
volatile-random Evict random keys with expiration
volatile-ttl Evict keys with shortest time to live

Advanced Configuration

Loading ConfigMap Configuration in Redis

To load the ConfigMap configuration into Redis, you can modify the container command:

containers:
- name: redis-container
  image: redis:alpine
  command: ["redis-server"]
  args: ["/redis-master/redis-config"]
Enter fullscreen mode Exit fullscreen mode

Adding Environment Variables

containers:
- name: redis-container
  image: redis:alpine
  env:
  - name: REDIS_PASSWORD
    value: "my-secure-password"
Enter fullscreen mode Exit fullscreen mode

Adding a Service for Redis

apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  selector:
    app: redis
  ports:
  - port: 6379
    targetPort: 6379
Enter fullscreen mode Exit fullscreen mode

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

ConfigMap Not Found

# Check ConfigMap exists
kubectl get configmaps

# Check ConfigMap details
kubectl describe configmap my-redis-config
Enter fullscreen mode Exit fullscreen mode

Volumes Not Mounted

# Check volume mounts
kubectl describe pod <pod-name> | grep -A 10 "Mounts:"

# Check volumes
kubectl describe pod <pod-name> | grep -A 10 "Volumes:"
Enter fullscreen mode Exit fullscreen mode

Redis Not Accessible

# Check if Redis is running
kubectl exec -it <pod-name> -- redis-cli PING

# Should return: PONG
Enter fullscreen mode Exit fullscreen mode

Best Practices

1. Resource Management

Set appropriate resource requests and limits:

resources:
  requests:
    memory: "256Mi"
    cpu: "500m"
  limits:
    memory: "512Mi"
    cpu: "1"
Enter fullscreen mode Exit fullscreen mode

2. Persistent Storage

Use PersistentVolumeClaims for data persistence:

volumes:
- name: redis-data
  persistentVolumeClaim:
    claimName: redis-pvc
Enter fullscreen mode Exit fullscreen mode

3. Configuration Management

Use ConfigMaps for Redis configuration:

volumes:
- name: redis-config
  configMap:
    name: redis-config
Enter fullscreen mode Exit fullscreen mode

4. Security

Enable Redis authentication:

env:
- name: REDIS_PASSWORD
  valueFrom:
    secretKeyRef:
      name: redis-secret
      key: password
Enter fullscreen mode Exit fullscreen mode

Useful Commands Reference

Command Purpose
kubectl get deployments List deployments
kubectl get pods List pods
kubectl get configmaps List ConfigMaps
kubectl describe configmap my-redis-config ConfigMap details
kubectl exec -it <pod> -- redis-cli CONFIG GET maxmemory Check Redis max memory
kubectl exec -it <pod> -- redis-cli INFO memory Check Redis memory info
kubectl exec -it <pod> -- redis-cli PING Check Redis connectivity
kubectl exec -it <pod> -- cat /redis-master/redis-config View mounted config file
kubectl logs <pod> View pod logs

Summary

In this challenge, we successfully:

  1. Created a ConfigMap to store Redis configuration (maxmemory 2mb)
  2. Deployed Redis on Kubernetes using the redis:alpine image
  3. Configured resource requests for the Redis container
  4. Mounted an EmptyDir volume for data storage
  5. Mounted a ConfigMap volume for configuration
  6. Verified the deployment, pod, and configuration

Redis is a powerful in-memory data store commonly used in microservices architectures. Deploying Redis on Kubernetes provides a scalable, resilient, and manageable solution for caching and data storage needs. The patterns demonstrated here can be extended to support more complex Redis configurations, persistent storage, and high-availability setups.

Top comments (0)