How to Simplify Your Local Kubernetes Development With Skaffold
Tags: devops, kubernetes, k3s, skaffold
Published: 2022-04-20 21:39:10

Let's answer honestly, how we usually imagine a Kubernetes related environment? So far we have:

- `docker` for building container images (and running them locally but we typically only do that for testing)
- a _docker registry_ for storing the container images and making them accessible for kubernetes to use
- _YAML manifests_ to describe what containers, pods... we actually want to run in Kubernetes. These YAML files could refer to docker images _we created ourselves_.
- `kubectl` as a tool to make requests to the kubernetes API (and create objects based on YAMLs).
- `helm` for packaging YAMLs together and making stuff configurable.

Let's add something new now. Suppose we are now working on a real app, and we want to make some code changes and deploy them. What we would need to do:

- first make the code changes.
- then build _new_ docker images. Better give them a different tag than the _old_ docker images so we can tell them apart.
- then push the _new_ docker images to the docker registry.
- then _re_-deploying the YAMLs to kubernetes. Probably using `helm`: the container images we want to use will be settings in `helm`. So we change the settings before deploying.

🐌🐌🐌 That's a lot of steps! Kubernetes is cool but _it slows down our development pensive_.

This is _where_ `skaffold` comes in the picture. Skaffold is _a little glue layer_ (it is more than that, but we use it as that for now) that:

- builds the docker images
- pushes them
- then deploys your kubernetes resources (optionally using `helm`) with the docker images it just built

And it does everything with one single command.

