Skip to content
Go back

Renovate for k8s GitOps

By SumGuy 10 min read
Renovate for k8s GitOps
Contents

You’re Manually Bumping Image Versions in Your GitOps Repo. Stop That.

If you’re running Kubernetes the right way, manifests in Git, ArgoCD or Flux syncing them to the cluster, you’ve probably noticed something annoying: new container image releases drop constantly, chart maintainers push updates, and somebody has to go hand-edit those YAML files and commit the changes. That somebody is usually you at 2 AM, wondering if you missed a tag somewhere.

Renovate fixes this. It’s a bot that watches your dependencies (images, charts, base images in Dockerfiles, whatever) and opens PRs when updates are available. You review, test, merge. Automation handles the tedious parts. It’s like hiring a very thorough intern who never sleeps and doesn’t complain about typos.

This isn’t your standard Renovate setup (that’s the Dependabot article). This is Renovate configured for Kubernetes and Helm specifically, the regex managers, scheduling strategy, grouping rules, and the gotchas that bite you when you’re deploying to a cluster instead of a Node.js app.


Why Renovate Over Dependabot (or Manual)?

Dependabot is GitHub’s native tool. It’s solid for npm and pip. It barely understands Helm. It doesn’t understand Kubernetes image references in YAML at all. It’s like showing up to a fight with a hammer when you need a wrench.

Manual updates are reliable until they’re not. You’ll miss a patch, forget to test it, ship a breaking chart change on Friday afternoon, or get burned when a new image version silently drops support for ARM64. There’s no audit trail, no consistency, no automation.

Renovate was built for monorepos and Kubernetes. It has first-class Helm support, regex managers for custom YAML formats, scheduling that doesn’t spam you with 50 PRs on Monday, and grouping rules so you can batch related updates together. It understands that you can’t test every single image version independently, you need to group them, rate-limit them, and merge them intelligently.


Getting Renovate Running

You have two paths: self-hosted or Renovate Cloud.

For most home lab GitOps setups, Renovate Cloud is the move. Install the Renovate app from the GitHub Marketplace (https://github.com/apps/renovate), authorize it on your repo, and you’re off. The free tier covers unlimited public and private repos. It’s honestly that simple, and the defaults are already decent.

But the real power unlocks when you write a renovate.json config tailored to your setup.


Basic renovate.json for Kubernetes + Helm

Here’s a starter config that handles the essentials, Helm chart updates, container image updates, and scheduling:

{
"extends": ["config:recommended"],
"timezone": "America/Los_Angeles",
"schedule": ["after 10pm every weekday", "before 5am on weekends"],
"labels": ["renovate", "automation"],
"ignorePaths": ["archive/**", "deprecated/**"],
"helm": {
"enabled": true
},
"vulnerabilityAlerts": {
"labels": ["security", "urgent"],
"assignees": ["@me"]
},
"packageRules": [
{
"matchDatasources": ["docker"],
"groupName": "Docker images",
"schedule": ["after 10pm every weekday"]
},
{
"matchDatasources": ["helm"],
"groupName": "Helm charts",
"schedule": ["after 10pm on weekends"]
},
{
"matchUpdateTypes": ["patch"],
"automerge": true,
"automergeType": "pr",
"automergeStrategy": "squash"
}
]
}

What’s happening here:

This covers 80% of what you need. The remaining 20% is regex managers for edge cases.


Regex Managers: Taming Kubernetes YAML

Kubernetes manifests don’t always follow standard dependency formats. You might have image references baked into a Kustomization, a custom YAML format, or embedded in a ConfigMap. Renovate handles this with regex managers.

Here’s a realistic example: you have a k3s cluster, and you’re pinning Traefik in your traefik-values.yaml like this:

image:
repository: traefik
tag: 3.1.0

Renovate won’t find that out of the box (it needs to know how to parse it). You tell it with a regex manager:

{
"extends": ["config:recommended"],
"helm": {
"enabled": true
},
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": ["/helm/.*values\\.ya?ml$/", "/.*-values\\.ya?ml$/"],
"matchStrings": [
"image:\\n\\s+repository:\\s+(?<depName>[\\w\\-\\.]+/[\\w\\-\\.]+)\\n\\s+tag:\\s+(?<currentValue>[\\w\\-\\.]+)"
],
"datasourceTemplate": "docker",
"versioningTemplate": "semver"
},
{
"customType": "regex",
"managerFilePatterns": ["/.*\\.ya?ml$/"],
"matchStrings": [
"image:\\s+(?<depName>[\\w\\-\\.]+/[\\w\\-\\.]+):(?<currentValue>[\\w\\-\\.]+)@(?<currentDigest>sha256:[a-f0-9]{64})"
],
"datasourceTemplate": "docker",
"pinDigests": true
}
]
}

What’s going on:

