diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a323c4 --- /dev/null +++ b/README.md @@ -0,0 +1,261 @@ +# Backstage Helm Chart + +Helm chart for deploying the Backstage Developer Portal for the OnlineSales ephemeral testing platform. + +## Overview + +This chart deploys Backstage with: +- Cloud SQL PostgreSQL database (via Cloud SQL Proxy) +- External Secrets Operator integration for GCP Secret Manager +- Ingress configuration for external access +- ServiceAccount with Workload Identity for GCP integration + +## Prerequisites + +- Kubernetes cluster 1.25+ +- Helm 3.0+ +- [External Secrets Operator](https://external-secrets.io/) installed +- Cloud SQL PostgreSQL instance provisioned +- GCP Service Account for Workload Identity +- ClusterSecretStore configured (see below) + +## Installation + +### Quick Install + +```bash +helm install backstage ./backstage-chart \ + --namespace backstage \ + --create-namespace \ + -f values.yaml +``` + +### With Custom Values + +```bash +helm install backstage ./backstage-chart \ + --namespace backstage \ + --create-namespace \ + --set image.tag=latest \ + --set ingress.hosts[0].host=backstage.example.com +``` + +## Configuration + +### Key Values + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `image.repository` | Backstage image repository | `gcr.io/prj-onlinesales-test-framework/backstage` | +| `image.tag` | Backstage image tag | `latest` | +| `replicaCount` | Number of replicas | `1` | +| `serviceAccount.name` | ServiceAccount name | `backstage` | +| `serviceAccount.annotations` | SA annotations (Workload Identity) | `{}` | +| `ingress.enabled` | Enable ingress | `true` | +| `ingress.hosts` | Ingress hostnames | `[]` | +| `externalSecrets.enabled` | Enable External Secrets | `true` | +| `externalSecrets.secretStore` | SecretStore reference | `gcp-secret-store` | +| `cloudSqlProxy.enabled` | Enable Cloud SQL Proxy sidecar | `true` | +| `cloudSqlProxy.instanceConnectionName` | Cloud SQL connection string | `""` | + +### External Secrets Configuration + +The chart uses External Secrets Operator to sync secrets from GCP Secret Manager: + +```yaml +externalSecrets: + enabled: true + secretStore: gcp-secret-store # ClusterSecretStore name + refreshInterval: 1h + secrets: + # Backstage database credentials + POSTGRES_HOST: backstage-db/host + POSTGRES_PORT: backstage-db/port + POSTGRES_USER: backstage-db/username + POSTGRES_PASSWORD: backstage-db/password + # Integration credentials + GITEA_URL: backstage-secrets/GITEA_URL + GITEA_USERNAME: backstage-secrets/GITEA_USERNAME + GITEA_PASSWORD: backstage-secrets/GITEA_PASSWORD + ARGOCD_AUTH_TOKEN: backstage-secrets/ARGOCD_AUTH_TOKEN + ARGO_WORKFLOWS_TOKEN: backstage-secrets/ARGO_WORKFLOWS_TOKEN +``` + +### Cloud SQL Proxy Setup + +The chart deploys Cloud SQL Proxy as a sidecar: + +```yaml +cloudSqlProxy: + enabled: true + image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8.0 + instanceConnectionName: "project:region:instance" + port: 5432 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi +``` + +**Workload Identity Setup:** +```bash +# Create GCP service account +gcloud iam service-accounts create backstage-sa \ + --display-name="Backstage Service Account" + +# Grant Cloud SQL Client role +gcloud projects add-iam-policy-binding $PROJECT_ID \ + --member="serviceAccount:backstage-sa@$PROJECT_ID.iam.gserviceaccount.com" \ + --role="roles/cloudsql.client" + +# Configure Workload Identity +gcloud iam service-accounts add-iam-policy-binding \ + backstage-sa@$PROJECT_ID.iam.gserviceaccount.com \ + --role="roles/iam.workloadIdentityUser" \ + --member="serviceAccount:$PROJECT_ID.svc.id.goog[backstage/backstage]" + +# Annotate Kubernetes SA +kubectl annotate serviceaccount backstage \ + --namespace backstage \ + iam.gke.io/gcp-service-account=backstage-sa@$PROJECT_ID.iam.gserviceaccount.com +``` + +## Database Setup + +1. **Create Cloud SQL Instance:** + ```bash + gcloud sql instances create backstage-db \ + --database-version=POSTGRES_14 \ + --tier=db-f1-micro \ + --region=$REGION \ + --root-password=$ROOT_PASSWORD + ``` + +2. **Create Database:** + ```bash + gcloud sql databases create backstage --instance=backstage-db + ``` + +3. **Create User:** + ```bash + gcloud sql users create backstage_user \ + --instance=backstage-db \ + --password=$USER_PASSWORD + ``` + +4. **Store Credentials in Secret Manager:** + ```bash + echo -n "backstage_user" | gcloud secrets create backstage-db-username --data-file=- + echo -n "$USER_PASSWORD" | gcloud secrets create backstage-db-password --data-file=- + ``` + +## RBAC Setup + +Backstage requires cluster-wide permissions for environment provisioning: + +```bash +kubectl apply -f - < -c backstage -- \ + psql -h localhost -U backstage_user -d backstage -c "SELECT 1" +``` + +### Database migration issues + +```bash +# Check Backstage logs for migration errors +kubectl logs -n backstage -l app.kubernetes.io/name=backstage | grep -i migration +``` + +## Upgrading + +```bash +helm upgrade backstage ./backstage-chart \ + --namespace backstage \ + -f values.yaml +``` + +## Uninstalling + +```bash +helm uninstall backstage --namespace backstage +kubectl delete namespace backstage +``` + +## Related Documentation + +- [GCP Deployment Guide](../GCP-DEPLOYMENT-GUIDE.md) +- [Backstage App README](../backstage-app/README.md) +- [External Secrets Operator](https://external-secrets.io/) +- [Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) + +## License + +Proprietary - OnlineSales.ai diff --git a/values.yaml b/values.yaml index 10ec069..d085bf6 100644 --- a/values.yaml +++ b/values.yaml @@ -6,7 +6,7 @@ namespaceOverride: "backstage" # Backstage application image image: repository: gcr.io/prj-onlinesales-test-framework/backstage - tag: "main-05ae5e2" + tag: "main-1cdfa76" pullPolicy: IfNotPresent # Replica count