Ejemplo n.º 1
0
def query_cluster_nodes(ctx_cluster: CtxCluster,
                        exclude_master: bool = True) -> Dict:
    """查询节点数据
    包含标签、污点、状态等供前端展示数据
    """
    # 获取集群中的节点列表
    node_client = Node(ctx_cluster)
    try:
        cluster_node_list = node_client.list(is_format=False)
    except ApiException:
        # 查询集群内节点异常,返回空字典
        return {}

    nodes = {}
    for node in cluster_node_list.items:
        labels = node.labels
        # 现阶段节点页面展示及操作,需要排除master
        if exclude_master and labels.get(
                node_constants.K8S_NODE_ROLE_MASTER) == "true":
            continue

        # 使用inner_ip作为key,主要是方便匹配及获取值
        nodes[node.inner_ip] = {
            "inner_ip": node.inner_ip,
            "name": node.name,
            "status": node.node_status,
            "labels": labels,
            "taints": node.taints,
            "unschedulable": node.data.spec.unschedulable or False,
        }
    return nodes
Ejemplo n.º 2
0
def query_cluster_nodes(ctx_cluster: CtxCluster) -> Dict[str, Dict]:
    # 查询集群下node信息
    client = Node(ctx_cluster)
    nodes = client.list()
    # 根据传入的inner_ip过滤节点信息
    data = {}
    for node in nodes:
        node_data = node.data
        # 解析数据用于前端展示
        metadata = node_data.get("metadata", {})
        labels = metadata.get("labels", {})

        # 过滤掉master
        if labels.get("node-role.kubernetes.io/master") == "true":
            continue

        taints = getitems(node_data, ["spec", "taints"], [])

        # 组装数据,用于展示
        data[node.inner_ip] = {
            "inner_ip":
            node.inner_ip,
            "name":
            node.name,
            "labels":
            labels,
            "taints":
            taints,
            "status":
            get_node_status(getitems(node_data, ["status", "conditions"], [])),
            "unschedulable":
            getitems(node_data, ["spec", "unschedulable"], False),
        }

    return data
Ejemplo n.º 3
0
 def query_taints(self, request, project_id, cluster_id):
     """查询node的污点"""
     params = self.params_validate(slz.QueryNodeListSLZ)
     node_client = Node(request.ctx_cluster)
     return Response(
         node_client.filter_nodes_field_data("taints",
                                             params["node_name_list"]))
Ejemplo n.º 4
0
class NodeRespBuilder:
    """构造节点 API 返回

    TODO: 现阶段返回先方便前端处理,拆分后,调整返回为{manifest: xxx, manifest_ext: xxx}
          manifest中放置原始node数据, manifest_ext中存放处理的状态等数据
    """
    def __init__(self, ctx_cluster: CtxCluster):
        self.client = Node(ctx_cluster)

    def list_nodes(self) -> Dict:
        """查询节点列表"""
        nodes = self.client.list(is_format=False)
        return {
            "manifest": nodes.data.to_dict(),
            "manifest_ext": {
                node.metadata["uid"]: {
                    "status": node.node_status,
                    "labels": {
                        key: "readonly"
                        for key in filter_label_keys(node.labels.keys())
                    },
                }
                for node in nodes.items
            },
        }

    def query_labels(self, node_names: List[str]) -> Dict[str, Dict]:
        """查询节点标签
        TODO: 这里是兼容处理,方便前端使用,后续前端直接通过列表获取数据
        """
        node_labels = self.client.filter_nodes_field_data(
            "labels", filter_node_names=node_names, default_data={})
        return node_labels
