From 2667a63a6d9165b556be746631769b08d97713d4 Mon Sep 17 00:00:00 2001 From: Etienne Champetier Date: Mon, 29 Apr 2024 15:08:41 -0400 Subject: [PATCH] [kubernetes] plugin improvements - enable when k8s services are running - enable when kubelet package is present - add admin.conf as default kubeconfig - ensure we are not enabled if Openshift is - use 'oc' when present: this is relevant only for old OpenShift installs move limitranges / resourcequotas to the base plugin - collect journal only for enabled services - scrub collected files Signed-off-by: Etienne Champetier --- sos/report/plugins/kubernetes.py | 119 +++++++++++++++++++------------ 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/sos/report/plugins/kubernetes.py b/sos/report/plugins/kubernetes.py index eb3e3747d..e15bb7447 100644 --- a/sos/report/plugins/kubernetes.py +++ b/sos/report/plugins/kubernetes.py @@ -13,7 +13,26 @@ import re from sos.report.plugins import (Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin, PluginOpt) +from sos.utilities import is_executable import json +import os + +KUBE_PACKAGES = ( + 'kubelet', + 'kubernetes', +) + +KUBE_SVCS = ( + 'kubelet', + 'kube-apiserver', + 'kube-proxy', + 'kube-scheduler', + 'kube-controller-manager', +) + +KUBECONFIGS = ( + '/etc/kubernetes/admin.conf', +) class Kubernetes(Plugin): @@ -46,6 +65,8 @@ class Kubernetes(Plugin): 'cronjobs', 'clusterroles', 'clusterrolebindings' + 'limitranges', + 'resourcequotas', ] # these are not namespaced, must pull separately. @@ -69,6 +90,14 @@ class Kubernetes(Plugin): kube_cmd = "kubectl" + def set_kubeconfig(self): + if os.environ.get('KUBECONFIG'): + return + for _kconf in self.files: + if self.path_exists(_kconf): + self.kube_cmd += f" --kubeconfig={_kconf}" + break + def check_is_master(self): """ Check if this is the master node """ return any(self.path_exists(f) for f in self.files) @@ -83,21 +112,9 @@ def setup(self): 'KUBERNETES_NO_PROXY' ]) - svcs = [ - 'kubelet', - 'kube-apiserver', - 'kube-proxy', - 'kube-scheduler', - 'kube-controller-manager', - 'snap.kubelet.daemon', - 'snap.kube-apiserver.daemon', - 'snap.kube-proxy.daemon', - 'snap.kube-scheduler.daemon', - 'snap.kube-controller-manager.daemon' - ] - - for svc in svcs: - self.add_journal(units=svc) + for svc in self.services: + if self.is_service_enabled(svc): + self.add_journal(units=svc) # We can only grab kubectl output from the master if not self.check_is_master(): @@ -247,62 +264,74 @@ def postproc(self): # output that is not hit by the previous iteration. self.do_cmd_private_sub(self.kube_cmd) + pathexp = fr'^({"|".join(self.config_files)})' + self.do_file_private_sub(pathexp) + + # clear base64 encoded PEM from kubeconfigs files + regexp = r'LS0tLS1CRUdJ[A-Za-z0-9+/=]+' + subst = '***** SCRUBBED BASE64 PEM *****' + pathexp = fr'^({"|".join(self.files+self.config_files)})' + self.do_path_regex_sub(pathexp, regexp, subst) + class RedHatKubernetes(Kubernetes, RedHatPlugin): - # OpenShift Container Platform uses the atomic-openshift-master package - # to provide kubernetes - packages = ('kubernetes', 'kubernetes-master', 'atomic-openshift-master') + packages = KUBE_PACKAGES + ( + 'kubernetes-master', + 'atomic-openshift-master' + ) - files = ( + files = KUBECONFIGS + ( '/etc/origin/master/admin.kubeconfig', '/etc/origin/node/pods/master-config.yaml', ) - kube_cmd = "kubectl" + services = KUBE_SVCS + + def check_enabled(self): + # do not run at the same time as the openshift plugin + if self.is_installed("openshift-hyperkube"): + return False + return super().check_enabled() def setup(self): - # Rather than loading the config file, use the OCP command directly - # that wraps kubectl, so we don't have to manually account for any - # other changes the `oc` binary may implement - if self.path_exists('/etc/origin/master/admin.kubeconfig'): + self.set_kubeconfig() + + # if present, use `oc` command and add some OCP specific ressources + if is_executable('oc'): self.kube_cmd = 'oc' - self.resources.extend([ - 'limitranges', - 'policies', - 'resourcequotas', - 'routes' - ]) - self.global_resources.extend([ - 'projects', - 'pvs' - ]) + self.resources.extend([ + 'policies', + 'routes' + ]) + self.global_resources.extend([ + 'projects', + 'pvs' + ]) super().setup() class UbuntuKubernetes(Kubernetes, UbuntuPlugin, DebianPlugin): - packages = ('kubernetes',) + packages = KUBE_PACKAGES - files = ( + files = KUBECONFIGS + ( '/root/cdk/cdk_addons_kubectl_config', - '/etc/kubernetes/admin.conf', '/var/snap/microk8s/current/credentials/client.config', ) - services = ( + services = KUBE_SVCS + ( + 'snap.kubelet.daemon', + 'snap.kube-apiserver.daemon', + 'snap.kube-proxy.daemon', + 'snap.kube-scheduler.daemon', + 'snap.kube-controller-manager.daemon' # CDK 'cdk.master.auth-webhook', ) def setup(self): - for _kconf in self.files: - if self.path_exists(_kconf): - self.kube_cmd += f" --kubeconfig={_kconf}" - break - - for svc in self.services: - self.add_journal(units=svc) + self.set_kubeconfig() if self.is_installed('microk8s'): self.kube_cmd = 'microk8s kubectl'