GitOps101 — Deployment Files and Cluster Preparation (Part 3)

Alper Peker
Codable
Published in
4 min readJan 13, 2023

This is the fourth article in a series of (6+1 bonus =) 7 articles.

This series was written by Alper Peker and Yağız Küçükkambak, from OBSS DevOps Team.

Welcome back! Up to this point, we have built the React application and have created a docker image out of it. In this part, we will focus on the deployment and will create the files required to make a Kubernetes deployment using ArgoCD. To achieve that, we will get help from Kustomize.

Photo by Maarten van den Heuvel on Unsplash

The files, which we will discuss shortly, will configure the Kubernetes deployment that define its contents and expected behavior. We need to store these files in a separate repository. There are 8 different files we will discuss:

  • autoscaler.yaml
  • configmap.yaml
  • credentials.yaml
  • deployment.yaml
  • ingress.yaml
  • kustomization.yaml
  • secret.yaml
  • service.yaml

First of all, before we go into variables definitions in the files, the files themselves must be declared. That’s why kustomization.yaml would be an appropriate start since it will organize and define the remaining yaml files. Actually, this is the main purpose of this file. This file is also important for ArgoCD to use these manifest files to create deployments so if a file is not declared in the resources section it won’t be deployed even if it is stored on the repo.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- autoscaler.yaml
- configmap.yaml
- credentials.yaml
- deployment.yaml
- secret.yaml
- service.yaml
- ingress.yaml

It is now time to decide on more deployment options that can provide deeper customization. Some of these are; the number of instances that will be created, technical specs of liveness and readiness probes such as ports, CPU and memory limitations, metadata definitions and annotations …etc. Note that deployment.yaml contains references to the credentials.yaml. Also, pay attention to respectIgnoreDifferences variable for the ArgoCD deployment. When it is set to true, the replicas property will be ignored so only maximum and minimum boundaries will be honored.

apiVersion: apps/v1
kind: Deployment
metadata:
name: gitops-react-app
labels:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
template:
metadata:
labels:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
spec:
imagePullSecrets:
- name: gitops-react-app-docker-credentials
securityContext:
{}
containers:
- name: app
command: [nginx]
args:
- -g
- daemon off;
securityContext:
{}
image: registry.gitlab.com/***
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 30
periodSeconds: 15
ports:
- containerPort: 80
name: http
protocol: TCP
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 30
periodSeconds: 15
workingDir: /app
resources:
limits:
cpu: 900m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
env:
- name: init
valueFrom:
configMapKeyRef:
name: gitops-react-app
key: init
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 10
podAffinityTerm:
labelSelector:
matchExpressions:
- key: fullname
operator: In
values:
- gitops-react-app
topologyKey: "kubernetes.io/hostname"

As we have just mentioned, credentials.yaml contains “encrypted” credentials that are used to connect to the Kubernetes cluster when deploying the app.

apiVersion: v1
kind: Secret
metadata:
name: gitops-react-app-docker-credentials
labels:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: ***

We are producing manifests and properties, one-by-one, but we also need an environment to apply these configurations. The configmap.yaml allows us to bind these files and elements to containers and pods. In this specific scenario, most of the configuration elements like attributes/properties, port definitions, etc.. are defined in several different files.

---
kind: ConfigMap
apiVersion: v1
metadata:
name: gitops-react-app
labels:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
data:
init: default

Up until now, the files covered -generally- defined the deployment. However the next file, autoscaler.yaml, focuses on the behavior. Here the max and min numbers of app instances and when these replicas will be created are decided, thus the cluster will know how to behave in case of any errors or crashes in high stress/load.

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: gitops-react-app
labels:
helm.sh/chart: architecture-angular-0.1.0
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
app.kubernetes.io/managed-by: Helm
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: gitops-react-app
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 95

As its name suggests, secrets.yaml is where we store sensitive data. Instead of keeping this information on Dockerfiles, containers, and pods, we will take advantage of secrets.yaml to keep confidential data away from easy access.

---
kind: Secret
apiVersion: v1
metadata:
name: gitops-react-app
labels:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app
data:
{}

Kubernetes services are one of those assets that need to be configured, like the access protocol and ports that will listen to and serve the application. service.yaml is the file that contains the configuration for those services.

apiVersion: v1
kind: Service
metadata:
name: gitops-react-app
labels:
app.kubernetes.io/name: angular
app.kubernetes.io/instance: architecture
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app

Last but not least, ingress.yaml focuses on the ingress network and access to the deployed application. Ingress is (usually) deployed as a cluster-wide controller which manages inbound routing rules for the cluster (and the application). This file allows us to to add inbound layer-7 rules for our application.

apiVersion: v1
kind: Service
metadata:
name: gitops-react-app
labels:
app.kubernetes.io/name: angular
app.kubernetes.io/instance: architecture
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app.kubernetes.io/name: gitops-react-app
app.kubernetes.io/instance: gitops-react-app

And that’s it! We have covered all the files to make a Kubernetes deployment. It is recommended to store the files on a repository that is accessible by ArgoCD. In the next part, the main focus will be utilizing ArgoCD to make the deployments and managing those deployments.

--

--