diff --git a/README.md b/README.md index 1c55de3..1145973 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ * 一期: 基础模板 (已完成) * 二期: k8s管理平台 (开发中) - * pod 列表 (已完成) + * node/service/pod 列表 (已完成) * pod webssh (已完成) diff --git a/k8s/consumers.py b/k8s/consumers.py index a381427..249efd6 100644 --- a/k8s/consumers.py +++ b/k8s/consumers.py @@ -28,7 +28,7 @@ class MyThread(threading.Thread): self.number += 1 if "kubectl exec -it" in str_data: - #不返回内容 + # 不返回内容 pass else: if "rpc error" in str_data: @@ -68,6 +68,7 @@ class EchoConsumer(WebsocketConsumer): def connect(self): # 创建channels group, 命名为:用户名 (最好不要中文名字),并使用channel_layer写入到redis + async_to_sync(self.channel_layer.group_add)(self.scope['user'].username, self.channel_name) self.sshclient = paramiko.SSHClient() @@ -80,6 +81,7 @@ class EchoConsumer(WebsocketConsumer): t1 = MyThread(self) t1.setDaemon(True) t1.start() + # 可以在这里根据 用户 要访问的pod 进行 权限控制 path = self.scope['path'].split('/') cmd = f"kubectl exec -it {path[2]} -n {path[3]} sh \r" self.chan.send(cmd) diff --git a/k8s/k8sApi/core.py b/k8s/k8sApi/core.py index 7f55e59..1fd55ed 100644 --- a/k8s/k8sApi/core.py +++ b/k8s/k8sApi/core.py @@ -20,35 +20,50 @@ class K8sApi(object): v1 = client.CoreV1Api(aApiClient) return v1 - def get_podlist(self): + def get_node_list(self): + client_v1 = self.get_client() + ret = client_v1.list_node() + return ret + + def get_service_list(self): + client_v1 = self.get_client() + ret = client_v1.list_service_for_all_namespaces(watch=False) + return ret + + def get_pod_list(self): client_v1 = self.get_client() ret_pod = client_v1.list_pod_for_all_namespaces(watch=False) return ret_pod - def get_namespacelist(self): + def get_pod_detail(self, name, namespace): + client_v1 = self.get_client() + ret_pod = client_v1.read_namespaced_pod(name, namespace) + return ret_pod + + def get_namespace_list(self): client_v1 = self.get_client() ret_namespace = client_v1.list_namespace() return ret_namespace - def test_pods_connect(self, podname, namespace, command, container=None): - client_v1 = self.get_client() - if stream(client_v1.connect_get_namespaced_pod_exec, podname, namespace, command=command, - container=container, - stderr=True, stdin=False, - stdout=True, tty=False): - return True - else: - return False - - def get_pods_exec(self, podname, namespace, command, container=None): - client_v1 = self.get_client() - if container: - rest = stream(client_v1.connect_get_namespaced_pod_exec, podname, namespace, command=command, - container=container, - stderr=True, stdin=False, - stdout=True, tty=False) - else: - rest = stream(client_v1.connect_get_namespaced_pod_exec, podname, namespace, command=command, - stderr=True, stdin=False, - stdout=True, tty=False) - return rest + # def test_pod_connect(self, podname, namespace, command, container=None): + # client_v1 = self.get_client() + # if stream(client_v1.connect_get_namespaced_pod_exec, podname, namespace, command=command, + # container=container, + # stderr=True, stdin=False, + # stdout=True, tty=False): + # return True + # else: + # return False + # + # def get_pod_exec(self, podname, namespace, command, container=None): + # client_v1 = self.get_client() + # if container: + # rest = stream(client_v1.connect_get_namespaced_pod_exec, podname, namespace, command=command, + # container=container, + # stderr=True, stdin=False, + # stdout=True, tty=False) + # else: + # rest = stream(client_v1.connect_get_namespaced_pod_exec, podname, namespace, command=command, + # stderr=True, stdin=False, + # stdout=True, tty=False) + # return rest diff --git a/k8s/tests.py b/k8s/tests.py index 3d29e55..1f4a063 100644 --- a/k8s/tests.py +++ b/k8s/tests.py @@ -12,9 +12,12 @@ def main(): client.Configuration.set_default(configuration) v1 = client.CoreV1Api() ret = v1.list_pod_for_all_namespaces(watch=False) - for i in ret.items: - print("%s\t%s\t%s" % - (i.status.pod_ip, i.metadata.namespace, i.metadata.name)) + + ret1 = v1.read_namespaced_pod("nginx-58bdcbcd-z8v2s","default") + print(ret1) + # for i in ret.items: + # print("%s\t%s\t%s" % + # (i.status.pod_ip, i.metadata.namespace, i.metadata.name)) if __name__ == '__main__': diff --git a/k8s/urls.py b/k8s/urls.py index 002a540..c9aeede 100644 --- a/k8s/urls.py +++ b/k8s/urls.py @@ -1,8 +1,14 @@ from django.urls import path from k8s import views + app_name = "k8s" urlpatterns = [ + path('k8s-node-list', views.K8sNodeListView.as_view(), name='k8s-node-list'), + + path('k8s-service-list', views.K8sServiceListView.as_view(), name='k8s-service-list'), + path('k8s-pod-list', views.K8sPodListView.as_view(), name='k8s-pod-list'), - path('k8s-pod-webssh', views.K8sPodWebssh.as_view(), name='k8s-pod-webssh') + path('k8s-pod-webssh', views.K8sPodWebssh.as_view(), name='k8s-pod-webssh'), + path('k8s-pod-detail', views.K8sPodDetail.as_view(), name='k8s-pod-detail') ] diff --git a/k8s/views.py b/k8s/views.py index 34a6932..92d6673 100644 --- a/k8s/views.py +++ b/k8s/views.py @@ -16,12 +16,48 @@ from k8s.k8sApi.core import K8sApi logger = logging.getLogger('k8s') +class K8sNodeListView(LoginRequiredMixin, PermissionRequiredMixin, View): + permission_required = ('k8s.view_ecs',) + + def get(self, request): + obj = K8sApi() + ret = obj.get_node_list() + data = {} + for i in ret.items: + print(i) + data[i.metadata.name] = {"name": i.metadata.name, + "status": i.status.conditions[-1].type if i.status.conditions[ -1].status == "True" else "NotReady", + "ip": i.status.addresses[0].address, + "kubelet_version": i.status.node_info.kubelet_version, + "os_image": i.status.node_info.os_image, + } + return render(request, "k8s/k8s-node-list.html", {"data": data}) + + +class K8sServiceListView(LoginRequiredMixin, PermissionRequiredMixin, View): + permission_required = ('k8s.view_ecs',) + + def get(self, request): + obj = K8sApi() + ret = obj.get_service_list() + data = {} + for i in ret.items: + print(i) + ports = [] + for j in i.spec.ports: + ports.append(f"{j.target_port}/{j.port}/{j.node_port}") + data[i.metadata.name] = {"name": i.metadata.name, "cluster_ip": i.spec.cluster_ip, "type": i.spec.type, + "external_i_ps": i.spec.external_i_ps, + "port": ports} + return render(request, "k8s/k8s-service-list.html", {"data": data}) + + class K8sPodListView(LoginRequiredMixin, PermissionRequiredMixin, View): permission_required = ('k8s.view_ecs',) def get(self, request): obj = K8sApi() - ret = obj.get_podlist() + ret = obj.get_pod_list() data = {} for i in ret.items: data[i.metadata.name] = {"ip": i.status.pod_ip, "namespace": i.metadata.namespace} @@ -34,5 +70,15 @@ class K8sPodWebssh(LoginRequiredMixin, PermissionRequiredMixin, View): def get(self, request): name = self.request.GET.get("name") namespace = self.request.GET.get("namespace") - return render(request, "k8s/k8s-pod-webssh.html",{"name":name,"namespace":namespace}) + return render(request, "k8s/k8s-pod-webssh.html", {"name": name, "namespace": namespace}) + +class K8sPodDetail(LoginRequiredMixin, PermissionRequiredMixin, View): + permission_required = ('k8s.view_ecs',) + + def get(self, request): + name = self.request.GET.get("name") + namespace = self.request.GET.get("namespace") + obj = K8sApi() + data = obj.get_pod_detail(name, namespace) + return render(request, "k8s/k8s-pod-detail.html", {"name": name, "namespace": namespace, "data": data}) diff --git a/templates/base/_nav.html b/templates/base/_nav.html index 5121aa8..30f5f6a 100644 --- a/templates/base/_nav.html +++ b/templates/base/_nav.html @@ -55,19 +55,28 @@ + {% if perms.k8s.view_ecs %}