Skip to content

Commit b6ae308

Browse files
Track Kubernetes Channels for latest versions (#351)
Co-authored-by: Maria Reynoso <[email protected]> Co-authored-by: maria-reynoso <[email protected]> Co-authored-by: Maria Reynoso <[email protected]>
1 parent e0bc8cd commit b6ae308

File tree

15 files changed

+1500
-16
lines changed

15 files changed

+1500
-16
lines changed

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,29 @@
66
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/jetstack/version-checker)
77

88
version-checker is a Kubernetes utility for observing the current versions of
9-
images running in the cluster, as well as the latest available upstream. These
10-
checks get exposed as Prometheus metrics to be viewed on a dashboard, or _soft_
11-
alert cluster operators.
9+
images running in the cluster, as well as the latest available upstream. Additionally,
10+
it monitors the Kubernetes cluster version against the latest available releases
11+
using official Kubernetes release channels. These checks get exposed as Prometheus
12+
metrics to be viewed on a dashboard, or _soft_ alert cluster operators.
13+
14+
## Features
15+
16+
- **Container Image Version Checking**: Monitor and compare container image versions running in the cluster against their latest upstream versions
17+
- **Kubernetes Version Monitoring**: Track your cluster's Kubernetes version against the latest available releases from official Kubernetes channels
18+
- **Prometheus Metrics Integration**: Export all version information as Prometheus metrics for monitoring and alerting
19+
- **Flexible Channel Selection**: Configure which Kubernetes release channel to track (stable, latest, etc.)
1220

1321
---
1422

1523
## Why Use version-checker?
1624

17-
- **Improved Security**: Ensures images are up-to-date, reducing the risk of using vulnerable or compromised versions.
18-
- **Enhanced Visibility**: Provides a clear overview of all running container versions across clusters.
19-
- **Operational Efficiency**: Automates image tracking and reduces manual intervention in version management.
20-
- **Compliance and Policy**: Enforcement: Helps maintain version consistency and adherence to organizational policies.
25+
- **Improved Security**: Ensures images and Kubernetes clusters are up-to-date, reducing the risk of using vulnerable or compromised versions.
26+
- **Enhanced Visibility**: Provides a clear overview of all running container versions and cluster versions across clusters.
27+
- **Operational Efficiency**: Automates image and Kubernetes version tracking and reduces manual intervention in version management.
28+
- **Compliance and Policy Enforcement**: Helps maintain version consistency and adherence to organizational policies for both applications and infrastructure.
2129
- **Incremental Upgrades**: Facilitates frequent, incremental updates to reduce the risk of large, disruptive upgrades.
2230
- **Add-On Compatibility**: Ensures compatibility with the latest versions of Kubernetes add-ons and dependencies.
31+
- **Proactive Cluster Management**: Stay informed about Kubernetes security updates and new features through automated version monitoring.
2332

2433
---
2534

@@ -45,6 +54,7 @@ These registries support authentication.
4554

4655
- [Installation Guide](docs/installation.md)
4756
- [Metrics](docs/metrics.md)
57+
- [New Features](docs/new_features.md)
4858

4959
---
5060

cmd/app/app.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,36 @@ func NewCommand(ctx context.Context) *cobra.Command {
110110
return fmt.Errorf("failed to setup image registry clients: %s", err)
111111
}
112112

