Tenant Onboarding
Purpose: For platform engineers, documents how to onboard new application teams with namespace isolation, RBAC, quotas, and network policies through the GitOps workflow.
Prerequisites
- openCenter cluster with FluxCD running
- Keycloak configured with OIDC integration
- rbac-manager service enabled
- Kyverno policies active
- Access to the customer GitOps repository
What the Platform Team Creates
Onboarding a tenant involves creating five resources in the GitOps repository:
| Resource | Purpose |
|---|---|
| Namespace | Isolation boundary for the team's workloads |
| ResourceQuota | CPU, memory, and object limits |
| RBACDefinition | Maps Keycloak groups to Kubernetes roles |
| NetworkPolicy | Default deny + allow rules for the namespace |
| FluxCD Kustomization | Reconciles the team's manifests |
Step 1 — Create the Keycloak Group
In Keycloak (Admin Console → Realm opencenter → Groups):
- Create a group named
team-<name>(e.g.,team-payments). - Add team members to the group.
- The OIDC
groupsclaim propagates group membership to the Kubernetes API server.
Verify the group appears in tokens:
# Decode a team member's token
kubectl get --raw /api/v1/namespaces/default/serviceaccounts/default/token | jq -r '.status.token' | jwt decode -
# Look for: "groups": ["team-payments"]
Step 2 — Create Namespace and ResourceQuota
Create applications/overlays/<cluster>/managed-services/tenants/team-payments/namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: team-payments
labels:
opencenter.io/tenant: "team-payments"
pod-security.kubernetes.io/enforce: "restricted"
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-payments-quota
namespace: team-payments
spec:
hard:
requests.cpu: "8"
requests.memory: "16Gi"
limits.cpu: "16"
limits.memory: "32Gi"
pods: "50"
services: "10"
persistentvolumeclaims: "20"
secrets: "30"
configmaps: "30"
Step 3 — Create RBACDefinition
Create applications/overlays/<cluster>/managed-services/tenants/team-payments/rbac.yaml:
apiVersion: rbacmanager.reactiveops.io/v1beta1
kind: RBACDefinition
metadata:
name: team-payments
spec:
rbacBindings:
- name: team-payments-admin
subjects:
- kind: Group
name: oidc:team-payments
roleBindings:
- namespace: team-payments
clusterRole: admin
- name: team-payments-view
subjects:
- kind: Group
name: oidc:team-payments
clusterRoleBindings:
- clusterRole: view
The oidc: prefix matches the kube_oidc_groups_prefix configured in the cluster's OIDC settings.
Step 4 — Create NetworkPolicy
Create applications/overlays/<cluster>/managed-services/tenants/team-payments/networkpolicy.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: team-payments
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: team-payments
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-intra-namespace
namespace: team-payments
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
Step 5 — Create FluxCD Kustomization for the Team
Create applications/overlays/<cluster>/managed-services/tenants/team-payments/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- rbac.yaml
- networkpolicy.yaml
Then add a FluxCD Kustomization to wire it into reconciliation. Create applications/overlays/<cluster>/services/fluxcd/tenant-team-payments.yaml:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: tenant-team-payments
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: customer-repo
path: ./applications/overlays/<cluster>/managed-services/tenants/team-payments
prune: true
dependsOn:
- name: kyverno
- name: rbac-manager
Verification
# Namespace exists with labels
kubectl get namespace team-payments --show-labels
# Quota applied
kubectl describe resourcequota team-payments-quota -n team-payments
# RBAC bindings created by rbac-manager
kubectl get rolebindings -n team-payments
# Network policies active
kubectl get networkpolicies -n team-payments
# FluxCD reconciling
flux get kustomization tenant-team-payments
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| RoleBinding not created | rbac-manager not running | kubectl get pods -n rbac-manager and check logs |
| User denied access | Group claim missing from token | Verify Keycloak group membership and OIDC config |
| Pods stuck Pending | ResourceQuota exceeded | kubectl describe resourcequota -n team-payments |
| Pods cannot reach DNS | NetworkPolicy too restrictive | Verify the allow-dns policy targets kube-system |