Overview of Skaffold for Kubernetes Development

Overview of Skaffold for Kubernetes Development

A year and a half ago, on March 5, 2018, Google released the first alpha version of its Open Source CI/CD project called Skaffold, whose goal was to create "simple and reproducible development under Kubernetes" so that developers could focus on development, not administration. What might be interesting about Skaffold? As it turns out, it has a few tricks up its sleeve, thanks to which it can become a strong tool for a developer, and maybe even an operations engineer. Let's get acquainted with the project and its possibilities.

NB: By the way, we have already talked briefly about Skaffold in our general overview of developer tools, whose life is connected with Kubernetes.

Theory. Purpose and opportunities

So, speaking in general, Skaffold solves the problem of automating the CI / CD cycle (at the build, push, deploy stages), offering the developer prompt feedback, i.e. the ability to quickly get the result of the next code changes - in the form of an updated application running in a Kubernetes cluster. And it can work in different circuits (dev, stage, production ...), for which Skaffold helps to describe the corresponding pipelines for rollout.

The Skaffold source code is written in the Go language, spreads under the free Apache License 2.0 (GitHub).

Consider the main functions and features. The first ones include the following:

  • Skaffold offers tools for creating CI/CD pipelines.
  • Allows you to monitor changes in the source code in the background and start an automated process of building code into container images, publishing these images to the Docker Registry and deploying them to a Kubernetes cluster.
  • Synchronizes the files in the repository with the working directory in the container.
  • Automatically tests with container-structure-test.
  • Forwarding ports.
  • Reads the logs of an application running in a container.
  • Helps in debugging applications written in Java, Node.js, Python, Go.

Now - about the features:

  • Skaffold itself has no components on the cluster side. That is, you do not need to additionally configure Kubernetes to use this utility.
  • Different pipelines for your application. Do you need to roll out the code to the local Minikube while you are developing, and then to the stage or production? For this, there are Profiles and user configurations, environment variables and flags, which allow you to describe different pipelines for one application.
  • CLI. Only console utility and configurations in YAML. On the net you can find references to attempts to create experimental GUI, but at the moment it rather only means that someone needs it, but not really.
  • Modularity. Skaffold is not a stand-alone harvester, but seeks to use individual modules or already existing solutions for specific tasks.

Illustration of the latter:

  • At the build stage, you can use:
    • docker build locally, on a cluster using kaniko, or on Google Cloud Build;
    • Bazel locally;
    • Jib Maven and Jib Gradle locally or on Google Cloud Build;
    • custom build scripts run locally. If you need to run another (more flexible/familiar/…) build solution, it is described in the script so that Skaffold will run it (example from documentation). This allows you to use generally any collector that can be called using a script;
  • At the testing stage, the already mentioned container-structure-test;
  • Deployment includes:
    • Kubectl;
    • Helms;
    • customize.

Thanks to this, Skaffold can be called a peculiar framework for building CI/CD. Here is an example workflow when using it (from the project documentation):

Overview of Skaffold for Kubernetes Development

What does Skaffold's work look like in general terms?

  1. The utility watches for changes in the source code directory. If modifications are made to the files, they are synchronized with the application pod in the Kubernetes cluster. If possible, without rebuilding the image. Otherwise, a new image is assembled.
  2. The built image is checked with container-structure-test, tagged, and submitted to the Docker Registry.
  3. After that, the image is deployed - deployed in a Kubernetes cluster.
  4. If the launch was initialized with the command skaffold dev, then we start receiving logs from the application, and Skaffold is waiting for changes in order to repeat all the actions again.

Overview of Skaffold for Kubernetes Development
Illustration of the main stages of the work of Skaffold

Practice. Trying Skaffold

To demonstrate the use of Skaffold, I will take an example from GitHub project repository. By the way ibid. You can find many other examples that take into account different specifics. All actions will be performed locally in Minikube. Installation is simple and takes a few minutes, and you'll need kubectl to get started.

Install Skaffold:

curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
chmod +x skaffold
sudo mv skaffold /usr/local/bin
skaffold version
v0.37.1

Let's clone the Skaffold repository with the necessary examples:

git clone https://github.com/GoogleContainerTools/skaffold
cd skaffold/examples/microservices

I chose an example with two pods, each containing one small Go application. One application is the frontend (leeroy-web), redirecting the request to the second application - the backend (leeroy-app). Let's see what it looks like:

~/skaffold/examples/microservices # tree
.
├── leeroy-app
│   ├── app.go
│   ├── Dockerfile
│   └── kubernetes
│       └── deployment.yaml
├── leeroy-web
│   ├── Dockerfile
│   ├── kubernetes
│   │   └── deployment.yaml
│   └── web.go
├── README.adoc
└── skaffold.yaml
 
4 directories, 8 files

leeroy-app and leeroy-web contain the Go code and simple Dockerfiles to build this code locally:

~/skaffold/examples/microservices # cat leeroy-app/Dockerfile
FROM golang:1.12.9-alpine3.10 as builder
COPY app.go .
RUN go build -o /app .
 
FROM alpine:3.10
CMD ["./app"]
COPY --from=builder /app .

I will not give the application code - it is enough to know that leeroy-web accepts requests and proxies them to leeroy-app. Therefore, in the files Deployment.yaml there is a Service only for app (for internal routing). Pod port web we will swipe ourselves for quick access to the application.

