As stated on their website, "Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications." Here we'll take a Rails app, create an image using a Dockerfile, and let Kubernetes manage the containers for us.
We will discuss the following:
• Running locally via Minikube
We'll start by creating a Kubernetes secret. This secret contains the secret key base and database credentials required by the Rails application. To generate a secret key base, run
$ bundle exec rake secret
Encode the secret key base using base64.
$ echo -n "8d428e9d27e3323f1b1ec0089482017480224c9984fc10327f95b0990ec46175d43d756fd644c3bca3703a337a94ced69c868ab0470ac201cd1b6a80c3f89e4a" | base64
Next, encode the database credentials. Use the format DB_ADAPTER://USER:PASSWORD@HOSTNAME/DB_NAME. If you are using mysql with a user 'deploy' and a password 'secret' on 127.0.0.1 and have a database railsapp, run
$ echo -n "mysql://deploy:email@example.com/railsapp"
Create a YAML file of the secret and save it anywhere in your local machine. You can use any filename. Here we use railsapp_secrets.yaml.
After creating the secret, we next create a deployment. A deployment contains the name of the image of your Rails app and the number of containers you want Kubernetes to run.
Deployments are used to rollout a new version of your app, rollback to a previous version, and to scale your app by running more containers.
You only need to change the values of "replicas" and "image". Notice we use the secrets we created earlier as environment variables. You should not put your credentials on your image and instead use a secret.
- name: railsapp
- containerPort: 3000
- name: DATABASE_URL
- name: SECRET_KEY_BASE
If you do not have a Docker image on Docker Hub yet, check out the Dockerfile on our blog post on Using Docker For Rails. It's important to set the app to log to standard out instead of a log file so that Kubernetes logging works.
You can name the yaml file railsapp_deployment.yaml.
Lastly, you have to create a service to be able to access the app. We use the type NodePort on Minikube where Kubernetes will forward requests to a port on the Minikube VM to the application.
When using AWS I use the type LoadBalancer where Kubernetes will create an ELB that points to the 3 containers.
- name: http protocol: TCP port: 80 targetPort: 3000
Name the file railsapp_service.yaml.
The instructions used here are for the Mac. If you have a different operation system, please refer to the Minikube documentation.
I use VirtualBox which you can download for free here.
Download the kubectl and move it to your path.
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
Download Minikube and move it to your path.
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.21.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
Feel free to leave off the sudo mv minikube /usr/local/bin if you would like to add minikube to your path manually.
$ minikube start
Starting local Kubernetes v1.7.0 cluster...
Downloading Minikube ISO
97.80 MB / 97.80 MB [==============================================] 100.00% 0s
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Starting cluster components...
Connecting to cluster...
Setting up kubeconfig...
Kubectl is now configured to use the cluster.
Check that kubectl can connect to the cluster with
kubectl version and
Now create the secret, deployment, and service from above.
$ kubectl create -f railsapp_secrets.yaml
$ kubectl create -f railsapp_deployment.yaml
$ kubectl create -f railsapp_service.yaml
Check the status.
$ kubectl get secrets
NAME TYPE DATA AGE
default-token-9flwv kubernetes.io/service-account-token 3 2m
railsapp-secrets Opaque 2 45s
$ kubectl get deployments,pods
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
railsapp-deployment 3 3 3 0 1m
NAME READY STATUS RESTARTS AGE
railsapp-deployment-1000337448-2qkpd 0/1 ContainerCreating 0 1m
railsapp-deployment-1000337448-9lrjc 0/1 ContainerCreating 0 1m
railsapp-deployment-1000337448-qnmlr 0/1 ContainerCreating 0 1m
You can see here that Kubernetes is still pulling the Docker image. When the image is ready and the containers are running you should see 3 under AVAILABLE on the deployment and Running under STATUS on the pods.
e $ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.0.0.1 443/TCP 12m
railsapp-service 10.0.0.186 80:31596/TCP 1s
The app will be available on the Minkube IP and the node port of the service. To get the Minikube IP, run
minikube ip. On my local machine, the app is available on 192.168.99.100:31596.
You can also run
minikube service railsapp-service and Minikube will open the URL on your browser.
Kubernetes makes it easier to scale and manage applications. Kubernetes is a complex system but you can start with the basics - Secrets, Deployments, Services. With these 3, you can already start running your Rails application inside Kubernetes.
I've shown you how to run Rails on Kubernetes on your local machine via Minikube. In production, you can create a cluster say in AWS and still mostly the same Kubernetes secret (with different credentials), deployment, and service. We've only scratched the surface. If you want to hear more about Kubernetes and Rails, do let us know by leaving a comment.