mirror of
https://github.com/avinal/avinal.github.io.git
synced 2026-07-04 07:40:09 +05:30
@@ -0,0 +1,208 @@
|
||||
---
|
||||
title: Developing Minimal Tekton Server
|
||||
date: 2022-02-27 20:47
|
||||
modified: 2022-03-07 22:47
|
||||
category: development
|
||||
tags: [tekton, go, kubernetes, openshift, redhat, intern, golang, openshift-pipelines]
|
||||
---
|
||||
|
||||
# Developing Minimal Tekton Server [<img src="/images/mks_logo.png" class="align-middle" style="width:1.5em"
|
||||
|
||||
This blog is a descreptive account of the development of Minimal Tekton Server.
|
||||
This is highly technical in nature, so please make sure that you have sufficient
|
||||
knowledge about Golang, Docker, Kubernetes and TektonCD. You can refer to my
|
||||
[previous blog]("https://avinal.space/posts/development/i-am-loving-it-redhat.html")
|
||||
to know about these topics.
|
||||
|
||||
As mentioned in my last blog, we were given to implement an application
|
||||
named **Minimal Tekton Server**. The problem statement reads:
|
||||
|
||||
> We will be designing and implementing an application that will be
|
||||
> talking to Tekton APIs to create resources on a Kubernetes/OpenShift
|
||||
> Cluster. The application will expose some fields of the Tekton
|
||||
> Resources which the user will provide and then this application will
|
||||
> create Tekton resources by talking to Tekton APIs available on the
|
||||
> cluster to create the resources based on the user-provided fields.
|
||||
|
||||
There are three parts in this project for the application and two more
|
||||
parts for the CI/CD using TektonCD and Kubernetes/OpenShift. I will go
|
||||
through each part descriptively and try to explain what we did.
|
||||
|
||||
## The Architecture of MKS
|
||||
|
||||
The first task in the development of the Minimal Tekton Server was
|
||||
creating its architectural diagram. Our first diagram was trash compared
|
||||
to the final diagram. Yeah, we learned. I will be explaining our
|
||||
final(obviously) architectural diagram and try to make some sense out of
|
||||
band-aids and duct tapes.
|
||||
|
||||
<img src="/images/mks-architecture.png"
|
||||
class="img-fluid my-3 img-fluid my-3" alt="The MKS Arhitecture" />
|
||||
|
||||
Let me start with explaining **What are MKS Resources?**. I hope you
|
||||
know at least tidbits about Kubernetes and by the definition: *A
|
||||
resource is an endpoint in the Kubernetes API that stores a collection
|
||||
of API objects of a certain kind; for example, the built-in
|
||||
:code:\`pods\` resource contains a collection of Pod objects.* But
|
||||
developers soon realized that these in-built resources were not enough
|
||||
for the ever-growing applications of Kubernetes. Here [custom
|
||||
resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
|
||||
comes into the picture. *A custom resource is an extension of the
|
||||
Kubernetes API that is not necessarily available in a default Kubernetes
|
||||
installation.* To define a custom resource we use something called
|
||||
[Custom Resource
|
||||
Definition](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/).
|
||||
So MKS Resources are such custom resources that correspond to the
|
||||
TektonCD custom resources.
|
||||
|
||||
<img src="/images/venus-flytrap.gif"
|
||||
class="float-md-right ml-3 float-md-right ml-3" width="250"
|
||||
alt="A venus flytrap engulphing an insect." />
|
||||
|
||||
Let us now focus on the box containing `Controller` and `API server`.
|
||||
The controller can be said as a stimulus-response mechanism. Take the
|
||||
analogy of a Venus Flytrap plant. The trap is initially open. There are
|
||||
`trigger` hairs on the inside of the trap. Once an insect is detected,
|
||||
there is a change of state and the trap closes in a blick on the eye.
|
||||
The controller works the same way. It listens for the change in the
|
||||
state of the MKS resources and immediately transfers the request to the
|
||||
Tekton API to reflect the change in the corresponding Tekton resources.
|
||||
The changes can be creation, deletion, or updating. The API server
|
||||
ensures that there is a working connection between our controller and
|
||||
the Tekton API.
|
||||
|
||||
MKS Server also exposes APIs to introduce a change of state in the MKS
|
||||
resources. In technical terms these are called `verbs`. There are five
|
||||
such verbs that we have exposed: `create`, `update`, `get`, `delete`,
|
||||
and `list`. They can be utilized by a REST client, or in our case **MKS
|
||||
CLI** to introduce desired change. The MKS command-line interface
|
||||
provides commands and subcommands to do the desired tasks.
|
||||
|
||||
Whenever there is a change in the state, there is a logic running inside
|
||||
the controller to react on that and that also affects our database. We
|
||||
store four datapoints in our database: `created`, `deleted`,
|
||||
`completed`, and `failed`. They tell us about the current statistcs of
|
||||
our MKS resource using a single-page web app called **MKS Dashboard**
|
||||
(or UI).
|
||||
|
||||
This was about the architecture of the Minimal Tekton Server. Let us
|
||||
jump into more technical stuff.
|
||||
|
||||
## How to implement a CRD controller?
|
||||
|
||||
During this assignment, something that took the most time and effort was
|
||||
the implementation of a controller for our custom resources. This isn't
|
||||
very hard if you go by the rules and do the things according to the
|
||||
well-defined documents and blogs since this is a standard step in the
|
||||
implementation of any custom resource controller. But did we follow the
|
||||
rules? Hell no! But this time, let us go step-by-step.
|
||||
|
||||
1. The first step is to define a `CustomResourceDefinition` for our custom
|
||||
resource. Let us define a CRD called `spacetime`. To do this you can write a
|
||||
YAML file like below.
|
||||
|
||||
``` yaml
|
||||
# file: spacetime-crd.yaml
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
# name must match the spec fields below, and be in the form: <plural>.<group>
|
||||
name: spacetimes.example.com
|
||||
spec:
|
||||
# group name to use for REST API: /apis/<group>/<version>
|
||||
group: example.com
|
||||
# list of versions supported by this CustomResourceDefinition
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
# Each version can be enabled/disabled by Served flag.
|
||||
served: true
|
||||
# One and only one version must be marked as the storage version.
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
# either Namespaced or Cluster
|
||||
scope: Namespaced
|
||||
names:
|
||||
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
|
||||
plural: spacetimes
|
||||
# singular name to be used as an alias on the CLI and for display
|
||||
singular: spacetime
|
||||
# kind is normally the CamelCased singular type. Your resource manifests use this.
|
||||
kind: SpaceTime
|
||||
# shortNames allow shorter string to match your resource on the CLI
|
||||
shortNames:
|
||||
- st
|
||||
```
|
||||
|
||||
You can learn more about the fields and options
|
||||
[here](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/).
|
||||
The CRD that we defined above corresponds to the `CustomResource` given
|
||||
below. Once you apply the above file you will be able to see the
|
||||
`spacetime` custom resource on your Kubernetes/OpenShift cluster.
|
||||
|
||||
``` yaml
|
||||
# file: spacetime-cr.yaml
|
||||
apiVersion: spacetimes.example.com/v1alpha1
|
||||
kind: SpaceTime
|
||||
metadata:
|
||||
name: spacetime-cr
|
||||
spec:
|
||||
message: "Hello from space!"
|
||||
```
|
||||
|
||||
Apply them using the following commands:
|
||||
|
||||
``` bash
|
||||
kubectl apply -f spacetime-crd.yaml
|
||||
kubectl apply -f spacetime-cr.yaml
|
||||
```
|
||||
|
||||
1. Once we have defined our custom resources, we need to define the
|
||||
types that will correspond to this custom resource definition. This
|
||||
can be done using `k8s.io/apimachinery/pkg/apis/meta/v1` package
|
||||
written in golang. Did I tell you that this is all in golang? Well,
|
||||
now you know. Create a package structure for a golang project and
|
||||
add the definition of the type as given below.
|
||||
|
||||
``` bash
|
||||
mkdir -p pkg/api/spacetime/v1alpha1
|
||||
touch pkg/api/spacetime/v1alpha1/{spacetime_types,register,doc}.go pkg/api/spacetime/register.go
|
||||
```
|
||||
|
||||
Add the following content to the corresponding files.
|
||||
|
||||
``` golang
|
||||
// file: /pkg/api/spacetime/v1alpha1/spacetime_types.go
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type SpaceTime struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec SpaceTimeSpec `json:"spec"`
|
||||
}
|
||||
|
||||
type SpaceTimeSpec struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type SpaceTimeList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []SpaceTime `json:"items"`
|
||||
}
|
||||
```
|
||||
|
||||
### To be Continued
|
||||
Reference in New Issue
Block a user