Skip to main content

Verify Kubernetes deployments match a version manifest with deep stability auditing. Checks convergence, revision consistency, and pod health.

Project description

kubernify

PyPI version Python versions CI License

Verify Kubernetes deployments match a version manifest with deep stability auditing. Checks convergence, revision consistency, and pod health.


Features

  • Manifest-driven verification - Provide a JSON manifest of expected versions; kubernify verifies the cluster matches
  • Deep stability auditing - Goes beyond version checks: convergence, revision consistency, pod health, DaemonSet scheduling, Job completion
  • Retry-until-converged loop - Waits for rollouts to complete rather than just snapshot-checking
  • Repository-relative image parsing - Flexible component name extraction from any image registry format
  • Comprehensive workload support - Deployments, StatefulSets, DaemonSets, Jobs, and CronJobs
  • Zero-replica awareness - Verifies version from PodSpec even when HPA/KEDA has scaled to zero
  • Structured JSON reports - Machine-readable output for CI/CD pipeline integration

Installation

pip install kubernify

Or with pipx for isolated CLI usage:

pipx install kubernify

Or with uv:

uv add kubernify

Quick Start

# Verify backend and frontend match expected versions in the "production" namespace
kubernify \
  --context my-cluster-context \
  --anchor my-app \
  --namespace production \
  --manifest '{"backend": "v1.2.3", "frontend": "v1.2.4"}'

kubernify will connect to the cluster, discover all matching workloads, verify their image versions against the manifest, run stability audits, and exit with code 0 (pass), 1 (fail), or 2 (timeout).


CLI Reference

kubernify [OPTIONS]
Argument Description Default
--context Kubeconfig context name. Mutually exclusive with --gke-project. From kubeconfig
--gke-project GCP project ID for GKE context resolution. Mutually exclusive with --context.
--anchor (required) Image path anchor for component name extraction. See How Image Anchor Works.
--manifest (required) JSON version manifest, e.g. '{"backend": "v1.2.3"}'.
--namespace Kubernetes namespace to verify. From kubeconfig context
--required-workloads Comma-separated workload name patterns that must exist.
--skip-containers Comma-separated container name patterns to skip during verification.
--min-uptime Minimum pod uptime in seconds for stability checks. 0
--restart-threshold Maximum acceptable container restart count. Use 0 to forbid any restarts, or -1 to skip the restart check entirely. 3
--timeout Global timeout in seconds for the verification loop. 300
--allow-zero-replicas Allow workloads with zero replicas to pass verification. false
--dry-run Snapshot check without waiting for convergence. false
--include-statefulsets Include StatefulSets in workload discovery. false
--include-daemonsets Include DaemonSets in workload discovery. false
--include-jobs Include Jobs and CronJobs in workload discovery. false

Usage Examples

Basic Usage - Direct Kubeconfig Context

kubernify \
  --context my-cluster-context \
  --anchor my-app \
  --namespace production \
  --manifest '{"backend": "v1.2.3", "frontend": "v1.2.4"}'

GKE Shorthand - Resolve Context from GCP Project

kubernify \
  --gke-project my-gke-project-123456 \
  --anchor my-app \
  --namespace production \
  --manifest '{"backend": "v1.2.3", "frontend": "v1.2.4"}'

In-Cluster - Running Inside a Kubernetes Pod

# No --context needed; auto-detects in-cluster config and namespace
kubernify \
  --anchor my-app \
  --manifest '{"backend": "v1.2.3", "frontend": "v1.2.4"}'

Full-Featured - All Options

kubernify \
  --context my-cluster-context \
  --anchor my-app \
  --namespace production \
  --manifest '{"backend": "v1.2.3", "frontend": "v1.2.4", "worker": "v1.2.3"}' \
  --required-workloads "backend, frontend, worker" \
  --skip-containers "istio-proxy, envoy, fluent-bit" \
  --include-statefulsets \
  --include-daemonsets \
  --include-jobs \
  --min-uptime 120 \
  --restart-threshold 5 \
  --timeout 600 \
  --allow-zero-replicas

Dry Run - Snapshot Check Without Waiting

kubernify \
  --context my-cluster-context \
  --anchor my-app \
  --manifest '{"backend": "v1.2.3"}' \
  --dry-run

CI/CD Integration - GitHub Actions

