Skip to content

Resource Management

omni_kube provides a comprehensive Postgres-based interface for managing Kubernetes resources through SQL views and functions. This system allows you to interact with Kubernetes API resources using standard SQL operations.

Overview

The resource management system consists of several key components:

  1. API Group Discovery: Views that expose Kubernetes API groups and versions
  2. Resource Introspection: Functions to discover available resources within API groups
  3. Dynamic Resource Views: Generated views that provide CRUD operations for specific Kubernetes resources

API Group Views

omni_kube.api_group

Lists all available Kubernetes API groups with their preferred versions.

Columns:

  • name (text): API group name ('core' for core Kubernetes resources)
  • preferred_version (text): The preferred version for this API group
select *
from omni_kube.api_group;

omni_kube.api_group_version

Shows all available versions for each API group.

Columns:

  • name (text): API group name
  • version (text): Version identifier (e.g., 'v1', 'v1beta1')
  • group_version (text): Full group/version identifier
select *
from omni_kube.api_group_version
where name = 'apps';

omni_kube.api_group_openapi_v3_url

Maps API groups to their OpenAPI specification URLs.

Columns:

  • name (text): API group name
  • group_version (text): Group/version identifier
  • url (text): Server-relative URL for the API specification

Resource Discovery Functions

omni_kube.group_resources(group_version text)

Returns detailed information about all resources available in a specific API group version.

Parameters:

  • group_version: The group/version identifier (e.g., 'v1', 'apps/v1')

Returns:

  • name (text): Resource name (e.g., 'pods', 'deployments')
  • singular_name (text): Singular form of the resource name
  • namespaced (boolean): Whether the resource is namespace-scoped
  • kind (text): Kubernetes kind name (e.g., 'Pod', 'Deployment')
  • verbs (text[]): Supported operations (e.g., ['get', 'list', 'create', 'update', 'delete'])
  • storage_version_hash (text): Internal version hash

Example:

select name, kind, namespaced, verbs
from omni_kube.group_resources('apps/v1')
where name = 'deployments';

omni_kube.resources(group_version text, resource text[, label_selector text][, field_selector text])

Retrieves the actual resource instances from the Kubernetes API.

Parameters:

  • group_version: The group/version identifier
  • resource: The resource type name
  • label_selector: Optional label selector (e.g., 'app=web-app')
  • field_selector: Optional field selector (e.g., 'metadata.name=web-app')

Returns:

  • jsonb: Complete resource definition as returned by the Kubernetes API

Example:

select resource -> 'metadata' ->> 'name' as name,
       resource -> 'spec' ->> 'replicas' as replicas
from omni_kube.resources('apps/v1', 'deployments') resource;

Dynamic Resource Views

omni_kube.resource_view(view_name name, group_version text, resource text[, label_selector text][, field_selector text])

Creates a dynamic view that provides a SQL interface for managing specific Kubernetes resources.

Parameters:

  • view_name: Name for the generated view
  • group_version: API group/version (e.g., 'v1', 'apps/v1')
  • resource: Resource type (e.g., 'pods', 'deployments')
  • label_selector: Optional label selector (e.g., 'app=web-app')
  • field_selector: Optional field selector (e.g., 'metadata.name=web-app')

Returns:

  • regclass: The created view's object identifier

The generated view includes:

  • uid (text): Kubernetes resource UID
  • name (text): Resource name
  • namespace (text): Resource namespace (null for cluster-scoped resources)
  • resource (jsonb): Complete resource specification

Generated View Operations

Insert Operations

Create new resources by inserting into the view:

-- create a view for pods
select omni_kube.resource_view('my_pods', 'v1', 'pods');

-- insert a new pod
insert into my_pods (resource)
values ('{
  "metadata": {
    "name": "nginx-pod-omni-kube"
  },
  "spec": {
    "containers": [{
      "name": "test",
      "image": "nginx"
    }]
  }
}');

Insert Requirements:

  • uid must be null (auto-generated by Kubernetes)
  • name can be specified in the view column or within resource.metadata.name
  • namespace must match resource.metadata.namespace if both are specified
  • resource must contain valid Kubernetes resource specification

Update Operation

Modify existing resources:

update my_pods
set resource = jsonb_set(
        resource,
        '{metadata,annotations}',
        coalesce(resource -> 'metadata' -> 'annotations', '{}'::jsonb) || '{"test": "passed"}'::jsonb
               )
where name = 'nginx-pod-omni-kube';

Update Requirements:

  • Resource must exist (identified by name and namespace)
  • Name and namespace consistency rules apply as with insert

Delete Operations

Remove resources:

delete
from my_pods
where name = 'nginx-pod-omni-kube'
  and namespace = 'default';

