python过滤 Kubernetes api数据
一、需求分析
Kubernetes endpoints api地址
http://ip地址:端口/api/v1/namespaces/default/endpoints
services api地址
http://ip地址:端口/api/v1/namespaces/default/services
下面主要展示 endpoints api的部分数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{ "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个端口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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开头的
三、正式代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/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)
执行输出:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{"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格式化工具,效果如下:
那么有了这些数据,就可以做端口的健康检测了!