jobs:
  verify-deployment:
    runs-on: ubuntu-latest
    steps:
      - name: Set up kubeconfig
        run: |
          echo "${{ secrets.KUBECONFIG }}" > /tmp/kubeconfig
          export KUBECONFIG=/tmp/kubeconfig

      - name: Install kubernify
        run: pip install kubernify

      - name: Verify deployment
        run: |
          kubernify \
            --context ${{ secrets.KUBE_CONTEXT }} \
            --anchor my-app \
            --manifest '${{ steps.build.outputs.manifest }}' \
            --timeout 600 \
            --min-uptime 60

Programmatic Usage

kubernify can be used as a Python library for custom verification workflows:

from kubernify import __version__, VerificationStatus
from kubernify.kubernetes_controller import KubernetesController
from kubernify.workload_discovery import WorkloadDiscovery
from kubernify.cli import construct_component_map, verify_versions

controller = KubernetesController(context="my-cluster")
discovery = WorkloadDiscovery(k8s_controller=controller)

workloads, _ = discovery.discover_cluster_state(namespace="production")
component_map = construct_component_map(
    workloads=workloads,
    manifest={"backend": "v1.2.3"},
    repository_anchor="my-app",
)
results = verify_versions(manifest={"backend": "v1.2.3"}, component_map=component_map)

if results.errors:
    print(f"Verification failed: {results.errors}")

How Image Anchor Works

kubernify uses a repository-relative anchor to extract component names from container image paths. The --anchor argument specifies the path segment after which the component name is derived.

Image: registry.example.com/my-org-foo/my-app-bar/backend:v1.2.3-x
       └──── registry ─────┘ └─ org ─┘ └ anchor ┘└ comp.┘└─ tag ─┘

More examples:

Image --anchor Extracted Component
registry.example.com/my-org/my-app/backend:v1.2.3 my-app backend
registry.example.com/my-org/my-app/api/server:v2.0.0 my-app api/server
gcr.io/my-project/my-app/worker:v1.0.0 my-app worker

The extracted component name is then matched against the keys in your --manifest JSON to verify the correct version is deployed.



Exit Codes

Code Meaning Description
0 PASS All workloads match the manifest and pass stability audits
1 FAIL One or more workloads have version mismatches or stability issues
2 TIMEOUT Verification did not converge within the --timeout window

Prerequisites

Python

  • Python >= 3.10

For GKE Users

If using --gke-project for automatic GKE context resolution:

  1. Install the Google Cloud SDK
  2. Install the GKE auth plugin:
    gcloud components install gke-gcloud-auth-plugin
    
  3. Authenticate:
    gcloud auth login
    gcloud container clusters get-credentials CLUSTER_NAME --project PROJECT_ID
    

RBAC Permissions

kubernify requires read-only access to workloads and pods. Apply the following RBAC configuration:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: kubernify-reader
  namespace: <namespace>
rules:
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets", "daemonsets", "replicasets"]
    verbs: ["get", "list"]
  - apiGroups: ["batch"]
    resources: ["jobs", "cronjobs"]
    verbs: ["get", "list"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernify-reader-binding
  namespace: <namespace>
subjects:
  - kind: ServiceAccount
    name: kubernify
    namespace: <namespace>
roleRef:
  kind: Role
  name: kubernify-reader
  apiGroup: rbac.authorization.k8s.io

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for development setup, coding standards, and the PR process.


License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kubernify-1.0.2.tar.gz (103.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kubernify-1.0.2-py3-none-any.whl (32.4 kB view details)

Uploaded Python 3

File details

Details for the file kubernify-1.0.2.tar.gz.

File metadata

  • Download URL: kubernify-1.0.2.tar.gz
  • Upload date:
  • Size: 103.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for kubernify-1.0.2.tar.gz
Algorithm Hash digest
SHA256 a40557909d4471c87eb3df9492552753cb830692df0e1fdf2d584be841b71be1
MD5 9fb795c06050e8de44bc8226eadd199c
BLAKE2b-256 1bed95e31638335a96329b9f70d4a222ecc8aecbed4dafd9cf73301fd85d6aef

See more details on using hashes here.

File details

Details for the file kubernify-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: kubernify-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 32.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for kubernify-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9b8c94c9175d69fb1f99d7b7f60a0c3e2e671be7cc38ae3ec5ba50695785015c
MD5 8f213118fa1e4553ecc5681f2699b71f
BLAKE2b-256 1d588f3dbeda25f51c39ce0b88bb6e1f44661efca675ec27f2ee1ce053827389

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page