III: Building kubernetes home lab with k3d — Service mesh and Postgres
02.02.2021 - AYB - Reading time ~5 Minutes
Part III: Deploying service mesh and Postgres to our homelab kubernetes cluster
Traefik Mesh
We’re not going to deploy something like shiny enterprizeish Istio. Instead we will deploy the simplest service mesh of all time — Traefik Mesh
If you don’t know what service mesh is and not required with the task to have a service mesh capabilities, then most likely you don’t need it and may skip this part.
So, first things first:
helm repo add traefik-mesh https://helm.traefik.io/mesh
helm repo update
To make this mesh work properly, we should specify to use KubeDNS subsystem and our custom domain name.
helm install traefik-mesh traefik-mesh/traefik-mesh --set kubedns=true --set clusterDomain=k3d.local --namespace traefik-mesh --create-namespace
Output:
NAME: traefik-mesh
LAST DEPLOYED: Mon May 30 00:58:56 2022
NAMESPACE: traefik-mesh
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing traefik-mesh.
Your release is named traefik-mesh.
To learn more about the release, try:
$ helm status traefik-mesh
$ helm get traefik-mesh
That’s it. Done.
I will not copy-cat here the test procedure — you’re welcome to perform tests yourself
I recommend using Lens to launch terminal sessions in pods just for simplicity.
To make your service supported by the mesh you need to make some changes to your deployment yaml
. Details are in Traefik Mesh documentation
Postgres
We’ll install a kubernetes-native Stackgres version of the Postgres, that runs as a cluster with a lot of bells a whistles helping to diagnose, debug and service databases.
Custom deployment
Helm deployment is below: Deployment using Helm
Stackgres operator
First, install Stackgres operator to our cluster. Download the yml for this operator:
wget https://stackgres.io/downloads/stackgres-k8s/stackgres/1.2.0/stackgres-operator-demo.yml
Then edit it at the line around 4030:
apiVersion: v1
kind: Service
metadata:
namespace: stackgres
name: stackgres-restapi
annotations:
meta.helm.sh/release-name: stackgres-operator
meta.helm.sh/release-namespace: stackgres
labels:
app.kubernetes.io/managed-by: Helm
spec:
#type: 'LoadBalancer'
type: 'ClusterIP' #<<=== here is your edit. Original line is above.
selector:
app: stackgres-restapi
ports:
- name: https
protocol: TCP
port: 443
targetPort: https
Now apply it:
kubectl apply -f stackgres-operator-demo.yml
Output:
namespace/stackgres created
customresourcedefinition.apiextensions.k8s.io/sgbackups.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgbackupconfigs.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgclusters.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgdbops.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgdistributedlogs.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sginstanceprofiles.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgobjectstorages.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgpoolconfigs.stackgres.io created
customresourcedefinition.apiextensions.k8s.io/sgpgconfigs.stackgres.io created
clusterrolebinding.rbac.authorization.k8s.io/stackgres-restapi-admin created
clusterrolebinding.rbac.authorization.k8s.io/stackgres-restapi created
service/stackgres-operator created
service/stackgres-restapi created
deployment.apps/stackgres-operator created
deployment.apps/stackgres-restapi created
serviceaccount/stackgres-operator-crd-upgrade created
serviceaccount/stackgres-operator-init created
serviceaccount/stackgres-operator created
clusterrole.rbac.authorization.k8s.io/stackgres-operator-crd-upgrade created
clusterrolebinding.rbac.authorization.k8s.io/stackgres-operator-crd-upgrade created
clusterrolebinding.rbac.authorization.k8s.io/stackgres-operator-init created
job.batch/stackgres-operator-crd-upgrade created
serviceaccount/stackgres-restapi created
job.batch/stackgres-operator-create-certificate created
job.batch/stackgres-operator-bootstrap created
job.batch/stackgres-operator-wait created
secret/stackgres-restapi created
configmap/stackgres-operator-grafana-dashboard created
configmap/stackgres-restapi-nginx created
clusterrole.rbac.authorization.k8s.io/stackgres-operator created
clusterrole.rbac.authorization.k8s.io/stackgres-restapi created
clusterrolebinding.rbac.authorization.k8s.io/stackgres-operator created
Ingressroute for Stackgres operator
Now create a new ingressroute for this new service: ingressroute.stackgres.yml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: stackgres-operator
spec:
entryPoints:
- web
routes:
- match: Host(`stackgres.k3d.local`)
kind: Rule
services:
- name: stackgres-operator
port: 443
Now edit /etc/hosts
again to make the line look that: 127.0.0.1 localhost k3d.local grafana.k3d.local stackgres.k3d.local
Now apply the ingress route yaml: k apply -f ingressroute.stackgres.yml
And wait for everything starts. This may take a while since docker images for this stuff are quite heavy.
kubectl wait -n stackgres deployment -l group=stackgres.io --for=condition=Available
This command will exit only when everything have started.
Deploying the cluster
Time to power-up the Cluster!
Create a stackgresCluster.yml
:
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: PGCluster
spec:
instances: 2
postgres:
version: 'latest'
pods:
persistentVolume:
size: '5Gi'
and apply it with kubectl create -f stackgresCluster.yml
This will take a LONG time. Watch your Lens-Workload-Pods page to control the state.
At least you have the time to have a coffee.
Now check it works:
kubectl exec -ti "$(kubectl get pod --selector app=StackGresCluster,role=master -o name)" -c postgres-util -- psql
Should open psql
shell.
Connecting to a cluster web-interface
Get admin credentials
kubectl get secret -n stackgres stackgres-restapi --template 'username = {{ printf "%s\n" (.data.k8sUsername | base64decode) }}password = {{ printf "%s\n" ( .data.clearPassword | base64decode) }}'
Output:
username = admin
password = LJAo0A8qfGsg4djg8PpmCvsjMyjOlbdjNtfRSTYF
Now run in a separate termianl window:
POD_NAME=$(kubectl get pods --namespace stackgres -l "app=stackgres-restapi" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward "$POD_NAME" 8443:9443 --namespace stackgres
This will run a proxy that will be alive while terminal window is alive.
Now you can open admin panel, login and do some stuff.
Deployment using Helm
helm repo add stackgres-charts https://stackgres.io/downloads/stackgres-k8s/stackgres/helm/
helm repo update
Now deploy the operator
helm install --namespace stackgres stackgres-operator --set-string adminui.service.type=ClusterIP stackgres-charts/stackgres-operator
Output:
_____ _ _ _____
/ ____| | | | / ____|
| (___ | |_ __ _ ___| | _| | __ _ __ ___ ___
\___ \| __/ _` |/ __| |/ / | |_ | '__/ _ \/ __|
____) | || (_| | (__| <| |__| | | | __/\__ \
|_____/ \__\__,_|\___|_|\_\\_____|_| \___||___/
by OnGres, Inc.
Check if the operator was successfully deployed and is available:
kubectl describe deployment -n stackgres stackgres-operator
kubectl wait -n stackgres deployment/stackgres-operator --for condition=Available
Check if the restapi was successfully deployed and is available:
kubectl describe deployment -n stackgres stackgres-restapi
kubectl wait -n stackgres deployment/stackgres-restapi --for condition=Available
To access StackGres Operator UI from localhost, run the below commands:
POD_NAME=$(kubectl get pods --namespace stackgres -l "app=stackgres-restapi" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward "$POD_NAME" 8443:9443 --namespace stackgres
Read more about port forwarding here: http://kubernetes.io/docs/user-guide/kubectl/kubectl_port-forward/
Now you can access the StackGres Operator UI on:
https://localhost:8443
To get the username, run the command:
kubectl get secret -n stackgres stackgres-restapi --template '{{ printf "username = %s\n" (.data.k8sUsername | base64decode) }}'
To get the generated password, run the command:
kubectl get secret -n stackgres stackgres-restapi --template '{{ printf "password = %s\n" (.data.clearPassword | base64decode) }}'
Remember to remove the generated password hint from the secret to avoid security flaws:
kubectl patch secrets --namespace stackgres stackgres-restapi --type json -p '[{"op":"remove","path":"/data/clearPassword"}]'
Ingressroute for Stackgres operator
Now create a new ingressroute for this new service: ingressroute.stackgres.yml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: stackgres-operator
spec:
entryPoints:
- web
routes:
- match: Host(`stackgres.k3d.local`)
kind: Rule
services:
- name: stackgres-operator
port: 443
Now you can go to stackgres.k3d.local and have fun with StackGres web UI.
Previous: Monitoring
Next: Deploy kafka (RedPanda actually) to our k3d cluster