Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions docs/content/getting-started/build-the-platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,21 @@ against this capacity without knowing which cluster it runs on.
- AWS access key ID and secret access key
{{< /tab >}}
{{< tab "GKE" >}}
- A GCP account with permissions to create GKE clusters, VPCs, and IAM roles
- A GCP service account JSON key
- A GCP service account JSON key, granted these roles on the project:

| Role | Needed for |
|---|---|
| `roles/container.admin` | the cluster and its node pools |
| `roles/compute.admin` | the VPC network and subnet |
| `roles/serviceusage.serviceUsageAdmin` | enabling the APIs the cluster needs |
| `roles/iam.serviceAccountAdmin` | the node service account |
| `roles/iam.serviceAccountKeyAdmin` | the node service account's key |
| `roles/iam.serviceAccountUser` | attaching that account to the nodes |
| `roles/resourcemanager.projectIamAdmin` | granting the node account `container.admin` |

The last one is worth a look before you hand the key over. Modelplane grants
the node service account `roles/container.admin`, so the credential doing the
provisioning has to be able to set project IAM policy.
{{< /tab >}}
{{< tab "AKS" >}}
- An Azure account with permissions to create AKS clusters and managed identities
Expand Down
20 changes: 20 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ server exposes both, so the pod goes Ready without a real model or GPU.
| Control-plane `InferenceGateway` + cross-cluster routing to the replica | |
| Status propagation and foreground-deletion ordering | |

### Why cloud provisioning cannot be tested here

`lean-control-plane.yaml` trims the control plane to what a BYO cluster needs,
and both trims stop a cloud `InferenceCluster` from reconciling at all. Neither
announces itself, so this is what to expect if you point this control plane at a
real cloud:

- The MRAP activates only `*.kubernetes.m.crossplane.io` and
`*.helm.m.crossplane.io`. A cloud provider's managed resources are then never
activated, so they sit with **no status conditions at all** — which reads as
nothing happening rather than as an error.
- The `dormant-cloud-providers` `ImageConfig` maps every
`xpkg.upbound.io/upbound/provider-*` to a zero-replica runtime config. Editing
that `ImageConfig` is not enough on its own: it is resolved when a package
revision reconciles, so existing Deployments keep their replica count until
something scales them.

Undoing both is possible but leaves a control plane that is no longer the one CI
runs, so prefer a separate control plane for cloud work.

## Prerequisites

- **Docker** with real headroom — **≥ 16 GB memory** and **plenty of disk**
Expand Down
14 changes: 11 additions & 3 deletions functions/compose-gke-cluster/function/fn.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,11 @@ def _cred_name(self) -> str:
def resolve_project(self) -> str | None:
"""Fetch the GCP provider config and return its projectID.

The GCP provider uses projectID from the ProviderConfig/ClusterProviderConfig
as the default for all managed resources, so we only need the value
explicitly for the workloadPool string in the GKE cluster spec.
The GCP provider late-initializes projectID from the
ProviderConfig/ClusterProviderConfig into most managed resources, so the
value is needed explicitly only where that does not happen: the
workloadPool string in the GKE cluster spec, and the ProjectIAMMember,
which creates with an empty project unless it is set.

When the ProviderConfig is transiently gone but the cluster already
exists, falls back to the project embedded in the observed cluster's
Expand Down Expand Up @@ -506,6 +508,12 @@ def compose_iam_binding(self) -> None:
forProvider=iamv1beta1.ForProvider(
role="roles/container.admin",
member=f"serviceAccount:{sa_email}",
# Set explicitly. The provider late-initializes `project`
# from the ProviderConfig for the Network, Subnetwork and
# ServiceAccount, but not for this resource: it goes to
# create with an empty project and the GCP call 404s on
# "Error retrieving IAM policy for project ''".
project=self.project,
),
),
),
Expand Down
1 change: 1 addition & 0 deletions functions/compose-gke-cluster/tests/test_fn.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ def _iam_binding(
"forProvider": {
"role": "roles/container.admin",
"member": f"serviceAccount:{sa_email}",
"project": "my-gcp-project",
},
},
}
Expand Down
Loading