Skip to content




building homelab cluster part 10


Table of Content

building homelab cluster part 10

I will setup bytebase in this part which enables the GitOps workflow for databases.

  • [x] create a postgres database for bytebase using postgres operator
  • [x] create a secret containing postgres dsn for bytebase to use
  • [x] deploy bytebase on kubernetes cluster using helm
  • [x] setup gateway and httproute for the bytebase GUI access
  • [x] setup gitops integration on bytebase using self-managed gitlab

bytebase

https://github.com/bytebase/bytebase

Bytebase is a Database CI/CD solution for the Developers and DBAs

helm chart

https://github.com/bytebase/bytebase/tree/main/helm-charts/bytebase

As usual, I will get the chart, confirm version, and download the values file.

# add helm repo
helm repo add bytebase-repo https://bytebase.github.io/bytebase

# confirm the version, and it's 1.1.0 as of March 2024
helm search repo -l bytebase
helm show chart bytebase-repo/bytebase

# get the values file
helm show values bytebase-repo/bytebase --version=1.1.0 > bytebase-values.yaml

values file

https://www.bytebase.com/docs/administration/production-setup/

There are few things listed in the production setup guide, and I will ensure they are set in the values file.

  • enable https and websocket
  • configure external URL
  • store metadata in external postgres database

The https access will be ready through the gateway using NGINX Gateway Fabric.

The external URL can be set at bytebase.option.external-url in the values file.

As for the external postgres database, I can pass the URL or DSN using the secret. I of course need the database first, so here we go.

postgres database for bytebase

I will use the postgres operator setup in the previous part.

First of all, the namespace is going to be "bytebase" with gateway access.

./clusters/homelab/namespace/bytebase.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: bytebase
  labels:
    service: bytebase
    type: infrastructure
    gateway-available: yes

Next, I will create a postgres database for bytebase. I will copy-paste the keycloak database manifest and prepare something like this. And do not forget to add this to the infra-config ks.

./infrastructure/homelab/configs/bytebase-db.yaml
---
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: bytebase-db
  namespace: bytebase
spec:
  teamId: "acid"
  volume:
    size: 2Gi
    storageClass: directpv-min-io
  numberOfInstances: 2
  users:
    bb: # database owner
      - superuser
      - createdb
  databases: # {database name}:{database owner}
    bytebase: bb
  postgresql:
    version: "16"
  resources:
    requests:
      cpu: 10m
      memory: 100Mi
    limits:
      cpu: 500m
      memory: 500Mi
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: app.kubernetes.io/part-of
              operator: In
              values:
                - directpv

This will spin up the database and create secret storing credentials for the user "bb". This command will display the password string.

kubectl -n bytebase get secret bb.bytebase-db.credentials.postgresql.acid.zalan.do -o jsonpath='{.data.password}' | base64 -d

https://www.bytebase.com/docs/get-started/install/external-postgres/#pg-connection-string

Now prepare the DSN secret.

postgresql://<>:<>@<>:<>/<>

postgres dsn for bytebase
# on sops repo
cd clusters/homelab
mkdir bytebase
cd bytebase
kubectl create secret generic bytebase-db \
  --from-literal=dsn='postgresql://bb:{PASSWORD_HERE}@bytebase-db/bytebase' \
  -n bytebase \
  --dry-run=client \
  -o yaml > bytebase-db.yaml

sops -i --encrypt bytebase-db.yaml

# git commit and push

deploying bytebase

I will prepare the same usual script to generate flux helmrepo and helmrelease manifest for bytebase.

./infrastructure/homelab/controllers/bytebase.sh
# add flux helmrepo to the manifest
flux create source helm bytebase-repo \
    --url=https://bytebase.github.io/bytebase \
    --interval=1h0m0s \
    --export >bytebase.yaml

# add flux helm release to the manifest including the customized values.yaml file
flux create helmrelease bytebase \
    --interval=10m \
    --target-namespace=bytebase \
    --source=HelmRepository/bytebase-repo \
    --chart=bytebase \
    --chart-version=1.1.0 \
    --values=./bytebase-values.yaml \
    --export >>bytebase.yaml

enable https access through gateway

I will copy-paste the keycloak-routes.yaml created in the previous part, and modify a little bit and prepare something like this as the HTTPRoute for bytebase GUI access.

./infrastructure/homelab/configs/bytebase-routes.yaml
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: bytebase
  namespace: bytebase
spec:
  parentRefs:
    - name: gateway
      sectionName: https-bytebase
      namespace: gateway
  hostnames:
    - "bytebase.blink-1x52.net"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: bytebase-entrypoint
          port: 80

And of course I am going to add the gateway listener named "https-bytebase". The gateway manifest file is fairly long now, so below is just the listener section added.

./infrastructure/homelab/configs/gateway.yaml
- name: https-bytebase
  hostname: bytebase.blink-1x52.net
  port: 443
  protocol: HTTPS
  allowedRoutes:
    namespaces:
      from: Selector
      selector:
        matchLabels:
          gateway-available: yes
  tls:
    mode: Terminate
    certificateRefs:
      - name: tls-bytebase-20240324
        namespace: gateway
        kind: Secret

Add bytebase-routes.yaml to the infra-config ks and all is set. I can access https://bytebase.blink-1x52.net, and it will ask to register the admin account.

database gitops, vcs integration

https://www.bytebase.com/docs/vcs-integration/overview/

I can use bytebase to change database using GitOps methodology, and to do that I need to setup a project and associated database on bytebase to manage through GitOps.

