Skip to content

Commit

Permalink
feat: scrape minimum kubelet version from k8s nodes (#223)
Browse files Browse the repository at this point in the history
* feat: scrape minimum kubelet version from k8s nodes

* log pinger errors
  • Loading branch information
floreks authored Jun 17, 2024
1 parent 7243acc commit a3cbfb6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
3 changes: 2 additions & 1 deletion pkg/ping/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
"k8s.io/apimachinery/pkg/version"
)

func pingAttributes(info *version.Info, pods []string) console.ClusterPing {
func pingAttributes(info *version.Info, pods []string, minKubeletVersion *string) console.ClusterPing {
vs := strings.Split(info.GitVersion, "-")
return console.ClusterPing{
CurrentVersion: strings.TrimPrefix(vs[0], "v"),
Distro: lo.ToPtr(findDistro(append(pods, info.GitVersion))),
KubeletVersion: minKubeletVersion,
}
}
51 changes: 47 additions & 4 deletions pkg/ping/pinger.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ package ping
import (
"context"

"github.com/pluralsh/deployment-operator/pkg/client"
"github.com/Masterminds/semver/v3"
"github.com/samber/lo"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/kubectl/pkg/cmd/util"

"github.com/pluralsh/deployment-operator/pkg/client"
)

type Pinger struct {
Expand All @@ -28,27 +32,66 @@ func New(console client.Client, discovery *discovery.DiscoveryClient, factory ut
func (p *Pinger) Ping() error {
info, err := p.discoveryClient.ServerVersion()
if err != nil {
klog.ErrorS(err, "failed to get server version")
return err
}

cs, err := p.factory.KubernetesClientSet()
if err != nil {
klog.ErrorS(err, "failed to create kubernetes clientset")
return nil
}

podNames := []string{}
var podNames []string
// can find some distro information by checking what's running in kube-system
if pods, err := cs.CoreV1().Pods("kube-system").List(context.TODO(), metav1.ListOptions{}); err == nil {
if pods, err := cs.CoreV1().Pods("kube-system").List(context.Background(), metav1.ListOptions{}); err == nil {
podNames = lo.Map(pods.Items, func(pod corev1.Pod, ind int) string {
return pod.Name
})
}

attrs := pingAttributes(info, podNames)
minKubeletVersion := p.minimumKubeletVersion(cs)

attrs := pingAttributes(info, podNames, minKubeletVersion)
if err := p.consoleClient.PingCluster(attrs); err != nil {
attrs.Distro = nil
return p.consoleClient.PingCluster(attrs) // fallback to no distro to support old console servers
}

return nil
}

// minimumKubeletVersion tries to scrape a minimum kubelet version across all nodes in the cluster.
// It is expected that the kubelet will report to the API a valid SemVer-ish version.
// If no parsable version is found across all nodes, nil will be returned.
func (p *Pinger) minimumKubeletVersion(client *kubernetes.Clientset) *string {
nodes, err := client.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{})
if err != nil {
klog.ErrorS(err, "failed to list nodes")
return nil
}

minKubeletVersion := new(semver.Version)
for _, node := range nodes.Items {
kubeletVersion, _ := semver.NewVersion(node.Status.NodeInfo.KubeletVersion)
if kubeletVersion == nil {
continue
}

// Initialize with first correctly parsed version
if len(minKubeletVersion.Original()) == 0 {
minKubeletVersion = kubeletVersion
continue
}

if kubeletVersion.LessThan(minKubeletVersion) {
minKubeletVersion = kubeletVersion
}
}

if len(minKubeletVersion.Original()) == 0 {
return nil
}

return lo.ToPtr(minKubeletVersion.Original())
}

0 comments on commit a3cbfb6

Please sign in to comment.