A read-only Python CLI that inspects Azure Kubernetes Service (AKS) networking capacity and produces operator-friendly or machine-readable reports.
Use it before cluster upgrades, node-pool scaling, migrations, or incident investigation to identify:
- subnet or pod-CIDR pressure
- node-pool provisioning failures
- risky
maxPodssettings - insufficient IP headroom for scaling and upgrades
Project status: pre-production. The base Azure scan, report generation, redaction, conversion, and validation paths are implemented. Pod-level and detailed cost-analysis flags are currently placeholders and are reported as
SKIPPED.
Python 3.10 or newer is required.
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install .For development:
pip install -e ".[dev]"The CLI uses DefaultAzureCredential, so Azure CLI credentials, managed identity, workload identity, and service-principal environment variables are supported.
For local use:
az login
az account set --subscription "<subscription-id>"Azure Reader access is normally sufficient for the base scan. Use the narrowest practical scope that includes the AKS cluster and its networking resources.
aks-ip-diagnostic scan \
--subscription-id "<subscription-id>" \
--resource-group "<resource-group>" \
--cluster-name "<cluster-name>"Text output is printed to the terminal. Non-text formats are saved under ./reports/ unless --output is supplied.
Save a validated JSON report:
aks-ip-diagnostic scan \
--subscription-id "<subscription-id>" \
--resource-group "<resource-group>" \
--cluster-name "<cluster-name>" \
--format json-pretty \
--validate-schema \
--output reports/aks-ip-report.jsonaks-ip-diagnostic scan [options]Required options:
| Option | Description |
|---|---|
--subscription-id |
Azure subscription ID |
--resource-group |
Resource group containing the AKS cluster |
--cluster-name |
AKS cluster name |
Common options:
| Option | Description |
|---|---|
--format, -f |
text, json, json-pretty, json-compact, yaml, markdown, or html |
--output, -o |
Explicit output path |
--redact |
Mask identifiers and IP addresses in the final report |
--validate-schema |
Validate generated report data before writing it |
--verbose |
Enable debug logging |
Accepted but not fully implemented in the current orchestrator:
| Option | Current behaviour |
|---|---|
--include-pod-analysis |
Adds a pod_analysis diagnostic with status SKIPPED |
--include-cost-analysis |
Adds a cost_analysis diagnostic with status SKIPPED |
--pod-lifecycle |
Parsed but not executed |
--kubeconfig |
Parsed but not used by the current scan workflow |
--region |
Parsed, but the built-in heuristic cost table is not region-aware |
aks-ip-diagnostic validate reports/aks-ip-report.jsonaks-ip-diagnostic convert reports/aks-ip-report.json \
--format markdown \
--output reports/aks-ip-report.mdRedact while converting:
aks-ip-diagnostic convert reports/aks-ip-report.json \
--format html \
--redact \
--output reports/redacted-report.htmlaks-ip-diagnostic versionThe implemented scan path:
- Reads AKS cluster metadata.
- Lists node pools.
- Discovers referenced virtual-network subnets.
- Falls back to the cluster pod CIDR when no custom subnet is available.
- Runs IP-exhaustion, provisioning-state, subnet-capacity, and
maxPodschecks. - Builds a structured report.
- Optionally validates and redacts the report.
- Formats the report and returns an automation-friendly exit code.
The tool does not create, update, patch, or delete Azure or Kubernetes resources.
The JSON report has these top-level sections:
{
"metadata": {},
"cluster_info": {},
"diagnostics": {},
"node_pools": [],
"subnets": [],
"issues": [],
"recommendations": [],
"summary": {}
}Use JSON for automation. Treat the current report contract as versioned but not yet stable enough for a 1.0 compatibility guarantee.
| Code | Meaning |
|---|---|
0 |
Healthy scan or successful utility command |
1 |
Scan completed with warnings |
2 |
Scan completed with critical findings |
3 |
Runtime, authentication, Azure API, or Kubernetes API failure |
4 |
Invalid CLI usage |
5 |
Report validation or conversion failure |
Example CI gate:
set +e
aks-ip-diagnostic scan \
--subscription-id "$AZURE_SUBSCRIPTION_ID" \
--resource-group "$RESOURCE_GROUP" \
--cluster-name "$CLUSTER_NAME" \
--format json-compact \
--validate-schema \
--output diagnostic-report.json
status=$?
set -e
case "$status" in
0) echo "Healthy" ;;
1) echo "Warnings found" ;;
2) echo "Critical findings"; exit 2 ;;
*) echo "Diagnostic failed with exit code $status"; exit "$status" ;;
esacThe project can be built locally or pulled from Docker Hub after a release. The image entry point is aks-ip-diagnostic, so arguments after the image name are passed directly to the CLI.
The package version is generated from Git tags by setuptools-scm. Docker build contexts normally do not include .git, so pass the version explicitly:
VERSION="0.1.0"
docker build \
--build-arg APP_VERSION="$VERSION" \
-t aks-ip-diagnostic:"$VERSION" \
-t aks-ip-diagnostic:local \
.Verify the image:
docker run --rm aks-ip-diagnostic:local version
docker run --rm aks-ip-diagnostic:local --helpReplace <dockerhub-user> and <version> with the published repository and release version:
docker pull <dockerhub-user>/aks-ip-diagnostic:<version>
docker run --rm <dockerhub-user>/aks-ip-diagnostic:<version> versionUse immutable version tags in automation. The latest tag is convenient for manual testing but does not identify a specific release.
docker run --rm \
-e AZURE_CLIENT_ID \
-e AZURE_TENANT_ID \
-e AZURE_CLIENT_SECRET \
<dockerhub-user>/aks-ip-diagnostic:<version> scan \
--subscription-id "<subscription-id>" \
--resource-group "<resource-group>" \
--cluster-name "<cluster-name>"The three Azure variables must already be exported in the host shell. Avoid placing secret values directly in shell history. An environment file can also be used:
cat > .env.azure <<'EOF'
AZURE_CLIENT_ID=<client-id>
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_SECRET=<client-secret>
EOF
chmod 600 .env.azure
docker run --rm \
--env-file .env.azure \
<dockerhub-user>/aks-ip-diagnostic:<version> scan \
--subscription-id "<subscription-id>" \
--resource-group "<resource-group>" \
--cluster-name "<cluster-name>"The container runs as an unprivileged user. Mount a writable host directory at /app/reports:
mkdir -p reports
chmod u+rwx reports
docker run --rm \
--env-file .env.azure \
--mount type=bind,src="$(pwd)/reports",dst=/app/reports \
<dockerhub-user>/aks-ip-diagnostic:<version> scan \
--subscription-id "<subscription-id>" \
--resource-group "<resource-group>" \
--cluster-name "<cluster-name>" \
--format json-pretty \
--validate-schema \
--output /app/reports/aks-ip-report.jsonInspect the output:
ls -l reports/
cat reports/aks-ip-report.json# Show local images
docker image ls aks-ip-diagnostic
# Inspect image metadata
docker image inspect aks-ip-diagnostic:local
# Run an interactive shell for troubleshooting
docker run --rm -it --entrypoint /bin/sh aks-ip-diagnostic:local
# Remove a local image
docker image rm aks-ip-diagnostic:local
# Remove unused build cache
docker builder pruneThe helm job in the release workflow validates and packages the Helm chart. It is useful when the CLI is intended to run inside Kubernetes, for example as a one-off Job, scheduled CronJob, or an operator-support utility.
The job normally performs three release checks:
helm lintchecks the chart for structural and template problems.helm packagecreates a versioned.tgzchart archive.actions/upload-artifactstores that archive with the workflow run.
The job does not deploy anything to a Kubernetes cluster and, as currently written, does not publish the chart to an OCI registry or Helm repository. If the project is only distributed as a Python package and Docker image, the Helm job is optional and can be removed. Keep it when Kubernetes installation is a supported distribution path.
For a release tag such as v0.1.0, package the chart with the matching version and application version:
helm lint charts/aks-ip-diagnostic
helm package charts/aks-ip-diagnostic \
--destination dist \
--version 0.1.0 \
--app-version 0.1.0Test a chart locally before publishing it:
helm template aks-ip-diagnostic charts/aks-ip-diagnostic \
--set image.repository=<dockerhub-user>/aks-ip-diagnostic \
--set image.tag=0.1.0
helm install aks-ip-diagnostic charts/aks-ip-diagnostic \
--namespace aks-ip-diagnostic \
--create-namespace \
--set image.repository=<dockerhub-user>/aks-ip-diagnostic \
--set image.tag=0.1.0
helm uninstall aks-ip-diagnostic --namespace aks-ip-diagnosticCLI
└── scan runner
├── scan configuration
├── orchestrator
│ ├── Azure collector and SDK wrappers
│ ├── diagnostic rules
│ └── report builder
├── schema validation
├── redaction
├── formatting
└── exit-code mapping
See docs/ARCHITECTURE.md for module responsibilities and extension points.
Run the local checks before opening a pull request:
python -m compileall -q src tests examples
pytest -q
ruff check .
ruff format --check .
bandit -r src -x tests
pip-auditThe GitHub CI workflow runs these checks across Python 3.10, 3.11, and 3.12 and also builds the Docker image.
Do not publish this as a production-supported tool until the high-priority items in docs/PRODUCTION_REVIEW.md are resolved. The main gaps are:
- optional pod and detailed cost analyses are not wired into the orchestrator
- no live Azure integration or recorded-contract test suite exists
- cost figures use a static heuristic table and should not be treated as billing data
- dependency resolution is not locked or reproducible
- release publishing needs stronger guards and provenance controls
- large diagnostic and formatting modules should be split before significant feature growth
| Document | Purpose |
|---|---|
QUICKSTART.md |
Minimal installation and first-scan path |
docs/ARCHITECTURE.md |
Execution flow and module ownership |
docs/PRODUCTION_REVIEW.md |
Prioritised production-readiness findings |
docs/PRODUCTION_READINESS.md |
Release gate, permissions, and operating rules |
docs/JSON_OUTPUT_GUIDE.md |
Report validation, conversion, and automation |
docs/TROUBLESHOOTING.md |
Common runtime and report problems |
CONTRIBUTING.md |
Contributor setup and change rules |
docs/RELEASE_GUIDE.md |
Versioning and release process |
docs/DOCS_INDEX.md |
Documentation ownership map |
- The tool is intended to be read-only.
- Redaction reduces exposure but does not replace a data-classification review.
- Capacity calculations depend on Azure SDK data and networking mode.
- Cost values are rough estimates, not invoices or pricing guarantees.
- Validate recommendations against the cluster’s networking design before making changes.