# Detect Deprecated Kubernetes APIs Before Upgrading
> Use Pluto to identify deprecated or removed Kubernetes APIs in your manifests and Helm charts before upgrading, ensuring smooth and predictable cluster upgrade.

Canonical: https://blog.abhimanyu-saharan.com/posts/detect-deprecated-kubernetes-apis-before-upgrading
Published: 2025-05-27
Last updated: 2025-05-24
Authors: Abhimanyu Saharan
Categories: Kubernetes

Kubernetes moves fast, and it deprecates just as fast. One release you’re fine, the next you’re staring at a broken CI pipeline or a failed Helm upgrade wondering what changed.

If you’ve ever seen this and panicked:

```
Error: UPGRADE FAILED: [unable to recognize "": no matches for kind "PodDisruptionBudget" in version "policy/v1beta1"]
```

You know what I’m talking about.

I faced this during an upgrade to Kubernetes v1.25. Our Helm deployment crashed because `policy/v1beta1` was _removed_, not just deprecated. It had been deprecated for several releases, but because Kubernetes auto-converts deprecated resources when queried, we missed it entirely in our pre-upgrade checks. I documented the full breakdown here: [Helm Upgrade Failed After v1.25 Due to PDB API](/posts/helm-upgrade-failed-after-v1-25-due-to-pdb-api).

That incident led me to **Pluto**, a utility that now sits at the front of all my upgrade workflows.

## What Is Pluto?

[Pluto](https://github.com/FairwindsOps/pluto) is a command-line tool developed by Fairwinds that scans your Kubernetes manifests, Helm charts, and live cluster resources to detect deprecated and removed `apiVersion`s.

Think of it as a linter, but for your cluster’s long-term health. Instead of warning you about indentation or typos, it warns you about objects that will break silently once you cross a certain Kubernetes version.

## Why Pluto Matters

### Kubernetes is _too helpful_ for its own good

The Kubernetes API server is designed to be backward-compatible. When you `kubectl get` or inspect objects, it quietly translates older APIs into their latest supported versions. That means even if you deployed a resource using `extensions/v1beta1`, you’ll likely see it returned as `apps/v1`.

That’s great for smooth operation, but it makes it extremely hard to **audit for upcoming breakage**.

### Helm doesn’t catch everything

Helm doesn’t throw warnings for deprecated APIs. If your template renders fine, it assumes it’s valid. But that rendered manifest might use an API that’s already been removed in your target version. The deploy will fail, and you’ll only find out after rollout starts.

### CI pipelines are blind to deprecation

Unless you explicitly add tools like Pluto to your CI, your pipeline won’t catch these issues until they’re too late.

## How Pluto Actually Works

Pluto works in three major modes:

1. **Static detection**: Scans YAML manifests and Helm templates in your codebase.
2. **Helm detection (live)**: Scans existing Helm releases in a running cluster.
3. **API resource detection**: Scans live cluster resources (CRDs, PSPs, Ingress, etc.).

It tells you:

- Whether the `apiVersion` is **deprecated** or **removed**
- Since which Kubernetes version the deprecation/removal applies
- If a **replacement** exists
- If that replacement is **available** in the current version

## Live Example: Pluto on an Older Cluster

To test Pluto’s effectiveness, I spun up an older Kubernetes cluster and scanned it using Pluto v5.21.4.

Here’s what I found with **live resource detection**:

```sh
$ ./pluto detect-api-resources

W0525 01:23:19.448885   warnings.go:70] v1 ComponentStatus is deprecated in v1.19+
W0525 01:23:29.541324   warnings.go:70] extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+
W0525 01:23:30.167640   warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+

NAME                      KIND                  VERSION          REPLACEMENT   REMOVED   DEPRECATED   REPL AVAIL
calico-kube-controllers   PodDisruptionBudget   policy/v1beta1   policy/v1     true      true         true

```

And then I scanned a Helm release, targeting Kubernetes v1.32.0:

```sh
$ ./pluto detect-helm --target-versions k8s=v1.32.0

NAME                                                KIND                VERSION          REPLACEMENT   REMOVED   DEPRECATED   REPL AVAIL
kube-state-metrics/kube-state-metrics-kube-system   PodSecurityPolicy   policy/v1beta1                 true      true         false
```

In both cases, Pluto detected deprecated resources, showed whether a replacement was available, and indicated the version where the removal occurs.

This is exactly the sort of signal I wish I had _before_ my Helm upgrade failed.

## How to Integrate Pluto into CI

Here’s the real value: Pluto isn’t just a manual tool. You can wire it into your CI/CD pipelines to block pull requests or Helm deployments that introduce deprecated APIs.

### GitHub Actions Example

```yaml
name: Check Deprecated Kubernetes APIs

on:
  pull_request:
    paths:
      - '**/*.yaml'
      - 'charts/**'

jobs:
  deprecations:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install Pluto
        run: |
          curl -sLO https://github.com/FairwindsOps/pluto/releases/download/v5.21.4/pluto_5.21.4_linux_amd64.tar.gz
          tar -xzf pluto_5.21.4_linux_amd64.tar.gz
          sudo mv pluto /usr/local/bin/

      - name: Run Pluto on Helm charts
        run: |
          helm template ./charts | pluto detect --target-versions k8s=v1.32.0 || exit_code=$?
          if [[ "$exit_code" -eq 2 || "$exit_code" -eq 3 ]]; then
            echo "::error ::Deprecated or removed APIs found. Fix before merge."
            exit 1
          fi

```

### Customize It

- Use `--only-show-removed` if you only care about **breakage**.
- Use `--output json` to generate reports that can be uploaded to artifact storage or dashboards.
- Use `--ignore-deprecations` in lower environments but block removals in staging and prod.

## Final Thoughts

Cluster upgrades are risky not because of the upgrade itself, but because of the **hidden deprecations** that lie in wait.

**Pluto is the upgrade audit tool Kubernetes never gave us.**

Add it to your workflow if:

- You deploy Helm charts regularly
- You manage more than one cluster
- You want to simulate upgrade readiness before touching `kubeadm upgrade`

I run it before every major version bump, and now I never go in blind.

## FAQ

### What problem does Pluto solve in Kubernetes upgrades?

Pluto detects deprecated or removed `apiVersions` in Kubernetes manifests, Helm charts, and live clusters, issues the API server masks by auto-converting versions.

### Why can’t I rely on the Kubernetes API server to find deprecated resources?

Because the API server auto-converts older versions (e.g., `extensions/v1beta1`) to newer ones (e.g., `apps/v1`) on read, hiding deprecated usage during inspection.

### How does Pluto help prevent Helm upgrade failures?

Pluto flags deprecated or removed APIs used in Helm charts before deployment, preventing runtime failures caused by missing or outdated `apiVersion`s.

### Can Pluto be used in CI/CD pipelines?

Yes. Pluto supports non-zero exit codes for deprecated or removed APIs, making it easy to fail CI jobs and enforce compatibility checks before merging or deploying.

### What are the different ways Pluto can scan for deprecated APIs?

Pluto can scan static YAML files, rendered Helm charts, live Helm releases in clusters, and active API resources like PodDisruptionBudgets or Ingress objects.
