Some time ago I’ve written a small blog about how to get openSUSE Leap Micro 6 up and running. As one of the use cases for this distributions is to run container workloads, the next natural step is to deploy a containerized workload. As I am mostly interested in PostgreSQL and it becomes more and more popular to run PostgreSQL in Kubernetes, I’ll use minicube to easily get a local Kubernetes cluster and CloudNativePG to get an operator for managing PostgreSQL.

If you want to replay that, just follow the initial post linked above, which gives you this:

micro-minicube:~ $ cat /etc/os-release
NAME="openSUSE Leap Micro"
VERSION="6.0"
ID="opensuse-leap-micro"
ID_LIKE="suse opensuse opensuse-leap suse-microos"
VERSION_ID="6.0"
PRETTY_NAME="openSUSE Leap Micro 6.0"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:opensuse:leap-micro:6.0"
BUG_REPORT_URL="https://bugs.opensuse.org"
HOME_URL="https://www.opensuse.org/"
DOCUMENTATION_URL="https://en.opensuse.org/Portal:LeapMicro"
LOGO="distributor-logo-LeapMicro"

From there you need to install minicube, which is really, really easy to do. As minicube should not run under “root”, create a dedicated user for it and configure sudo:

micro-minicube:~ $ groupadd minicube
micro-minicube:~ $ useradd -g minicube -m -s /bin/bash minicube
micro-minicube:~ $ echo "minicube ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/minicube
micro-minicube:~ $ su - minicube
minicube@micro-minicube:~> sudo ls
bin
minicube@micro-minicube:~>

Once you have that, it is time to install minicube:

minicube@micro-minicube:~> curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 91.1M  100 91.1M    0     0  14.2M      0  0:00:06  0:00:06 --:--:-- 17.1M

minicube@micro-minicube:~> sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64
minicube@micro-minicube:~> ls -l /usr/local/bin/minikube
-rwxr-xr-x. 1 root root 95595640 Jun  6 09:07 /usr/local/bin/minikube

That’s it. Start it up:

minicube@micro-minicube:~> minikube start
😄  minikube v1.33.1 on Opensuse-Leap-Micro 6.0 (kvm/amd64)
✨  Automatically selected the podman driver

🧯  The requested memory allocation of 1972MiB does not leave room for system overhead (total system memory: 1972MiB). You may face stability issues.
💡  Suggestion: Start minikube with less memory allocated: 'minikube start --memory=1972mb'

📌  Using Podman driver with root privileges
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.44 ...
💾  Downloading Kubernetes v1.30.0 preload ...
    > preloaded-images-k8s-v18-v1...:  342.90 MiB / 342.90 MiB  100.00% 11.58 M
    > gcr.io/k8s-minikube/kicbase...:  481.58 MiB / 481.58 MiB  100.00% 8.70 Mi
E0606 09:09:02.427139    3928 cache.go:189] Error downloading kic artifacts:  not yet implemented, see issue #8426
🔥  Creating podman container (CPUs=2, Memory=1972MB) ...
🐳  Preparing Kubernetes v1.30.0 on Docker 26.1.1 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔗  Configuring bridge CNI (Container Networking Interface) ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
💡  kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

… install kubctl or use the one from minicube (what I am doing here). I’ll also define an alias (this is from the offical minicube documentation linked above) to save some typing:


minicube@micro-minicube:~> minikube kubectl -- get po -A
    > kubectl.sha256:  64 B / 64 B [-------------------------] 100.00% ? p/s 0s
    > kubectl:  49.07 MiB / 49.07 MiB [-------------] 100.00% 7.37 MiB p/s 6.9s
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-7db6d8ff4d-bwr6n           1/1     Running   0          3m43s
kube-system   etcd-minikube                      1/1     Running   0          3m57s
kube-system   kube-apiserver-minikube            1/1     Running   0          3m57s
kube-system   kube-controller-manager-minikube   1/1     Running   0          3m57s
kube-system   kube-proxy-wl74w                   1/1     Running   0          3m44s
kube-system   kube-scheduler-minikube            1/1     Running   0          3m57s
kube-system   storage-provisioner                1/1     Running   0          3m56s
minicube@micro-minicube:~> echo "alias kubectl=\"minikube kubectl --\"" >> ~/.bashrc
minicube@micro-minicube:~> . .bashrc
minicube@micro-minicube:~> kubectl get po -A
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-7db6d8ff4d-bwr6n           1/1     Running   0          5m
kube-system   etcd-minikube                      1/1     Running   0          5m14s
kube-system   kube-apiserver-minikube            1/1     Running   0          5m14s
kube-system   kube-controller-manager-minikube   1/1     Running   0          5m14s
kube-system   kube-proxy-wl74w                   1/1     Running   0          5m1s
kube-system   kube-scheduler-minikube            1/1     Running   0          5m14s
kube-system   storage-provisioner                1/1     Running   0          5m13s

