def update_pod_with_init_container(pod, cmd, cmk_img, cmk_img_pol, args): container_template = k8s.get_container_template() container_template["image"] = cmk_img container_template["imagePullPolicy"] = cmk_img_pol container_template["args"][0] = args # Each container name should be distinct within a Pod. container_template["name"] = cmd pod_init_containers_list = [] version = util.parse_version(k8s.get_kube_version(None)) if version >= util.parse_version("v1.7.0"): pod["spec"]["initContainers"] = [container_template] else: init_containers_key = "pod.beta.kubernetes.io/init-containers" if init_containers_key in pod["metadata"]["annotations"]: init_containers = \ pod["metadata"]["annotations"][init_containers_key] pod_init_containers_list = json.loads(init_containers) pod_init_containers_list.append(container_template) pod["metadata"]["annotations"][init_containers_key] = \ json.dumps(pod_init_containers_list)
def cluster_init(host_list, all_hosts, cmd_list, cmk_img, cmk_img_pol, conf_dir, install_dir, num_exclusive_cores, num_shared_cores, pull_secret, serviceaccount, exclusive_mode, shared_mode, namespace, excl_non_isolcpus): logging.info("Used ServiceAccount: {}".format(serviceaccount)) cmk_node_list = get_cmk_node_list(host_list, all_hosts) logging.debug("CMK node list: {}".format(cmk_node_list)) cmk_cmd_list = [cmd.strip() for cmd in cmd_list.split(',')] logging.debug("CMK command list: {}".format(cmk_cmd_list)) # Check if all the flag values passed are valid. # Check if cmk_cmd_list is valid. valid_cmd_list = ["init", "discover", "install", "reconcile", "nodereport"] for cmk_cmd in cmk_cmd_list: if cmk_cmd not in valid_cmd_list: raise RuntimeError( "CMK command should be one of {}".format(valid_cmd_list)) if "init" in cmk_cmd_list and cmk_cmd_list[0] != "init": raise RuntimeError("init command should be run and listed first.") # Check if cmk_img_pol is valid. valid_img_pol_list = ["Never", "IfNotPresent", "Always"] if cmk_img_pol not in valid_img_pol_list: raise RuntimeError( "Image pull policy should be one of {}".format(valid_img_pol_list)) # Check if num_exclusive_cores and num_shared_cores are positive integers. if not num_exclusive_cores.isdigit(): raise RuntimeError("num_exclusive_cores cores should be a positive " "integer.") if not num_shared_cores.isdigit(): raise RuntimeError("num_shared_cores cores should be a positive " "integer.") # Split the cmk_cmd_list based on whether the cmd should be run as # one-shot job or long-running daemons. cmd_init_list = ["init", "discover", "install"] cmk_cmd_init_list = [cmd for cmd in cmk_cmd_list if cmd in cmd_init_list] cmk_cmd_list = [cmd for cmd in cmk_cmd_list if cmd not in cmd_init_list] # Run the pods based on the cmk_cmd_init_list and cmk_cmd_list with # provided options. if cmk_cmd_init_list: run_pods(None, cmk_cmd_init_list, cmk_img, cmk_img_pol, conf_dir, install_dir, num_exclusive_cores, num_shared_cores, cmk_node_list, pull_secret, serviceaccount, shared_mode, exclusive_mode, namespace, excl_non_isolcpus) if cmk_cmd_list: run_pods(cmk_cmd_list, None, cmk_img, cmk_img_pol, conf_dir, install_dir, num_exclusive_cores, num_shared_cores, cmk_node_list, pull_secret, serviceaccount, shared_mode, exclusive_mode, namespace, excl_non_isolcpus) # Run mutating webhook admission controller on supported cluster version = util.parse_version(k8s.get_kube_version(None)) if version >= util.parse_version("v1.9.0"): deploy_webhook(namespace, conf_dir, install_dir, serviceaccount, cmk_img)
def discover(namespace, no_taint=False): version = util.parse_version(k8s.get_kube_version(None)) if version == util.parse_version("v1.8.0"): logging.fatal("K8s 1.8.0 is not supported. Update K8s to " "version >=1.8.1 or rollback to previous versions") sys.exit(1) if version >= util.parse_version("v1.8.1"): # Patch the node with the appropriate CMK ER. logging.debug("Patching the node with the appropriate CMK ER.") add_node_er(namespace) else: # Patch the node with the appropriate CMK OIR. logging.debug("Patching the node with the appropriate CMK OIR.") add_node_oir(namespace) # Add appropriate CMK label to the node. logging.debug("Adding appropriate CMK label to the node.") add_node_label() # Add appropriate CMK taint to the node. if not no_taint: logging.debug("Adding appropriate CMK taint to the node.") add_node_taint()
def test_k8s_get_kube_version(): mock = MagicMock() with patch('intel.k8s.version_api_client_from_config', MagicMock(return_value=mock)): expected_version = "v1.7.0" mock.get_code.return_value.git_version = expected_version version = k8s.get_kube_version(None) assert version == expected_version
def add_node_taint(): node_name = os.getenv("NODE_NAME") try: node_resp = get_k8s_node(node_name) except K8sApiException as err: logging.error("Exception when getting the node obj: {}".format(err)) logging.error(ABORTING_DISCOVER) sys.exit(1) version = util.parse_version(k8s.get_kube_version(None)) node_taints_list = [] node_taints = [] if version >= util.parse_version("v1.7.0"): node_taints = node_resp["spec"]["taints"] if node_taints: node_taints_list = node_taints patch_path = "/spec/taints" else: node_taint_key = "scheduler.alpha.kubernetes.io/taints" if node_taint_key in node_resp["metadata"]["annotations"]: node_taints = node_resp["metadata"]["annotations"][node_taint_key] patch_path = "/metadata/annotations/scheduler.alpha.kubernetes.io~1taints" # noqa: E501 if node_taints: node_taints_list = json.loads(node_taints) # Filter existing "cmk" taint, if it exists. node_taints_list = [t for t in node_taints_list if t["key"] != "cmk"] node_taints_list.append({ "key": "cmk", "value": "true", "effect": "NoSchedule" }) if version >= util.parse_version("v1.7.0"): value = node_taints_list else: value = json.dumps(node_taints_list) # See: https://tools.ietf.org/html/rfc6902#section-4.1 patch_body = [ { "op": "add", "path": patch_path, "value": value } ] try: patch_k8s_node(patch_body) except K8sApiException as err: logging.error("Exception when tainting the node: {}".format(err)) logging.error(ABORTING_DISCOVER) sys.exit(1)
def run_cmd_pods(cmd_list, cmd_init_list, cmk_img, cmk_img_pol, conf_dir, install_dir, num_exclusive_cores, num_shared_cores, cmk_node_list, pull_secret, serviceaccount, shared_mode, exclusive_mode, namespace, excl_non_isolcpus): version = util.parse_version(k8s.get_kube_version(None)) pod = k8s.get_pod_template() if pull_secret: update_pod_with_pull_secret(pod, pull_secret) if cmd_list: update_pod(pod, "Always", conf_dir, install_dir, serviceaccount) if version >= util.parse_version("v1.7.0"): pod["spec"]["tolerations"] = [{"operator": "Exists"}] for cmd in cmd_list: args = "" if cmd == "reconcile": args = "/cmk/cmk.py isolate --pool=infra /cmk/cmk.py -- reconcile --interval=5 --publish" # noqa: E501 elif cmd == "nodereport": args = "/cmk/cmk.py isolate --pool=infra /cmk/cmk.py -- node-report --interval=5 --publish" # noqa: E501 update_pod_with_container(pod, cmd, cmk_img, cmk_img_pol, args) elif cmd_init_list: update_pod(pod, "Never", conf_dir, install_dir, serviceaccount) for cmd in cmd_init_list: args = "" if cmd == "init": args = ("/cmk/cmk.py init --num-exclusive-cores={} " "--num-shared-cores={} --shared-mode={} " "--exclusive-mode={} --excl-non-isolcpus={}")\ .format(num_exclusive_cores, num_shared_cores, shared_mode, exclusive_mode, excl_non_isolcpus) # If init is the only cmd in cmd_init_list, it should be run # as regular container as spec.containers is a required field. # Otherwise, it should be run as init-container. if len(cmd_init_list) == 1: update_pod_with_container(pod, cmd, cmk_img, cmk_img_pol, args) else: update_pod_with_init_container(pod, cmd, cmk_img, cmk_img_pol, args) else: if cmd == "discover": args = "/cmk/cmk.py discover" elif cmd == "install": args = "/cmk/cmk.py install" update_pod_with_container(pod, cmd, cmk_img, cmk_img_pol, args) for node_name in cmk_node_list: if cmd_list: update_pod_with_node_details(pod, node_name, cmd_list) daemon_set = k8s.ds_from(pod=pod, version=version) elif cmd_init_list: update_pod_with_node_details(pod, node_name, cmd_init_list) try: if cmd_list: cr_pod_resp = k8s.create_ds(None, daemon_set, namespace, version) logging.debug("Response while creating ds for {} command(s): " "{}".format(cmd_list, cr_pod_resp)) elif cmd_init_list: cr_pod_resp = k8s.create_pod(None, pod, namespace) logging.debug("Response while creating pod for {} command(s): " "{}".format(cmd_init_list, cr_pod_resp)) except K8sApiException as err: if cmd_list: logging.error("Exception when creating pod for {} command(s): " "{}".format(cmd_list, err)) elif cmd_init_list: logging.error("Exception when creating pod for {} command(s): " "{}".format(cmd_init_list, err)) logging.error("Aborting cluster-init ...") sys.exit(1)