由于工作中,经常会出现测试在群里发一个报错的url,发到群里面造成AOE范围伤害波及到运维,所以自己根据需求,整理了一个可 根据 服务名进行匹配,以及url 进行匹配对应服务的东西,便于排查问题;
因为Kubernetes本身各方面还是较为完善,所以在Master上开启一个 kubectl proxy 模式可以通过这个模式,直接通过http请求访问到对应日志、配置文件相关之类文件;
nohup kubectl proxy --address='0.0.0.0' --port=8080 --accept-hosts='^*$' &
以及后面通过命令行,快速生成字典:
kubectl get ing | grep -v NAME |awk 'BEGIN{print "{"}{print "\""$2"\"" ":" "\""$1"\""","}END{print "}"}'
注意删除最后一个逗号!
界面使用的示例:
然后发一下代码:Django部分就是很简单的配置,前端页面也是最简单的html + css
调用代码kubetools.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''通过输入server,取出所需的所有pod'''
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'books.settings' # 配置系统变量
import django
import urllib3
import datetime
import traceback
import socket
from kubernetes import client
from kubernetes.client.rest import ApiException
django.setup()
class FilterBundle():
def __init__(self, token, apiserver, namespace, server, scope=0):
self.token = token
self.apiserver = apiserver
self.namespace = namespace
self.server = server
self.scope = scope
def initSetting(self):
urllib3.disable_warnings()
configuration = client.Configuration()
configuration.host = self.apiserver
configuration.verify_ssl = False
configuration.api_key = {'authorization': 'Bearer ' + self.token}
client.Configuration.set_default(configuration)
return client
def telnet(self, ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.settimeout(2)
s.connect((ip, int(port)))
s.shutdown(2)
return True
except:
return False
def hostStatus(self, host):
try:
api_instance = self.initSetting().CoreV1Api()
api_response = api_instance.list_node()
for h in api_response.items:
svc_ip = h.status.addresses[0].address
if host in svc_ip:
host_status = h.status.conditions[3].status
return host_status
except ApiException as e:
traceback.print_exc(e)
def filterSvc(self):
try:
api_instance = self.initSetting().CoreV1Api()
api_response = api_instance.list_namespaced_service(self.namespace)
svc_list = api_response.items
for s in svc_list:
# svc name
svc_name = s.metadata.name
if self.server in svc_name:
# print(s)
svc_type = s.spec.type
svc_ip = s.spec.cluster_ip
svc_port = s.spec.ports[0].port
svc_message = "http://x.x.x.x:8080" + s.metadata.self_link
if self.namespace == 'default':
svc_bundle = {'svc_name': svc_name, 'svc_type': svc_type, 'svc_ip': svc_ip,
'svc_port': svc_port,
'socket_status': "阿里云暂不支持检测", 'svc_message': "暂不支持阿里云"}
else:
svc_bundle = {'svc_name': svc_name, 'svc_type': svc_type, 'svc_ip': svc_ip,
'svc_port': svc_port,
'socket_status': self.telnet(svc_ip, svc_port), 'svc_message': svc_message}
yield svc_bundle
except ApiException as e:
traceback.print_exc(e)
def readSvc(self):
try:
api_instance = self.initSetting().CoreV1Api()
api_response = api_instance.read_namespaced_service(name=self.server, namepace=self.namespace)
svc_list = api_response.items
# for s in svc_list:
# # svc name
svc_name = svc_list.metadata.name
if self.server in svc_name:
# print(s)
svc_type = svc_list.spec.type
svc_ip = svc_list.spec.cluster_ip
svc_port = svc_list.spec.ports[0].port
svc_message = "http://x.x.x.x:8080" + s.metadata.self_link
if self.namespace == 'default':
svc_bundle = {'svc_name': svc_name, 'svc_type': svc_type, 'svc_ip': svc_ip,
'svc_port': svc_port,
'socket_status': "阿里云暂不支持检测", 'svc_message': "暂不支持阿里云"}
else:
svc_bundle = {'svc_name': svc_name, 'svc_type': svc_type, 'svc_ip': svc_ip,
'svc_port': svc_port,
'socket_status': self.telnet(svc_ip, svc_port), 'svc_message': svc_message}
yield svc_bundle
except ApiException as e:
traceback.print_exc(e)
def filterPod(self):
try:
api_instance = self.initSetting().CoreV1Api()
api_response = api_instance.list_namespaced_pod(self.namespace)
pod_list = api_response.items
for p in pod_list:
# pod名字
pod_name = p.metadata.name
# print(self.server)
if self.server in pod_name or self.server[:-6] in pod_name:
# print(i)
# 镜像版本
image_version = p.status.container_statuses[0].image.split(':')[1]
# pod状态
pod_status = p.status.phase
pod_time = p.status.start_time + datetime.timedelta(hours=8)
# pod所在宿主机
pod_host = p.status.host_ip
pod_ip = p.status.pod_ip
log_url = "http://x.x.x.x:8080/api/v1/namespaces/{}/pods/{}/log".format(self.namespace,
pod_name)
if self.namespace == 'default':
pod_bundle = {'pod_name': pod_name, 'status': pod_status, 'pod_ip': pod_ip,
'version': image_version,
'starttime': str(pod_time).split('+')[0], 'host': pod_host,
'host_status': "阿里云暂不支持检测", "log_url": "暂不支持阿里云"}
else:
pod_bundle = {'pod_name': pod_name, 'status': pod_status, 'pod_ip': pod_ip,
'version': image_version,
'starttime': str(pod_time).split('+')[0], 'host': pod_host,
'host_status': self.hostStatus(pod_host), "log_url": log_url}
yield pod_bundle
except ApiException as e:
traceback.print_exc(e)
def filterIng(self):
try:
api_instance = self.initSetting().ExtensionsV1beta1Api()
api_response = api_instance.list_namespaced_ingress(namespace=self.namespace)
ing_list = api_response.items
for i in ing_list:
# pod名字
ing_http = i.spec.rules[0].http.paths
for s in ing_http:
ing_svc = s.backend.service_name
# print(self.server)
if self.server in ing_svc:
ing_name = i.metadata.name
ing_domain = i.spec.rules[0].host
ing_port = s.backend.service_port
ing_path = "http://" + ing_domain + s.path
ing_msg = "http://192.168.1.100:8080" + i.metadata.self_link
if self.namespace == 'default':
ing_msg = "暂不支持阿里云"
else:
ing_msg = "http://192.168.1.100:8080" + i.metadata.self_link
ing_bundle = {"ing_name": ing_name, "ing_domain": ing_domain, "ing_svc": ing_svc,
"ing_port": ing_port, "ing_path": ing_path, "ing_msg": ing_msg}
yield ing_bundle
except ApiException as e:
traceback.print_exc(e)
def filterPath(self, ingress_name, ingress_path):
try:
api_instance = self.initSetting().ExtensionsV1beta1Api()
api_response = api_instance.read_namespaced_ingress(name=ingress_name, namespace=self.namespace)
ing_http = api_response.spec.rules[0].http.paths
for s in ing_http:
ing_path = s.path
if ingress_path == ing_path:
ing_svc = s.backend.service_name
ing_name = api_response.metadata.name
ing_domain = api_response.spec.rules[0].host
ing_port = s.backend.service_port
ing_path = "http://" + ing_domain + s.path
ing_msg = "http://x.x.x.x:8080" + api_response.metadata.self_link
ing_bundle = {"ing_name": ing_name, "ing_domain": ing_domain, "ing_svc": ing_svc,
"ing_port": ing_port, "ing_path": ing_path, "ing_msg": ing_msg}
self.server = ing_svc
yield ing_bundle
except ApiException as e:
traceback.print_exc(e)
class ToolsBundle():
def __init__(self, serverName='', urlPath='', envName='sit'):
if envName == 'release':
self.apiserver = 'https://x.x.x.x:6443'
self.Token = 'token,自行通过命令行拿'
self.envName = 'default'
else:
self.Token = 'token,自行通过命令行拿'
self.apiserver = 'https://x.x.x.x:6443'
self.envName = envName
self.serverName = serverName
self.urlPath = urlPath
self.tools = FilterBundle(token=self.Token, apiserver=self.apiserver, server=self.serverName,
namespace=self.envName)
def pod(self):
pod_bundle = self.tools.filterPod()
return pod_bundle
def svc(self):
svc_bundle = self.tools.filterSvc()
return svc_bundle
def ing(self):
ing_bundle = self.tools.filterIng()
return ing_bundle
def ingpath(self):
dev_ingdata = {"域名":"ingressname",自行通过命令行用awk快速生成一下}
sit_ingdata = {"域名":"ingressname",自行通过命令行用awk快速生成一下}
release_ingdata = {"域名":"ingressname",自行通过命令行用awk快速生成一下}
if self.envName == 'sit':
ing_name = sit_ingdata.get(self.urlPath.split('/')[2])
ing_path = "/" + self.urlPath.split('/')[3]
elif self.envName == 'default':
ing_name = release_ingdata.get(self.urlPath.split('/')[2])
ing_path = "/" + self.urlPath.split('/')[3]
else:
ing_name = dev_ingdata.get(self.urlPath.split('/')[2])
ing_path = "/" + self.urlPath.split('/')[3]
ingpath_bundle = self.tools.filterPath(ingress_name=ing_name, ingress_path=ing_path)
return ingpath_bundle
def read(self):
return self.tools.readSvc()
views.py
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
import logman.kubetools as tools
def index(request):
if request.GET.get('svc') and request.GET.get('env'):
keyword = request.GET['svc']
if '_' in keyword:
keyword = keyword.replace('_', '-')
env = request.GET['env']
all = tools.ToolsBundle(serverName=keyword, envName=env)
svc_data = all.svc()
pod_data = all.pod()
ing_data = all.ing()
return render(request, "svc.html", {"PodBundle": pod_data, "SvcBundle": svc_data, "IngBundle": ing_data})
elif request.GET.get('urlpath') and request.GET.get('env'):
urlpath = request.GET['urlpath']
env = request.GET['env']
all = tools.ToolsBundle(urlPath=urlpath, envName=env)
dataing = all.ingpath()
ing_data = dataing
for s in ing_data:
server = s.get('ing_svc')
all2 = tools.ToolsBundle(serverName=server, envName=env)
svc_data = all2.svc()
pod_data = all2.pod()
ing_data = all2.ing()
return render(request, "svc.html", {"PodBundle": pod_data, "SvcBundle": svc_data, "IngBundle": ing_data})
else:
return render(request, 'svc.html')
前端页面 svc.html:
<!--注释-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Welcome</title>
<style type="text/css">
thead {
color: green
}
strong {
color: red;
font-size: 20px;
}
td div {
color: blue;
}
</style>
</head>
<body>
<div class=" body_div">
<a href="/logman/"><h1>服务可用性查询</h1></a>
<hr/>
<form action="/logman/" method="get">
<p>服务名或URL 条件二选一!</p>
<p>示例:stocking-cloud-grpc-stuff-return-server 或 http://order.chtwebapi.lingcb.net/retail_order/</p>
<p>
<label>服务:<input type="text" size="40px" name="svc" value=""
\></label>
</p>
<p>
<label>URL:<input type="text" size="200px" name="urlpath" value=""
\></label>
</p>
<p>
环境:
<select name="env">
<option name="sit" value="sit">sit</option>
<option name="dev" value="dev">dev</option>
<option name="release" value="release">release</option>
</select>
<input type="submit" value="提交" \>
</p>
</form>
</div>
<hr/>
<br>
<h3>Service</h3>
<table border="1">
<thead>
<tr>
<th>SvcName</th>
<th>SvcType</th>
<th>SvcIP</th>
<th><div>SvcPort</div></th>
<th>Socket_Status</th>
<th>message</th>
</tr>
</thead>
<tbody>
{% for line in SvcBundle %}
<tr>
<td>{{ line.svc_name }}</td>
<td>{{ line.svc_type }}</td>
<td>{{ line.svc_ip }}</td>
<td><div>{{ line.svc_port }}</div></td>
<td><strong>{{ line.socket_status }}</strong></td>
<td>{{ line.svc_message }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr/>
<br>
<h3>Pod</h3>
<table border="1">
<thead>
<tr>
<th>PodName</th>
<th>PodStatus</th>
<th>PodIP</th>
<th>PodVersion</th>
<th>启动时间</th>
<th>Host</th>
<th>HostStatus</th>
<th>LogURL</th>
</tr>
</thead>
<tbody>
{% for line in PodBundle %}
<tr>
<td>{{ line.pod_name }}</td>
<td><strong>{{ line.status }}</strong></td>
<td>{{ line.pod_ip }}</td>
<td>{{ line.version }}</td>
<td>{{ line.starttime }}</td>
<td>{{ line.host }}</td>
<td><strong>{{ line.host_status }}</strong></td>
<td>{{ line.log_url }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr/>
<br>
<h3>Ingress</h3>
<table border="1">
<thead>
<tr>
<th>IngName</th>
<th>IngDomain</th>
<th>IngSvc</th>
<th>IngPort</th>
<th>IngPath</th>
<th>IngMsg</th>
</tr>
</thead>
<tbody>
{% for line in IngBundle %}
<tr>
<td>{{ line.ing_name }}</td>
<td>{{ line.ing_domain }}</td>
<td>{{ line.ing_svc }}</td>
<td><div>{{ line.ing_port }}</div></td>
<td>{{ line.ing_path }}</td>
<td>{{ line.ing_msg }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
项目地址:https://github.com/J-jingwei/kubernetes-log/tree/master/Django