As the local Kubernetes is now up and running, CloudNativePG can be deployed on it (check for the most recent version, before you do this):

minicube@micro-minicube:~> kubectl apply --server-side -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.23/releases/cnpg-1.23.1.yaml
namespace/cnpg-system serverside-applied
customresourcedefinition.apiextensions.k8s.io/backups.postgresql.cnpg.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/clusterimagecatalogs.postgresql.cnpg.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/clusters.postgresql.cnpg.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/imagecatalogs.postgresql.cnpg.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/poolers.postgresql.cnpg.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/scheduledbackups.postgresql.cnpg.io serverside-applied
serviceaccount/cnpg-manager serverside-applied
clusterrole.rbac.authorization.k8s.io/cnpg-manager serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/cnpg-manager-rolebinding serverside-applied
configmap/cnpg-default-monitoring serverside-applied
service/cnpg-webhook-service serverside-applied
deployment.apps/cnpg-controller-manager serverside-applied
mutatingwebhookconfiguration.admissionregistration.k8s.io/cnpg-mutating-webhook-configuration serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/cnpg-validating-webhook-configuration serverside-applied
minicube@micro-minicube:~> kubectl get deployment -n cnpg-system cnpg-controller-manager
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
cnpg-controller-manager   1/1     1            1           30s

Before you can deploy PostgreSQL, you’ll need to describe your desired cluster. A very minimal definition is this (this comes from the official documentation as well):

minicube@micro-minicube:~> cat pg.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3

  storage:
    size: 1Gi

Deploy (or apply) it:

minicube@micro-minicube:~> kubectl apply -f pg.yaml
cluster.postgresql.cnpg.io/cluster-example created

… and monitor the creation of the pods until the cluster is finally ready:

minicube@micro-minicube:~> kubectl get pods
NAME                             READY   STATUS            RESTARTS   AGE
cluster-example-1-initdb-wtl27   0/1     PodInitializing   0          20s
minicube@micro-minicube:~> kubectl get pods
NAME                             READY   STATUS      RESTARTS   AGE
cluster-example-1                0/1     Running     0          5s
cluster-example-1-initdb-wtl27   0/1     Completed   0          30s
minicube@micro-minicube:~> kubectl get pods
NAME                             READY   STATUS      RESTARTS   AGE
cluster-example-1                1/1     Running     0          12s
cluster-example-1-initdb-wtl27   0/1     Completed   0          37s
cluster-example-2-join-92rqp     0/1     Pending     0          1s
minicube@micro-minicube:~> kubectl get pods
NAME                             READY   STATUS      RESTARTS   AGE
cluster-example-1                1/1     Running     0          22s
cluster-example-1-initdb-wtl27   0/1     Completed   0          47s
cluster-example-2                0/1     Running     0          3s
cluster-example-2-join-92rqp     0/1     Completed   0          11s
minicube@micro-minicube:~> kubectl get pods
NAME                             READY   STATUS      RESTARTS   AGE
cluster-example-1                1/1     Running     0          33s
cluster-example-1-initdb-wtl27   0/1     Completed   0          58s
cluster-example-2                1/1     Running     0          14s
cluster-example-2-join-92rqp     0/1     Completed   0          22s
cluster-example-3-join-rx8g6     0/1     Init:0/1    0          3s
minicube@micro-minicube:~> kubectl get pods
NAME                             READY   STATUS      RESTARTS   AGE
cluster-example-1                1/1     Running     0          46s
cluster-example-1-initdb-wtl27   0/1     Completed   0          71s
cluster-example-2                1/1     Running     0          27s
cluster-example-2-join-92rqp     0/1     Completed   0          35s
cluster-example-3                0/1     Running     0          9s
cluster-example-3-join-rx8g6     0/1     Completed   0          16s
minicube@micro-minicube:~> kubectl get pods
NAME                READY   STATUS    RESTARTS   AGE
cluster-example-1   1/1     Running   0          62s
cluster-example-2   1/1     Running   0          43s
cluster-example-3   1/1     Running   0          25s

All the nodes (as described in the yaml definition above) are up and running, which you also may verify by looking at the services:

minicube@micro-minicube:~> kubectl get services
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
cluster-example-r    ClusterIP   10.96.171.131    <none>        5432/TCP   3m41s
cluster-example-ro   ClusterIP   10.106.134.232   <none>        5432/TCP   3m41s
cluster-example-rw   ClusterIP   10.108.169.108   <none>        5432/TCP   3m41s
kubernetes           ClusterIP   10.96.0.1        <none>        443/TCP    21m

Happy testing.