From 6372a7f7f09511d864aa6bd894109d937f4fda65 Mon Sep 17 00:00:00 2001 From: Jake Hunsaker Date: Thu, 12 Jul 2018 12:36:25 -0400 Subject: [kubernetes|etcd] Support OpenShift 3.10 deployments The 3.10 version of OCP changes the deployment configurations for etcd and kubernetes components, and additionally changes the way the etcdctl command is called when running in a static pod. Update these plugins to support this new deployment style. Signed-off-by: Jake Hunsaker --- sos/plugins/etcd.py | 11 +++- sos/plugins/kubernetes.py | 148 +++++++++++++++++++++++----------------------- 2 files changed, 83 insertions(+), 76 deletions(-) diff --git a/sos/plugins/etcd.py b/sos/plugins/etcd.py index c343f750..c8ee3849 100644 --- a/sos/plugins/etcd.py +++ b/sos/plugins/etcd.py @@ -10,6 +10,7 @@ # See the LICENSE file in the source distribution for further information. from sos.plugins import Plugin, RedHatPlugin +from os import path class etcd(Plugin, RedHatPlugin): @@ -19,10 +20,14 @@ class etcd(Plugin, RedHatPlugin): plugin_name = 'etcd' packages = ('etcd',) profiles = ('container', 'system', 'services', 'cluster') - - cmd = 'etcdctl' + files = ('/etc/origin/node/pods/etcd.yaml',) def setup(self): + if path.exists('/etc/origin/node/pods/etcd.yaml'): + etcd_cmd = 'master-exec etcd etcd etcdctl' + else: + etcd_cmd = 'etcdctl' + etcd_url = self.get_etcd_url() self.add_forbidden_path('/etc/etcd/ca') @@ -35,7 +40,7 @@ class etcd(Plugin, RedHatPlugin): 'ls --recursive', ] - self.add_cmd_output(['%s %s' % (self.cmd, sub) for sub in subcmds]) + self.add_cmd_output(['%s %s' % (etcd_cmd, sub) for sub in subcmds]) urls = [ '/v2/stats/leader', diff --git a/sos/plugins/kubernetes.py b/sos/plugins/kubernetes.py index e75c7a37..21cb51df 100644 --- a/sos/plugins/kubernetes.py +++ b/sos/plugins/kubernetes.py @@ -18,11 +18,16 @@ class kubernetes(Plugin, RedHatPlugin): """Kubernetes plugin """ - # Red Hat Atomic Platform and OpenShift Enterprise use the - # atomic-openshift-master package to provide kubernetes + # OpenShift Container Platform uses the atomic-openshift-master package + # to provide kubernetes packages = ('kubernetes', 'kubernetes-master', 'atomic-openshift-master') profiles = ('container',) - files = ("/etc/origin/master/master-config.yaml",) + # use files only for masters, rely on package list for nodes + files = ( + "/var/run/kubernetes/apiserver.key", + "/etc/origin/master/", + "/etc/origin/node/pods/master-config.yaml" + ) option_list = [ ("all", "also collect all namespaces output separately", @@ -33,12 +38,7 @@ class kubernetes(Plugin, RedHatPlugin): ] def check_is_master(self): - if any([ - path.exists("/var/run/kubernetes/apiserver.key"), - path.exists("/etc/origin/master/master-config.yaml") - ]): - return True - return False + return any([path.exists(f) for f in self.files]) def setup(self): self.add_copy_spec("/etc/kubernetes") @@ -56,74 +56,76 @@ class kubernetes(Plugin, RedHatPlugin): self.add_journal(units=svc) # We can only grab kubectl output from the master - if self.check_is_master(): - kube_cmd = "kubectl " - if path.exists('/etc/origin/master/admin.kubeconfig'): - kube_cmd += "--config=/etc/origin/master/admin.kubeconfig" - - kube_get_cmd = "get -o json " - for subcmd in ['version', 'config view']: - self.add_cmd_output('%s %s' % (kube_cmd, subcmd)) - - # get all namespaces in use - kn = self.get_command_output('%s get namespaces' % kube_cmd) - knsps = [n.split()[0] for n in kn['output'].splitlines()[1:] if n] - - resources = [ - 'limitrange', - 'pods', - 'pvc', - 'rc', - 'resourcequota', - 'services' - ] - - # nodes and pvs are not namespaced, must pull separately. - # Also collect master metrics - self.add_cmd_output([ - "{} get -o json nodes".format(kube_cmd), - "{} get -o json pv".format(kube_cmd), - "{} get --raw /metrics".format(kube_cmd) - ]) - - for n in knsps: - knsp = '--namespace=%s' % n - if self.get_option('all'): - k_cmd = '%s %s %s' % (kube_cmd, kube_get_cmd, knsp) - - self.add_cmd_output('%s events' % k_cmd) + if not self.check_is_master(): + return + + kube_cmd = "kubectl " + if path.exists('/etc/origin/master/admin.kubeconfig'): + kube_cmd += "--config=/etc/origin/master/admin.kubeconfig" + + kube_get_cmd = "get -o json " + for subcmd in ['version', 'config view']: + self.add_cmd_output('%s %s' % (kube_cmd, subcmd)) + + # get all namespaces in use + kn = self.get_command_output('%s get namespaces' % kube_cmd) + knsps = [n.split()[0] for n in kn['output'].splitlines()[1:] if n] + + resources = [ + 'limitrange', + 'pods', + 'pvc', + 'rc', + 'resourcequota', + 'services' + ] + + # nodes and pvs are not namespaced, must pull separately. + # Also collect master metrics + self.add_cmd_output([ + "{} get -o json nodes".format(kube_cmd), + "{} get -o json pv".format(kube_cmd), + "{} get --raw /metrics".format(kube_cmd) + ]) + + for n in knsps: + knsp = '--namespace=%s' % n + if self.get_option('all'): + k_cmd = '%s %s %s' % (kube_cmd, kube_get_cmd, knsp) + + self.add_cmd_output('%s events' % k_cmd) - for res in resources: - self.add_cmd_output('%s %s' % (k_cmd, res)) - - if self.get_option('describe'): - # need to drop json formatting for this - k_cmd = '%s get %s' % (kube_cmd, knsp) - for res in resources: - r = self.get_command_output( - '%s %s' % (k_cmd, res)) - if r['status'] == 0: - k_list = [k.split()[0] for k in - r['output'].splitlines()[1:]] - for k in k_list: - k_cmd = '%s %s' % (kube_cmd, knsp) - self.add_cmd_output( - '%s describe %s %s' % (k_cmd, res, k)) - - if self.get_option('podlogs'): - k_cmd = '%s %s' % (kube_cmd, knsp) - r = self.get_command_output('%s get pods' % k_cmd) - if r['status'] == 0: - pods = [p.split()[0] for p in - r['output'].splitlines()[1:]] - for pod in pods: - self.add_cmd_output('%s logs %s' % (k_cmd, pod)) - - if not self.get_option('all'): - k_cmd = '%s get --all-namespaces=true' % kube_cmd for res in resources: self.add_cmd_output('%s %s' % (k_cmd, res)) + if self.get_option('describe'): + # need to drop json formatting for this + k_cmd = '%s get %s' % (kube_cmd, knsp) + for res in resources: + r = self.get_command_output( + '%s %s' % (k_cmd, res)) + if r['status'] == 0: + k_list = [k.split()[0] for k in + r['output'].splitlines()[1:]] + for k in k_list: + k_cmd = '%s %s' % (kube_cmd, knsp) + self.add_cmd_output( + '%s describe %s %s' % (k_cmd, res, k)) + + if self.get_option('podlogs'): + k_cmd = '%s %s' % (kube_cmd, knsp) + r = self.get_command_output('%s get pods' % k_cmd) + if r['status'] == 0: + pods = [p.split()[0] for p in + r['output'].splitlines()[1:]] + for pod in pods: + self.add_cmd_output('%s logs %s' % (k_cmd, pod)) + + if not self.get_option('all'): + k_cmd = '%s get --all-namespaces=true' % kube_cmd + for res in resources: + self.add_cmd_output('%s %s' % (k_cmd, res)) + def postproc(self): # First, clear sensitive data from the json output collected. # This will mask values when the "name" looks susceptible of -- cgit