[Skaffold](https://github.com/GoogleContainerTools/skaffold) is a ~13k ⭐ open source CLI tool created by Google that helps with continuous development and deployment of Kubernetes applications specifically aimed at developers.

You can iterate on your application source code locally then [deploy to local](https://skaffold.dev/docs/environment/local-cluster/) Kubernetes clusters. Skaffold handles the workflow for building, pushing and deploying your application. 

At the most basic level, Skaffold works this way; it:

- Creates Kubernetes configuration files for your apps
- Deploys your application to a local or remote cluster
- Monitors your source code and automatically re-deploys when needed
- Steams logs from your deployed pods to your local terminal

But Skaffold also offers several advanced features on top of this basic functionality. First of all, Skaffold provides an extensible pluggable architecture, allowing developers to choose the appropriate tools for each step involved in building and deploying their application. Skaffold also [attempts to provide portability](https://skaffold.dev/docs/environment/profiles/) for CI integrations among different build systems, image registries and deployment tools.

`skaffold` can also interact with Docker registries by pushing your application image. It is capable to work with plain Kubernetes manifests (using `helm` as a package manager is optional).

The figure below depicts the `skaffold` workflow, including the generation of the configuration files and the deployment lifecycle in both aforementioned execution modes.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bw223awao6h86gd9x7bh.png)

## Deployments with Skaffold

Skaffold can be used in two different modes:

### ⚙️ DEVELOPment mode 

By issuing the command `skaffold dev`. In development mode, it monitors the changes in source code, automatically generates all appropriate Docker images and deploys the images to the Kubernetes cluster. In addition, it provides logs streaming from deployed applications.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i07d445kgr8knpf5bqsx.png)

### ⚙️ DEPLOYment mode 

By issuing the command `skaffold run`. In this mode, Skaffold runs a pipeline only once and exits on any errors in the pipeline. This is useful because it can be used as a sanity check after the completion of the development of the application.

The main features of the Scaffold are:
- It monitors local changes in your source code and automatically triggers build/push deployments to local or remote Kubernetes clusters.
- It supports remote and local Docker engines and registries. (Note that using remote Docker engines may increase build times significantly.)
- Can track dependencies between applications and automatically deploy on what was changed.
- Supports existing tooling and workflows with the ability to build and deploy APIs that make each implementation composable to support various different workflows.

One of the main advantages of Skaffold is the number of integrations it provides. It has native support for:

- Buildkit
- [Google cloud build](https://github.com/GoogleCloudPlatform/cloud-builders-community/tree/master/skaffold)
- Helm
- [Kustomize](https://codersociety.com/blog/articles/build-and-deploy-kubernetes-applications-with-skaffold-and-kustomize)

The `skaffold.yaml` file, which is the main configuration file, has several options that you can use to change the way your application is built and deployed. It is essentially a mini CI/CD solution for local development that can also take care of testing or pushing images.

Our Skaffold installation will be completed using the standalone executable, for Linux. The installation steps are:

Download the latest version of Skaffold, unpack it and place it to your `$PATH`. Verify Skaffold executable and version

```bash
$ curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && \
sudo install skaffold /usr/local/bin/
```
##Application configuration

For this tutorial, a Spring-Boot application will be used. It provides one endpoint that returns a simple greeting message in `JSON` format.

In order to run the application, we first need to create a `Dockerfile` file to containerize our application. Here is an example:

```docker
FROM maven:3-jdk-11 as BUILD
COPY . /usr/src/app
RUN mvn --batch-mode -f /usr/src/app/pom.xml clean package
FROM openjdk:11-jre-slim
ENV PORT 42050
EXPOSE 42050
COPY --from=BUILD /usr/src/app/target /opt/target
WORKDIR /opt/target
CMD ["/bin/bash", "-c", "find -type f -name '*.jar' | xargs java -jar"]
```
In addition to the `Dockerfile`, we will also create a `k8s-app.yaml` file in order to generate the Skaffold configuration file. A simple version of `k8s-app.yaml` file is shown below:

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: skaffold-demo
spec:
  containers:
  - name: skaffold-demo
    image: somerepo/skaffold-demo
```
Now, the Skaffold configuration files can be generated by issuing the command:

```
$ skaffold init
```
This command will generate a `skaffold.yaml` [file containing all needed information](https://skaffold.dev/docs/references/yaml/) in order to build and deploy the application to the desired Kubernetes cluster. The generated `skaffold.yaml` file is:

```yaml
apiVersion: skaffold/v1beta28
kind: Config
build:
  artifacts:
  - image: somerepo/skaffold-demo
deploy:
  kubectl:
    manifests:
    - k8s-app.yaml
```
It is worth mentioning that when creating a new project, you can bootstrap Skaffold configs with `init` command (a very convenient feature). Also, you can [define several configs](https://skaffold.dev/docs/design/config/): one config for developing and another one to deploy to the stage environment via the run command (the same workflow as with `dev` except for, in this case, Skaffold doesn’t monitor for changes).

##Application deployment flow

After successful creation of the configuration files, there are two options to deploy the desired application. During development time, we can use the command:

```
$ skaffold dev --default-repo localhost:32000
```
The above command will continuously deploy your application when a file is changed (speeding up development). It monitors the source code files for every change and makes fast re-deployments.

If you want to deploy once and don’t track code changes, you need the run command:

```
$ skaffold run --default-repo localhost:32000
```
We use [insecure MicroK8s repo](https://microk8s.io/docs/registry-built-in) here, but you are free to use your own. If no `--default-repo` is provided by the user, [there is no automated image name rewriting](https://skaffold.dev/docs/environment/image-registries/), and Skaffold will try to push the image as provided in the YAML.

After a successful deployment you can check if your application has been deployed in your Kubernetes cluster using the familiar kubectl commands:

```
$ kubectl get pods
```
You can check that the application is running by using [k9s](https://k9scli.io/) or your Kubernetes dashboard to ensure your application has been deployed as expected.

Skaffold lets you set breakpoints and step through your application in debug purposes. You may find detailed manual about debugging [here](https://skaffold.dev/docs/workflows/debug/).

Finally, you can remove your deployed application with the delete command:

```
$ skaffold delete
```
🌖 In summary, `skaffold` is a very flexible solution that does not require `helm` and is very extensive on what kind of integrations it can be used with.

[To be continued](https://dev.to/otomato_io/how-to-speed-up-your-local-kubernetes-development-with-devspace-4ngb).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71evcrvufj9zxozy9rx0.jpg)