Fork me on GitHub

consul 下线服务 服务注销脚本

一、获取服务名

  1. 登陆 consul UI 平台, 找到我们对应的服务,他们服务在 consul 中的名称。

二、 脚本

注销基于的api: http://{}:{}/v1/agent/service/deregister/{}

注销脚本:

#!/usr/bin/env   python3
# -*- coding: utf-8 -*-
# @Time    : 2021/3/29 10:26
# @Author  : dongjiaxiao
# @Email   : 
# @File    : consul_deregister.py
# @Desc    :

import requests
import json
import logging
import sys


def http_request(url, methods):
    if methods == 'get':
        try:
            responce = requests.get(url=url, timeout=5)
            res_data = responce.json()
        except Exception as e:
            logging.error(e)
    elif methods == 'put':
        try:
            responce = requests.put(url=url, timeout=5)
            res_data = responce.status_code
        except Exception as e:
            logging.error(e)
    return res_data


def get_node_ip(nodeName):
    """
    获取nodeName 对应的IP
    :param nodeName:
    :return:
    """
    node_url = "http://{}:{}/v1/catalog/node/{}".format(consul_host, consul_port, nodeName)
    node_data = http_request(node_url, 'get')
    node_ip = node_data["Node"].get('Address', '')
    return node_ip


def check_service(service_name):
    """
    检查服务
    :return:
    """
    res = {'critical':[], 'passing': []}
    chek_url = 'http://{}:{}/v1/health/checks/{}'.format(consul_host, consul_port, service_name)
    check_data = http_request(chek_url, 'get')
    if check_data:
        for i in check_data:
            if i['Status'] == 'critical':
                node_ip = get_node_ip(i['Node'])
                res['critical'].append({'serviceID': i['ServiceID'], 'node': i['Node'], 'ip': node_ip})
            elif i['Status'] == 'passing':
                node_ip = get_node_ip(i['Node'])
                res['passing'].append({'serviceID': i['ServiceID'], 'node': i['Node'], 'ip': node_ip})
        return res
    else:
        logging.error("未找到服务 {}".format(service_name))
        return "未找到服务 {}".format(service_name)


def check_node_service(service_name, hostIp):
    """
    基于 服务名和 主机ip 进行查找节点信息
    :param service_name:
    :return:
    """
    res = []
    chek_url = 'http://{}:{}/v1/health/checks/{}'.format(consul_host, consul_port, service_name)
    check_data = http_request(chek_url, 'get')
    if check_data:
        for i in check_data:
            node_ip = get_node_ip(i['Node'])
            if node_ip == hostIp:
                res.append({'serviceID': i['ServiceID'], 'node': i['Node'], 'ip': hostIp})
    return res



def deregister_operation(nodeIp, serviceId):
    """
    注销服务
    :param nodeIp:
    :param serviceId:
    :return:
    """
    deregister_url = 'http://{}:{}/v1/agent/service/deregister/{}'.format(nodeIp, consul_port, serviceId)
    res = http_request(deregister_url, 'put')
    logging.info("注销节点url: {}  res: {}".format(deregister_url, res))
    return res


def deregister_service(service_name):
    res = check_service(service_name)
    if isinstance(res, dict):
        critical_service = res.get('critical')
        if critical_service:
            data = {"异常节点": [], '已经注销节点': []}
            for service_data in critical_service:
                serviceId = service_data.get('serviceID')
                nodeIp = service_data.get('ip')
                data['异常节点'].append(serviceId)
                if serviceId and nodeIp:
                    res_code = deregister_operation(nodeIp, serviceId)
                    if res_code == 200:
                        data['已经注销节点'].append(serviceId)
                else:
                    logging.error("serviceId  {} and nodeIp {}  缺少参数".format(serviceId, nodeIp))
            return data
        else:
            return "未找到异常节点"
    return res