113-
c := controller.NewPodReconciler(opts.CacheTimeout,
113+
_ = client
114+
115+
podController := controller.NewPodReconciler(opts.CacheTimeout,
114116
metricsServer,
115117
client,
116118
mgr.GetClient(),
117119
log,
118120
opts.RequeueDuration,
119121
opts.DefaultTestAll,
120122
)
121-
122-
if err := c.SetupWithManager(mgr); err != nil {
123+
if err := podController.SetupWithManager(mgr); err != nil {
123124
return err
124125
}
125126

127+
kubeController := controller.NewKubeReconciler(
128+
log,
129+
mgr.GetConfig(),
130+
metricsServer,
131+
opts.KubeInterval,
132+
opts.KubeChannel,
133+
)
134+
135+
// Only add to manager if controller was created (channel was specified)
136+
if kubeController != nil {
137+
if err := mgr.Add(kubeController); err != nil {
138+
return err
139+
}
140+
log.WithField("channel", opts.KubeChannel).Info("Kubernetes version checking enabled")
141+
}
142+
126143
// Start the manager and all controllers
127144
log.Info("Starting controller manager")
128145
if err := mgr.Start(ctx); err != nil {

cmd/app/options.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ type Options struct {
7575
CacheSyncPeriod time.Duration
7676
RequeueDuration time.Duration
7777

78+
KubeChannel string
79+
KubeInterval time.Duration
80+
81+
// kubeConfigFlags holds the flags for the kubernetes client
7882
kubeConfigFlags *genericclioptions.ConfigFlags
7983

8084
selfhosted selfhosted.Options
@@ -141,7 +145,15 @@ func (o *Options) addAppFlags(fs *pflag.FlagSet) {
141145

142146
fs.DurationVarP(&o.CacheSyncPeriod,
143147
"cache-sync-period", "", 5*time.Hour,
144-
"The time in which all resources should be updated.")
148+
"The duration in which all resources should be updated.")
149+
150+
fs.DurationVarP(&o.KubeInterval,
151+
"kube-interval", "", o.CacheSyncPeriod,
152+
"The time in which kubernetes channels updates are checked.")
153+
154+
fs.StringVarP(&o.KubeChannel,
155+
"kube-channel", "", "stable",
156+
"The Kubernetes channel to check against for cluster updates.")
145157

146158
fs.DurationVarP(&o.GracefulShutdownTimeout,
147159
"graceful-shutdown-timeout", "", 10*time.Second,

docs/metrics.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,32 @@
22

33
By default, version-checker exposes the following Prometheus metrics on `0.0.0.0:8080/metrics`:
44

5+
## Container Image Metrics
6+
57
- `version_checker_is_latest_version`: Indicates whether the container in use is using the latest upstream registry version.
68
- `version_checker_last_checked`: Timestamp when the image was last checked.
79
- `version_checker_image_lookup_duration`: Duration of the image version check.
810
- `version_checker_image_failures_total`: Total of errors encountered during image version checks.
911

12+
## Kubernetes Version Metrics
13+
14+
- `version_checker_is_latest_kube_version`: Indicates whether the cluster is running the latest version from the configured Kubernetes release channel.
15+
- Labels: `current_version`, `latest_version`, `channel`
16+
- Value `1`: Cluster is up-to-date
17+
- Value `0`: Update available
18+
1019
---
1120

12-
## Example Prometheus Query
21+
## Example Prometheus Queries
1322

23+
### Check container image versions
1424
```sh
1525
QUERY="version_checker_is_latest_version"
1626
curl -s --get --data-urlencode query=$QUERY <PROMETHEUS_URL>
17-
```
27+
```
28+
29+
### Check Kubernetes cluster version
30+
```sh
31+
QUERY="version_checker_is_latest_kube_version"
32+
curl -s --get --data-urlencode query=$QUERY <PROMETHEUS_URL>
33+
```

docs/new_features.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Kubernetes Version Monitoring
2+
3+
version-checker now includes built-in Kubernetes cluster version monitoring capabilities. This feature automatically compares your cluster's current Kubernetes version against the latest available versions from official Kubernetes release channels.
4+
5+
### How It Works
6+
7+
The Kubernetes version checker:
8+
- Fetches the current cluster version using the Kubernetes Discovery API
9+
- Compares it against the latest version from the configured Kubernetes release channel (using official `https://dl.k8s.io/release/` endpoints)
10+
- Exposes the comparison as Prometheus metrics for monitoring and alerting
11+
- Strips metadata from versions for accurate semantic version comparison (e.g., `v1.28.2-gke.1` becomes `v1.28.2`)
12+
13+
### Configuration
14+
15+
You can configure the Kubernetes version checking behavior using the following CLI flags:
16+
17+
- `--kube-channel`: Specifies which Kubernetes release channel to check against (default: `"stable"`)
18+
- Examples: `stable`, `latest`, `stable-1.28`, `latest-1.29`
19+
- `--kube-interval`: How often to check for Kubernetes version updates (default: same as `--cache-sync-period`, 5 hours)
20+
21+
### Metrics
22+
23+
The Kubernetes version monitoring exposes the following Prometheus metric:
24+
25+
```
26+
version_checker_is_latest_kube_version{current_version="1.28.2", latest_version="1.29.1", channel="stable"} 0
27+
```
28+
29+
- Value `1`: Cluster is running the latest version from the specified channel
30+
- Value `0`: Cluster is not running the latest version (update available)
31+
32+
### Supported Channels
33+
34+
version-checker uses official Kubernetes release channels:
35+
36+
- `stable` - Latest stable Kubernetes release (recommended)
37+
- `latest` - Latest Kubernetes release (including pre-releases)
38+
- `latest-1.28` - Latest patch for Kubernetes 1.28.x
39+
- `latest-1.27` - Latest patch for Kubernetes 1.27.x
40+
41+
### Examples
42+
43+
```bash
44+
# Check against latest stable Kubernetes
45+
version-checker --kube-version-channel=stable
46+
47+
# Check against latest Kubernetes (including alpha/beta)
48+
version-checker --kube-version-channel=latest
49+
50+
# Check against latest 1.28.x patch
51+
version-checker --kube-version-channel=latest-1.28
52+
53+
# Monitor against a specific version channel with custom interval
54+
./version-checker --kube-channel=stable-1.28 --kube-interval=1h
55+
```
56+
57+
### Managed Kubernetes Support
58+
59+
Works with all managed Kubernetes services:
60+
- **Amazon EKS**: Compares `v1.28.2-eks-abc123` against upstream `v1.28.2`
61+
- **Google GKE**: Compares `v1.28.2-gke.1034000` against upstream `v1.28.2`
62+
- **Azure AKS**: Compares `v1.28.2-aks-xyz789` against upstream `v1.28.2`

pkg/client/docker/docker.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
retryablehttp "github.com/hashicorp/go-retryablehttp"
1818
"github.com/jetstack/version-checker/pkg/api"
1919
"github.com/jetstack/version-checker/pkg/client/util"
20+
leveledlogger "github.com/jetstack/version-checker/pkg/leveledlogrus"
2021
)
2122

2223
// Ensure that we are an ImageClient
@@ -69,7 +70,7 @@ func New(opts Options, log *logrus.Entry) (*Client, error) {
6970
retryclient.RetryWaitMin = 1 * time.Second
7071
// This custom backoff will fail requests that have a max wait of the RetryWaitMax
7172
retryclient.Backoff = util.HTTPBackOff
72-
retryclient.Logger = log.WithField("client", "docker")
73+
retryclient.Logger = leveledlogger.Logger{Entry: log.WithField("client", "docker")}
7374
client := retryclient.StandardClient()
7475

7576
// Setup Auth if username and password used.

pkg/client/fallback/fallback.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ func (c *Client) Tags(ctx context.Context, host, repo, image string) (tags []api
5656

5757
remaining := len(c.clients) - i - 1
5858
if remaining == 0 {
59-
c.log.Debugf("failed to lookup via %q, Giving up, no more clients", client.Name())
59+
c.log.Infof("failed to lookup via %q, Giving up, no more clients", client.Name())
6060
} else {
61-
c.log.Debugf("failed to lookup via %q, continuing to search with %v clients remaining", client.Name(), remaining)
61+
c.log.Infof("failed to lookup via %q, continuing to search with %v clients remaining", client.Name(), remaining)
6262
}
6363
}
6464

pkg/client/quay/quay.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/jetstack/version-checker/pkg/api"
1414
"github.com/jetstack/version-checker/pkg/client/util"
15+
leveledlogger "github.com/jetstack/version-checker/pkg/leveledlogrus"
1516
)
1617

1718
const (
@@ -39,6 +40,7 @@ func New(opts Options, log *logrus.Entry) *Client {
3940
if opts.Transporter != nil {
4041
client.HTTPClient.Transport = opts.Transporter
4142
}
43+
client.Logger = leveledlogger.Logger{Entry: log.WithField("client", "quay")}
4244

4345
return &Client{
4446
Options: opts,

0 commit comments

Comments
 (0)