Here is what I am going to do to setup the GitOps on bytebase:

  • create a new namespace "dns-report-cloudflare"
  • create a new repository on my self-managed GitLab to be the VCS of this project
  • create a new postgres database for this namespace for a cronjob to insert record of metric data obtained using Cloudflare API for DNS service
  • register the database on bytebase
  • create a new project for the database on bytebase
  • setup GitOps integration with the GitLab repo for the bytebase project
  • (GitOps DEMO) create a table using bytebase database GitOps
  • prepare necessary credentials for a cloudflare-dns-report script to run as encrypted secret on sops repository
  • prepare CronJob manifest to run the script periodically

create namespace "dns-report-cloudflare"

./clusters/homelab/namespace/dns-report-cloudflare
---
apiVersion: v1
kind: Namespace
metadata:
  name: dns-report-cloudflare
  labels:
    service: dns-report-cloudflare
    type: application

create a new repository "dns-report-cloudflare"

I will create a separate repository to store manifests, and create flux gitrepo and kustomization to watch and reconcile the cluster using the manifests on the repository.

  • [x] create a new blank project on my self-managed GitLab
  • [x] create a read-only deploy token
  • [x] create a secret from the deploy token username and password and place it and encrypt it on SOPS repository
  • [x] place flux gitrepo and kustomization manifest in ./apps/base/dns-report-cloudflare/repo.yaml and include it in ./apps/homelab/kustomization.yaml

deploy token secret

kubectl create secret generic deploy-token-dns-report-cloudflare \
  --from-literal=username="DEPLOY_TOKEN_NAME" \
  --from-literal=password="DEPLOY_TOKEN_PASSWORD" \
  --dry-run=client \
  --namespace=flux-system \
  -o yaml > {./clusters/homelab/flux-system/deploy-token-dns-report-cloudflare.yaml on SOPS repo}

flux gitrepo and kustomization for the new repository

./apps/base/dns-report-cloudflare/repo.yaml
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: dns-report-cloudflare
  namespace: flux-system
spec:
  interval: 1m0s
  ref:
    branch: main
  secretRef:
    name: deploy-token-dns-report-cloudflare
  url: https://cp.blink-1x52.net/network/dns-report-cloudflare.git
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: dns-report-cloudflare
  namespace: flux-system
spec:
  interval: 1m0s
  path: ./deploy/homelab
  prune: true
  sourceRef:
    kind: GitRepository
    name: dns-report-cloudflare
  targetNamespace: dns-report-cloudflare

create database

Add this manifest and include it on infra-config ks. Note that there is no hyphen used in the database name.

./infrastructure/homelab/configs/app-db-dns-report-cloudflare.yaml
---
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: db
  namespace: dns-report-cloudflare
spec:
  teamId: "acid"
  volume:
    size: 5Gi
    storageClass: directpv-min-io
  numberOfInstances: 2
  users:
    dns-report-cloudflare-user:
      - superuser
      - createdb
  databases:
    dnsreportcloudflare: dns-report-cloudflare-user
  postgresql:
    version: "16"
  resources:
    requests:
      cpu: 10m
      memory: 100Mi
    limits:
      cpu: 500m
      memory: 500Mi
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: app.kubernetes.io/part-of
              operator: In
              values:
                - directpv

register the database on bytebase

Navigate to instances and click "add instance" to add the database created.

  • select PostgreSQL as the database type
  • give it an instance name - "dns-report-cloudflare"
  • select environment - "Prod"
  • host or socket - db.dns-report-cloudflare:5432
  • username: dns-report-cloudflare-user
  • password: kubectl -n dns-report-cloudflare get secret dns-report-cloudflare-user.db.credentials.postgresql.acid.zalan.do -o jsonpath='{.data.password}' | base64 -d
  • database - dnsreportcloudflare, note that there is no hyphen when creating the db and the same name goes here
  • ssl and ssh connections - select None

Test the connection and add the instance.

create a bytebase project

Navigate to projects and click "new project" to create a new bytebase project.

  • give it a name - dns-report-cloudflare
  • key - anything
  • mode - standard

add database to the bytebase project

Navigate to Database > Databases menu on left pane and click "transfer in DB" to add the unassigned database just created.

setup gitops workflow

Navigate to Integration > GitOps to start GitOps workflow configuration.

  • url - https://cp.blink-1x52.net
  • display name - anything
  • follow the guide to fill the rest ... https://www.bytebase.com/docs/vcs-integration/self-host-gitlab/
    • create a new app on self-managed gitlab as admin
    • set the app id and secret provided by gitlab on bytebase
    • confirm and add

Once the GitOps integration is configured, go to the project > Integration > GitOps menu again to select the configured GitOps integration to choose the repository and branch to use to manage the bytebase project (and its database).

  • select repository - the new gitlab repo created for this
  • branch - main by default
  • base directory - bytebase by default
  • schema change type - imperative, DDL, by default
  • file path template - {{ENV_ID}}/{{DB_NAME}}##{{VERSION}}##{{TYPE}}##{{DESCRIPTION}}.sql by default

add DDL SQL to create a table

Add this file on "dns-report-cloudflare" repository and bytebase will pick this up, create an issue, apply necessary changes to the database, and resolve/close the issue on the project.

./bytebase/prod/dnsreportcloudflare##2024032701##ddl##create-dnstable.sql
CREATE TABLE dnsreport (
  hashed_id TEXT PRIMARY KEY,
  time TIMESTAMP WITH TIME ZONE,  -- iso8601, 2000-01-23T01:23:45Z
  dname TEXT,
  metric INTEGER
);