The author selected Girls Who Code to receive a donation as part of the Write for DOnations program.
The Okteto CLI is an open-source project that provides a local development experience for applications running on Kubernetes. With it you can write your code on your local IDE and as soon as you save a file, the changes can be pushed to your Kubernetes cluster and your app will immediately update. This whole process happens without the need to build Docker images or apply Kubernetes manifests, which can take considerable time.
In this tutorial, you’ll use Okteto to improve your productivity when developing a Kubernetes-native application. First, you’ll create a Kubernetes cluster and use it to run a standard “Hello World” application. Then you’ll use Okteto to develop and automatically update your application without having to install anything locally.
Before you begin this tutorial, you’ll need the following:
kubectl
and doctl
installed and configured to communicate with your cluster.The “Hello World” program is a time-honored tradition in web development. In this case, it is a simple web service that responds “Hello World” to every request. Now that you’ve created your Kubernetes cluster, let’s create a “Hello World” app in Golang and the manifests that you’ll use to deploy it on Kubernetes.
First change to your home directory:
- cd ~
Now make a new directory called hello_world
and move inside it:
- mkdir hello_world
- cd hello_world
Create and open a new file under the name main.go
with your favorite IDE or text editor:
- nano main.go
main.go
will be a Golang web server that returns the message Hello world!
. So, let’s use the following code:
package main
import (
"fmt"
"net/http"
)
func main() {
fmt.Println("Starting hello-world server...")
http.HandleFunc("/", helloServer)
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
func helloServer(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello world!")
}
The code in main.go
does the following:
package
name. Executable commands must always use package main
.import
section indicates which packages the code depends on. In this case it uses fmt
for string manipulation, and net/http
for the HTTP server.main
function is the entry point to your binary. The http.HandleFunc
method is used to configure the server to call the helloServer
function when a request to the /
path is received. http.ListenAndServe
starts an HTTP server that listens on all network interfaces on port 8080
.helloServer
function contains the logic of your request handler. In this case, it will write Hello world!
as the response to the request.You need to create a Docker image and push it to your Docker registry so that Kubernetes can pull it and then run the application.
Open a new file under the name Dockerfile
with your favorite IDE or text editor:
- nano Dockerfile
The Dockerfile
will contain the commands required to build your application’s Docker container. Let’s use the following code:
FROM golang:alpine as builder
RUN apk --update --no-cache add bash
WORKDIR /app
ADD . .
RUN go build -o app
FROM alpine as prod
WORKDIR /app
COPY --from=builder /app/app /app/app
EXPOSE 8080
CMD ["./app"]
The Dockerfile
contains two stages, builder
and prod
:
builder
stage contains the Go build tools. It’s responsible for copying the files and building the Go binary.prod
stage is the final image. It will contain only a stripped down OS and the application binary.This is a good practice to follow. It makes your production containers smaller and safer since they only contain your application and exactly what is needed to run it.
Build the container image (replace your_DockerHub_username
with your Docker Hub username):
- docker build -t your_DockerHub_username/hello-world:latest
Now push it to Docker Hub:
- docker push your_DockerHub_username/hello-world:latest
Next, create a new folder for the Kubernetes manifests:
- mkdir k8s
When you use a Kubernetes manifest, you tell Kubernetes how you want your application to run. This time, you’ll create a deployment object. So, create a new file deployment.yaml
with your favorite IDE or text editor:
- nano k8s/deployment.yaml
The following content describes a Kubernetes deployment object that runs the okteto/hello-world:latest
Docker image. Add this content to your new file, but in your case replace okteto
listed after the image
label with your_DockerHub_username
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
selector:
matchLabels:
app: hello-world
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: your_DockerHub_username/hello-world:latest
ports:
- containerPort: 8080
The deployment manifest has three main sections:
metadata
defines the name for your deployment.replicas
defines how many copies of it you want running.template
tells Kubernetes what to deploy, and what labels to add. In this case, a single container, with the okteto/hello-world:latest
image, listening on port 8080
, and with the app: hello-world
label. Note that this label is the same used in the selector
section.You’ll now need a way to access your application. You can expose an application on Kubernetes by creating a service object. Let’s continue using manifests to do that. Create a new file called service.yaml
with your favorite IDE or text editor:
- nano k8s/service.yaml
The following content describes a service that exposes the hello-world
deployment object, which under the hood will use a DigitalOcean Load Balancer:
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 8080
name: http
selector:
app: hello-world
The service manifest has four main sections:
metadata
tells Kubernetes how to name your service.type
tells Kubernetes how you want to expose your service. In this case, it will expose it externally through a Digital Ocean Load Balancer.ports
label tells Kubernetes which ports you want to expose, and how to map them to your deployment. In this case, you will expose port 80
externally and direct it to port 8080
in your deployment.selector
tells Kubernetes how to direct traffic. In this case, any pod with the app: hello-world
label will receive traffic.You now have everything ready to deploy your “Hello World” application on Kubernetes. We will do this next.
In this step you’ll deploy your “Hello World” application on Kubernetes, and then you’ll validate that it is working correctly.
Start by deploying your application on Kubernetes:
- kubectl apply -f k8s
You’ll see the following output:
Outputdeployment.apps "hello-world" created
service "hello-world" created
After about one minute or so, you will be able to retrieve your application’s IP. Use this kubectl
command to check your service:
- kubectl get service hello-world
You’ll see an output like this listing your Kubernetes service objects. Note your application’s IP in the the EXTERNAL-IP
column:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world ClusterIP your_cluster_ip your_external_ip 8080/TCP 37s
Open your browser and go to your_external_ip
listed for your “Hello World” application. Confirm that your application is up and running before continuing with the next step.
Until this moment, you’ve followed a fairly traditional pathway for developing applications with Kubernetes. Moving forward, whenever you want to change the code in your application, you’ll have to build and push a new Docker image, and then pull that image from Kubernetes. This process can take quite some time. Okteto was designed to streamline this development inner-loop. Let’s look at the Okteto CLI and see just how it can help.
You will now improve your Kubernetes development productivity by installing the Okteto CLI. The Okteto command line interface is an open-source project that lets you synchronize application code changes to an application running on Kubernetes. You can continue using your favorite IDE, debuggers, or compilers without having to commit, build, push, or redeploy containers to test your application–as you did in the previous steps.
To install the Okteto CLI on a macOS or Linux machine, run the following command:
- curl https://get.okteto.com -sSfL | sh
Let’s take a closer look at this command:
curl
command is used to transfer data to and from a server.-s
flag suppresses any output.-S
flag shows errors.-f
flag causes the request to fail on HTTP errors.-L
flag makes the request follow redirects.|
operator pipes this output to the sh
command, which will download and install the latest okteto
binary in your local machine.If you are running Windows, you can alternately download the file through your web browser and manually add it to your $PATH
.
Once the Okteto CLI is installed, you are ready to put your “Hello World” application in development mode.
The Okteto CLI is designed to swap the application running on a Kubernetes cluster with the code you have in your machine. To do so, Okteto uses the information provided from an Okteto manifest file. This file declares the Kubernetes deployment object that will swap with your local code.
Create a new file called okteto.yaml
with your favorite IDE or text editor:
- nano okteto.yaml
Let’s write a basic manifest where you define the deployment object name, the Docker base image to use, and a shell. We will return to this information later. Use the following sample content file:
name: hello-world
image: okteto/golang:1
workdir: /app
command: ["bash"]
Prepare to put your application in development mode by running the following command:
- okteto up
Output ✓ Development environment activated
✓ Files synchronized
Namespace: default
Name: hello-world
Welcome to your development environment. Happy coding!
default:hello-world /app>
The okteto up
command swaps the “Hello World” application into a development environment, which means:
The Hello World application container is updated with the docker image okteto/golang:1
. This image contains the required dev tools to build, test, debug, and run the “Hello World” application.
A file synchronization service is created to keep your changes up-to-date between your local filesystem and your application pods.
A remote shell starts in your development environment. Now you can build, test, and run your application as if you were in your local machine.
Whatever process you run in the remote shell will get the same incoming traffic, the same environment variables, volumes, or secrets as the original “Hello World” application pods. This, in turn, gives you a highly realistic, production-like development environment.
In the same console, now run the application as you would typically do (without building and pushing a Docker image), like this:
- go run main.go
OutputStarting hello-world server...
The first time you run the application, Go will download your dependencies and compile your application. Wait for this process to finish and test your application by opening your browser and refreshing the page of your application, just as you did previously.
Now you are ready to begin developing directly on Kubernetes.
Let’s start making changes to the “Hello World” application and then see how these changes get reflected in Kubernetes.
Open the main.go
file with your favorite IDE or text editor. For example, open a separate console and run the following command:
- nano main.go
Then, change your response message to Hello world from DigitalOcean!
:
package main
import (
"fmt"
"net/http"
)
func main() {
fmt.Println("Starting hello-world server...")
http.HandleFunc("/", helloServer)
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
func helloServer(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello world from DigitalOcean!")
}
It is here that your workflow changes. Instead of building images and redeploying containers to update the “Hello World” application, Okteto will synchronize your changes to your development environment on Kubernetes.
From the console where you executed the okteto up
command, cancel the execution of go run main.go
by pressing CTRL + C
. Now rerun the application:
- default:hello-world /app> go run main.go
OutputStarting hello-world server...
Go back to the browser and reload the page for your “Hello World” application.
Your code changes were applied instantly to Kubernetes, and all without requiring any commits, builds, or pushes.
Okteto transforms your Kubernetes cluster into a fully-featured development platform with the click of a button. In this tutorial you installed and configured the Okteto CLI to iterate your code changes directly on Kubernetes as fast as you can type code. Now you can head over to the Okteto samples repository to see how to use Okteto with different programming languages and debuggers.
Also, if you share a Kubernetes cluster with your team, consider giving each member access to a secure Kubernetes namespace, configured to be isolated from other developers working on the same cluster. This great functionality is also provided by the Okteto App in the DigitalOcean Kubernetes Marketplace.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!