Run Memcached persistently on Kubernetes
When running Memcached on the Kubernetes cluster, the cache data will disappear whenever the pod restarts. I know that Redis has the built-in replication and it can be able to have data on persistence disks. However, I have some reasons to run the Memecached on our Kubernetes cluster. So, I was thinking about it and I came across my mind the way using postStart and preStop in lifecycle settings.
Before explaining, the disadvantages of this way are as follows.
- Cannot cope with node failures
- Need to add a persistent volume
First, create a script file that loads a dump file if it exists, and then output an empty file for the readiness probe. (post_start.sh)
1#!/bin/ash
2memc_host="127.0.0.1"
3memc_port=11211
4
5# Load previous prestop data
6dump_file="${DUMP_DIR}/${HOSTNAME}.dump.prestop"
7if [ -f $dump_file ];then
8 echo "Loading previous prestop data..."
9 cat $dump_file | nc $memc_host $memc_port
10fi
11
12# For readiness probe
13touch /tmp/ready
And then, create a script that dump data before termination.
1#!/bin/ash
2
3# Load previous prestop data
4/memcached-tool ${HOSTNAME} dump > ${DUMP_DIR}/${HOSTNAME}.dump.prestop
After creating the above scripts, build the container image with the scripts by the following Dockerfile.
1FROM memcached:1.6.6-alpine
2
3# Switch to root for installing packages
4USER root
5
6RUN apk --update --no-cache add \
7 bash \
8 busybox-extras \
9 perl
10
11COPY memcached-tool /
12COPY post_start.sh /
13COPY pre_stop.sh /
14
15# Switch to memcache for running
16USER memcache
Finally, create the following YAML file and deploy it to the Kubernetes cluster.
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: memcached
5 namespace: app
6 labels:
7 app: memcached
8spec:
9 replicas: 2
10
11 selector:
12 matchLabels:
13 app: memcached
14
15 serviceName: memcached
16 template:
17 metadata:
18 labels:
19 app: memcached
20 spec:
21 affinity:
22 podAntiAffinity:
23 requiredDuringSchedulingIgnoredDuringExecution:
24 - labelSelector:
25 matchExpressions:
26 - key: app
27 operator: In
28 values:
29 - memcached
30 topologyKey: "kubernetes.io/hostname"
31
32 containers:
33 - name: memcached
34 image: registry/my-memcached:202010051112
35 imagePullPolicy: IfNotPresent
36 args: ["-U", "0", "-B", "ascii"]
37
38 ports:
39 - containerPort: 11211
40
41 env:
42 - name: DUMP_DIR
43 value: "/var/tmp/memcache-dump"
44
45 resources:
46 requests:
47 cpu: 10m
48 memory: 16Mi
49
50 livenessProbe:
51 tcpSocket:
52 port: 11211
53 initialDelaySeconds: 2
54 periodSeconds: 5
55
56 readinessProbe:
57 exec:
58 command:
59 - cat
60 - /tmp/ready
61 initialDelaySeconds: 5
62 periodSeconds: 5
63
64 lifecycle:
65 postStart:
66 exec:
67 command: ["/post_start.sh"]
68 preStop:
69 exec:
70 command: ["/pre_stop.sh"]
71
72 volumeMounts:
73 - name: "memcache-dump"
74 mountPath: "/var/tmp/memcache-dump"
75
76 volumes:
77 - name: "memcache-dump"
78 persistentVolumeClaim:
79 claimName: memcache-efs
I know this is not a sophisticated way but it’s easy to create. So, I think it’s useful in some situations.