Ejemplo n.º 5
0
class LBController:
    def __init__(self, ctx_cluster: CtxCluster):
        self.node_client = Node(ctx_cluster)

    def add_labels(self, ip_list: List[str]):
        """添加lb的标签"""
        node_label_list = self._construct_node_label_list(ip_list)
        self.node_client.set_labels_for_multi_nodes(node_label_list)

    def delete_labels(self, ip_list: List[str]):
        node_label_list = self._construct_node_label_list(ip_list, LBLabelOp.DELETE)
        self.node_client.set_labels_for_multi_nodes(node_label_list)

    def _construct_node_label_list(self, ip_list: List[str], op: str = LBLabelOp.ADD) -> List:
        """查询节点的标签"""
        node_list = self.node_client.list(is_format=False)
        # 获取节点标签
        node_label_list = []
        for node in node_list.items:
            if node.inner_ip not in ip_list:
                continue
            labels = self._construct_labels_by_op(node.labels, op)
            node_label_list.append({"node_name": node.name, "labels": labels})
        return node_label_list

    def _construct_labels_by_op(self, labels: Dict, op: str = LBLabelOp.ADD) -> Dict:
        if op == LBLabelOp.ADD:
            labels.update(K8S_LB_LABEL)
        else:
            for key in K8S_LB_LABEL:
                labels[key] = None
        return labels
Ejemplo n.º 6
0
    def set_taints(self, request, project_id, cluster_id):
        """设置污点"""
        params = self.params_validate(slz.NodeTaintListSLZ)
        node_client = Node(request.ctx_cluster)
        node_client.set_taints_for_multi_nodes(params["node_taint_list"])

        # 获取节点名称,用于审计
        node_names = get_nodes_repr([n["node_name"] for n in params["node_taint_list"]])
        request.audit_ctx.update_fields(resource=node_names, extra=params, description=_("节点设置污点"))

        return Response()
Ejemplo n.º 7
0
 def _get_cluster_masters(self) -> List[Dict]:
     """查询集群中的master ip和name"""
     node_client = Node(self.ctx_cluster)
     # NOTE: 返回节点出现异常,直接报错
     cluster_nodes = node_client.list(is_format=False)
     # 过滤 master 信息
     masters = []
     for node in cluster_nodes.items:
         if not node.is_master():
             return
         masters.append({"inner_ip": node.inner_ip, "host_name": node.name})
     return masters
Ejemplo n.º 8
0
def query_cluster_nodes(ctx_cluster: CtxCluster, exclude_master: bool = True) -> Dict:
    """查询节点数据
    包含标签、污点、状态等供前端展示数据
    """
    # 获取集群中的节点列表
    # NOTE: 现阶段会有两个agent,新版agent上报集群信息到bcs api中,可能会有时延,导致bcs api侧找不到集群信息;处理方式:
    # 1. 初始化流程调整,创建集群时,注册一次集群信息
    # 2. 应用侧,兼容处理异常
    try:
        cluster_node_list = Node(ctx_cluster).list(is_format=False)
    except Exception as e:  # 兼容处理现阶段kube-agent没有注册时,连接不上集群的异常
        logger.error("query cluster nodes error, %s", e)
        # 查询集群内节点异常,返回空字典
        return {}

    nodes = {}
    for node in cluster_node_list.items:
        labels = node.labels
        # 现阶段节点页面展示及操作,需要排除master
        if exclude_master and node.is_master():
            continue

        # 使用inner_ip作为key,主要是方便匹配及获取值
        nodes[node.inner_ip] = {
            "inner_ip": node.inner_ip,
            "name": node.name,
            "status": node.node_status,
            "labels": labels,
            "taints": node.taints,
            "unschedulable": node.data.spec.unschedulable or False,
        }
    return nodes
Ejemplo n.º 9
0
    def set_schedule_status(self, request, project_id, cluster_id):
        """设置节点调度状态
        通过传递状态, 设置节点的调度状态
        """
        params = self.params_validate(slz.NodeStatusSLZ)
        # NOTE: 如果状态为REMOVABLE,则期望的是停止调度状态, 以便于进一步操作
        unschedulable = True if params["status"] == node_status.REMOVABLE else False
        client = Node(request.ctx_cluster)
        client.set_nodes_schedule_status(unschedulable, params["node_name_list"])

        request.audit_ctx.update_fields(
            resource=get_nodes_repr(params["node_name_list"]),
            extra=params,
            description=_("节点停止调度") if unschedulable else _("节点允许调度"),
        )

        return Response()
