def check_cilium_version_cb(): """Checks whether cilium version is >= minimum supported version. Args: None Returns: True if successful, False otherwise. """ ret_code = True for name, ready_status, status, node_name, namespace in \ utils.get_pods_status_iterator_by_labels("k8s-app=cilium", []): cmd = ("kubectl describe pod {}" " -n {} | grep \"Image:.*docker.io/cilium/cilium\" | " "awk '{{print $2}}' " "| awk -F ':' '{{print $2}}'").format(name, namespace) output = "" try: encoded_output = subprocess.check_output(cmd, shell=True) except subprocess.CalledProcessError as grepexc: log.error("command to fetch cilium version has failed." "error code: {} {}".format(grepexc.returncode, grepexc.output)) ret_code = False break output = encoded_output.decode().strip(' \t\n\r') m = re.match(r"v(\d+).(\d+).(\d+)", output) if not m: log.warning("cilium version {} not in the expected format " "vX.Y.Z".format(output)) ret_code = True break major = int(m.group(1)) minor = int(m.group(2)) patch = int(m.group(3)) print_error = True if major > MINIMUM_SUPPORTED_CILIUM_VERSION_MAJOR: print_error = False elif major == MINIMUM_SUPPORTED_CILIUM_VERSION_MAJOR: if minor > MINIMUM_SUPPORTED_CILIUM_VERSION_MINOR: print_error = False elif minor == MINIMUM_SUPPORTED_CILIUM_VERSION_MINOR: if patch >= MINIMUM_SUPPORTED_CILIUM_VERSION_PATCH: print_error = False if print_error: log.error('cilium version is {}. Minimum supported ' 'version is: v{}.{}.{}'.format( output, MINIMUM_SUPPORTED_CILIUM_VERSION_MAJOR, MINIMUM_SUPPORTED_CILIUM_VERSION_MINOR, MINIMUM_SUPPORTED_CILIUM_VERSION_PATCH)) ret_code = False else: log.info('cilium version is {}'.format(output)) break # We do not need to inspect every cilium pod. Break here. return ret_code
def check_rbac_cb(): """Checks whether RBAC is enabled on all the kube-apiservers. Args: None Returns: True if successful, False otherwise. """ ret_code = True for name, ready_status, status, node_name, namespace in \ utils.get_pods_status_iterator_by_labels( "component=kube-apiserver", [], False): cmd = "kubectl describe pod {} -n {}".format(name, namespace) try: encoded_output = subprocess.check_output(cmd, shell=True) except subprocess.CalledProcessError as exc: log.error( "command to check kube-apiserver pod configuration has failed." "error code: {} {}".format(exc.returncode, exc.output)) ret_code = False else: output = encoded_output.decode() if "--authorization-mode=RBAC" in output or \ "--authorization-mode=ABAC" in output: log.info("RBAC is enabled on the cluster") else: log.info("RBAC has been disabled on this cluster") return ret_code
def check_access_log_config_cb(): """Checks cilium access log parameter. Args: None Returns: True if successful, False otherwise. """ ret_code = True for name, ready_status, status, node_name in \ utils.get_pods_status_iterator_by_labels("k8s-app=cilium", []): # TODO: Add volume checks. config = utils.get_pod_config(name) if not config: log.warn('could not check access log configuration on cilium' ' pod {} on node {}'.format(name, node_name)) ret_code = False continue if re.search('^.*--access-log.*/var/run/cilium/access.log.*', config, re.DOTALL) is None: log.warn('cilium pod {} on node {} ' 'has not been configured with ' '--access-log parameter or the ' 'access log filename is incorrect.' ' Fix this if you would like' ' to see Layer 7 proxy logs.'.format(name, node_name)) ret_code = False else: log.info('cilium pod {} on node {} ' 'has been configured with ' '--access-log parameter and the ' 'access log filename is correct'.format(name, node_name)) return ret_code
def collect_gops(self, label_selector, type_of_stat): pool = ThreadPool(multiprocessing.cpu_count() - 1) pool.map( functools.partial(self.collect_gops_per_pod, type_of_stat=type_of_stat), utils.get_pods_status_iterator_by_labels(label_selector)) pool.close() pool.join()
def collect_cilium_bugtool_output(self, label_selector, node_ip_filter): pool = ThreadPool(multiprocessing.cpu_count()) pool.map( self.collect_cilium_bugtool_output_per_pod, utils.get_pods_status_iterator_by_labels( label_selector, node_ip_filter)) pool.close() pool.join()
def collect_logs(self, label_selector, node_ip_filter): pool = ThreadPool(min(32, multiprocessing.cpu_count() + 4)) pool.map( self.collect_logs_per_pod, utils.get_pods_status_iterator_by_labels(label_selector, node_ip_filter)) pool.close() pool.join()
def collect_gops(self, pool, label_selector, node_filter, type_of_stat): must_exist = not("hubble" in label_selector) # hubble is optional pool.map_async( functools.partial(self.collect_gops_per_pod, type_of_stat=type_of_stat), utils.get_pods_status_iterator_by_labels( label_selector, node_filter, must_exist=must_exist, ))
def collect_cilium_bugtool_output(self, pool, label_selector, node_filter): log.info("collecting cilium-bugtool output ...") must_exist = not("hubble" in label_selector) # hubble is optional pool.map_async( self.collect_cilium_bugtool_output_per_pod, utils.get_pods_status_iterator_by_labels( label_selector, node_filter, must_exist=must_exist, ))
def collect_logs(self, pool, subject, label_selector, node_filter): log.info("collecting {} logs ...".format(subject)) must_exist = not("hubble" in label_selector) # hubble is optional pool.map_async( self.collect_logs_per_pod, utils.get_pods_status_iterator_by_labels( label_selector, node_filter, must_exist=must_exist, ))
def collect_cilium_bugtool_output(self, label_selector, node_ip_filter): pool = ThreadPool(min(32, multiprocessing.cpu_count() + 4)) must_exist = not("hubble" in label_selector) # hubble is optional pool.map( self.collect_cilium_bugtool_output_per_pod, utils.get_pods_status_iterator_by_labels( label_selector, node_ip_filter, must_exist=must_exist, )) pool.close() pool.join()
def collect_gops(self, label_selector, node_ip_filter, type_of_stat): pool = ThreadPool(min(32, multiprocessing.cpu_count() + 4)) must_exist = not("hubble" in label_selector) # hubble is optional pool.map( functools.partial(self.collect_gops_per_pod, type_of_stat=type_of_stat), utils.get_pods_status_iterator_by_labels( label_selector, node_ip_filter, must_exist=must_exist, )) pool.close() pool.join()
def check_trace_notifications_enabled_cb(): """Checks whether TraceNotification is enabled Args: None Returns: True if successful, False otherwise. """ ret_code = True for name, ready_status, status, node_name in \ utils.get_pods_status_iterator_by_labels("k8s-app=cilium"): cmd = "kubectl exec -it " + name + \ " -n kube-system cilium config " \ "| grep TraceNotification | awk '{print $2}'" output = "" try: encoded_output = subprocess.check_output(cmd, shell=True) except subprocess.CalledProcessError as grepexc: log.error("command to fetch cilium config has failed." "error code: {} {}".format(grepexc.returncode, grepexc.output)) ret_code = False continue output = encoded_output.decode() if "Enabled" not in output.strip(' \t\n\r'): # Can't use exact match/string comparison as the output has # ASCII-encoded characters. log.error('cilium pod {} on ' 'node {} has TraceNotifications {}'.format( name, node_name, repr(output.strip(' \t\n\r')))) ret_code = False else: log.info('cilium pod {} on ' 'node {} has TraceNotifications {}'.format( name, node_name, output.strip(' \t\n\r'))) return ret_code