Skip to content

Rodrigo Urubatan – About Code

Helping ruby developers to use the best tools for each job so they can solve hard problems, with less bugs and have more free time.

Menu
  • Home
  • My last presentations
  • About
  • Privacy Policy
Menu

Rails from “zero” to kubernetes – a service to access your pod

Posted on 2020-01-08 by Rodrigo Urubatan

In the previous post, we created our first kubernetes pod, but one important part is missing, it is not possible to access that application, we’ll solve this with a service now.

In kubernetes, even thou a pod is similar to a docker container, it doesn’t have a public or private IP address.

Of course if you check the underlying container implementation you’ll be able to access the pod, but that way you’ll loose all the benefits of kubernetes.

The basic idea is that a pod can be in any node, and the pods for a deployment can be in many nodes, and kubernetes will make that transparent for us using a service.

To make things clearer, and show only what is important, I’ve cleaned up the YAML for the deployment we’ve created in the previous post and we’ll start from there.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: rails-sample
  name: rails-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      run: rails-sample
  template:
    metadata:
      labels:
        run: rails-sample
    spec:
      containers:
      - args:
        - rails
        - s
        - -b
        - 0.0.0.0
        - -p
        - "3000"
        env:
        - name: DATABASE_HOST
          value: 192.168.0.15 
        - name: DATABASE_USERNAME
          value: root 
        - name: DATABASE_PASSWORD
          value: password
        image: urubatan/urubatan_rails_docker_sample:1.0.0
        name: rails-sample
        ports:
        - containerPort: 3000
          protocol: TCP

Assuming that yaml file is called “deployment.yaml” we can go back to the same state we were before with a “kubectl apply -f deployment.yaml”

And now to access the application, we’ll do the same as before and start with the command line, then go to the yaml, but right now, we already have one point to rememter, the “key” that kubernetes will use to match the service to the pods, is anything that we’ve added in the “labels” section, right now it is “run: rails-sample” but we can use any label we create, and the labels can be mostly any key/value pair.

To create a simple service to access our pods from that deployment, we can simply run: kubectl expose deployment.apps/rails-sample

And now, running a “kubectl get svc” you’ll see something similar to:

$ kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.152.183.1    <none>        443/TCP    18d
rails-sample   ClusterIP   10.152.183.16   <none>        3000/TCP   43s

From there, we can see that the services have a name, a type (we’ll see more on that later) a cluster IP, an external IP and ports.

The cluster IP is the service IP inside the kubernetes cluster, since we are running it locally now, we can use it to access the service, so right now, in my machine, if you go to http://10.152.183.16:3000 you’ll be able to access the rails sample app.

Only some types of services have external IPs.

The service type, can be any of:

  • ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the default ServiceType.
  • NodePort: Exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You’ll be able to contact the NodePort Service, from outside the cluster, by requesting :.
  • LoadBalancer: Exposes the Service externally using a cloud provider’s load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
  • ExternalName: Maps the Service to the contents of the externalName field (e.g. foo.bar.example.com), by returning a CNAME record

Now lets do the same as before, and take a look at the YAML that represents this service, we’ll get the yaml with the command: kubectl get service/rails-sample -o=yaml, and the result will be:

apiVersion: v1
kind: Service
metadata:
  labels:
    run: rails-sample
  name: rails-sample
spec:
  ports:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    run: rails-sample
  type: ClusterIP

As before I’ve cleaned up the output a little bit, removing some state from the yaml.

What is really important for us right now, is what is in the “spec” portion.

  • type is where we specify exactly what we want, I usually set ClusterIP for anything that doesn’t need to be externally accessible and LoadBalancer for what needs to have external access, so lets change it to LoadBalancer in this case.
  • selector is where we tell what pods this service will map to, as mentioned before, the label is matched to the service, so be careful to not set the same label to different pod types, because that can create a really confusing experience 😀
  • ports is where we tell kubernetes what we’ll be exposing from the target pods, we can have different “port” and “targetPort” for each entry, where port is the externally accessible port, and targetPort is the pod port mapped to it.

If you saved that yaml as for example, service.yaml, changed the service type to LoadBalancer and then executed “kubectl apply -f service.yaml”, now you should have something similar to:

$ kubectl get svc
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
kubernetes     ClusterIP      10.152.183.1    <none>          443/TCP          18d
rails-sample   LoadBalancer   10.152.183.16   192.168.0.150   3000:31865/TCP   16m

And with the external IP for our new load balancer, we can access the service from outside your machine.

If you are running this on AWS or Google Cloud, you’ll have their load balancer name in that field.

If you are running this locally with microk8s and you do not have an external IP listed, it is probably because you didn’t enable the “metallb” addon.

So I think it is all that you need to start playing with services, come back here in a couple of days and we’ll see how to increase the availability and performance of our services with automatic horizontal scaling.

And as always, please let me know if you have any question in the comment section bellow, if you liked or not this post and if you want to see any other type of content around here.

Related

2 thoughts on “Rails from “zero” to kubernetes – a service to access your pod”

  1. Pingback: Rails from "zero" to kubernetes – horizontal autoscaling | Rodrigo Urubatan - About Code
  2. Pingback: Rails from "zero" to kubernetes – ingress reverse proxy | Rodrigo Urubatan - About Code

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent posts

  • Why Embrace Nesting in Ruby Modules?
  • An easy way to have a local “Github Copilot” for free
  • SPA without touching Javascript – The magic of Ruby on rails and Hotwire
  • I see Dead Jobs everywhere (sidekiq DeadSet)
  • Quick tips that help: rails notes

Arquives

  • May 2024
  • April 2024
  • February 2023
  • January 2023
  • December 2022
  • June 2021
  • March 2020
  • January 2020
  • July 2019
  • June 2019
  • May 2019
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • February 2018
  • January 2018
  • November 2017
  • August 2015
  • August 2014
  • July 2014
  • August 2007

Categories

  • AI
  • articles
  • cfp
  • firebase
  • gems
  • git
  • opinion
  • presentations
  • projects
  • rails6
  • ruby
  • Sem categoria
  • server-api
  • tutorials
  • Uncategorized
© 2025 Rodrigo Urubatan – About Code | Powered by Minimalist Blog WordPress Theme