Ejemplo n.º 10
0
def create_and_delete_master(ctx_cluster):
    client = Node(ctx_cluster)
    client.update_or_create(
        body={
            "apiVersion": "v1",
            "kind": "Node",
            "metadata": {"name": fake_node_name, "labels": {"node-role.kubernetes.io/master": "true"}},
            "spec": {},
            "status": {
                "addresses": [
                    {"address": fake_inner_ip, "type": "InternalIP"},
                ],
                "conditions": [
                    {
                        "lastHeartbeatTime": "2021-10-25T04:13:48Z",
                        "lastTransitionTime": "2020-10-25T05:24:53Z",
                        "message": "kubelet is posting ready status",
                        "reason": "KubeletReady",
                        "status": "True",
                        "type": "Ready",
                    }
                ],
            },
        },
        name=fake_node_name,
    )
    yield
    client.delete_wait_finished(fake_node_name)
Ejemplo n.º 11
0
def set_labels(ctx_cluster: CtxCluster, label_list: List):
    """节点设置标签

    ctx_cluster: 集群模型数据
    taint_list: 节点的污点内容,格式: [{"node_name": "demo", "labels": {"key1": "value1", "key2": "value2"}]
    """
    client = Node(ctx_cluster)
    # 下发的body格式: {"metadata": {"labels": {"demo": "demo"}}}
    tasks = [
        functools.partial(client.patch, {"metadata": {
            "labels": l["labels"]
        }}, l["node_name"]) for l in label_list
    ]
    # 当有操作失败的,抛出异常
    async_run(tasks)
Ejemplo n.º 12
0
def set_taints(ctx_cluster: CtxCluster, taint_list: List):
    """节点设置污点,因为可能有多个节点分别调用接口完成打污点,使用asyncio处理,减少耗时

    ctx_cluster: 集群模型数据
    taint_list: 节点的污点内容,格式: [{"node_name": "demo", "taints": [{"key": xxx, "value": xxx, "effect": xxx}]]
    """
    client = Node(ctx_cluster)
    # 下发的body格式: {"spec": {"taints": [{"key": xxx, "value": xxx, "effect": xxx}]}}
    tasks = [
        functools.partial(client.patch, {"spec": {
            "taints": t["taints"]
        }}, t["node_name"]) for t in taint_list
    ]
    # 当有操作失败的,抛出异常
    async_run(tasks)
Ejemplo n.º 13
0
def get_cluster_nodes(access_token, project_id, cluster_id):
    """获取集群下的node信息
    NOTE: 节点数据通过集群中获取,避免数据不一致
    """
    ctx_cluster = CtxCluster.create(
        id=cluster_id,
        project_id=project_id,
        token=access_token,
    )
    try:
        cluster_nodes = Node(ctx_cluster).list(is_format=False)
    except Exception as e:
        logger.error("查询集群内节点数据异常, %s", e)
        return []
    return [{
        "inner_ip": node.inner_ip,
        "status": node.node_status
    } for node in cluster_nodes.items]
Ejemplo n.º 14
0
 def set_labels(self, request, project_id, cluster_id):
     """设置节点标签"""
     params = self.params_validate(slz.NodeLabelListSLZ)
     node_client = Node(request.ctx_cluster)
     node_client.set_labels_for_multi_nodes(params["node_label_list"])
     return Response()
Ejemplo n.º 15
0
 def detail(self) -> Dict[str, Any]:
     # 通过集群获取
     client = Node(self.ctx_cluster)
     node_data = client.get(self.name).get("data", {})
     # 过滤需要的信息: 包含节点名称、IP、版本、OS、运行时、镜像、标签、污点、pods
     return self._detail(node_data)
Ejemplo n.º 16
0
 def client(self, ctx_cluster):
     return Node(ctx_cluster)
Ejemplo n.º 17
0
 def __init__(self, ctx_cluster: CtxCluster):
     self.node_client = Node(ctx_cluster)
Ejemplo n.º 18
0
 def set_taints(self, request, project_id, cluster_id):
     """设置污点"""
     params = self.params_validate(slz.NodeTaintListSLZ)
     node_client = Node(request.ctx_cluster)
     node_client.set_taints_for_multi_nodes(params["node_taint_list"])
     return Response()