源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,565 @@
|
||||
# Deploy OpenWork EE on Google Cloud with GKE and Helm
|
||||
|
||||
Status: self-host operator guide
|
||||
Related: `packaging/helm/openwork-ee`, `packaging/helm/openwork-ee/examples/values.gcp-ingress.yaml`
|
||||
|
||||
This is the recommended Google Cloud path for a first production-like OpenWork
|
||||
EE self-host install. Use Helm on GKE Autopilot with Cloud SQL for MySQL. For
|
||||
web/API exposure, use GKE Ingress with Google-managed certificates, a reserved
|
||||
global IP address, and explicit backend health checks.
|
||||
|
||||
Google recommends Gateway API for new L7 traffic management, and GKE Ingress is
|
||||
in maintenance mode. The current OpenWork chart emits Ingress resources, so GKE
|
||||
Ingress is the simplest supported GCP path today. Treat Gateway API support as a
|
||||
future chart/platform hardening item.
|
||||
|
||||
Do not use raw Kubernetes `LoadBalancer` Services as the normal GCP path for
|
||||
OpenWork. GKE `LoadBalancer` Services are useful for TCP services and quick
|
||||
smoke tests, but the customer-facing web app and SSO flow need HTTP(S) load
|
||||
balancing, host routing, managed certificates, and backend health checks.
|
||||
|
||||
## What this deploys
|
||||
|
||||
- Den API on port `8788`
|
||||
- Den Web on port `3005`
|
||||
- optional inference service, disabled by default
|
||||
- one Cloud SQL for MySQL database
|
||||
- one single-org OpenWork deployment
|
||||
- one external GKE Ingress backed by a Google Cloud Application Load Balancer
|
||||
- one Google-managed certificate covering web and API hosts
|
||||
|
||||
Google Cloud owns the GKE cluster, Autopilot compute lifecycle, VPC networking,
|
||||
Cloud Load Balancing, managed certificates, Cloud SQL, IAM, and firewall rules.
|
||||
The OpenWork Helm chart owns OpenWork Deployments, Services, ConfigMaps,
|
||||
Secrets, health probes, the optional Ingress, and the database migration Job.
|
||||
The `BackendConfig` and `ManagedCertificate` resources in this guide are
|
||||
GKE-specific platform resources applied alongside the chart.
|
||||
|
||||
## Use Helm or something else?
|
||||
|
||||
Use Helm on GKE for Google Cloud unless the customer explicitly cannot run
|
||||
Kubernetes. The OpenWork EE release artifact is already a Helm chart, and GKE
|
||||
Autopilot keeps the first customer path small while still supporting migration
|
||||
Jobs, separate web/API services, SSO-ready HTTPS, and later enterprise network
|
||||
controls. The practical gap to fill is GCP-specific ingress and database
|
||||
guidance, not a different OpenWork packaging format.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Google Cloud CLI authenticated to the target project.
|
||||
- `kubectl`, `helm`, and `gke-gcloud-auth-plugin`.
|
||||
- Permission to create GKE, Compute Engine networking and global addresses,
|
||||
Cloud SQL, Service Networking, DNS, IAM, and Kubernetes resources.
|
||||
- Enabled APIs: Kubernetes Engine API, Compute Engine API, Cloud SQL Admin API,
|
||||
and Service Networking API.
|
||||
- A real admin email address for the first owner account.
|
||||
- A domain you control, such as `openwork.example.com` and
|
||||
`api.openwork.example.com`.
|
||||
|
||||
Google Cloud docs used for this guide:
|
||||
|
||||
- GKE Autopilot clusters: https://cloud.google.com/kubernetes-engine/docs/how-to/creating-an-autopilot-cluster
|
||||
- GKE Ingress for Application Load Balancers: https://cloud.google.com/kubernetes-engine/docs/concepts/ingress
|
||||
- GKE external Ingress and NEGs: https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing
|
||||
- GKE managed certificates: https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs
|
||||
- GKE Ingress configuration and BackendConfig: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-configuration
|
||||
- GKE Ingress health checks: https://cloud.google.com/kubernetes-engine/docs/troubleshooting/ingress-health-checks
|
||||
- Cloud SQL private IP: https://cloud.google.com/sql/docs/mysql/private-ip
|
||||
- Cloud SQL from GKE: https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine
|
||||
|
||||
## 1. Create the GKE cluster
|
||||
|
||||
For a first deployment, create a regional Autopilot cluster:
|
||||
|
||||
```bash
|
||||
export GCP_PROJECT=REPLACE_PROJECT_ID
|
||||
export GCP_REGION=us-central1
|
||||
export GKE_CLUSTER=openwork-ee
|
||||
|
||||
gcloud config set project "$GCP_PROJECT"
|
||||
|
||||
gcloud services enable \
|
||||
container.googleapis.com \
|
||||
compute.googleapis.com \
|
||||
sqladmin.googleapis.com \
|
||||
servicenetworking.googleapis.com
|
||||
|
||||
gcloud container clusters create-auto "$GKE_CLUSTER" \
|
||||
--location "$GCP_REGION" \
|
||||
--project "$GCP_PROJECT"
|
||||
|
||||
# If the cluster command reports that the auth plugin is missing:
|
||||
gcloud components install gke-gcloud-auth-plugin --quiet
|
||||
|
||||
gcloud container clusters get-credentials "$GKE_CLUSTER" \
|
||||
--location "$GCP_REGION" \
|
||||
--project "$GCP_PROJECT"
|
||||
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
GKE enables HTTP load balancing by default. Do not disable it; GKE Ingress needs
|
||||
that add-on.
|
||||
|
||||
Some standalone Google Cloud SDK installations do not include
|
||||
`gke-gcloud-auth-plugin`. If `kubectl` cannot authenticate after cluster
|
||||
creation, install the component as shown above, rerun `get-credentials`, and
|
||||
verify with `kubectl get nodes` before debugging Kubernetes resources.
|
||||
|
||||
## 2. Create Cloud SQL for MySQL
|
||||
|
||||
Create Cloud SQL for MySQL with private IP in the same VPC as the GKE cluster.
|
||||
The most important requirements are:
|
||||
|
||||
- MySQL 8-compatible Cloud SQL instance.
|
||||
- Database name: `openwork_den`.
|
||||
- Private services access configured for the VPC.
|
||||
- Private IP enabled on the Cloud SQL instance.
|
||||
- GKE is VPC-native and can reach the private IP.
|
||||
- Backups enabled.
|
||||
- Public IP disabled for production unless there is a documented exception.
|
||||
|
||||
Private IP requires a one-time private services access connection for the VPC:
|
||||
|
||||
```bash
|
||||
export VPC_NETWORK=default
|
||||
export SQL_RANGE=openwork-sql-range
|
||||
|
||||
gcloud compute addresses create "$SQL_RANGE" \
|
||||
--global \
|
||||
--purpose=VPC_PEERING \
|
||||
--prefix-length=16 \
|
||||
--network="$VPC_NETWORK"
|
||||
|
||||
gcloud services vpc-peerings connect \
|
||||
--service=servicenetworking.googleapis.com \
|
||||
--ranges="$SQL_RANGE" \
|
||||
--network="$VPC_NETWORK"
|
||||
```
|
||||
|
||||
Create the instance and database:
|
||||
|
||||
```bash
|
||||
export SQL_INSTANCE=openwork-ee-mysql
|
||||
|
||||
gcloud sql instances create "$SQL_INSTANCE" \
|
||||
--database-version=MYSQL_8_0 \
|
||||
--region="$GCP_REGION" \
|
||||
--network="projects/$GCP_PROJECT/global/networks/$VPC_NETWORK" \
|
||||
--no-assign-ip
|
||||
|
||||
gcloud sql databases create openwork_den \
|
||||
--instance="$SQL_INSTANCE"
|
||||
|
||||
gcloud sql users create openwork \
|
||||
--instance="$SQL_INSTANCE" \
|
||||
--password=REPLACE_DB_PASSWORD
|
||||
```
|
||||
|
||||
Get the private IP:
|
||||
|
||||
```bash
|
||||
gcloud sql instances describe "$SQL_INSTANCE" \
|
||||
--format='value(ipAddresses[0].ipAddress)'
|
||||
```
|
||||
|
||||
Example database URL:
|
||||
|
||||
```text
|
||||
mysql://openwork:<password>@<cloud-sql-private-ip>:3306/openwork_den
|
||||
```
|
||||
|
||||
This guide uses direct private IP because the current OpenWork chart does not
|
||||
inject Cloud SQL Auth Proxy sidecars. Cloud SQL Auth Proxy is a stronger future
|
||||
hardening path when the chart supports sidecars or an operator-managed proxy
|
||||
pattern.
|
||||
|
||||
If the Cloud SQL instance enforces encrypted client connections, use
|
||||
`?sslaccept=accept` for the simple private-MySQL smoke path. This keeps TLS on
|
||||
without requiring a cloud CA bundle to be mounted into the OpenWork image. Use
|
||||
strict certificate verification later, after you provide the required CA bundle,
|
||||
with a hardened value such as `sslmode=verify-ca` or `sslmode=verify-full`.
|
||||
Verify the same URL works for both the migration Job and runtime pods before
|
||||
testing the browser flow.
|
||||
|
||||
Before installing OpenWork, verify network access from the cluster:
|
||||
|
||||
```bash
|
||||
kubectl run mysql-client \
|
||||
--rm \
|
||||
-it \
|
||||
--restart=Never \
|
||||
--image=mysql:8 \
|
||||
-- mysql \
|
||||
--host="REPLACE_CLOUD_SQL_PRIVATE_IP" \
|
||||
--user=openwork \
|
||||
--password \
|
||||
--execute "select 1"
|
||||
```
|
||||
|
||||
## 3. Reserve a global IP and create GKE resources
|
||||
|
||||
Reserve a global IP address for the HTTPS load balancer:
|
||||
|
||||
```bash
|
||||
gcloud compute addresses create openwork-ee-ip \
|
||||
--global
|
||||
|
||||
gcloud compute addresses describe openwork-ee-ip \
|
||||
--global \
|
||||
--format='value(address)'
|
||||
```
|
||||
|
||||
Create the namespace:
|
||||
|
||||
```bash
|
||||
kubectl create namespace openwork-ee
|
||||
```
|
||||
|
||||
Create a Google-managed certificate resource:
|
||||
|
||||
```bash
|
||||
kubectl apply -n openwork-ee -f - <<'YAML'
|
||||
apiVersion: networking.gke.io/v1
|
||||
kind: ManagedCertificate
|
||||
metadata:
|
||||
name: openwork-ee-cert
|
||||
spec:
|
||||
domains:
|
||||
- REPLACE_WEB_HOST
|
||||
- REPLACE_API_HOST
|
||||
YAML
|
||||
```
|
||||
|
||||
Create explicit backend health checks for the two OpenWork services:
|
||||
|
||||
```bash
|
||||
kubectl apply -n openwork-ee -f - <<'YAML'
|
||||
apiVersion: cloud.google.com/v1
|
||||
kind: BackendConfig
|
||||
metadata:
|
||||
name: openwork-ee-den-api-backend
|
||||
spec:
|
||||
healthCheck:
|
||||
type: HTTP
|
||||
requestPath: /ready
|
||||
port: 8788
|
||||
checkIntervalSec: 15
|
||||
timeoutSec: 5
|
||||
---
|
||||
apiVersion: cloud.google.com/v1
|
||||
kind: BackendConfig
|
||||
metadata:
|
||||
name: openwork-ee-den-web-backend
|
||||
spec:
|
||||
healthCheck:
|
||||
type: HTTP
|
||||
requestPath: /api/ready
|
||||
port: 3005
|
||||
checkIntervalSec: 15
|
||||
timeoutSec: 5
|
||||
YAML
|
||||
```
|
||||
|
||||
The Helm values annotate the OpenWork Services so GKE associates these
|
||||
`BackendConfig` objects with the Google Cloud backend services.
|
||||
|
||||
## 4. Prepare Helm values
|
||||
|
||||
Copy the starter file:
|
||||
|
||||
```bash
|
||||
cp packaging/helm/openwork-ee/examples/values.gcp-ingress.yaml values.gcp.yaml
|
||||
```
|
||||
|
||||
Replace every `REPLACE_*` placeholder.
|
||||
|
||||
Generate secrets:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 48
|
||||
openssl rand -base64 48
|
||||
```
|
||||
|
||||
Use the first value for `secret.values.betterAuthSecret` and the second for
|
||||
`secret.values.denDbEncryptionKey`. Do not reuse either value across
|
||||
environments.
|
||||
|
||||
To send transactional email, configure SMTP in the same values file:
|
||||
|
||||
```yaml
|
||||
secret:
|
||||
values:
|
||||
emailFrom: "OpenWork <no-reply@example.com>"
|
||||
smtpHost: "smtp.example.com"
|
||||
smtpPort: "587"
|
||||
smtpUser: "openwork@example.com"
|
||||
smtpPass: "REPLACE_SMTP_PASSWORD"
|
||||
smtpSecure: "false"
|
||||
```
|
||||
|
||||
These values become `EMAIL_FROM`, `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`,
|
||||
`SMTP_PASS`, and `SMTP_SECURE` in Den API. If you use `secret.create=false`,
|
||||
add those keys to the existing Kubernetes Secret referenced by
|
||||
`secret.existingSecret`. SMTP delivery requires both `EMAIL_FROM` and
|
||||
`SMTP_HOST`; leave `smtpHost` blank only when SMTP-backed transactional email
|
||||
should be disabled.
|
||||
|
||||
Use a values file, not a long list of `--set` flags. Several OpenWork values are
|
||||
comma-separated strings, such as `config.public.corsOrigins`, and plain `--set`
|
||||
parsing commonly breaks them.
|
||||
|
||||
Make sure your file uses the current chart keys. Public URL values belong under
|
||||
`config.public.*`; database and app secrets belong under `secret.values.*`.
|
||||
Values such as `config.urls`, `config.databaseUrl`, or `secrets.*` are ignored
|
||||
by the chart.
|
||||
|
||||
Before installing, render the chart and verify the migration Job will use your
|
||||
Cloud SQL URL:
|
||||
|
||||
```bash
|
||||
helm template openwork-ee oci://ghcr.io/different-ai/charts/openwork-ee \
|
||||
--version REPLACE_OPENWORK_VERSION \
|
||||
--namespace openwork-ee \
|
||||
-f values.gcp.yaml > /tmp/openwork-rendered.yaml
|
||||
|
||||
grep -E 'DATABASE_URL|DEN_BASE_URL|DEN_WEB_PUBLIC_ORIGIN|EMAIL_FROM|SMTP_HOST|SMTP_PORT|SMTP_SECURE' /tmp/openwork-rendered.yaml
|
||||
```
|
||||
|
||||
Redact secrets before sharing rendered manifests or terminal output.
|
||||
|
||||
## 5. Install OpenWork
|
||||
|
||||
Published chart releases live in GHCR:
|
||||
|
||||
```bash
|
||||
helm upgrade --install openwork-ee oci://ghcr.io/different-ai/charts/openwork-ee \
|
||||
--version REPLACE_OPENWORK_VERSION \
|
||||
--namespace openwork-ee \
|
||||
--create-namespace \
|
||||
-f values.gcp.yaml
|
||||
```
|
||||
|
||||
For a checkout-local test:
|
||||
|
||||
```bash
|
||||
helm upgrade --install openwork-ee ./packaging/helm/openwork-ee \
|
||||
--namespace openwork-ee \
|
||||
--create-namespace \
|
||||
-f values.gcp.yaml
|
||||
```
|
||||
|
||||
If GHCR image pulls fail with `ImagePullBackOff`, authenticate to GHCR and add
|
||||
an `imagePullSecrets` entry. Public releases should not require this, but
|
||||
private packages or private forks do:
|
||||
|
||||
```bash
|
||||
kubectl create secret docker-registry ghcr-pull-secret \
|
||||
--namespace openwork-ee \
|
||||
--docker-server=ghcr.io \
|
||||
--docker-username="$GITHUB_USER" \
|
||||
--docker-password="$GITHUB_TOKEN"
|
||||
```
|
||||
|
||||
```yaml
|
||||
imagePullSecrets:
|
||||
- name: ghcr-pull-secret
|
||||
```
|
||||
|
||||
## 6. Migration troubleshooting
|
||||
|
||||
The migration Job runs before the Deployments are useful. If it fails, fix that
|
||||
before debugging web/API readiness.
|
||||
|
||||
Avoid `kubectl describe job openwork-ee-migrate` in shared reports because the
|
||||
hook Job currently includes `DATABASE_URL` and `DEN_DB_ENCRYPTION_KEY` in the
|
||||
rendered environment. Use logs and redacted rendered manifests instead.
|
||||
|
||||
For a retained-log debug attempt, temporarily disable hook behavior:
|
||||
|
||||
```yaml
|
||||
migrations:
|
||||
enabled: true
|
||||
hook: false
|
||||
backoffLimit: 0
|
||||
```
|
||||
|
||||
Then run Helm and inspect the normal Job logs:
|
||||
|
||||
```bash
|
||||
helm upgrade --install openwork-ee oci://ghcr.io/different-ai/charts/openwork-ee \
|
||||
--version REPLACE_OPENWORK_VERSION \
|
||||
--namespace openwork-ee \
|
||||
--create-namespace \
|
||||
-f values.gcp.yaml \
|
||||
--wait=false
|
||||
|
||||
kubectl get jobs,pods -n openwork-ee
|
||||
kubectl logs -n openwork-ee -l job-name=openwork-ee-migrate --all-containers=true
|
||||
```
|
||||
|
||||
Return to the default hook mode after debugging:
|
||||
|
||||
```yaml
|
||||
migrations:
|
||||
enabled: true
|
||||
hook: true
|
||||
backoffLimit: 2
|
||||
```
|
||||
|
||||
## 7. Point DNS at the global load balancer IP
|
||||
|
||||
Get the reserved IP address:
|
||||
|
||||
```bash
|
||||
gcloud compute addresses describe openwork-ee-ip \
|
||||
--global \
|
||||
--format='value(address)'
|
||||
```
|
||||
|
||||
Create DNS records:
|
||||
|
||||
- `openwork.example.com` -> the reserved global IP address.
|
||||
- `api.openwork.example.com` -> the reserved global IP address.
|
||||
|
||||
GKE can take several minutes to provision the load balancer. Google-managed
|
||||
certificates can take up to an hour to become active after DNS points at the
|
||||
load balancer.
|
||||
|
||||
Check status:
|
||||
|
||||
```bash
|
||||
kubectl get ingress -n openwork-ee
|
||||
kubectl describe managedcertificate openwork-ee-cert -n openwork-ee
|
||||
kubectl describe ingress openwork-ee -n openwork-ee
|
||||
```
|
||||
|
||||
If you are still using temporary hosts before DNS/TLS is ready, temporarily
|
||||
update the corresponding `config.public.*` origins in `values.gcp.yaml`, then
|
||||
run `helm upgrade` again. Do not leave production deployments on raw IPs or
|
||||
placeholder hostnames.
|
||||
|
||||
The current chart rolls the Den API, Den Web, and inference pods automatically
|
||||
when ConfigMap or Secret content changes. On older chart versions, manually
|
||||
restart the deployments after changing public origin values:
|
||||
|
||||
```bash
|
||||
kubectl rollout restart deployment/openwork-ee-den-api deployment/openwork-ee-den-web -n openwork-ee
|
||||
kubectl rollout status deployment/openwork-ee-den-api -n openwork-ee --timeout=180s
|
||||
kubectl rollout status deployment/openwork-ee-den-web -n openwork-ee --timeout=180s
|
||||
```
|
||||
|
||||
## 8. Verify readiness
|
||||
|
||||
Check Kubernetes state:
|
||||
|
||||
```bash
|
||||
helm status openwork-ee -n openwork-ee
|
||||
kubectl get pods -n openwork-ee
|
||||
kubectl get jobs -n openwork-ee
|
||||
kubectl get ingress -n openwork-ee
|
||||
kubectl describe backendconfig openwork-ee-den-api-backend -n openwork-ee
|
||||
kubectl describe backendconfig openwork-ee-den-web-backend -n openwork-ee
|
||||
kubectl logs -n openwork-ee deploy/openwork-ee-den-api
|
||||
kubectl logs -n openwork-ee deploy/openwork-ee-den-web
|
||||
```
|
||||
|
||||
Check readiness from your machine:
|
||||
|
||||
```bash
|
||||
curl -fsS https://api.openwork.example.com/ready
|
||||
curl -fsS https://openwork.example.com/api/ready
|
||||
```
|
||||
|
||||
## 9. Bootstrap the first owner
|
||||
|
||||
The chart defaults to `single_org`. Set these before first sign-in:
|
||||
|
||||
```yaml
|
||||
config:
|
||||
tenancy:
|
||||
mode: "single_org"
|
||||
singleOrgName: "Acme"
|
||||
singleOrgSlug: "acme"
|
||||
ownerEmails: "admin@acme.com"
|
||||
requireEmailVerification: "false"
|
||||
public:
|
||||
bootstrapAdminEmails: "admin@acme.com"
|
||||
secret:
|
||||
values:
|
||||
initialAdminBootstrapCode: "REPLACE_BOOTSTRAP_CODE"
|
||||
```
|
||||
|
||||
For releases that include initial-administrator bootstrap, inject the
|
||||
release-documented one-time setup secret through the Kubernetes Secret referenced
|
||||
by `secret.existingSecret`. Do not store the code in the values file or a
|
||||
ConfigMap. Then open `https://openwork.example.com/setup`, enter the configured
|
||||
owner email and one-time operator code, and create the first account. OpenWork
|
||||
creates the singleton organization, grants owner and configured platform-admin
|
||||
access, and signs the administrator in. Public signup remains disabled. After
|
||||
the first user exists, the setup code cannot bootstrap another account.
|
||||
|
||||
`ownerEmails` and `bootstrapAdminEmails` authorize roles; neither setting creates
|
||||
an account or password. There is no default administrator password. Chart
|
||||
versions without `/setup` do not support private initial-administrator bootstrap
|
||||
and must be upgraded before following this step.
|
||||
|
||||
## 10. Configure SSO with a test IdP
|
||||
|
||||
Self-hosted installs keep plan gating off unless the operator explicitly sets
|
||||
`DEN_PLAN_GATING_ENABLED=true`, so SSO management should be available in the EE
|
||||
self-host default.
|
||||
|
||||
Use OIDC first for a smoke test because most IdPs provide discovery metadata.
|
||||
Auth0, Okta trial, and Google Cloud Identity test tenants all work as realistic
|
||||
demo IdPs.
|
||||
|
||||
Configure the IdP application with this callback URL:
|
||||
|
||||
```text
|
||||
https://openwork.example.com/api/auth/sso/callback/openwork-sso-<org-id>
|
||||
```
|
||||
|
||||
In OpenWork, sign in as the owner, open the organization SSO settings, and enter
|
||||
the IdP issuer/client details. After saving, the organization sign-in path is:
|
||||
|
||||
```text
|
||||
https://openwork.example.com/sso/<singleOrgSlug>
|
||||
```
|
||||
|
||||
For SAML, OpenWork shows the generated ACS URL and metadata URL after the SAML
|
||||
connection is registered. Use those values in the IdP rather than guessing.
|
||||
OpenWork rejects unsigned or weak SAML responses, so configure the IdP to sign
|
||||
assertions.
|
||||
|
||||
After SSO is configured, root sign-in shows the SSO-only experience for the
|
||||
single organization. Password sign-in for that organization is rejected.
|
||||
|
||||
## 11. Troubleshooting
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---|---|---|
|
||||
| Ingress does not reconcile | HTTP load balancing add-on is disabled or Ingress annotation is wrong | Keep HTTP load balancing enabled and use `kubernetes.io/ingress.class: gce` |
|
||||
| Backends are unhealthy | GKE load balancer health checks do not match OpenWork readiness endpoints | Apply the `BackendConfig` resources and keep the service annotations from the starter values |
|
||||
| Ingress events report `TimeoutSec should be less than checkIntervalSec` | The backend health-check timeout is greater than or equal to its effective interval | Set `checkIntervalSec: 15` and `timeoutSec: 5` on both `BackendConfig` resources |
|
||||
| Managed certificate is not `Active` | DNS does not point at the load balancer or provisioning is still running | Point both hosts at the reserved global IP and wait; check `kubectl describe managedcertificate` |
|
||||
| Migration Job fails to connect to MySQL | Private services access, VPC, credentials, IP, or TLS mode are wrong | Test from `mysql-client`, confirm the private IP, and confirm GKE and Cloud SQL share VPC reachability |
|
||||
| Migration Job logs show `self-signed certificate in certificate chain` | Strict certificate verification is being used without the cloud MySQL CA bundle | Use `?sslaccept=accept` for the smoke path or mount/configure the CA bundle before strict verification |
|
||||
| `ImagePullBackOff` from GHCR | Private image or missing pull token | Add `imagePullSecrets` |
|
||||
| Browser auth loops or CORS errors | Public origins do not match DNS/TLS | Set `webOrigin`, `apiOrigin`, `corsOrigins`, `betterAuthTrustedOrigins`, and `authCallbackUrl` to the final HTTPS domains |
|
||||
| SSO callback rejected | IdP callback URL does not match OpenWork | Use the callback/ACS URL shown by OpenWork for that org/provider |
|
||||
| SSO settings show Enterprise gating | `DEN_PLAN_GATING_ENABLED=true` or org is not entitled | Leave plan gating off for self-host smoke tests, or grant enterprise entitlement |
|
||||
|
||||
## 12. Cleanup
|
||||
|
||||
For a disposable test:
|
||||
|
||||
```bash
|
||||
helm uninstall openwork-ee -n openwork-ee
|
||||
gcloud compute addresses delete openwork-ee-ip --global
|
||||
gcloud container clusters delete "$GKE_CLUSTER" --location "$GCP_REGION"
|
||||
gcloud sql instances delete "$SQL_INSTANCE"
|
||||
```
|
||||
|
||||
Delete DNS records, retained backups, private service access ranges, and any IAM
|
||||
resources if they were only for the test.
|
||||
Reference in New Issue
Block a user