III: Building kubernetes home lab with k3d — Service mesh and Postgres

02.02.2021 - AYB - Reading time ~5 Minutes

K3D Logo

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

Source

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