The zoperator is a kubernetes operator built suing Kubebuilder that manages
tenant configs and their resources during and after creation of the tenants.
It introduces UserConfig that defines tenant-specific settings and automatically
provisions required resources based on the configuration.
- Custom Resource Definition (CRD) for managing user configurations
- Automated namespace creation for each tenant
- Resource lifecycle management with finalizers
- Status tracking for UserConfig resources
- Comprehensive validation rules for configuration fields
- Support for various resource permissions and configurations
- Integration with Sealed Secrets for secure secret management
The operator requires the following RBAC permissions:
# UserConfig resources
- apiGroups: ["myoperator.01cloud.io"]
resources: ["userconfigs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["myoperator.01cloud.io"]
resources: ["userconfigs/status"]
verbs: ["get", "update", "patch"]
- apiGroups: ["myoperator.01cloud.io"]
resources: ["userconfigs/finalizers"]
verbs: ["update"]
# Sealed Secrets
- apiGroups: ["bitnami.com"]
resources: ["sealedsecrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]The operator manages the following resources for each UserConfig:
-
Namespace
- Created with name format:
<userconfig-name>-namespace - Labeled with:
app.kubernetes.io/managed-by: userconfig-operatoruserconfig.myoperator.01cloud.io/name: <userconfig-name>
- Automatically deleted when UserConfig is deleted
- Created with name format:
-
Sealed Secrets
- Managed within the tenant namespace
- Supports creation and updates
- Automatically cleaned up during tenant deletion
- Requires proper encryption using kubeseal
The UserConfig resource maintains the following states:
Active: Resources successfully reconciledError: Issues encountered during reconciliation
apiVersion: myoperator.01cloud.io/v1alpha1
kind: UserConfig
metadata:
name: tenant-1
spec:
identity:
username: "tenant-1"
contact: "tenant@example.com"
secrets:
- name: my-secret
type: sealed
sealedSecret:
encryptedData:
key1: <encrypted-value>
key2: <encrypted-value>To create a sealed secret:
- Create a regular secret:
kubectl create secret generic my-secret --from-literal=key1=value1 --dry-run=client -o yaml > secret.yaml - Encrypt it using kubeseal:
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
- Copy the encryptedData section to your UserConfig manifest
- go version v1.22.0+
- docker version 17.03+.
- kubectl version v1.11.3+.
- Access to a Kubernetes v1.11.3+ cluster.
- kubeseal CLI tool (for sealed secrets)
-
Install Kubebuilder:
curl -L -o kubebuilder "https://go.kubebuilder.io/dl/v4.3.1/$(go env GOOS)/$(go env GOARCH)" chmod +x kubebuilder && sudo mv kubebuilder /usr/local/bin/
-
Install kubeseal CLI:
# For Linux wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.5/kubeseal-0.24.5-linux-amd64.tar.gz tar -xvzf kubeseal-0.24.5-linux-amd64.tar.gz sudo install -m 755 kubeseal /usr/local/bin/kubeseal # For MacOS brew install kubeseal
-
Create a KInd cluster:
kind create cluster --name operator-test
-
Install Sealed Secrets Controller:
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.27.3/controller.yaml
-
Make Manifests and CRD:
# creat the CRD make manifestsThe project layout looks like this:
. ├── api/ │ └── v1alpha1/ │ ├── userconfig_types.go # CRD type definitions │ └── zz_generated.deepcopy.go ├── config/ │ ├── crd/ # CRD manifests │ ├── rbac/ # RBAC configurations │ └── samples/ # Sample CR manifests └── controllers/ └── userconfig_controller.go # Main reconciliation logic -
Install the CRDs into the cluster:
make install
-
Run the operator:
make run
-
Apply below sample manifest:
apiVersion: myoperator.01cloud.io/v1alpha1 kind: UserConfig metadata: name: tenant-1 spec: identity: username: "tenant-1" contact: "tenant@example.com" groups: - viewer permissions: resources: - resource: deployment level: CRUD
-
Verify the resources created:
kubectl get userconfig tenant-1 -o yaml kubectl get ns tenant-1-namespace
-
CRD Not Found
- Ensure CRDs are installed:
make install - Check CRD status:
kubectl get crds | grep userconfig
- Ensure CRDs are installed:
-
Namespace Creation Failed
- Check operator logs:
kubectl logs -n zoperator-system <pod-name> - Verify RBAC permissions:
kubectl auth can-i create namespace --as system:serviceaccount:zoperator-system:zoperator-controller-manager
- Check operator logs:
-
Status Updates Failed
- Ensure status subresource is enabled in CRD
- Check for validation errors in the status update
-
Sealed Secrets Issues
- Verify Sealed Secrets controller is running:
kubectl get pods -n kube-system | grep sealed-secrets - Check if kubeseal can connect to the controller:
kubeseal --fetch-cert - Verify secret encryption: Try encrypting a test secret with kubeseal
- Verify Sealed Secrets controller is running:
- Include SealedSecrets operator
- Shared informer between this two operator.
The UserConfig CRD (Custom Resource Definition) provides a declarative way to manage tenant configurations and their associated resources in a Kubernetes cluster.
spec:
identity:
username: "tenant-1" # Required, DNS-compatible (3-63 chars)
contact: "user@org.com" # Required, valid email
groups: # Optional, max 6 groups
- viewer
- developer # Allowed: viewer, developer, tester, admin, operations, security
labels: # Optional classification
- team-aspec:
permissions:
resources:
- resource: deployment # Supported: deployment, service, secret, pods, configmap, ingress
level: editor # Levels: viewer, editor, admin, CRUD, R, RU
clusterRoles: # Default: ["viewer"]
- viewer # Available: viewer, developer, admin, testerSupports two types of secrets:
spec:
secrets:
- name: "db-creds"
type: sealed
sealedSecret:
encryptedData:
username: "encrypted-value"
password: "encrypted-value"spec:
secrets:
- name: "api-keys"
type: external
externalSecret:
provider: aws # Supported: aws, gcp, azure, vault
endpoint: "https://..."
credentials:
accessKey: "key"
secretKey: "secret"
secretPath: "path/to/secret"spec:
resourceQuota:
"requests.cpu": "1"
"requests.memory": "1Gi"
"limits.cpu": "2"
"limits.memory": "2Gi"spec:
limitRange:
limits:
- type: Container
max:
cpu: "2"
memory: "2Gi"
min:
cpu: "100m"
memory: "100Mi"
default:
cpu: "500m"
memory: "500Mi"spec:
networkPolicy:
- allowTrafficFrom:
pods:
- app: "frontend"
namespaces:
- environment: "prod"
- allowTrafficTo:
pods:
- app: "database"spec:
serviceAccounts:
- name: "app-sa"
imagePullSecrets:
- "registry-creds"The UserConfig maintains status information:
status:
state: Active # Possible values: Pending, Active, Error
lastUpdated: "2024-03-21T10:00:00Z"
conditions:
- type: Ready
status: "True"
reason: ResourcesCreated
message: "All resources successfully reconciled"-
Identity:
- Username: Must be DNS-compatible, 3-63 characters
- Groups: Maximum 6 groups from predefined list
- Contact: Valid email format required
-
Permissions:
- Resources must be from supported list
- Access levels must match predefined values
- ClusterRoles default to "viewer" if not specified
-
Secrets:
- Secret names must be DNS-compatible
- Type must be either "sealed" or "external"
- Provider-specific fields required for external secrets
-
Resource Controls:
- Resource values must use valid Kubernetes quantity format
- LimitRange type must be "Container"
- Valid resource metrics (cpu, memory) required
-
Resource Management:
- Always set resource quotas for production tenants
- Configure appropriate limit ranges to prevent resource abuse
- Use default limits for predictable behavior
-
Security:
- Use minimum required permissions
- Implement network policies for isolation
- Rotate secrets regularly
- Use sealed secrets for sensitive information
-
Naming and Organization:
- Use consistent naming conventions
- Apply meaningful labels
- Group related configurations
-
Monitoring:
- Watch for status changes
- Monitor resource usage against quotas
- Track permission changes
-
External Systems:
- Secret management systems (AWS Secrets Manager, Vault)
- Identity providers
- Monitoring systems
-
Other Operators:
- Sealed Secrets Operator
- External Secrets Operator
- Cert Manager
- Ingress Controllers