def deregister_service_host(service_name, hostIp):
    """
    基于 服务名和 主机ip 进行注销对应主机上的节点信息
    :param service_name:
    :return:
    """
    res = check_node_service(service_name, hostIp)
    if res:
        data = {"需要注销节点": [], '已经注销节点': []}
        for service_data in res:
            serviceId = service_data.get('serviceID')
            nodeIp = service_data.get('ip')
            data['需要注销节点'].append(serviceId)
            if serviceId and nodeIp:
                res_code = deregister_operation(nodeIp, serviceId)
                if res_code == 200:
                    data['已经注销节点'].append(serviceId)
                    logging.info("serviceId  {} and nodeIp {}, res: {} ".format(serviceId, nodeIp, res))
            else:
                logging.error("serviceId  {} and nodeIp {}  缺少参数".format(serviceId, nodeIp))
        return data
    return '在主机未找到该服务'


if __name__ == '__main__':
    consul_host = '10.60.6.37'
    consul_port = '8500'
    file_handler = logging.FileHandler(filename='./consul_deregister.log', encoding='utf-8')
    logging.basicConfig(format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt='%Y-%m-%d %H:%M:%S',
                        level=logging.INFO, handlers={file_handler})
    if len(sys.argv) == 3 and sys.argv[1] == "check":  # 获取异常节点
        service_name = sys.argv[2]
        data = check_service(service_name)
        if isinstance(data, dict):
            print("异常节点信息: {}".format(data.get('critical')))
            print("正常节点信息: {}".format(data.get('passing')))
        else:
            print(data)
    elif len(sys.argv) == 3 and sys.argv[1] == "deregister":  # 注销异常节点, 指定服务名
        service_name = sys.argv[2]
        print(deregister_service(service_name))
    elif len(sys.argv) == 4 and sys.argv[1] == "deregister":  # 注销异常节点, 指定服务名和ip
        service_name = sys.argv[2]
        hostIp = sys.argv[3]
        print(deregister_service_host(service_name, hostIp))
    elif len(sys.argv) == 4 and sys.argv[1] == "deregister_serviceid":  # 注销异常节点, 指定nodeip(注册的consul client ip) 和  service_id
        hostIp = sys.argv[3]
        service_id = sys.argv[2]
        print(deregister_operation(hostIp, service_id))
    else:
        print("please  use parameter  check|deregister  service_name")

三、基本功能操作

  1. 获取某个服务当前状态。

     python3 consul_tools.py check cmdb-front-dp-test
    

    响应:

    [root@djx scripts]# python3 consul_tools.py check cmdb-front-dp-test
    异常节点信息: []
    正常节点信息: [{'serviceID': 'docker-57-58.baidu.com:cmdb-front-dp_0_22fecc7-190308.170959:80', 'node': 'docker-57-58.baidu.com', 'ip': '192.168.57.58'}]
    
    
  2. 注销服务当前异常节点

    会拿上面异常节点的信息,然后进行注销服务

    python3 consul_tools.py deregister  cmdb-front-dp-test
    

    响应:

    • 未找到节点

    • {'异常节点': ['docker-110-89.baidu.com:user-server-sit-skywalking_0_v2.1:8080'], '已经注销节点': ['docker-110-89.baidu.com:user-server-sit-skywalking_0_v2.1:8080']}
      
  3. 下线指定机器 ip 上的指定服务

    适用场景:

    • 某机器上的某个节点忽好忽坏,我们获取机器ip 和 服务名后,不管该服务是否健康检查通过,都将其下线。

    不管该机器上的对应服务节点是正常,还是异常都会进行下线。

    python3 consul_tools.py deregister  cmdb-front-dp-test  10.57.57.58
    

    响应:

    1. 如果在主机上未找到

      在主机未找到该服务
      
    2. 下线

      {'需要注销节点': ['docker-10-58.baidu.com:cmdb-front-dp_0_22fecc7-190308.170959:80'], '已经注销节点': ['docker-10-58.baidu.com:cmdb-front-dp_0_22fecc7-190308.170959:80']}
      
  4. 已经知道要下线的服务的 ID ,形如, docker-10-58.baidu.com:cmdb-front-dp_0_22fecc7-190308.170959:80 和 知道该服务注册的 consul ip

    python3 consul_tools.py deregister_serviceid   192.168.57.58  docker-10-58.baidu.com:cmdb-front-dp_0_22fecc7-190308.170959:80
    
posted @ 2021-06-30 11:26  自由早晚乱余生  阅读(1378)  评论(0编辑  收藏  举报