Heads up: recent Renovate renamed fileMatch to managerFilePatterns in custom managers. The old key still works via auto-migration (you’ll just get a “config migration necessary” nag), but if you’re writing a config fresh, use managerFilePatterns and wrap regex values in slashes (/.../), plain strings are now treated as globs.

Regex managers are powerful but annoying to debug. Pro tip: test them in the Renovate REPL (settings → Renovate settings in the PR) or use an online regex tester and validate your matchStrings before committing.


Helm Chart Dependencies (The Easy Way)

If you’re using Helm properly, your charts have dependencies defined in Chart.yaml:

dependencies:
- name: argocd
version: "7.3.x"
repository: https://argoproj.github.io/argo-helm
- name: longhorn
version: "1.6.x"
repository: https://charts.longhorn.io

Renovate will automatically detect and update these if helm.enabled: true is set. No regex needed. It’ll respect your version constraints (the x lets it bump patch versions but not minor), and it’ll validate the chart exists on the repo before opening a PR.

Add this to your config to group all Helm updates together:

{
"packageRules": [
{
"matchDatasources": ["helm"],
"groupName": "Helm chart dependencies",
"schedule": ["after 10pm on Sunday"],
"reviewers": ["@me"]
}
]
}

Scheduling and Grouping (So You Don’t Wake Up to 50 PRs)

This is where most people trip up. If you don’t schedule and group, Renovate will open a PR for every single version bump, and you’ll have 30 PRs by Monday morning, each one needing individual review and test cycles. That’s worse than doing it manually.

Here’s a smarter approach:

{
"extends": ["config:recommended"],
"timezone": "America/Denver",
"schedule": ["after 10pm every weekday", "before 7am on weekends"],
"packageRules": [
{
"matchDatasources": ["docker"],
"groupName": "Docker image updates",
"groupSlug": "docker-updates",
"schedule": ["after 10pm on Monday"],
"minimumReleaseAge": "7 days",
"automerge": true,
"automergeType": "pr",
"automergeStrategy": "squash",
"matchUpdateTypes": ["patch", "minor"]
},
{
"matchDatasources": ["docker"],
"matchUpdateTypes": ["major"],
"labels": ["breaking-change"],
"schedule": ["after 10pm on Friday"],
"automerge": false
},
{
"matchDatasources": ["helm"],
"groupName": "Helm chart updates",
"schedule": ["after 2am on Sunday"],
"minimumReleaseAge": "14 days"
},
{
"matchPackageNames": ["prometheus", "grafana", "loki"],
"groupName": "Observability stack",
"schedule": ["after 6pm on Wednesday"]
}
]
}

The strategy:

minimumReleaseAge matters. It means “don’t open a PR for a version that’s been out for less than X days.” This filters out the garbage, you avoid early adopter pain and let maintainers squash any immediate bugs.


ArgoCD and Flux Compatibility

Both ArgoCD and Flux are GitOps operators. Renovate doesn’t care which one you use, it just commits to your Git repo, and your operator syncs the changes. Here’s the shape of it:

With ArgoCD:

With Flux:

In both cases, Renovate just needs write access to your repo. No special integration needed. It’s blissfully simple.

But here’s a gotcha: if you have a commit hook or branch protection rule that runs tests, Renovate respects it. Your CI will run against Renovate’s PR, and if the tests fail, the PR stays open until you fix it. This is actually good, you catch bad chart versions before they’re deployed, but it means you need solid test coverage on your manifests. At minimum, a helm lint and a kube-score check.


Common Mistakes

Mistake 1: Not pinning versions in your base Helm charts. If your Chart.yaml says version: "*", Renovate will open a PR for every new version, even breaking ones. Use semver constraints: "3.x" for minor/patch safety, ">=3.0.0,<4.0.0" for explicit ranges.

Mistake 2: Ignoring the digest. If you’re pinning image digests (good practice), Renovate needs to know. Set pinDigests: true in your regex manager, and make sure your regex captures both tag and currentDigest. Otherwise you’ll have stale digests pointing to old images.

Mistake 3: Opening too many PRs at once. If you don’t schedule and group, Renovate becomes noise, and you’ll disable it. Start with one grouping strategy (e.g., “all Docker images weekly”), prove it works for a month, then add complexity.

Mistake 4: Not configuring vulnerabilityAlerts. Security patches should never be grouped with regular updates. They should be fast-tracked, labeled, and reviewed immediately. Make them impossible to ignore.

Mistake 5: Forgetting Renovate’s branch protection. If your repo requires branch protection (reviews, status checks), Renovate’s PRs will respect that. If you trust Renovate’s patch updates, set up auto-merge, but only for patch versions. Major versions still need human eyes.


The Endgame

After a few months of Renovate doing its thing, you’ll have:

It’s not magic. It’s just the boring work automated away so you can focus on the stuff that actually matters, testing, incident response, and building the next thing.

Set it and forget it. Your future self will thank you.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Next Post
MetalLB for Bare-Metal LoadBalancer

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts