In this post, I would be showing you how to deploy a golang application to Kubernetes using Kubestack. Kubestack is a Gitops automation built on Terraform to reduce the risk of deploying and increasing development speed. That being said I would not be covering how to set up kubestack but rather how to deploy Kubernetes manifests using Kubestack, for more info on how to up a working Kubestack pipeline check out the getting started guide over here.
Now let's dive in.
Setup
Once you have your kubestack pipeline set up your folder structure should look something like this
.
├── Dockerfile
├── Dockerfile.loc
├── README.md
├── aks_zero_cluster.tf
├── aks_zero_ingress.tf
├── aks_zero_providers.tf
├── manifests
└── versions.tf
to deploy our Kubernetes manifest we would be making use of a cluster service module. Cluster service modules in Kubestack allows Terraform to interact directly with Kubernetes through Terraform, this covers things like deploying and creating namespaces, creating deployments..etc.
Open up ask-zero_cluster.tf
and add the following lines
...
module "custom_manifests" {
providers = {
kustomization = kustomization.aks_zero
}
source = "kbst.xyz/catalog/custom-manifests/kustomization"
version = "0.1.0"
configuration = {
apps = {
namespace = "apps-${terraform.workspace}"
resources = [
"${path.root}/manifests/apps/namespace.yaml",
"${path.root}/manifests/apps/deployment.yaml",
"${path.root}/manifests/apps/service.yaml",
"${path.root}/manifests/apps/ingress.yaml"
]
common_labels = {
"env" = terraform.workspace
}
}
ops = {}
loc = {}
}
}
Here we initialize the custom manifest cluster service module and tell kustomize to use the existing aks_zero
module using.
providers = {
kustomization = kustomization.aks_zero
}
The configuration block is where the magic happens, first, we specify we declare what workspace we want our resources to be deployed to using
apps = {
namespace = "apps-${terraform.workspace}"
resources = [
"${path.root}/manifests/apps/namespace.yaml",
"${path.root}/manifests/apps/deployment.yaml",
"${path.root}/manifests/apps/service.yaml",
"${path.root}/manifests/apps/ingress.yaml"
]
common_labels = {
"env" = terraform.workspace
}
}
Next, we declare what namespace the manifests should be deployed to using namespace = "apps${terraform.workspace}"
which would translate to apps-ops
or apps-apps
depending on your current workspace, next the resources block tells terraform to look in manifests folder in the current directory for the manifests we want to deploy. Now that we have the cluster module set up let's create the manifests.
Run the following commands:
mkdir manifests/apps && cd manifests/apps && touch deployment.yaml service.yaml ingress.yaml
Now populate the files with the following code.
# manifests/apps/namespace.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: apps-apps
---
apiVersion: v1
kind: Namespace
metadata:
name: apps-ops
Note: since this is a fresh Kubernetes cluster I have included a manifest for a namespace as kubestack would deploy the resources in the order specified in the module so the namespace apps-apps
would need to exist first.
#manifests/apps/deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ping-api
spec:
selector:
matchLabels:
app: ping-api
template:
metadata:
labels:
app: ping-api
spec:
containers:
- name: ping-api
image: ghcr.io/s1ntaxe770r/evil-ekow:latest
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
env:
- name: REDIS_CACHE_HOST
value: "redis-svc"
- name: REDIS_PORT
value: "6379"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 6379
# manifests/apps/service.yaml
--
apiVersion: v1
kind: Service
metadata:
name: redis-svc
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: ping-svc
spec:
selector:
app: ping-api
ports:
- port: 80
targetPort: 8080
# manifests/apps/ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myingress
labels:
name: myingress
spec:
rules:
- host: prod.evil.corp
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: ping-svc
port:
number: 80
The above manifests will deploy a version of an API that uses Redis to store key-value pairs. You can check the source code out here.
Next, you can test out these changes locally by running kbst apply local
, if all looks good you should be able to tag and deploy like this:
$ git tag apps-deploy-1
$ git push origin apps-deploy-1
Accessing your deployment
Because I don't have a valid domain at the time of writing I would be using my ingress controller external IP to access the deployment, however, if you have your domain properly configured pls refer to this portion of the
Kubestack documentation.
First, grab your ingress controller\'s external IP using:
$ kubectl get ingresses -A
Next, create the following entry in /etc/hosts
10.10.20.5 prod.evil.corp
be sure to change the IP to your ingress controllers external IP ,now you should be able to access the swagger docs at
http://prod.evil.corp
Conclusion
In this post, I covered how to deploy your Kubernetes manifests using Kubestack on Azure do note that this is not limited to azure as Kubetack also supports GKE and AWS at the time of writing this post, so be sure to check out the
documentation for any provider-specific steps. Now go forth and git deploying 😄
Top comments (0)