python过滤 Kubernetes api数据

发布时间:2020-02-18 09:46:16编辑:admin阅读(2073)

    一、需求分析

    Kubernetes endpoints api地址

    http://ip地址:端口/api/v1/namespaces/default/endpoints

    services api地址

    http://ip地址:端口/api/v1/namespaces/default/services

    下面主要展示 endpoints api的部分数据

    {
        "kind": "EndpointsList",
        "apiVersion": "v1",
        "metadata": {
            "selfLink": "/api/v1/namespaces/default/endpoints",
            "resourceVersion": "9715086"
        },
        "items": [{
            "metadata": {
                "name": "voucher-center-master",
                "namespace": "default",
                "selfLink": "/api/v1/namespaces/default/endpoints/voucher-center-master",
                "uid": "8fd980bf-0507-11e9-a3b3-005056bb4630",
                "resourceVersion": "9051672",
                "creationTimestamp": "2018-12-21T10:02:44Z"
            },
            "subsets": [
                {
                    "addresses": [
                        {
                            "ip": "192.169.167.105",
                            "nodeName": "job-node149",
                            "targetRef": {
                                "kind": "Pod",
                                "namespace": "default",
                                "name": "voucher-center-rc-p20kk",
                                "uid": "76dd6355-1269-11e9-95a3-005056bb4630",
                                "resourceVersion": "9051584"
                            }
                        },
                        {
                            "ip": "192.169.183.26",
                            "nodeName": "job-node137",
                            "targetRef": {
                                "kind": "Pod",
                                "namespace": "default",
                                "name": "voucher-center-rc-vknkt",
                                "uid": "7751e013-1269-11e9-95a3-005056bb4630",
                                "resourceVersion": "9051604"
                            }
                        },
                        {
                            "ip": "192.169.242.29",
                            "nodeName": "job-node145",
                            "targetRef": {
                                "kind": "Pod",
                                "namespace": "default",
                                "name": "voucher-center-rc-0x482",
                                "uid": "7790169d-1269-11e9-95a3-005056bb4630",
                                "resourceVersion": "9051627"
                            }
                        },
                        {
                            "ip": "192.169.76.159",
                            "nodeName": "job-node151",
                            "targetRef": {
                                "kind": "Pod",
                                "namespace": "default",
                                "name": "voucher-center-rc-xtxfb",
                                "uid": "771842c8-1269-11e9-95a3-005056bb4630",
                                "resourceVersion": "9051577"
                            }
                        },
                        {
                            "ip": "192.169.98.159",
                            "nodeName": "job-node147",
                            "targetRef": {
                                "kind": "Pod",
                                "namespace": "default",
                                "name": "voucher-center-rc-n9wkl",
                                "uid": "77cb9ffc-1269-11e9-95a3-005056bb4630",
                                "resourceVersion": "9051637"
                            }
                        }
                    ],
                    "ports": [
                        {
                            "name": "beejob-3011",
                            "port": 3011,
                            "protocol": "TCP"
                        },
                        {
                            "name": "server-30012",
                            "port": 8012,
                            "protocol": "TCP"
                        }
                    ]
                }
            ]
        }, ]
    }

     

    需要提取以下数据

    items-->metadata-->name
    items-->subsets-->addresses-->ip
    items-->subsets-->addresses-->nodeName
    items-->subsets-->addresses-->targetRef-->name
    items-->subsets-->ports-->port
    items-->subsets-->ports-->port

     

    在应用的yaml文件中,定义了2个端口

    apiVersion: v1
    kind: Service
    metadata:
      name: voucher-center-master
      namespace: xx
    spec:
      type: NodePort
      ports:
        - port: 8012
          targetPort: 8012
          protocol: TCP
          nodePort: 31012
          name: server-31012
        - port: 3011
          targetPort: 3011
          protocol: TCP
          name: beejob-3011
      selector:
        name: voucher-center

     

    一个是server-port,一个是beejob-port

    我需要对server-port和beejob-port做健康检测!

    二、数据结构

    上面的api需要提取6个字段信息,最终的数据结构如下:

    {
        "voucher-center-master":[
            {
                "ip":"192.169.167.105",
                "nodeName":"job-node149",
                "pod_name":"voucher-center-rc-p20kk",
                "server_port":"8012",
                "beejob_port":"3101",
            },
            {
                "ip":"192.169.183.26",
                "nodeName":"job-node137",
                "pod_name":"voucher-center-rc-vknkt",
                "server_port":"8012",
                "beejob_port":"3101",
            },
            ...
        ],
    }

     

    其中 pod_name 对应 items-->subsets-->addresses-->targetRef-->name

    server_port 对应 items-->subsets-->ports-->port  注意:ports里面的name必须是以server开头的

    beejob_port 对应 items-->subsets-->ports-->port  注意:ports里面的name必须是以beejob开头的

     

    三、正式代码

    #!/usr/bin/env python3
    # coding: utf-8
    import sys
    import json
    import socket
    import ipaddress
    import requests
    
    """
    要求的数据格式
    beejob_port是动态的,存在即有
    {
        "voucher-center-master":[
            {
                "ip":"192.169.167.105",
                "nodeName":"job-node149",
                "pod_name":"voucher-center-rc-p20kk",
                "server_port":"8012",
                "beejob_port":"3101",
            },
            {
                "ip":"192.169.183.26",
                "nodeName":"job-node137",
                "pod_name":"voucher-center-rc-vknkt",
                "server_port":"8012",
                "beejob_port":"3101",
            },
            ...
        ],
    }
    """
    
    
    class Endpoints(object):
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        def check_tcp(self, ip, port, timeout=1):
            """
            检测tcp端口
            :param ip: ip地址
            :param port: 端口号
            :param timeout: 超时时间
            :return: bool
            """
            flag = False
            try:
                socket.setdefaulttimeout(timeout)  # 整个socket层设置超时时间
                cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                address = (str(ip), int(port))
                status = cs.connect_ex((address))  # 开始连接
                cs.settimeout(timeout)
    
                if not status:
                    flag = True
    
                return flag
            except Exception as e:
                print("error:%s" % e)
                return flag
    
        def valid_ip(self, ip):
            """
            验证ip是否有效,比如192.168.1.256是一个不存在的ip
            :return: bool
            """
            try:
                # 判断 python 版本
                if sys.version_info[0] == 2:
                    ipaddress.ip_address(ip.strip().decode("utf-8"))
                elif sys.version_info[0] == 3:
                    # ipaddress.ip_address(bytes(ip.strip().encode("utf-8")))
                    ipaddress.ip_address(ip)
    
                return True
            except Exception as e:
                print(e)
                return False
    
    
        def main(self):
            """
            主程序
            :return: json
            """
            valid_ip = self.valid_ip(self.ip)
            if not valid_ip:
                return "%s ip不合法" % self.ip
    
            check_tcp = self.check_tcp(self.ip,self.port)
            if not check_tcp:
                return "%s 端口不可达" % self.port
    
            # 需要访问的url
            url = "http://{}:{}/api/v1/namespaces/default/endpoints".format(self.ip, self.port)
    
            response = requests.get(url, )  # get请求地址
            content = (response.content).decode('utf-8')  # 二进制转换为字符串
            dic = json.loads(content)  # 反序列化成字典
            # print(dic,type(dic))
    
            filter_dic = {}  # 筛选结果
    
            for i in dic['items']:
                if not filter_dic.get(i['metadata']['name']):  # 判断name是否存在
                    filter_dic[i['metadata']['name']] = []  # 初始化列表
    
                if i.get('subsets'):  # 判断subsets是否存在
                    for j in i['subsets']:
                        for k in j['addresses']:  # 遍历字典
                            filter_dic[i['metadata']['name']].append({})  # 添加空字典
                            for m in filter_dic[i['metadata']['name']]:  # 遍历列表
                                if not m.get('ip'):
                                    # print("-->ip:",k['ip'])
                                    # 设置ip地址
                                    m['ip'] = k['ip']
    
                                if k.get('nodeName'):
                                    # print("-->nodeName:", k['nodeName'])
                                    if not m.get('nodeName'):
                                        # 设置nodeName
                                        m['nodeName'] = k['nodeName']
    
                                if k.get('targetRef'):
                                    if not m.get('pod_name'):
                                        # 设置pod_name
                                        m['pod_name'] = k['targetRef']['name']
    
                        for ports in j['ports']:
                            if ports.get('name'):  # 判断键值存在时
                                # 遍历字典
                                for m in filter_dic[i['metadata']['name']]:
                                    # 判断name值以server开头时
                                    if ports['name'].startswith('server'):
                                        if not m.get('server_port'):
                                            # 增加键值对
                                            m['server_port'] = ports['port']
                                    if ports['name'].startswith('beejob'):
                                        if not m.get('beejob_port'):
                                            m['beejob_port'] = ports['port']
    
            # print(filter_dic)
            # print(json.dumps(filter_dic))
            return json.dumps(filter_dic)
    
    
    if __name__ == '__main__':
        # 参数个数,由于sys.argv[0]就是脚本名,所以要减1
        num = len(sys.argv) - 1
        if num < 2 or num > 2:
            print("参数错误,必须传2个参数,分别是ip和端口")
            print("比如:python endpoints_v1.py 192.168.1.1 8080")
            exit()
    
        ip = sys.argv[1]  # ip
        port = sys.argv[2]  # 端口
    
        # ip = "192.168.1.1"
        # port = "8080"
        res = Endpoints(ip, port).main()
        print(res)


    执行输出:

    {"voucher-center-master":[{"server_port":8012,"ip":"192.169.167.105","pod_name":"voucher-center-rc-p20kk","nodeName":"job-node149","beejob_port":3011},{"server_port":8012,"ip":"192.169.183. 26","pod_name":"voucher-center-rc-vknkt","nodeName":"job-node137","beejob_port":3011},{"server_port":8012,"ip":"192.169.242.29","pod_name":"voucher-center-rc-0x482","nodeName":"job-node145","beejob_port":3011},{"server_port":8012,"ip":"192.169.76.159","pod_name":"voucher-center-rc-xtxfb","nodeName":"job-node151","beejob_port":3011},{"server_port":8012,"ip":"192.169.98.159","pod_name":"voucher-center-rc-n9wkl","nodeName":"job-node147","beejob_port":3011}]}

     

    使用json格式化工具,效果如下:

    1.png

     

    那么有了这些数据,就可以做端口的健康检测了!

     


关键字