diff --git a/README.md b/README.md index eee4c237..f6dcb5f3 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,10 @@ kubectl apply -f config/samples/coder_v1alpha1_codercontrolplane.yaml kubectl get codercontrolplanes -A ``` +## Examples + +- [`examples/cloudnativepg/`](examples/cloudnativepg/) - Deploy a `CoderControlPlane` with a CloudNativePG-managed PostgreSQL backend. + ## KIND development cluster (for k9s demos) Bootstrap a KIND cluster and install CRDs/RBAC (**this also switches your current kubectl context**): diff --git a/examples/cloudnativepg/00-namespace.yaml b/examples/cloudnativepg/00-namespace.yaml new file mode 100644 index 00000000..67aec19c --- /dev/null +++ b/examples/cloudnativepg/00-namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: coder + labels: + app.kubernetes.io/part-of: coder-k8s-example diff --git a/examples/cloudnativepg/README.md b/examples/cloudnativepg/README.md new file mode 100644 index 00000000..0bc17690 --- /dev/null +++ b/examples/cloudnativepg/README.md @@ -0,0 +1,83 @@ +# CloudNativePG-backed CoderControlPlane example + +This example deploys a `CoderControlPlane` backed by a PostgreSQL cluster managed by [CloudNativePG](https://cloudnative-pg.io/). + +It creates: + +- a `coder` namespace +- a CloudNativePG `Cluster` named `coder-db` +- a `CoderControlPlane` named `coder` wired to the CloudNativePG app Secret (`coder-db-app`) + +## Prerequisites + +- A Kubernetes cluster +- `kubectl` configured for that cluster +- `helm` + +## 1. Install the CloudNativePG operator + +```bash +helm repo add cnpg https://cloudnative-pg.github.io/charts +helm repo update +helm upgrade --install cnpg cnpg/cloudnative-pg \ + --namespace cnpg-system \ + --create-namespace +``` + +## 2. Install the coder-k8s controller + +Follow [Deploy the controller (in-cluster)](../../docs/how-to/deploy-controller.md), or run: + +```bash +kubectl create namespace coder-system +kubectl apply -f config/crd/bases/ +kubectl apply -f deploy/rbac.yaml +kubectl apply -f deploy/controller-deployment.yaml +kubectl rollout status deployment/coder-k8s-controller -n coder-system +``` + +## 3. Deploy this example + +```bash +kubectl apply -f examples/cloudnativepg/ +``` + +The namespace manifest is prefixed (`00-namespace.yaml`) so `kubectl apply -f` creates `coder` before namespaced resources. + +Wait for PostgreSQL and verify the generated Secret: + +```bash +kubectl -n coder wait --for=condition=Ready cluster/coder-db --timeout=10m +kubectl -n coder get secret coder-db-app +``` + +Wait for the `CoderControlPlane` deployment: + +```bash +kubectl -n coder rollout status deployment/coder --timeout=10m +kubectl -n coder get codercontrolplane coder +``` + +## 4. Access Coder + +In one terminal: + +```bash +kubectl -n coder port-forward svc/coder 8080:80 +``` + +Then open: + +- + +Use the setup flow to create the first admin user. + +## Important limitation of this quickstart + +This example sets: + +- `CODER_ACCESS_URL=http://localhost:8080` + +That value is convenient for UI smoke tests through `kubectl port-forward`, but it is not suitable for end-to-end workspace connectivity because in-cluster components cannot reach your local `localhost`. + +For a full setup, expose Coder with an ingress/load balancer and set `CODER_ACCESS_URL` to a real external URL (for example, `https://coder.example.com`). diff --git a/examples/cloudnativepg/cnpg-cluster.yaml b/examples/cloudnativepg/cnpg-cluster.yaml new file mode 100644 index 00000000..6cc119d0 --- /dev/null +++ b/examples/cloudnativepg/cnpg-cluster.yaml @@ -0,0 +1,13 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: coder-db + namespace: coder +spec: + instances: 1 + storage: + size: 5Gi + bootstrap: + initdb: + database: coder + owner: coder diff --git a/examples/cloudnativepg/codercontrolplane.yaml b/examples/cloudnativepg/codercontrolplane.yaml new file mode 100644 index 00000000..2258d090 --- /dev/null +++ b/examples/cloudnativepg/codercontrolplane.yaml @@ -0,0 +1,18 @@ +apiVersion: coder.com/v1alpha1 +kind: CoderControlPlane +metadata: + name: coder + namespace: coder +spec: + replicas: 1 + service: + type: ClusterIP + port: 80 + extraEnv: + - name: CODER_PG_CONNECTION_URL + valueFrom: + secretKeyRef: + name: coder-db-app + key: uri + - name: CODER_ACCESS_URL + value: http://localhost:8080