Service accounts
A service account is a directory identity for a workload instead of a person. An agent, job, or service running in Kubernetes calls the AI Gateway and the Connector Gateway as its service account by presenting the projected ServiceAccount token Kubernetes gives its pod. There's no key to issue, store, or rotate. The account has its own groups, model set grants, and budget, and its spend is attributed to it.
Use a service account when a Kubernetes workload should act independently of any user. Use a virtual API key when a script or CI job should act as a person: the key carries its owner's access and budget, and the client stores it.
How a workload is recognized
A workload's token signs it in when three conditions hold:
- A trusted issuer tells Stacklok Enterprise which cluster's tokens to accept: the cluster's issuer URL, where its public signing keys are, and the audience workloads request their token for.
- A binding maps the workload's Kubernetes ServiceAccount, by namespace and name and optionally its UID, to one service account.
- The service account is Active.
After sign-in, the account's model access and budgets decide which models it can call, and its groups decide which connectors it reaches, as they do for a user. See What an account can reach.
Prerequisites
- An AI Gateway connected to the directory. A cluster administrator completes Accept service account workloads once per installation.
- The platform admin grant, which covers directory administration.
- The Kubernetes ServiceAccount the workload runs as. Stacklok Enterprise doesn't create it. Note its namespace and name.
In the console, select Administration under Experience in the account menu, then open Service Accounts.
Trust the cluster's issuer
Each cluster whose workloads call the gateway needs one trusted issuer. You can also add an issuer from the Bindings step when you create an account.
-
Open the Trusted issuers tab and select Add issuer.
-
Choose where the issuer is:
-
This cluster trusts the cluster that runs Stacklok Enterprise. Gateways read its keys from the Kubernetes API, so choose it only when every AI Gateway runs in this cluster. Check that Issuer URL matches the issuer this command prints, which on managed clusters such as Amazon EKS is a public URL:
kubectl get --raw /.well-known/openid-configuration | jq -r .issuer -
Another issuer trusts any other cluster. Enter its public Issuer URL, then give its public keys as a JWKS URL or with Upload JWKS.
-
-
Keep the default Audience,
stacklok-enterprise-platform, or enter another value that only Stacklok Enterprise accepts. Workloads request their token for this audience, so share it with the teams that deploy them. -
Select Add issuer.
Gateways install a new or changed issuer on their next poll of the directory, every 30 seconds by default.
The default Signing algorithms, under Advanced, accept RS256. Change
them only when the cluster signs its tokens with another type of key.
Disabling an issuer refuses its workloads and keeps their bindings, so enabling it again lets them back in. You can delete an issuer only when no binding uses it.
Create a service account
On the Accounts tab, select New service account. The wizard walks through five steps, and every step after Details can be skipped and completed later from the account's tabs.
-
Details: enter a Name and a description that says which workload uses the account.
-
Connectors: add the account to groups, or create a group, and choose the connectors each group is granted. The account gets everything a group confers, including its connectors, budget pool, and model set grants. A change to a group's connectors applies to every member of that group. The list leaves out groups your identity provider manages through SCIM, because SCIM controls their membership, and connectors that can't serve a service account.
-
Model Sets: grant model sets directly, and optionally set a Budget amount and period for the account.
-
Bindings: choose the Issuer URL, then enter the Namespace and ServiceAccount name of the workload's ServiceAccount. To pin the binding to that exact ServiceAccount, also enter its UID:
kubectl get serviceaccount <SERVICE_ACCOUNT_NAME> -n <NAMESPACE> \-o jsonpath='{.metadata.uid}' -
Review: check the summary and select Create and activate service account.
Without a binding, the button reads Create service account and the account is created Suspended. Add a binding on its Bindings tab, then activate it.
Two rules differ from users. The All Users model set never applies to a service account, so with model access on, an account calls only the models its own grants and its groups' grants cover. The organization default budget never funds an account either: it spends its own budget first, then its groups' pools, and is refused once they are spent or when none applies.
Once the account is active, the team that deploys the workload configures it as described in Call the AI Gateway from Kubernetes workloads.
Choose between a pinned and a name-only binding
A name-only binding matches any ServiceAccount with its namespace and name. That
includes a ServiceAccount deleted and created again under the same name, and one
created by anyone who can create ServiceAccounts in that namespace, which the
built-in Kubernetes edit role allows. Pin the UID when the account's grants
and budget are worth more than what the cluster already grants that
ServiceAccount name.
A pinned binding takes precedence over a name-only binding for its UID. When another account already reaches the same ServiceAccount by name, the console asks you to confirm with Reassign. The new account takes over the ServiceAccount with that UID, and the other account keeps its name-only binding for any other ServiceAccount with that name, such as one created again later.
Bindings can't be edited. To change one, remove it from the account's Bindings tab and add a new one. Each change applies on the workload's next request.
Activate and suspend an account
A service account authenticates only while it's Active. Activating it requires at least one binding to an enabled issuer, and the account's page says what's missing when it isn't ready. Activate a suspended account from the alert on its page, and suspend an active one from its actions menu.
Revoke a workload's access
To stop a workload at once, suspend its account or remove its binding. The gateway refuses the workload's next request, and requests already admitted finish.
Deleting the Kubernetes ServiceAccount isn't enough. The gateway verifies tokens by their signature, so a token already issued keeps working until it expires, which can take up to 60 minutes. With a name-only binding, a ServiceAccount created again under the same name is the account again.
An account that loses its last binding, or whose issuers are all disabled, stays Active but its workloads are refused. Its page shows Active, but its workloads can't authenticate with a link to fix it.
Deleting a service account is permanent. It removes the account's bindings, group memberships, and grants. The account stays listed as Deleted, so its past spend remains attributed to it.
What an account can reach
A trusted issuer accepts tokens from every namespace in its cluster. Bindings decide which ServiceAccounts sign in, and the gateways refuse any workload without an active, bound account.
An account reaches a connector only through a group the connector is granted to, and only when the connector uses None, Bearer token, or Header injection authentication. The other authentication types act as the calling person, and a service account has no person behind it. The account's Connectors tab lists the connectors it reaches and the group each one comes through, and lets you change its groups and their connectors.
The AI Gateway's model access and budget settings decide which models the account can call:
| Model access | Budgets | An active, bound account can call |
|---|---|---|
| On | On | The models its grants cover, within budget |
| On | Off (budgets.acknowledgeUnmetered) | The models its grants cover, unmetered |
| Off | On | Any model, within budget |
| Off | Off (budgets.acknowledgeUnmetered) | Any model, unmetered |
Users get the same treatment, so a gateway with neither model access nor budgets admits every bound workload as freely as every signed-in user. See Control model access and Budgets and pricing.
Next steps
- Call the AI Gateway from Kubernetes workloads to configure the workload's token and requests.
- Manage budgets to give an account its own budget.
- Control model access to grant an account the models it needs.
Troubleshooting
Activate is unavailable
The account has no binding, or every issuer its bindings use is disabled. Add a binding on the account's Bindings tab, or enable an issuer on the Trusted issuers tab.
A workload is refused with 401 or 403
See Handle errors for what each response means and where to find the reason.