Looks like skaffold.yaml:

~/skaffold/examples/microservices # cat skaffold.yaml
apiVersion: skaffold/v1beta13
kind: Config
build:
  artifacts:
    - image: leeroy-web
      context: ./leeroy-web/
    - image: leeroy-app
      context: ./leeroy-app/
deploy:
  kubectl:
    manifests:
      - ./leeroy-web/kubernetes/*
      - ./leeroy-app/kubernetes/*
portForward:
  - resourceType: deployment
    resourceName: leeroy-web
    port: 8080
    localPort: 9000

All the stages mentioned above are described here. In addition to this config, there is also a file with global settings - ~/.skaffold/config. It can be edited manually or through the CLI - for example, like this:

skaffold config set --global local-cluster true

This command will set the global variable local-cluster in value true, after which Skaffold will not try to 'push' images into the remote registry. If you're developing locally, you can use this command to stack images locally as well.

We return to skaffold.yaml:

  • On the stage build we specify that we need to build and save the image locally. After the assembly starts for the first time, we will see the following:
    // т.к. Minikube создает кластер в отдельной виртуальной машине,
    // придется проникнуть внутрь, чтобы найти образы
    # minikube ssh
    $ docker images
    REPOSITORY                                TAG                                                                IMAGE ID            CREATED             SIZE 
    leeroy-app                                7d55a50803590b2ff62e47e6f240723451f3ef6f8c89aeb83b34e661aa287d2e   7d55a5080359        4 hours ago         13MB 
    leeroy-app                                v0.37.1-171-g0270a0c-dirty                                         7d55a5080359        4 hours ago         13MB
    leeroy-web                                5063bfb29d984db1ff70661f17d6efcc5537f2bbe6aa6907004ad1ab38879681   5063bfb29d98        5 hours ago         13.1MB
    leeroy-web                                v0.37.1-171-g0270a0c-dirty                                         5063bfb29d98        5 hours ago         13.1MB

    As you can see, Skaffold independently tagged the images. By the way, several tagging policies are supported.

  • Next in the config is context: ./leeroy-app/, i.e. the context in which the image is built is specified.
  • At the deployment stage, it is determined that we will use kubectl and a mask for the necessary manifests.
  • PortForward: similar to how we usually forward ports with kubectl port-forward, we give Skaffold instructions to call this command. In this case, the local port 9000 is forwarded to 8080 in the Deployment with the name leeroy-web.

It's time to run skaffold dev: The command will create an ongoing "feedback loop" i.e. will not only collect everything and deploy it to the cluster, but also tell you about the state of the pods at the moment, monitor changes and update the state of the pods.

Here is the run result skaffold dev --port-forward when reassembling:

Overview of Skaffold for Kubernetes Development

First, you can see that the cache is being used. Next - the application is assembled, deployed, ports are forwarded. Because specified --port-forward, Skaffold forwarded the port to webas requested, and here app he cast at his own discretion (he chose the nearest free one). After that, we receive the first logs from applications.

Let's check the performance?

~/skaffold/examples/microservices # kubectl get po
NAME                          READY   STATUS    RESTARTS   AGE
leeroy-app-6998dfcc95-2nxvf   1/1     Running   0          103s
leeroy-web-69f7d47c9d-5ff77   1/1     Running   0          103s
~/skaffold/examples/microservices # curl localhost:9000
leeroooooy app!!!

Modifying the file leeroy-app/app.go - a few seconds pass ... and:

~/skaffold/examples/microservices # kubectl get po
NAME                          READY   STATUS    RESTARTS   AGE
leeroy-app-ffd79d986-l6nwp    1/1     Running   0          11s
leeroy-web-69f7d47c9d-5ff77   1/1     Running   0          4m59s
~/skaffold/examples/microservices # curl localhost:9000
leeroooooy Habr!!!

At the same time, Skaffold himself displayed the same thing on the console as before, with the exception of one moment: he only rolled out leeroy-app, not all at once.

More practice

It is worth mentioning that when creating a new project, Skaffold configs can be 'bootstrap'ed using the command initwhich is very convenient. In addition, you can write several configs: develop on the default config, and then roll out to the stage with the command run (same process as dev, just does not follow the changes), using a different config.

On katacoda there is guide with an example is even easier. But it offers a ready-made sandbox with Kubernetes, an application, and Skaffold. A great option if you are interested in trying the very basics yourself.

One possible use case for Skaffold is to do development on a remote cluster. It’s not convenient for everyone to run Minikube on their own hardware, then roll out the application and expect it to function adequately ... In this case, Skaffold perfectly solves the task, which can be confirmed, for example, by Reddit engineers, as we have already wrote in our blog.

And in this publication from Weaveworks you can find an example of creating a pipeline for production.

Conclusion

Skaffold is a handy tool for building pipelines that involve rolling out applications to Kubernetes and focused primarily on development needs. With it, it is quite easy to create a “short” pipeline that takes into account the basic needs of the developer, however, if desired, you can organize larger processes. As one of the clear examples of the use of Skaffold in CI / CD processes is given such test project of 10 microservices using Kubernetes, gRPC, Istio and OpenCensus Tracing.

Skaffold has almost 8000+ stars on GitHub, developed by Google and part of GoogleContainerTools - in general, at the moment there is every reason to believe that the project will develop happily ever after.

PS

Read also on our blog:

Source: habr.com

Add a comment