def _get_namespace_limits(kube, namespace): ns = kubelib.Namespace(kube).get(namespace) # print(repr(ns)) if hasattr(ns.status, "phase"): if ns.status.phase == 'Terminating': LOG.info('Skipping %s (phase is %s)', ns.metadata.name, ns.status.phase) return [] else: LOG.error('Failed to retrieve limits from namespace %s', namespace) return [] return kubelib.LimitRange(kube).get_list()
def see_limits(): """ View all current namespace limits. Usage: see_limits [--context=<context>] [--namespace=<namespace>] Options: --context=<context> kube context [default: None] --namespace=<namespace> kube namespace [default: None] """ args = docopt.docopt(see_limits.__doc__) context = args['--context'] exit_code = 0 errors = [] if context == "None": LOG.debug('Defaulting to the current kubectl context') context = sh.kubectl.config('current-context').stdout.strip().decode('ascii') namespace_name = args['--namespace'] tv = TableView() namespace = TableView('Namespace', center=True, link="namespace") pod_name = TableView('Pod Name', center=True, link="pod.name") container_name = TableView('Container Name', center=True, link="container.name") pod = TableView('Pod', center=True) pod_cpu = TableView('CPU', center=True) pod_cpu_min = TableView('min', center=True, link="pod.min.cpu") pod_cpu_max = TableView('max', center=True, link="pod.max.cpu") pod_cpu.add_columns([pod_cpu_min, pod_cpu_max]) pod_mem = TableView('Memory', center=True) pod_mem_min = TableView('min', center=True, link="pod.min.memory") pod_mem_max = TableView('max', center=True, link="pod.max.memory") pod_mem.add_columns([pod_mem_min, pod_mem_max]) pod.add_columns([pod_cpu, pod_mem]) container = TableView('Container', center=True) container_restart = TableView('Restarts', center=True, link="container.restart") container_last = TableView('LastState', center=True, link="container.laststate") container_cpu = TableView('CPU', center=True) container_cpu_min = TableView('min', center=True, link="container.min.cpu") container_cpu_max = TableView('max', center=True, link="container.max.cpu") container_cpu.add_columns([container_cpu_min, container_cpu_max]) container_mem = TableView('Memory', center=True) container_mem_min = TableView('min', center=True, link="container.min.memory") container_mem_max = TableView('max', center=True, link="container.max.memory") container_mem.add_columns([container_mem_min, container_mem_max]) container_default = TableView('Default', center=True) container_default_cpu = TableView('cpu', center=True, link="container.default.cpu") container_default_mem = TableView('mem', center=True, link="container.default.memory") container_default.add_columns([ container_default_cpu, container_default_mem ]) container_defaultreq = TableView('Def Request', center=True) container_defaultreq_cpu = TableView('cpu', center=True, link="container.defaultRequest.cpu") container_defaultreq_mem = TableView('mem', center=True, link="container.defaultRequest.memory") container_defaultreq.add_columns([ container_defaultreq_cpu, container_defaultreq_mem ]) container_maxratio = TableView('Max Ratio', center=True) container_maxratio_cpu = TableView('cpu', center=True, link="container.maxLimitRequestRatio.cpu") container_maxratio.add_column(container_maxratio_cpu) container.add_columns([ container_restart, container_last, container_cpu, container_mem, container_default, container_defaultreq, container_maxratio ]) pvc = TableView('PVC', center=True) pvc_min = TableView('min', center=True, link="pvc.min.storage") pvc_max = TableView('max', center=True, link="pvc.max.storage") pvc.add_columns([pvc_min, pvc_max]) tv.add_columns([namespace, pod_name, container_name, pod, container, pvc]) if namespace_name in [None, "None"]: # all namespaces = [] kube = kubelib.KubeConfig(context=context, namespace="") namespace_objects = kubelib.Namespace(kube).get_list() for ns in namespace_objects: namespaces.append(ns.metadata.name) else: namespaces = [namespace_name] for namespace_name in namespaces: kube = kubelib.KubeConfig(context=context, namespace=namespace_name) limits_list = _get_namespace_limits(kube, namespace_name) namespace_limit = { 'namespace': namespace_name, 'pod.name': '', 'container.name': '' } for limits in limits_list: # can there be multiple namespace limits? for limit in limits.spec.limits: if limit.type == "Pod": namespace_limit['pod.min.cpu'] = limit.min.cpu namespace_limit['pod.min.memory'] = limit.min.memory namespace_limit['pod.max.cpu'] = limit.max.cpu namespace_limit['pod.max.memory'] = limit.max.memory elif limit.type == "Container": try: namespace_limit['container.min.cpu'] = limit.min.cpu except AttributeError: pass try: namespace_limit['container.min.memory'] = limit.min.memory except AttributeError: pass try: namespace_limit['container.max.cpu'] = limit.max.cpu except AttributeError: pass try: namespace_limit['container.max.memory'] = limit.max.memory except AttributeError: pass # default try: namespace_limit['container.default.cpu'] = limit.default.cpu except AttributeError: pass try: namespace_limit['container.default.memory'] = limit.default.memory except AttributeError: pass # defrequest namespace_limit['container.defaultRequest.cpu'] = limit.defaultRequest.cpu try: namespace_limit['container.defaultRequest.memory'] = limit.defaultRequest.memory except AttributeError: pass # maxratio try: namespace_limit['container.maxLimitRequestRatio.cpu'] = limit.maxLimitRequestRatio.cpu except AttributeError: pass elif limit.type == "PersistentVolumeClaim": namespace_limit['pvc.min.storage'] = limit.min.storage namespace_limit['pvc.max.storage'] = limit.max.storage data = [ namespace_limit ] # gather pod limits pods = kubelib.Pod(kube).get_list() for pod in pods: pod_name = pod.metadata.name cstatus = {} for cstatus_dict in getattr(pod.status, "containerStatuses", []): cstatus[cstatus_dict['name']] = cstatus_dict for container in pod.spec.containers: row = { 'namespace': namespace_name, 'pod.name': pod_name, 'container.name': container.name, 'container.restart': cstatus.get(container.name, {}).get("restartCount", '?'), 'container.laststate': cstatus.get(container.name, {}).get("lastState", {}).get('terminated', {}).get('reason', ''), 'container.min.cpu': container.get( "resources", {} ).get( 'requests', {} ).get( 'cpu', namespace_limit.get('container.defaultRequest.cpu') ), 'container.min.memory': container.get( "resources", {} ).get( 'requests', {} ).get( 'memory', namespace_limit.get('container.defaultRequest.memory') ), 'container.max.cpu': container.get( "resources", {} ).get( 'limits', {} ).get( 'cpu', namespace_limit.get('container.default.cpu') ), 'container.max.memory': container.get( "resources", {} ).get( 'limits', {} ).get( 'memory', namespace_limit.get('container.default.memory') ), } if namespace_limit.get('container.min.memory') is None: # unlimited pass elif less_than( row['container.min.memory'], namespace_limit.get('container.min.memory') ): msg = ('%s Pod %s min memory %s is below namespace minimum %s' % ( namespace_name, pod_name, row['container.min.memory'], namespace_limit.get('container.min.memory') )) print(msg) errors.append(msg) exit_code = 1 if namespace_limit.get('container.max.memory') is None: # unlimited pass elif greater_than( row['container.max.memory'], namespace_limit.get('container.max.memory') ): msg = ('%s Pod %s max memory %s is above namespace maximum %s' % ( namespace_name, pod_name, row['container.max.memory'], namespace_limit.get('container.max.memory') )) print(msg) errors.append(msg) exit_code = 1 if namespace_limit.get('container.min.cpu') is None: # unlimited pass elif less_than( row['container.min.cpu'], namespace_limit.get('container.min.cpu') ): msg = ('%s Pod %s min cpu %s is below namespace minimum %s' % ( namespace_name, pod_name, row['container.min.cpu'], namespace_limit.get('container.min.cpu') )) print(msg) errors.append(msg) exit_code = 1 if namespace_limit.get('container.max.cpu') is None: # unlimited pass elif greater_than( row['container.max.cpu'], namespace_limit.get('container.max.cpu') ): msg = ('%s Pod %s max cpu %s is above namespace maximum %s' % ( namespace_name, pod_name, row['container.max.cpu'], namespace_limit.get('container.max.cpu') )) print(msg) errors.append(msg) exit_code = 1 # colorama.Fore.RED + "!! " + str + " !!" + colorama.Style.RESET_ALL) data.append(row) tv.set_data(data) print(tv) if errors: for err in errors: print(err) sys.exit(exit_code)
'formatter': 'detailed' } }, 'loggers': { 'kubelib': { 'level': 'DEBUG', 'propagate': True } }, 'root': { 'level': 'DEBUG', 'handlers': ['console'] } }) LOG = logging.getLogger(__name__) #k = kubelib.Nameubectl() #print repr(k.base_resources) #print repr(k.get_pod("www-controller-hi66l")) #print repr(k.get_namespaces()) #print ("\n\n") #print repr(k.create_namespace("jkane-test")) #print ("\n\n") #print repr(k.delete_namespace("jkane-test")) #print ("\n\n") for ns in kubelib.Namespace(kubelib.KubeConfig()).get_list(): print(ns.metadata.name)