Delete Requirements:

  • Resource is identified by name and namespace from the view columns or resource metadata

Error Handling

The system includes comprehensive validation:

  • Name/Namespace Consistency: Ensures view columns match resource metadata
  • Required Fields: Validates that resources have required name field
  • UID Restrictions: Prevents manual UID assignment for new resources
  • Resource Existence: Validates resources exist before update/delete operations

Add this section to your Resource Discovery Functions section, after the omni_kube.resources() function:

omni_kube.resources_metadata(group_version text, resource text)

Retrieves only the metadata section from a Kubernetes resource collection, which is useful for getting information like resource versions without fetching the entire resource list.

Parameters:

  • group_version: The group/version identifier (e.g., 'v1', 'apps/v1')
  • resource: The resource type name

Returns:

  • jsonb: The metadata object from the Kubernetes API response, typically containing fields like resourceVersion.

Example:

-- Get the current resource version for pods
select omni_kube.resources_metadata('v1', 'pods') ->> 'resourceVersion' as current_version;

Resource Tables

The omni_kube.resource_table() function provides an alternative to dynamic views by creating materialized tables that cache Kubernetes resource data locally. Like resource_view(), it accepts the same parameters for specifying the target API group, version, and resource type. The key advantage of resource tables is performance and a stable view – they store resource data locally in the database rather than making API calls on each query.

Each generated table has a corresponding refresh_<table_name>() function that synchronizes the local data with the current state of the Kubernetes cluster.

This refresh mechanism allows you to control when expensive API calls occur, making resource tables ideal for scenarios where you need to perform complex queries, joins, or analytics on Kubernetes data without the latency of repeated API requests. The refresh function can be called manually or scheduled for automated data synchronization.

Resource tables are particularly valuable for building Kubernetes operators and controllers, where you need to maintain local state, perform complex reconciliation logic across multiple resource types, or implement sophisticated filtering and aggregation operations that would be inefficient when executed against live API endpoints.

The function returns a table of (type text, object jsonb) where type is ADDED, MODIFIED or DELETED and object is the object in question.

Transactional Resource Tables

Resource tables can be made transactional by passing transactional => true to omni_kube.resource_table(). This simulates read committed-style isolation of changes to the cluster. That is, if you refresh a table within a transaction, it'll reflect current state of the cluster. All pending changes in the table are dry-run-verified but pooled until commit time. Subsequent changes to the same resource override the entry in the pool (so, for example, an update followed by another update is superseded; a deletion performed after update, wins, etc.)

This enables an approximation of atomic operations – a best-effort approach.

Important caveats

Commits may still fail due to conflicts with the actual cluster (newer resource versions in the cluster, resource deleted, etc.)

Commit operation can also fail due to HTTP errors and leave transaction's pending changes in an inconsistent state. A compensation mechanism can be devised (reconciling incomplete transaction). Future versions of this extension may provide tooling for this.

Usage Examples

Working with Deployments

-- create a deployments view
select omni_kube.resource_view('deployments', 'apps/v1', 'deployments');

-- list all deployments
select name,
       namespace,
       resource -> 'spec' ->> 'replicas'   as desired_replicas,
       resource -> 'status' ->> 'replicas' as current_replicas
from deployments;

-- create a new deployment
insert into deployments (resource)
values ('{
  "metadata": {
    "name": "web-app",
    "labels": {
      "app": "web-app",
      "version": "1.0"
    }
  },
  "spec": {
    "replicas": 3,
    "selector": {
      "matchLabels": {
        "app": "web-app"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "web-app",
          "version": "1.0"
        }
      },
      "spec": {
        "containers": [{
          "name": "web",
          "image": "nginx:1.21",
          "ports": [{
            "containerPort": 80
          }],
          "resources": {
            "requests": {
              "memory": "64Mi",
              "cpu": "250m"
            },
            "limits": {
              "memory": "128Mi", 
              "cpu": "500m"
            }
          }
        }]
      }
    }
  }
}');

-- scale the deployment
update deployments
set resource = jsonb_set(resource, '{spec,replicas}', '5'::jsonb)
where name = 'web-app';

Working with ConfigMaps

-- create a configmaps view
select omni_kube.resource_view('configmaps', 'v1', 'configmaps');

-- create a configuration
insert into configmaps (resource)
values ('{
  "metadata": {
    "name": "app-config"
  },
  "data": {
    "database_url": "postgres://localhost:5432/mydb",
    "debug": "true"
  }
}');

-- update it
update configmaps
set resource = jsonb_set(resource, '{data,debug}', '"false"'::jsonb)
where name = 'app-config';

This system provides a powerful SQL interface to Kubernetes resources while maintaining full compatibility with the Kubernetes API and its validation rules.