Running Rust Service in Kubernetes with only 3.5MB
Rust is a very exciting language. Not only for system programming but also for microservices and business development. Today I will show how we can create a simple service application in rust using Iron Framework. For this blog post, we will build a rust binary and run both in Docker and Kubernetes. In order to run kubernetes locally, I will be using minikube but you can use any kind of kubernetes cluster or distribution and it should work just fine. The most amazing thing is that we can build a rust executable with only 3.5MB and a docker image with the only 3.63MB. This is super lean!
Talk is Cheap, show me the Code!
Here we go. Behold the main.rs file.
Here we are using Iron Web Framework and also ust env utilities in order to access OS level Env variables. The server is running on the port 8080, there is a function called hello_world with revices a request from icon a returns an Iron result with a Response. Inside the function I'm defining a key, which is a simple string that represents the env var I'm looking for, in this case, called: RUST_SVC_VERSION. After that, I'm using env_var_os to check if the var is present, also using the good rust pattern matcher to see if their var is present or not. IF The var is present I will receive Some otherwise none. In the case that the var is empty I'm returning an undefined version of the app on the response otherwise I return the value of the var concatenated with the String Hello World! V:.
We need to declare an Iron dependency in Cargo.Toml file.
Now Let build our Rust application, we will use docker to build the app, we do this way. Let's take a look at release-rust.sh file.
Here we are using rust builder in order to build the binary in an optimized way. Now we can take a look at the Dockerfile.
As you can see the Dockerfile is dead simple, we just add 1 file, which is the binary we just built and we expose the port 8080. Call the binary as main CMD from Docker and that's it, folks. Let's bake this docker image doing:
Now that we build it, we just need to run it. Let's run it by doing:
As you can realize here, I'm passing an env var to docker, with version 1, feel free to change the value and see that it works.
Let's run it with Kubernetes now. Let's take a look at the deployment and service specs.
For the deployment yaml file (^^^) as you can see we are using my docker image we just built. This image is also in my docker hub, so thats why you dont need perform any craziness to run in your minikube :D
Now we have the service yaml file (^^^) keep in mind we dont want use ClusterIP in production folks this is just for development and fun. Having this 2 specs, we can create a folder called specs and we can deploy them to kubernetes using kubectl.
After the deploy, we can expose our service via port-forwarding and then we can call it :D
In the script above I'm using kubectl to select the pod I want using selectors, a great feature from kubernetes, I'm getting the name of the pods with the app==rustapp. Them storing this result in a bash variable and calling kubectl port-forwarding on this pod. I'm binding container 8080 port to my 8080 local port. That's it, now you can just do: curl http://localhost:8080/ and you will see it works.
Here is the complete source code in my github.
Cheers,
Diego Pacheco
Talk is Cheap, show me the Code!
Here we go. Behold the main.rs file.
Here we are using Iron Web Framework and also ust env utilities in order to access OS level Env variables. The server is running on the port 8080, there is a function called hello_world with revices a request from icon a returns an Iron result with a Response. Inside the function I'm defining a key, which is a simple string that represents the env var I'm looking for, in this case, called: RUST_SVC_VERSION. After that, I'm using env_var_os to check if the var is present, also using the good rust pattern matcher to see if their var is present or not. IF The var is present I will receive Some otherwise none. In the case that the var is empty I'm returning an undefined version of the app on the response otherwise I return the value of the var concatenated with the String Hello World! V:.
We need to declare an Iron dependency in Cargo.Toml file.
Now Let build our Rust application, we will use docker to build the app, we do this way. Let's take a look at release-rust.sh file.
Here we are using rust builder in order to build the binary in an optimized way. Now we can take a look at the Dockerfile.
As you can see the Dockerfile is dead simple, we just add 1 file, which is the binary we just built and we expose the port 8080. Call the binary as main CMD from Docker and that's it, folks. Let's bake this docker image doing:
Now that we build it, we just need to run it. Let's run it by doing:
As you can realize here, I'm passing an env var to docker, with version 1, feel free to change the value and see that it works.
Let's run it with Kubernetes now. Let's take a look at the deployment and service specs.
For the deployment yaml file (^^^) as you can see we are using my docker image we just built. This image is also in my docker hub, so thats why you dont need perform any craziness to run in your minikube :D
Now we have the service yaml file (^^^) keep in mind we dont want use ClusterIP in production folks this is just for development and fun. Having this 2 specs, we can create a folder called specs and we can deploy them to kubernetes using kubectl.
After the deploy, we can expose our service via port-forwarding and then we can call it :D
In the script above I'm using kubectl to select the pod I want using selectors, a great feature from kubernetes, I'm getting the name of the pods with the app==rustapp. Them storing this result in a bash variable and calling kubectl port-forwarding on this pod. I'm binding container 8080 port to my 8080 local port. That's it, now you can just do: curl http://localhost:8080/ and you will see it works.
Here is the complete source code in my github.
Cheers,
Diego Pacheco