How to deploy a node.js with redis on kubernetes?
I think I figured out a solution (using a Deployment and a Service).
For my deployment, I used two containers (webapp + redis) within one Pod, since it doesn't make sense for a webapp to run without active redis instance, and additionally it connects to redis upon application start. I could be wrong in this reasoning, so feel free to correct me if you think otherwise.
Here's my deployment:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-app-deploymentspec: selector: matchLabels: app: my-app-deployment template: metadata: labels: app: my-app-deployment spec: containers: - name: redis image: redis:latest ports: - containerPort: 6379 volumeMounts: - mountPath: /srv/www name: redis-storage - name: my-app image: my-app:latest imagePullPolicy: Never ports: - containerPort: 8080 volumes: - name: redis-storage emptyDir: {}
And here's the Service definition:
apiVersion: v1kind: Servicemetadata: name: my-app-servicespec: ports: - port: 8080 protocol: TCP type: NodePort selector: app: my-app-deployment
I create the deployment with:kubectl create -f deployment.yaml
Then, I create the service with kubectl create -f service.yaml
I read the IP with minikube ip
and extract the port from the output of kubectl describe service my-app-service
.
I agree with all of the previous answers. I'm just trying to things more simple by executing a single command.
First, create necessary manifests for redis in a file say redis.yaml
and service to expose it outside.
apiVersion: v1kind: Servicemetadata: name: redis labels: app: node-redisspec: ports: - name: redis port: 6379 targetPort: 6379 type: NodePort selector: app: node-redis---apiVersion: apps/v1kind: Deploymentmetadata: name: redisspec: selector: matchLabels: app: node-redis replicas: 1 template: metadata: labels: app: node-redis spec: containers: - name: redis image: redis:latest imagePullPolicy: IfNotPresent ports: - containerPort: 6379 # data volume where redis writes data volumeMounts: - name: data mountPath: /data readOnly: false volumes: - name: data persistentVolumeClaim: claimName: redis-data---# data volumeapiVersion: v1kind: PersistentVolumeClaimmetadata: name: redis-data labels: app: node-redisspec: accessModes: - ReadWriteOnce resources: requests: storage: 100Mi
Next put manifests for your app in another file say my-app.yaml
. Here i put the volume field so that you can use the data that stored by redis.
apiVersion: v1kind: Podmetadata: name: my-app labels: app: node-redisspec: containers: - name: my-app image: my-app:latest ports: - containerPort: 8080 # data volume from where my-app read data those are written by redis volumeMounts: - name: data mountPath: /data readOnly: false volumes: - name: data persistentVolumeClaim: claimName: redis-data
Now we can use the following bash file my-app.sh
.
#!/bin/bashkubectl create -f redis.yamlpod_name=$(kubectl get po -l app=node-redis | grep app-with-redis | awk '{print $1}')# check whether redis server is ready or notwhile true; do pong=$(kubectl exec -it $pod_name -c redis redis-cli ping) if [[ "$pong" == *"PONG"* ]]; then echo ok; break fidonekubectl create -f my-app.yaml
Just run chmod +x my-app.sh; ./my-app.sh
to deploy. To get the url run minikube service redis --url
. You can similarly get the url for your app. The only thing is you need a nodePort
type service for your app to access it from outside of the cluster.
So, everything is in your hand now.
I would run redis in a separate pod (i.e.: so your web app doesn't take down the redis server if itself crashes).
Here is your redis deployment & service:
deployment.yaml:
apiVersion: apps/v1kind: Deploymentmetadata: name: redisspec: selector: matchLabels: app: redis replicas: 1 template: metadata: labels: app: redis spec: volumes: - name: host-sys hostPath: path: /sys initContainers: - name: disable-thp image: redis:4.0-alpine volumeMounts: - name: host-sys mountPath: /host-sys command: ["sh", "-c", "echo never > /host-sys/kernel/mm/transparent_hugepage/enabled"] containers: - name: redis image: redis:4.0-alpine imagePullPolicy: IfNotPresent resources: requests: cpu: 350m memory: 1024Mi ports: - containerPort: 6379
service.yaml:
apiVersion: v1kind: Servicemetadata: name: redis labels: app: redisspec: ports: - port: 6379 name: redis selector: app: redis
Since we've exposed a kubernetes Service
you can then access your redis instance by hostname, or it's "service name", which is redis
.
You can check out my kubernetes redis repository at https://github.com/mateothegreat/k8-byexamples-redis. You can simply run make install
if you want the easier route.
Good luck and if you're still stuck please reach out!