From 34de510effed4f99703169d96120356843f7d289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=85=A8?= Date: Wed, 12 Jun 2019 11:40:16 +0800 Subject: [PATCH] =?UTF-8?q?v0.4.0=20=20=20=20k8s=20=20=20=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- k8s/consumers.py | 4 +- k8s/k8sApi/core.py | 63 +++++++----- k8s/tests.py | 9 +- k8s/urls.py | 8 +- k8s/views.py | 50 +++++++++- templates/base/_nav.html | 17 +++- templates/k8s/k8s-node-list.html | 148 ++++++++++++++++++++++++++++ templates/k8s/k8s-pod-detail.html | 75 ++++++++++++++ templates/k8s/k8s-pod-list.html | 23 ++--- templates/k8s/k8s-service-list.html | 136 +++++++++++++++++++++++++ 11 files changed, 484 insertions(+), 51 deletions(-) create mode 100644 templates/k8s/k8s-node-list.html create mode 100644 templates/k8s/k8s-pod-detail.html create mode 100644 templates/k8s/k8s-service-list.html 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 %}
  • - k8s管理 + k8s管理
  • - + {% endif %} {% ifequal user.is_superuser 1 %} diff --git a/templates/k8s/k8s-node-list.html b/templates/k8s/k8s-node-list.html new file mode 100644 index 0000000..c530051 --- /dev/null +++ b/templates/k8s/k8s-node-list.html @@ -0,0 +1,148 @@ +{% extends "base/base.html" %} +{% load asset_filter %} +{% load bootstrap4 %} +{% load static %} +{% block header-css %} + + + + + +{% endblock %} + +{% block title %}K8S{% endblock %} + + + +{% block page-content %} + + +
    +
    +
    + +
    + +
    +
    Node列表
    + +
    +
    + + + +
    + + +
    + {% csrf_token %} + + + + + + + + + + + + + + + + + + + {% for k,v in data.items %} + + + + + + + + + + + + + + + {% endfor %} + + +
    服务名状态IP版本镜像IPIP
    +
    {{ k }}
    +
    + {% if v.status == "Ready" %} +
    {{ v.status }}
    + {% else %} +
    {{ v.status }}
    + {% endif %} +
    +
    {{ v.ip}}
    +
    +
    {{ v.kubelet_version}}
    +
    +
    {{ v.os_image}}
    +
    +
    {{ v.ip}}
    +
    +
    {{ v.ip}}
    +
    + +
    + + +
    + +
    + + +
    +
    +
    +
    + + + + + + {% block footer-js %} + + + {% endblock %} + +{% endblock %} diff --git a/templates/k8s/k8s-pod-detail.html b/templates/k8s/k8s-pod-detail.html new file mode 100644 index 0000000..e132608 --- /dev/null +++ b/templates/k8s/k8s-pod-detail.html @@ -0,0 +1,75 @@ +{% extends "base/base.html" %} +{% block title %}资产详情{% endblock %} +{% block header-css %} + {% load bootstrap4 %} +{% endblock %} + + +{% block page-content %} + + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + {{ name }} +
    + + + + + + + +
    +
    +
    + +
    {{ data }}
    +                                    
    +
    +
    +
    + + + +
    +
    +
    +
    +
    + + + + + {% block footer-js %} + + + + {% endblock %} + + +{% endblock %} + + diff --git a/templates/k8s/k8s-pod-list.html b/templates/k8s/k8s-pod-list.html index 934add7..6ad0baf 100644 --- a/templates/k8s/k8s-pod-list.html +++ b/templates/k8s/k8s-pod-list.html @@ -69,6 +69,7 @@ 主机名 ip 命名空间 + 详情 操作 @@ -87,23 +88,15 @@
    {{ v.namespace}}
    - - webssh + + 详情 -{# {% if perms.assets.view_ecs %}#} -{# 详情#} -{# {% endif %}#} -{# {% if perms.assets.change_ecs %}#} -{# 编辑#} -{# {% endif %}#} -{# {% if perms.assets.delete_ecs %}#} -{# 删除#} -{# {% endif %}#} + + webssh + {% endfor %} diff --git a/templates/k8s/k8s-service-list.html b/templates/k8s/k8s-service-list.html new file mode 100644 index 0000000..7d201fa --- /dev/null +++ b/templates/k8s/k8s-service-list.html @@ -0,0 +1,136 @@ +{% extends "base/base.html" %} +{% load asset_filter %} +{% load bootstrap4 %} +{% load static %} +{% block header-css %} + + + + + +{% endblock %} + +{% block title %}K8S{% endblock %} + + + +{% block page-content %} + + +
    +
    +
    + +
    + +
    +
    Service列表
    + +
    +
    + + + +
    + + +
    + {% csrf_token %} + + + + + + + + + + + + + + + + + + {% for k,v in data.items %} + + + + + + + + + + + + {% endfor %} + + +
    服务名cluster_ip类型external_i_pstarget_port/port/node_port
    +
    {{ k }}
    +
    +
    {{ v.cluster_ip }}
    +
    +
    {{ v.type}}
    +
    +
    {{ v.external_i_ps}}
    +
    +
    {% for i in v.port %}{{ i }}
    {% endfor %}
    +
    + +
    + + +
    + +
    + + +
    +
    +
    +
    + + + + + + {% block footer-js %} + + + {% endblock %} + +{% endblock %}