This commit is contained in:
Bruce-Stark 2021-06-09 03:02:46 +08:00
parent 67c00fd817
commit bbef584c84
32 changed files with 1758 additions and 185 deletions

33
package-lock.json generated
View File

@ -21,6 +21,7 @@
"element-ui": "2.13.2",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"is-svg": "^4.3.1",
"js-cookie": "2.2.0",
"jsonlint": "1.6.3",
"jszip": "3.2.1",
@ -8367,6 +8368,14 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
"node_modules/fast-xml-parser": {
"version": "3.19.0",
"resolved": "https://registry.npm.taobao.org/fast-xml-parser/download/fast-xml-parser-3.19.0.tgz",
"integrity": "sha1-y2N+w/OZn1FAbdj/Dm/E2D5SDQE=",
"bin": {
"xml2js": "cli.js"
}
},
"node_modules/faye-websocket": {
"version": "0.11.4",
"resolved": "https://registry.nlark.com/faye-websocket/download/faye-websocket-0.11.4.tgz",
@ -10790,6 +10799,17 @@
"node": ">= 0.4"
}
},
"node_modules/is-svg": {
"version": "4.3.1",
"resolved": "https://registry.npm.taobao.org/is-svg/download/is-svg-4.3.1.tgz",
"integrity": "sha1-jGPsjGfIx/Co3gpxyMfVjsz0QGs=",
"dependencies": {
"fast-xml-parser": "^3.19.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/is-symbol": {
"version": "1.0.4",
"resolved": "https://registry.nlark.com/is-symbol/download/is-symbol-1.0.4.tgz?cache=0&sync_timestamp=1620501182675&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-symbol%2Fdownload%2Fis-symbol-1.0.4.tgz",
@ -28591,6 +28611,11 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
"fast-xml-parser": {
"version": "3.19.0",
"resolved": "https://registry.npm.taobao.org/fast-xml-parser/download/fast-xml-parser-3.19.0.tgz",
"integrity": "sha1-y2N+w/OZn1FAbdj/Dm/E2D5SDQE="
},
"faye-websocket": {
"version": "0.11.4",
"resolved": "https://registry.nlark.com/faye-websocket/download/faye-websocket-0.11.4.tgz",
@ -30533,6 +30558,14 @@
"integrity": "sha1-P+XVmS+w2TQE8yWE1LAXmnG1Sl8=",
"dev": true
},
"is-svg": {
"version": "4.3.1",
"resolved": "https://registry.npm.taobao.org/is-svg/download/is-svg-4.3.1.tgz",
"integrity": "sha1-jGPsjGfIx/Co3gpxyMfVjsz0QGs=",
"requires": {
"fast-xml-parser": "^3.19.0"
}
},
"is-symbol": {
"version": "1.0.4",
"resolved": "https://registry.nlark.com/is-symbol/download/is-symbol-1.0.4.tgz?cache=0&sync_timestamp=1620501182675&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-symbol%2Fdownload%2Fis-symbol-1.0.4.tgz",

View File

@ -27,6 +27,7 @@
"element-ui": "2.13.2",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"is-svg": "^4.3.1",
"js-cookie": "2.2.0",
"jsonlint": "1.6.3",
"jszip": "3.2.1",

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getNodeMessage(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/nodes?sortBy=createTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/nodes?sortBy=createTime',
method: 'get',
params: query
})
@ -17,14 +17,14 @@ export function getNodeStatus(customUrl) {
export function getMasterNum() {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/nodes?labelSelector=node-role.kubernetes.io%2Fmaster%3D',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/nodes?labelSelector=node-role.kubernetes.io%2Fmaster%3D',
method: 'get'
})
}
export function getTotalNum() {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/nodes?sortBy=createTime&limit=10',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/nodes?sortBy=createTime&limit=10',
method: 'get'
})
}

View File

@ -2,28 +2,28 @@ import request from '@/utils/request'
export function getAPIState() {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/components/apiserver?metrics_filter=apiserver_request_rate%7Capiserver_request_latencies',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/components/apiserver?metrics_filter=apiserver_request_rate%7Capiserver_request_latencies',
method: 'get'
})
}
export function getSchedulerState() {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/components/scheduler?metrics_filter=scheduler_schedule_attempts',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/components/scheduler?metrics_filter=scheduler_schedule_attempts',
method: 'get'
})
}
export function getClusterResource() {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/cluster?metrics_filter=cluster_cpu_usage%7Ccluster_cpu_total%7Ccluster_memory_usage_wo_cache%7Ccluster_memory_total%7Ccluster_disk_size_usage%7Ccluster_disk_size_capacity%7Ccluster_pod_running_count%7Ccluster_pod_quota%24',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/cluster?metrics_filter=cluster_cpu_usage%7Ccluster_cpu_total%7Ccluster_memory_usage_wo_cache%7Ccluster_memory_total%7Ccluster_disk_size_usage%7Ccluster_disk_size_capacity%7Ccluster_pod_running_count%7Ccluster_pod_quota%24',
method: 'get'
})
}
export function getNodeBriefMessage() {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/nodes?type=rank&metrics_filter=node_cpu_utilisation%7Cnode_cpu_usage%7Cnode_cpu_total%7Cnode_memory_utilisation%7Cnode_memory_usage_wo_cache%7Cnode_memory_total%7Cnode_disk_size_utilisation%7Cnode_disk_size_usage%7Cnode_disk_size_capacity%7Cnode_pod_utilisation%7Cnode_pod_running_count%7Cnode_pod_quota%7Cnode_disk_inode_utilisation%7Cnode_disk_inode_total%7Cnode_disk_inode_usage%7Cnode_load1%24&page=1&limit=5&sort_type=desc&sort_metric=node_cpu_utilisation',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/nodes?type=rank&metrics_filter=node_cpu_utilisation%7Cnode_cpu_usage%7Cnode_cpu_total%7Cnode_memory_utilisation%7Cnode_memory_usage_wo_cache%7Cnode_memory_total%7Cnode_disk_size_utilisation%7Cnode_disk_size_usage%7Cnode_disk_size_capacity%7Cnode_pod_utilisation%7Cnode_pod_running_count%7Cnode_pod_quota%7Cnode_disk_inode_utilisation%7Cnode_disk_inode_total%7Cnode_disk_inode_usage%7Cnode_load1%24&page=1&limit=5&sort_type=desc&sort_metric=node_cpu_utilisation',
method: 'get'
})
}

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getBriefUserProject(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/namespaces?sortBy=createTime&labelSelector=kubesphere.io%2Fworkspace%21%3Dsystem-workspace%2C%21kubesphere.io%2Fkubefed-host-namespace%2C%21kubesphere.io%2Fdevopsproject',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/namespaces?sortBy=createTime&labelSelector=kubesphere.io%2Fworkspace%21%3Dsystem-workspace%2C%21kubesphere.io%2Fkubefed-host-namespace%2C%21kubesphere.io%2Fdevopsproject',
method: 'get',
params: query
})
@ -17,7 +17,7 @@ export function getDetailUserProject(customUrl) {
export function getBriefSystemProject(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/namespaces?sortBy=createTime&labelSelector=kubesphere.io%2Fworkspace%3Dsystem-workspace',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/namespaces?sortBy=createTime&labelSelector=kubesphere.io%2Fworkspace%3Dsystem-workspace',
method: 'get',
params: query
})

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getVolume(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/persistentvolumeclaims?sortBy=createTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/persistentvolumeclaims?sortBy=createTime',
method: 'get',
params: query
})

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getDeployments(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/deployments?sortBy=updateTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/deployments?sortBy=updateTime',
method: 'get',
params: query
})
@ -10,7 +10,7 @@ export function getDeployments(query) {
export function getStatefulSets(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/statefulsets?sortBy=createTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/statefulsets?sortBy=createTime',
method: 'get',
params: query
})
@ -18,7 +18,7 @@ export function getStatefulSets(query) {
export function getDaemonSets(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/daemonsets?sortBy=createTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/daemonsets?sortBy=createTime',
method: 'get',
params: query
})
@ -26,7 +26,7 @@ export function getDaemonSets(query) {
export function getPods(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/pods?sortBy=startTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/pods?sortBy=startTime',
method: 'get',
params: query
})
@ -34,7 +34,7 @@ export function getPods(query) {
export function getServices(query) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/services?sortBy=createTime',
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/services?sortBy=createTime',
method: 'get',
params: query
})

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getNodeDetails(customurl) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/nodes/' + customurl,
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/nodes/' + customurl,
method: 'get'
})
}
@ -16,21 +16,21 @@ export function getNodeStatus(customUrl) {
export function getMonitorData(url) {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/nodes?' + url + 'metrics_filter=node_cpu_utilisation%7Cnode_memory_utilisation%7Cnode_disk_size_utilisation%7Cnode_pod_utilisation%24',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/nodes?' + url + 'metrics_filter=node_cpu_utilisation%7Cnode_memory_utilisation%7Cnode_disk_size_utilisation%7Cnode_pod_utilisation%24',
method: 'get'
})
}
export function getMonitorDetailData(url) {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/nodes?' + url + 'metrics_filter=node_cpu_utilisation%7Cnode_load1%7Cnode_load5%7Cnode_load15%7Cnode_memory_utilisation%7Cnode_disk_size_utilisation%7Cnode_disk_inode_utilisation%7Cnode_disk_inode_usage%7Cnode_disk_inode_total%7Cnode_disk_read_iops%7Cnode_disk_write_iops%7Cnode_disk_read_throughput%7Cnode_disk_write_throughput%7Cnode_net_bytes_transmitted%7Cnode_net_bytes_received%24',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/nodes?' + url + 'metrics_filter=node_cpu_utilisation%7Cnode_load1%7Cnode_load5%7Cnode_load15%7Cnode_memory_utilisation%7Cnode_disk_size_utilisation%7Cnode_disk_inode_utilisation%7Cnode_disk_inode_usage%7Cnode_disk_inode_total%7Cnode_disk_read_iops%7Cnode_disk_write_iops%7Cnode_disk_read_throughput%7Cnode_disk_write_throughput%7Cnode_net_bytes_transmitted%7Cnode_net_bytes_received%24',
method: 'get'
})
}
export function getPodDetails(customurl) {
return request({
url: 'kapis/resources.kubesphere.io/v1alpha3/pods?' + customurl,
url: 'kapis/clusters/bj-member2/resources.kubesphere.io/v1alpha3/pods?' + customurl,
method: 'get'
})
}

View File

@ -2,14 +2,14 @@ import request from '@/utils/request'
export function getPodDetails(customurl) {
return request({
url: 'api/v1/namespaces/' + customurl,
url: 'api/clusters/bj-member2/v1/namespaces/' + customurl,
method: 'get'
})
}
export function getMonitorDetailData(url) {
return request({
url: 'kapis/monitoring.kubesphere.io/v1alpha3/namespaces/' + url + 'metrics_filter=pod_cpu_usage%7Cpod_memory_usage_wo_cache%7Cpod_net_bytes_transmitted%7Cpod_net_bytes_received%24',
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/namespaces/' + url + 'metrics_filter=pod_cpu_usage%7Cpod_memory_usage_wo_cache%7Cpod_net_bytes_transmitted%7Cpod_net_bytes_received%24',
method: 'get'
})
}

View File

@ -2,8 +2,21 @@ import request from '@/utils/request'
export function getWorkloadDetails(customurl) {
return request({
url: 'apis/apps/v1/namespaces/' + customurl,
url: 'apis/clusters/bj-member2/apps/v1/namespaces/' + customurl,
method: 'get'
})
}
export function getMonitorPodsData(url) {
return request({
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/namespaces/' + url + '/pods?sort_metric=pod_cpu_usage&limit=5&page=1',
method: 'get'
})
}
export function getMonitorDetailData(url) {
return request({
url: 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/namespaces/' + url + 'metrics_filter=pod_cpu_usage%7Cpod_memory_usage_wo_cache%7Cpod_net_bytes_transmitted%7Cpod_net_bytes_received%24',
method: 'get'
})
}

View File

@ -160,14 +160,14 @@ const podRouter = {
},
{
path: ':project/deployments/:name',
component: () => import('@/views/workloadsManagement/detail'),
component: () => import('@/views/workloadsManagement/deploymentsDetail'),
name: 'DeploymentDetail',
meta: { activeMenu: '/workloadsManagement' },
hidden: true,
children: [
{
path: 'resource-status',
component: () => import('@/views/workloadsManagement/resource-status'),
component: () => import('@/views/workloadsManagement/deploymentsResourceStatus'),
meta: { activeMenu: '/workloadsManagement', keepAlive: true }
},
{
@ -184,14 +184,14 @@ const podRouter = {
},
{
path: ':project/statefulsets/:name',
component: () => import('@/views/workloadsManagement/detail'),
component: () => import('@/views/workloadsManagement/statefulsetsDetail'),
name: 'StatefulSetDetail',
meta: { activeMenu: '/workloadsManagement' },
hidden: true,
children: [
{
path: 'resource-status',
component: () => import('@/views/workloadsManagement/resource-status'),
component: () => import('@/views/workloadsManagement/statefulsetsResourceStatus'),
meta: { activeMenu: '/workloadsManagement', keepAlive: true }
},
{
@ -208,14 +208,14 @@ const podRouter = {
},
{
path: ':project/daemonsets/:name',
component: () => import('@/views/workloadsManagement/detail'),
component: () => import('@/views/workloadsManagement/daemonsetsDetail'),
name: 'DaemonSetDetail',
meta: { activeMenu: '/workloadsManagement' },
hidden: true,
children: [
{
path: 'resource-status',
component: () => import('@/views/workloadsManagement/resource-status'),
component: () => import('@/views/workloadsManagement/daemonsetsResourceStatus'),
meta: { activeMenu: '/workloadsManagement', keepAlive: true }
},
{

View File

@ -62,7 +62,7 @@ const getNodeStatusList = (params) => {
getNodeMessage(params).then(res => {
const { items } = res
const namespace = items.map((item) => { return item.metadata.name })
const baseUrl = 'kapis/monitoring.kubesphere.io/v1alpha3/nodes?cluster=default&resources_filter='
const baseUrl = 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/nodes?cluster=default&resources_filter='
const customUrl = baseUrl + items.map(function(v) { return v.metadata.name }).join('%7C') + '%24&metrics_filter=node_cpu_usage%7Cnode_cpu_total%7Cnode_cpu_utilisation%7Cnode_memory_usage_wo_cache%7Cnode_memory_total%7Cnode_memory_utilisation%7Cnode_pod_running_count%7Cnode_pod_quota%24'
getNodeStatus(customUrl).then(re => {
const { results } = re
@ -183,7 +183,7 @@ const getUserProjectList = (params) => {
getBriefUserProject(params).then(res => {
const { items } = res
const namespace = items.map((item) => { return item.metadata.name })
const baseUrl = 'kapis/monitoring.kubesphere.io/v1alpha3/namespaces?resources_filter='
const baseUrl = 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/namespaces?resources_filter='
const customUrl = baseUrl + items.map(function(v) { return v.metadata.name }).join('%7C') + '%24&metrics_filter=namespace_cpu_usage%7Cnamespace_memory_usage_wo_cache%7Cnamespace_pod_count%24'
getDetailUserProject(customUrl).then(re => {
const { results } = re
@ -201,7 +201,7 @@ const getSystemProjectList = (params) => {
getBriefSystemProject(params).then(res => {
const { items } = res
const namespace = items.map((item) => { return item.metadata.name })
const baseUrl = 'kapis/monitoring.kubesphere.io/v1alpha3/namespaces?resources_filter='
const baseUrl = 'kapis/clusters/bj-member2/monitoring.kubesphere.io/v1alpha3/namespaces?resources_filter='
const customUrl = baseUrl + items.map(function(v) { return v.metadata.name }).join('%7C') + '%24&metrics_filter=namespace_cpu_usage%7Cnamespace_memory_usage_wo_cache%7Cnamespace_pod_count%24'
getDetailSystemProject(customUrl).then(re => {
const { results } = re

View File

@ -94,8 +94,8 @@ export default {
}
return {
loginForm: {
username: 'admin',
password: 'P@88w0rd'
username: 'nudt',
password: 'Nudt@123'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],

View File

@ -23,13 +23,13 @@
<div class="nodeNumMark">
<div class="blue">
<p>Master节点数量</p>
<i class="bigNum">3</i>
<i class="bigNum">1</i>
</div>
</div>
<div class="nodeNumMark">
<div class="green">
<p>Worker节点数量</p>
<i class="bigNum">4</i>v
<i class="bigNum">3</i>
</div>
</div>
@ -75,7 +75,7 @@ export default {
fontSize: 14,
fontWeight: 'bold'
},
data: [{ value: 16, name: '节点数量' }],
data: [{ value: 3, name: '节点数量' }],
itemStyle: {
color: 'transparent'
// show: false,
@ -88,7 +88,7 @@ export default {
endAngle: -180,
progress: {
show: true,
width: 17,
width: 0,
itemStyle: { color: '#30c0b7' }
},
axisLine: { lineStyle: { color: [[1, '#409eff']], width: 10 }}

View File

@ -1,14 +1,20 @@
<template>
<div>
<!-- <div id="myEchart" ref="myEchart" style="width:1000px; height:600px" />-->
<div id="cpuChart" ref="cpuChart" style="width:1200px; height:300px" />
<div id="workflowChart" ref="workflowChart" style="width:1200px; height:300px" />
<div id="memoryChart" ref="memoryChart" style="width:1200px; height:300px" />
<div id="storageChart" ref="storageChart" style="width:1200px; height:300px" />
<div id="inodeChart" ref="inodeChart" style="width:1200px; height:300px" />
<div id="iopsChart" ref="iopsChart" style="width:1200px; height:300px" />
<div id="diskChart" ref="diskChart" style="width:1200px; height:300px" />
<div id="netChart" ref="netChart" style="width:1200px; height:300px" />
<div id="cpuChart" ref="cpuChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="workflowChart" ref="workflowChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="memoryChart" ref="memoryChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="storageChart" ref="storageChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="inodeChart" ref="inodeChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="iopsChart" ref="iopsChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="diskChart" ref="diskChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="netChart" ref="netChart" style="width:1300px; height:300px" />
</div>
</template>

View File

@ -200,9 +200,11 @@ export default {
methods: {
unitConverter(data) {
if (data.charAt(data.length - 1) === 'm') {
return (parseFloat(data.slice(0, -1)) / 1000).toFixed(2) + ' Core ('
return (parseFloat(data.slice(0, -1)) / 1000).toFixed(2) + ' Core'
} if (data.charAt(data.length - 1) === 'i') {
return ((parseFloat(data.slice(0, -2))) / 1000).toFixed(2) + ' Gi ('
return ((parseFloat(data.slice(0, -2))) / 1000).toFixed(2) + ' Gi'
} if (/^\d+$/.test(data) === true) {
return (parseFloat(data) / (1024 * 1024 * 1024)).toFixed(2) + ' Gi'
} else {
return '-'
}
@ -217,10 +219,10 @@ export default {
getFormData() {
const customUrl = this.$route.path.split('/')[2]
getNodeDetails(customUrl).then(res => {
this.allocatedData.cpuRequest = this.unitConverter(res.metadata.annotations['node.kubesphere.io/cpu-requests']) + res.metadata.annotations['node.kubesphere.io/cpu-requests-fraction'] + ')'
this.allocatedData.cpuLimit = this.unitConverter(res.metadata.annotations['node.kubesphere.io/cpu-limits']) + res.metadata.annotations['node.kubesphere.io/cpu-limits-fraction'] + ')'
this.allocatedData.memoryRequest = this.unitConverter(res.metadata.annotations['node.kubesphere.io/memory-requests']) + res.metadata.annotations['node.kubesphere.io/memory-requests-fraction'] + ')'
this.allocatedData.memoryLimit = this.unitConverter(res.metadata.annotations['node.kubesphere.io/memory-limits']) + res.metadata.annotations['node.kubesphere.io/memory-limits-fraction'] + ')'
this.allocatedData.cpuRequest = this.unitConverter(res.metadata.annotations['node.kubesphere.io/cpu-requests']) + ' (' + res.metadata.annotations['node.kubesphere.io/cpu-requests-fraction'] + ')'
this.allocatedData.cpuLimit = this.unitConverter(res.metadata.annotations['node.kubesphere.io/cpu-limits']) + ' (' + res.metadata.annotations['node.kubesphere.io/cpu-limits-fraction'] + ')'
this.allocatedData.memoryRequest = this.unitConverter(res.metadata.annotations['node.kubesphere.io/memory-requests']) + ' (' + res.metadata.annotations['node.kubesphere.io/memory-requests-fraction'] + ')'
this.allocatedData.memoryLimit = this.unitConverter(res.metadata.annotations['node.kubesphere.io/memory-limits']) + ' (' + res.metadata.annotations['node.kubesphere.io/memory-limits-fraction'] + ')'
this.healthData.networkUnavailable = this.statusConverter(res.status.conditions[0].status)
this.healthData.memoryPressure = this.statusConverter(res.status.conditions[1].status)
this.healthData.diskPressure = this.statusConverter(res.status.conditions[2].status)

View File

@ -1,9 +1,12 @@
<template>
<div>
<div id="cpuChart" ref="cpuChart" style="width:1200px; height:300px" />
<div id="memoryChart" ref="memoryChart" style="width:1200px; height:300px" />
<div id="receivedChart" ref="receivedChart" style="width:1200px; height:300px" />
<div id="transmittedChart" ref="transmittedChart" style="width:1200px; height:300px" />
<div id="cpuChart" ref="cpuChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="memoryChart" ref="memoryChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="receivedChart" ref="receivedChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="transmittedChart" ref="transmittedChart" style="width:1300px; height:300px" />
</div>
</template>
@ -155,7 +158,6 @@ export default {
const startTime = endTime - 30000
const timeurl = startTime + '&end=' + Math.round(nowTime.getTime() / 1000)
const url = this.$route.path.split('/')[2] + '/pods/' + this.$route.path.split('/')[3] + '?cluster=default&start=' + timeurl + '&step=600s&times=50&'
console.log(url)
const chartData = {}
getMonitorDetailData(url).then(res => {
res.results.forEach(function(el) {

View File

@ -3,8 +3,8 @@
<h5>
容器
</h5>
<div v-for="(item, i) in dataMap" :key="i">
<FormData :column="4" :data="formData[i]" :data-map="item" />
<div v-for="(item, key) in dataMap" :key="key">
<FormData :column="3" :data="formData[key]" :data-map="item" />
</div>
</div>
</template>
@ -12,57 +12,40 @@
<script>
import { FormData } from '@/components/FormData'
import { getPodDetails } from '@/api/second-class-page/podInfo'
import { getPorts } from '@/utils/containerUtils'
export default {
components: { FormData },
data() {
return {
dataMap: [
{
image: '',
status: '状态',
restart: '重启次数',
port: '端口'
}
],
formData: [
{
image: '',
status: '',
restart: '',
port: ''
}
]
dataMap: [],
formData: []
}
},
mounted() {
this.getFormData()
},
methods: {
getPorts(obj) {
console.log(obj[0].containerPort)
// obj.forEach(v => {
// console.log(v)
// })
},
getFormData() {
const customurl = this.$route.path.split('/')[2] + '/pods/' + this.$route.path.split('/')[3]
getPodDetails(customurl).then(res => {
// const data = res.status.containerStatuses
res.status.containerStatuses.forEach(v => {
// console.log(res)
const temp = {}
temp.name = v.name
temp.image = v.image
temp.status = v.ready
temp.status = (v.ready === true) ? '运行中' : '异常中'
temp.restart = v.restartCount
res.spec.containers.forEach(container => {
console.log(container.ports)
if (container.ports != null) {
this.getPorts(container.ports)
} else {
if (container.ports != null && container.name === temp.name) {
temp.port = getPorts(container.ports)
}
if (container.ports === undefined && container.name === temp.name) {
temp.port = '-'
}
})
// console.log(temp)
const obj = { name: '容器名', image: '镜像', status: '状态', restart: '重启次数', port: '端口' }
this.dataMap.push(obj)
this.formData.push(temp)
})
})
}

View File

@ -3,22 +3,69 @@
<h5>
节点调度信息
</h5>
<FormData :column="4" :data="formData1" :data-map="dataMap1" />
<FormData :column="4" :data="formData" :data-map="dataMap" />
<h5>
<br>
容器状态分析
</h5>
<FormData :column="4" :data="healthData" :data-map="healthMap" />
<FormData :column="2" :data="healthData" :data-map="healthMap" />
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
import { getPodDetails } from '@/api/second-class-page/podInfo'
export default {
components: { FormData },
data() {
return {
dataMap: {
node: '调度至节点:',
time: '调度时间'
},
formData: {
node: '-',
time: '-'
},
healthMap: {
PodScheduled: '调度成功(PodScheduled)',
Initialized: 'Initialized',
ContainersReady: '容器准备就绪(ContainersReady)',
Ready: '开始运行(Ready)'
},
healthData: {
PodScheduled: '异常',
Initialized: '异常',
ContainersReady: '异常',
Ready: '异常'
}
}
},
mounted() {
this.getScheduledInfo()
},
methods: {
getScheduledInfo() {
const customurl = this.$route.path.split('/')[2] + '/pods/' + this.$route.path.split('/')[3]
getPodDetails(customurl).then(res => {
this.formData.node = res.spec.nodeName
res.status.conditions.forEach(item => {
if (item.type === 'PodScheduled') {
this.formData.time = item.lastTransitionTime
this.healthData.PodScheduled = (item.status === 'True') ? '正常' : '异常'
}
if (item.type === 'Initialized') {
this.healthData.Initialized = (item.status === 'True') ? '正常' : '异常'
}
if (item.type === 'ContainersReady') {
this.healthData.ContainersReady = (item.status === 'True') ? '正常' : '异常'
}
if (item.type === 'Ready') {
this.healthData.Ready = (item.status === 'True') ? '正常' : '异常'
}
})
})
}
}
}

View File

@ -55,7 +55,7 @@ export default {
this.activeName = i
}
}
this.getFormData()
// this.getFormData()
},
mounted() {
},

View File

@ -0,0 +1,228 @@
<template>
<div>
<el-card shadow="never">
<el-page-header content="详情" @back="goBack" />
<h2>{{ $route.params.name }}</h2> <!-- TODO: 这里显示别名和描述 -->
<div class="button-group">
<el-button plain round @click="editInfo">编辑信息</el-button>
<el-dropdown @command="handleCommand">
<el-button round>
更多操作<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-back" command="reset">版本回退</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit" command="editTemplate">编辑配置模板</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit" command="editSetting">编辑配置文件</el-dropdown-item>
<el-dropdown-item icon="el-icon-help" command="redeploy">重新部署</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete" command="deleteDeployment">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<el-dialog title="编辑信息" :visible.sync="dialogFormVisible">
<el-form ref="editInfoForm" :model="editInfoForm">
<el-form-item
prop="name"
label="名称"
>
<el-input v-model="editInfoForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="alias"
label="别名"
>
<el-input v-model="editInfoForm.alias" :maxlength="63" />
<span class="tips">别名可以由任意字符组成帮助您更好的区分资源最长 63 个字符</span>
</el-form-item>
<el-form-item
prop="description"
label="描述信息"
>
<el-input v-model="editInfoForm.description" type="textarea" :maxlength="256" />
<span class="tips">描述信息不超过 256 个字符</span>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitInfoEdit"> </el-button>
</div>
</el-dialog>
<el-dialog title="版本回退" :visible.sync="dialogResetVisible">
<el-form ref="resetForm" :model="resetForm">
<el-form-item
prop="name"
label="资源名称"
>
<el-input v-model="resetForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="currentVersion"
label="当前版本"
>
<el-input v-model="resetForm.currentVersion" :disabled="true" />
</el-form-item>
<el-form-item
prop="resetVersion"
label="回退版本"
required
>
<el-select v-model="resetForm.resetVersion">
<el-option
label="#2"
value="#2"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitReset"> </el-button>
</div>
</el-dialog>
<el-dialog title="编辑配置文件" :visible.sync="dialogEditSettingVisible">
<codemirror v-model="code" class="code-mirror" :options="cmOption" />
<div slot="footer" class="dialog-footer">
<el-button @click="dialogEditSettingVisible = false"> </el-button>
<el-button type="primary" @click="submitSettingEdit"> </el-button>
</div>
</el-dialog>
<FormData :data="formData" :data-map="dataMap" />
<el-tabs v-model="activeName" @tab-click="switchTab">
<el-tab-pane key="resource-status" label="资源状态" />
<el-tab-pane key="revision-control" label="版本记录" />
<el-tab-pane key="monitors" label="监控" />
</el-tabs>
<router-view />
</el-card>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
import { getWorkloadDetails } from '@/api/second-class-page/workloadInfo'
// import path from 'path'
export default {
components: { FormData },
data() {
return {
code: ``,
cmOption: {
autoCloseBrackets: true,
tabSize: 4,
styleActiveLine: true,
lineNumbers: true,
line: true,
mode: 'text/x-yaml',
theme: 'mbo'
// keyMap: "emacs"
},
dataMap: {
cluster: '集群',
namespace: '项目',
createTime: '创建时间',
updateTime: '更新时间',
creator: '创建者'
},
formData: {
cluster: 'default',
namespace: '-',
createTime: '-',
updateTime: '-',
creator: '-'
},
dialogFormVisible: false,
dialogResetVisible: false,
dialogEditSettingVisible: false,
asForm: {},
editInfoForm: {},
resetForm: {},
activeName: '',
tabList: {
'0': 'resource-status',
'1': 'revision-control',
'2': 'monitors'
}
}
},
watch: {
$route(route) {
if (route.path.search('resource-status') !== -1) {
this.getFormData()
}
}
},
created() {
for (const i in Object.keys(this.tabList)) {
if (this.$route.path.split('/')[3] === this.tabList[i]) {
this.activeName = i
}
}
this.getFormData()
},
methods: {
goBack() {
this.$router.push({ path: '/' + this.$route.path.split('/')[1] + '/' + this.$route.path.split('/')[3] })
},
switchTab(e) {
const tab = this.tabList[e.index]
if (this.$route.path.indexOf(tab) === -1) {
this.$router.push(tab)
}
},
getFormData() {
const customurl = this.$route.path.split('/')[2] + '/daemonsets/' + this.$route.path.split('/')[4]
getWorkloadDetails(customurl).then(res => {
this.formData.namespace = res.metadata.namespace
this.formData.createTime = res.metadata.creationTimestamp
this.formData.updateTime = (res.status.conditions != null) ? res.status.conditions[1].lastUpdateTime : res.metadata.creationTimestamp
})
},
editInfo() {
this.dialogFormVisible = true
},
submitInfoEdit() {
this.dialogFormVisible = false
this.$message.success('修改成功')
},
submitReset() {
this.dialogResetVisible = false
this.goBack()
},
submitSettingEdit() {
},
handleCommand(command) {
switch (command) {
case 'reset' :
this.dialogResetVisible = true
break
case 'editTemplate' :
break
case 'editSetting' :
this.dialogEditSettingVisible = true
break
case 'redeploy' :
this.$alert(`您即将重新部署工作负载 ${this.$route.params.name} (部署) , 容器组将根据更新策略进行重新部署,您的业务可能会被暂时中断。`, '确认重新部署 ?', {
confirmButtonText: '确定',
callback: () => {
this.$message.success('重新部署成功')
}
})
break
case 'deleteDeployment':
break
}
}
}
}
</script>
<style lang="scss" scoped>
.code-mirror{
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div>
<h5>
副本运行状态
</h5>
<FormData :column="4" :data="formData" :data-map="dataMap" />
<el-alert
:closable="false"
title="守护进程集 (DaemonSet) 可以确保集群中的每个节点运行一个副本,当有节点加入集群或者离开集群的时候,会自动地调整副本的数量来保证副本的数量与集群的节点数量一致。您可以使用守护进程集来运行存储服务,如 GlusterFSCeph 等;运行日志搜集服务,如 FluentdLogstash 等;运行监控服务等。"
show-icon
type="info"
/>
<h5>
端口
</h5>
<h5>
容器组
</h5>
<div>
<el-table :data="tableData" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<div v-for="(item, key) in props.row.container" :key="key">
<el-form-item label="容器名称">
<span>{{ item.name }}</span>
</el-form-item>
<el-form-item label="容器镜像">
<span>{{ item.image }}</span>
</el-form-item>
<el-form-item label="状态">
<span>{{ item.status }}</span>
</el-form-item>
<el-form-item label="重启次数">
<span>{{ item.restart }}</span>
</el-form-item>
<el-form-item label="端口">
<span>{{ item.port }}</span>
</el-form-item>
</div>
</el-form>
</template>
</el-table-column>
<el-table-column label="Pod名称" prop="pod" />
<el-table-column label="所属节点" prop="node" />
<el-table-column label="容器组IP" prop="ip" />
<el-table-column label="CPU监控" prop="cpu" />
<el-table-column label="内存监控" prop="memory" />
</el-table>
</div>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
// import * as echarts from 'echarts'
export default {
components: { FormData },
data() {
return {
dataMap: {
wantedCopy: '期望副本',
realityCopy: '实际运行副本'
},
formData: {
wantedCopy: '1',
realityCopy: '1'
},
tableData: [{
pod: 'kubectl-nudt-785fd767c5-jg9vp',
node: 'jcc-txy-003(10.206.0.15)',
ip: '10.244.2.13',
cpu: '',
memory: '',
container: [
{
name: 'kubectl',
image: 'kubesphere/kubectl:v1.19.0',
status: '运行中',
restart: '0',
port: '-'
}
]
}],
dataMap1: {
cpuUsage: 'CPU 请求',
storageUsage: 'CPU 限制',
podUsage: '内存请求',
localStorage: '内存限制'
},
formData1: {
cpuUsage: '0.787 Core (39%)',
storageUsage: '10.4 Core (520%)',
podUsage: '1.225 Gi (31%)',
localStorage: '20.857 Gi (543%)'
},
lineChartOption: {
title: {
subtext: 'CPU使用率'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [
'09:57:32',
'10:06:32',
'10:15:32',
'10:24:32',
'10:33:32',
'10:42:32',
'10:57:32'
]
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value}%'
}
},
series: [
{
name: 'CPU使用率',
type: 'line',
data: [10, 11, 13, 11, 12, 12, 9]
}
]
}
}
},
mounted() {
// this.$nextTick(() => {
// const lineChart = echarts.init(this.$refs.lineChart, 'dark')
// lineChart.setOption(this.lineChartOption)
// })
}
}
</script>
<style lang="scss" scoped>
#lineChart{
width:100%;
height: 200px;
}
</style>

View File

@ -0,0 +1,288 @@
<template>
<div>
<el-card shadow="never">
<el-page-header content="详情" @back="goBack" />
<h2>{{ $route.params.name }}</h2> <!-- TODO: 这里显示别名和描述 -->
<div class="button-group">
<el-button plain round @click="editInfo">编辑信息</el-button>
<el-dropdown @command="handleCommand">
<el-button round>
更多操作<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-back" command="reset">版本回退</el-dropdown-item>
<el-dropdown-item icon="el-icon-s-data" command="autoScaling">弹性伸缩</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit" command="editTemplate">编辑配置模板</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit" command="editSetting">编辑配置文件</el-dropdown-item>
<el-dropdown-item icon="el-icon-help" command="redeploy">重新部署</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete" command="deleteDeployment">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<el-dialog title="编辑信息" :visible.sync="dialogFormVisible">
<el-form ref="editInfoForm" :model="editInfoForm">
<el-form-item
prop="name"
label="名称"
>
<el-input v-model="editInfoForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="alias"
label="别名"
>
<el-input v-model="editInfoForm.alias" :maxlength="63" />
<span class="tips">别名可以由任意字符组成帮助您更好的区分资源最长 63 个字符</span>
</el-form-item>
<el-form-item
prop="description"
label="描述信息"
>
<el-input v-model="editInfoForm.description" type="textarea" :maxlength="256" />
<span class="tips">描述信息不超过 256 个字符</span>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitInfoEdit"> </el-button>
</div>
</el-dialog>
<el-dialog title="版本回退" :visible.sync="dialogResetVisible">
<el-form ref="resetForm" :model="resetForm">
<el-form-item
prop="name"
label="资源名称"
>
<el-input v-model="resetForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="currentVersion"
label="当前版本"
>
<el-input v-model="resetForm.currentVersion" :disabled="true" />
</el-form-item>
<el-form-item
prop="resetVersion"
label="回退版本"
required
>
<el-select v-model="resetForm.resetVersion">
<el-option
label="#2"
value="#2"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitReset"> </el-button>
</div>
</el-dialog>
<el-dialog title="弹性伸缩" :visible.sync="dialogASVisible">
<el-alert
:closable="false"
title="根据 CPU 和内存使用情况自动伸缩副本。如果同时指定 CPU 和内存,则满足任一条件后即添加或删除副本"
show-icon
type="info"
/>
<el-form ref="asForm" :model="asForm">
<el-form-item
prop="name"
label="资源名称"
>
<el-input v-model="asForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="cpuTargetUsagePer"
label="CPU 目标使用率 (单位: %)"
>
<el-input v-model="asForm.cpuTargetUsagePer" />
<span class="tips"> CPU 使用率超过或低于此目标值时将添加或删除副本</span>
</el-form-item>
<el-form-item
prop="cpuTargetUsage"
label="内存目标使用量 (单位: Mi)"
>
<el-input v-model="asForm.cpuTargetUsage" />
<span class="tips">当内存使用量超过或低于此目标值时将添加或删除副本</span>
</el-form-item>
<el-form-item
prop="minCopy"
label="最小副本数"
>
<el-input v-model="asForm.minCopy" />
<span class="tips">弹性伸缩可以设置的副本数量的下限</span>
</el-form-item>
<el-form-item
prop="maxCopy"
label="最大副本数"
>
<el-input v-model="asForm.maxCopy" />
<span class="tips">副本数量的上限</span>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitAS"> </el-button>
</div>
</el-dialog>
<el-dialog title="编辑配置文件" :visible.sync="dialogEditSettingVisible">
<codemirror v-model="code" class="code-mirror" :options="cmOption" />
<div slot="footer" class="dialog-footer">
<el-button @click="dialogEditSettingVisible = false"> </el-button>
<el-button type="primary" @click="submitSettingEdit"> </el-button>
</div>
</el-dialog>
<FormData :data="formData" :data-map="dataMap" />
<el-tabs v-model="activeName" @tab-click="switchTab">
<el-tab-pane key="resource-status" label="资源状态" />
<el-tab-pane key="revision-control" label="版本记录" />
<el-tab-pane key="monitors" label="监控" />
</el-tabs>
<router-view />
</el-card>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
import { getWorkloadDetails } from '@/api/second-class-page/workloadInfo'
// import path from 'path'
export default {
components: { FormData },
data() {
return {
code: ``,
cmOption: {
autoCloseBrackets: true,
tabSize: 4,
styleActiveLine: true,
lineNumbers: true,
line: true,
mode: 'text/x-yaml',
theme: 'mbo'
// keyMap: "emacs"
},
dataMap: {
cluster: '集群',
namespace: '项目',
application: '应用',
createTime: '创建时间',
updateTime: '更新时间',
creator: '创建者'
},
formData: {
cluster: 'bj-member2',
namespace: '-',
application: '-',
createTime: '-',
updateTime: '-',
creator: '-'
},
dialogFormVisible: false,
dialogResetVisible: false,
dialogASVisible: false,
dialogEditSettingVisible: false,
asForm: {},
editInfoForm: {},
resetForm: {},
activeName: '',
tabList: {
'0': 'resource-status',
'1': 'revision-control',
'2': 'monitors'
}
}
},
watch: {
$route(route) {
if (route.path.search('resource-status') !== -1) {
this.getFormData()
}
}
},
created() {
for (const i in Object.keys(this.tabList)) {
if (this.$route.path.split('/')[3] === this.tabList[i]) {
this.activeName = i
}
}
this.getFormData()
},
methods: {
goBack() {
this.$router.push({ path: '/' + this.$route.path.split('/')[1] + '/' + this.$route.path.split('/')[3] })
},
switchTab(e) {
const tab = this.tabList[e.index]
if (this.$route.path.indexOf(tab) === -1) {
this.$router.push(tab)
}
},
getFormData() {
const customurl = this.$route.path.split('/')[2] + '/deployments/' + this.$route.path.split('/')[4]
getWorkloadDetails(customurl).then(res => {
this.formData.namespace = res.metadata.namespace
this.formData.application = (res.metadata.labels !== undefined) ? res.metadata.labels['app.kubernetes.io/name'] : '-'
this.formData.createTime = res.metadata.creationTimestamp
this.formData.updateTime = res.status.conditions[1].lastUpdateTime
})
},
editInfo() {
this.dialogFormVisible = true
},
submitInfoEdit() {
this.dialogFormVisible = false
this.$message.success('修改成功')
},
submitReset() {
this.dialogResetVisible = false
this.goBack()
},
submitAS() {
this.dialogASVisible = false
this.$message.success('回退成功')
},
submitSettingEdit() {
},
handleCommand(command) {
switch (command) {
case 'reset' :
this.dialogResetVisible = true
break
case 'autoScaling' :
this.dialogASVisible = true
break
case 'editTemplate' :
break
case 'editSetting' :
this.dialogEditSettingVisible = true
break
case 'redeploy' :
this.$alert(`您即将重新部署工作负载 ${this.$route.params.name} (部署) , 容器组将根据更新策略进行重新部署,您的业务可能会被暂时中断。`, '确认重新部署 ?', {
confirmButtonText: '确定',
callback: () => {
this.$message.success('重新部署成功')
}
})
break
case 'deleteDeployment':
break
}
}
}
}
</script>
<style lang="scss" scoped>
.code-mirror{
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div>
<h5>
副本运行状态
</h5>
<FormData :column="4" :data="formData" :data-map="dataMap" />
<el-alert
:closable="false"
title="部署 (Deployment) 用来描述期望应用达到的目标状态,主要用来描述无状态应用,副本的数量和状态由其背后的控制器来维护,确保状态与定义的期望状态一致。您可以增加副本数量来满足更高负载;回滚部署的版本来消除程序的错误修改;创建自动伸缩器来弹性应对不同场景下的负载。"
show-icon
type="info"
/>
<h5>
端口
</h5>
<h5>
容器组
</h5>
<div>
<el-table :data="tableData" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<div v-for="(item, key) in props.row.container" :key="key">
<el-form-item label="容器名称">
<span>{{ item.name }}</span>
</el-form-item>
<el-form-item label="容器镜像">
<span>{{ item.image }}</span>
</el-form-item>
<el-form-item label="状态">
<span>{{ item.status }}</span>
</el-form-item>
<el-form-item label="重启次数">
<span>{{ item.restart }}</span>
</el-form-item>
<el-form-item label="端口">
<span>{{ item.port }}</span>
</el-form-item>
</div>
</el-form>
</template>
</el-table-column>
<el-table-column label="Pod名称" prop="pod" />
<el-table-column label="所属节点" prop="node" />
<el-table-column label="容器组IP" prop="ip" />
<el-table-column label="CPU监控" prop="cpu" />
<el-table-column label="内存监控" prop="memory" />
</el-table>
</div>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
// import * as echarts from 'echarts'
export default {
components: { FormData },
data() {
return {
dataMap: {
wantedCopy: '期望副本',
realityCopy: '实际运行副本'
},
formData: {
wantedCopy: '1',
realityCopy: '1'
},
tableData: [{
pod: 'kubectl-nudt-785fd767c5-jg9vp',
node: 'jcc-txy-003(10.206.0.15)',
ip: '10.244.2.13',
cpu: '',
memory: '',
container: [
{
name: 'kubectl',
image: 'kubesphere/kubectl:v1.19.0',
status: '运行中',
restart: '0',
port: '-'
}
]
}],
dataMap1: {
cpuUsage: 'CPU 请求',
storageUsage: 'CPU 限制',
podUsage: '内存请求',
localStorage: '内存限制'
},
formData1: {
cpuUsage: '0.787 Core (39%)',
storageUsage: '10.4 Core (520%)',
podUsage: '1.225 Gi (31%)',
localStorage: '20.857 Gi (543%)'
},
lineChartOption: {
title: {
subtext: 'CPU使用率'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [
'09:57:32',
'10:06:32',
'10:15:32',
'10:24:32',
'10:33:32',
'10:42:32',
'10:57:32'
]
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value}%'
}
},
series: [
{
name: 'CPU使用率',
type: 'line',
data: [10, 11, 13, 11, 12, 12, 9]
}
]
}
}
},
mounted() {
// this.$nextTick(() => {
// const lineChart = echarts.init(this.$refs.lineChart, 'dark')
// lineChart.setOption(this.lineChartOption)
// })
}
}
</script>
<style lang="scss" scoped>
#lineChart{
width:100%;
height: 200px;
}
</style>

View File

@ -164,6 +164,14 @@ export default {
theme: 'mbo'
// keyMap: "emacs"
},
dataMap: {
cluster: '集群',
namespace: '项目',
application: '应用',
createTime: '创建时间',
updateTime: '更新时间',
creator: '创建者'
},
formData: {
cluster: 'default',
namespace: '-',
@ -179,14 +187,6 @@ export default {
asForm: {},
editInfoForm: {},
resetForm: {},
dataMap: {
cluster: '集群',
namespace: '项目',
application: '应用',
createTime: '创建时间',
updateTime: '更新时间',
creator: '创建者'
},
activeName: '',
tabList: {
'0': 'resource-status',

View File

@ -1,15 +1,132 @@
<template>
<div>
<div id="myEchart" ref="myEchart" style="width:1000px; height:600px" />
<div id="cpuChart" ref="cpuChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="memoryChart" ref="memoryChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="receivedChart" ref="receivedChart" style="width:1300px; height:300px" />
<div><br></div>
<div id="transmittedChart" ref="transmittedChart" style="width:1300px; height:300px" />
</div>
</template>
<script>
import * as echarts from 'echarts'
import { getMonitorPodsData, getMonitorDetailData } from '@/api/second-class-page/workloadInfo'
export default {
data() {
return {
lineChartOption: {
cpuOption: {
title: {
subtext: 'CPU使用量m'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: []
},
yAxis: {
type: 'value',
scale: true,
axisLabel: {
formatter: '{value}'
}
},
series: [
{
name: 'CPU使用量m',
type: 'line',
data: []
}
]
},
memoryOption: {
title: {
subtext: '内存使用量Mi'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: []
},
yAxis: {
type: 'value',
scale: true,
axisLabel: {
formatter: '{value}'
}
},
series: [
{
name: '内存使用量Mi',
type: 'line',
data: []
}
]
},
receivedOption: {
title: {
subtext: '网络流入速率bps'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: []
},
yAxis: {
type: 'value',
scale: true,
axisLabel: {
formatter: '{value}'
}
},
series: [
{
name: '网络流入速率bps',
type: 'line',
data: []
}
]
},
transmittedOption: {
title: {
subtext: '网络流出速率bps'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: []
},
yAxis: {
type: 'value',
scale: true,
axisLabel: {
formatter: '{value}'
}
},
series: [
{
name: '网络流出速率bps',
type: 'line',
data: []
}
]
}
},
interval: '',
second: 0
}
@ -32,70 +149,140 @@ export default {
}
},
dynamicData() {
const data = []
for (let i = 0; i < 10; i += 1) {
data.push(this.randomData())
if (this.$route.path.split('/')[3] === 'deployments') {
const url1 = this.$route.path.split('/')[2] + '/workloads/deployment/' + this.$route.path.split('/')[4]
getMonitorPodsData(url1).then(res => {
let resourcesFilter = 'resources_filter='
res.results[0].data.result.forEach(pod => {
resourcesFilter += pod.metric.pod + '%7C'
})
resourcesFilter = resourcesFilter.slice(0, -3) + '%24&'
const nowTime = new Date()
const endTime = Math.round(nowTime.getTime() / 1000)
const startTime = endTime - 30000
const timeurl = startTime + '&end=' + Math.round(nowTime.getTime() / 1000)
const url2 = url1 + '/pods?cluster=bj-member2&start=' + timeurl + '&step=600s&times=50&' + resourcesFilter
getMonitorDetailData(url2).then(res => {
console.log(res)
})
})
}
const option = {
title: {
text: '动态数据'
},
tooltip: {
trigger: 'axis',
// formatter: function (params) {
// params = params[0];
// var date = new Date(params.name);
// return date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear()
// + ' : ' + params.value[1];
// },
axisPointer: {
animation: false
}
},
xAxis: {
type: 'category',
splitLine: {
show: false
}
},
yAxis: {
type: 'value',
boundaryGap: [0, '100%'],
splitLine: {
show: false
}
},
series: [{
name: '模拟数据',
type: 'line',
showSymbol: false,
hoverAnimation: false,
data
}]
if (this.$route.path.split('/')[3] === 'statefulsets') {
const url1 = this.$route.path.split('/')[2] + '/workloads/statefulset/' + this.$route.path.split('/')[4]
getMonitorPodsData(url1).then(res => {
let resourcesFilter = 'resources_filter='
res.results[0].data.result.forEach(pod => {
resourcesFilter += pod.metric.pod + '%7C'
})
resourcesFilter = resourcesFilter.slice(0, -3) + '%24&'
const nowTime = new Date()
const endTime = Math.round(nowTime.getTime() / 1000)
const startTime = endTime - 30000
const timeurl = startTime + '&end=' + Math.round(nowTime.getTime() / 1000)
const url2 = url1 + '/pods?cluster=bj-member2&start=' + timeurl + '&step=600s&times=50&' + resourcesFilter
getMonitorDetailData(url2).then(res => {
console.log(res)
})
})
}
if (this.$route.path.split('/')[3] === 'daemonsets') {
const url1 = this.$route.path.split('/')[2] + '/workloads/daemonset/' + this.$route.path.split('/')[4]
getMonitorPodsData(url1).then(res => {
let resourcesFilter = 'resources_filter='
res.results[0].data.result.forEach(pod => {
resourcesFilter += pod.metric.pod + '%7C'
})
resourcesFilter = resourcesFilter.slice(0, -3) + '%24&'
const nowTime = new Date()
const endTime = Math.round(nowTime.getTime() / 1000)
const startTime = endTime - 30000
const timeurl = startTime + '&end=' + Math.round(nowTime.getTime() / 1000)
const url2 = url1 + '/pods?cluster=bj-member2&start=' + timeurl + '&step=600s&times=50&' + resourcesFilter
getMonitorDetailData(url2).then(res => {
console.log(res)
})
})
}
},
dynamicData1() {
const cpuChart = echarts.init(this.$refs.cpuChart, 'dark')
const memoryChart = echarts.init(this.$refs.memoryChart, 'dark')
const receivedChart = echarts.init(this.$refs.receivedChart, 'dark')
const transmittedChart = echarts.init(this.$refs.transmittedChart, 'dark')
// const myChart = echarts.init(this.$refs.myEchart);
// window.onresize = myChart.resize;
// myChart.setOption(
// option);
let flag = false
const myChart = echarts.init(this.$refs.myEchart, 'dark')
const nowTime = new Date()
const endTime = Math.round(nowTime.getTime() / 1000)
const startTime = endTime - 30000
const timeurl = startTime + '&end=' + Math.round(nowTime.getTime() / 1000)
const url = this.$route.path.split('/')[2] + '/pods/' + this.$route.path.split('/')[3] + '?cluster=default&start=' + timeurl + '&step=600s&times=50&'
const chartData = {}
getMonitorPodsData(url).then(res => {
res.results.forEach(function(el) {
if (el.metric_name === 'pod_cpu_usage') {
const tempX = []
const tempY = []
let index = 0
el.data.result[0].values.forEach(item => {
tempX[index] = new Date(item[0] * 1000).toLocaleString()
tempY[index] = (item[1] * 100).toFixed(2)
index++
})
chartData.cpuOptionX = tempX
chartData.cpuOptionY = tempY
}
if (el.metric_name === 'pod_memory_usage_wo_cache') {
const tempX = []
const tempY = []
let index = 0
el.data.result[0].values.forEach(item => {
tempX[index] = new Date(item[0] * 1000).toLocaleString()
tempY[index] = (item[1] * 100).toFixed(2)
index++
})
chartData.memoryOptionX = tempX
chartData.memoryOptionY = tempY
}
if (el.metric_name === 'pod_net_bytes_received') {
const tempX = []
const tempY = []
let index = 0
el.data.result[0].values.forEach(item => {
tempX[index] = new Date(item[0] * 1000).toLocaleString()
tempY[index] = (item[1] * 100).toFixed(2)
index++
})
chartData.receivedOptionX = tempX
chartData.receivedOptionY = tempY
}
if (el.metric_name === 'pod_net_bytes_transmitted') {
const tempX = []
const tempY = []
let index = 0
el.data.result[0].values.forEach(item => {
tempX[index] = new Date(item[0] * 1000).toLocaleString()
tempY[index] = (item[1] * 100).toFixed(2)
index++
})
chartData.transmittedOptionX = tempX
chartData.transmittedOptionY = tempY
}
})
this.lineChartOption.cpuOption.xAxis.data = chartData.cpuOptionX
this.lineChartOption.cpuOption.series[0].data = chartData.cpuOptionY
cpuChart.setOption(this.lineChartOption.cpuOption)
this.interval = setInterval(() => {
for (let i = 0; i < 5; i += 1) {
// data.shift();
data.push(this.randomData())
}
this.percentage += 10
myChart.setOption(option)
if (flag === false) {
flag = true
setTimeout(() => {
clearInterval(this.interval)
}, 9000)//
}
}, 1000) // ,func使
this.lineChartOption.memoryOption.xAxis.data = chartData.memoryOptionX
this.lineChartOption.memoryOption.series[0].data = chartData.memoryOptionY
memoryChart.setOption(this.lineChartOption.memoryOption)
this.lineChartOption.receivedOption.xAxis.data = chartData.receivedOptionX
this.lineChartOption.receivedOption.series[0].data = chartData.receivedOptionY
receivedChart.setOption(this.lineChartOption.receivedOption)
this.lineChartOption.transmittedOption.xAxis.data = chartData.transmittedOptionX
this.lineChartOption.transmittedOption.series[0].data = chartData.transmittedOptionY
transmittedChart.setOption(this.lineChartOption.transmittedOption)
})
},
beforeDestroy() {
clearInterval(this.interval)

View File

@ -3,6 +3,7 @@
<h5>
副本运行状态
</h5>
<FormData :column="4" :data="formData" :data-map="dataMap" />
<el-alert
:closable="false"
title="部署 (Deployment) 用来描述期望应用达到的目标状态,主要用来描述无状态应用,副本的数量和状态由其背后的控制器来维护,确保状态与定义的期望状态一致。您可以增加副本数量来满足更高负载;回滚部署的版本来消除程序的错误修改;创建自动伸缩器来弹性应对不同场景下的负载。"
@ -15,27 +16,72 @@
<h5>
容器组
</h5>
<div>
<el-table :data="tableData" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<div v-for="(item, key) in props.row.container" :key="key">
<el-form-item label="容器名称">
<span>{{ item.name }}</span>
</el-form-item>
<el-form-item label="容器镜像">
<span>{{ item.image }}</span>
</el-form-item>
<el-form-item label="状态">
<span>{{ item.status }}</span>
</el-form-item>
<el-form-item label="重启次数">
<span>{{ item.restart }}</span>
</el-form-item>
<el-form-item label="端口">
<span>{{ item.port }}</span>
</el-form-item>
</div>
</el-form>
</template>
</el-table-column>
<el-table-column label="Pod名称" prop="pod" />
<el-table-column label="所属节点" prop="node" />
<el-table-column label="容器组IP" prop="ip" />
<el-table-column label="CPU监控" prop="cpu" />
<el-table-column label="内存监控" prop="memory" />
</el-table>
</div>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
// import * as echarts from 'echarts'
export default {
components: { FormData },
data() {
return {
dataMap: {
cpuUsage: 'CPU 使用率',
storageUsage: '内存使用率',
podUsage: '容器组用量',
localStorage: '本地存储用量'
wantedCopy: '期望副本',
realityCopy: '实际运行副本'
},
formData: {
cpuUsage: '4.18%',
storageUsage: '32.3%',
podUsage: '15.45%',
localStorage: '34.22%'
wantedCopy: '1',
realityCopy: '1'
},
tableData: [{
pod: 'kubectl-nudt-785fd767c5-jg9vp',
node: 'jcc-txy-003(10.206.0.15)',
ip: '10.244.2.13',
cpu: '',
memory: '',
container: [
{
name: 'kubectl',
image: 'kubesphere/kubectl:v1.19.0',
status: '运行中',
restart: '0',
port: '-'
}
]
}],
dataMap1: {
cpuUsage: 'CPU 请求',
storageUsage: 'CPU 限制',

View File

@ -1,8 +1,9 @@
<template>
<div>
<h5>
记录
版本记录
</h5>
TODO接口调用
</div>
</template>

View File

@ -0,0 +1,277 @@
<template>
<div>
<el-card shadow="never">
<el-page-header content="详情" @back="goBack" />
<h2>{{ $route.params.name }}</h2> <!-- TODO: 这里显示别名和描述 -->
<div class="button-group">
<el-button plain round @click="editInfo">编辑信息</el-button>
<el-dropdown @command="handleCommand">
<el-button round>
更多操作<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-back" command="reset">版本回退</el-dropdown-item>
<el-dropdown-item icon="el-icon-s-data" command="editService">编辑服务</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit" command="editTemplate">编辑配置模板</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit" command="editSetting">编辑配置文件</el-dropdown-item>
<el-dropdown-item icon="el-icon-help" command="redeploy">重新部署</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete" command="deleteDeployment">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<el-dialog title="编辑信息" :visible.sync="dialogFormVisible">
<el-form ref="editInfoForm" :model="editInfoForm">
<el-form-item
prop="name"
label="名称"
>
<el-input v-model="editInfoForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="alias"
label="别名"
>
<el-input v-model="editInfoForm.alias" :maxlength="63" />
<span class="tips">别名可以由任意字符组成帮助您更好的区分资源最长 63 个字符</span>
</el-form-item>
<el-form-item
prop="description"
label="描述信息"
>
<el-input v-model="editInfoForm.description" type="textarea" :maxlength="256" />
<span class="tips">描述信息不超过 256 个字符</span>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitInfoEdit"> </el-button>
</div>
</el-dialog>
<el-dialog title="版本回退" :visible.sync="dialogResetVisible">
<el-form ref="resetForm" :model="resetForm">
<el-form-item
prop="name"
label="资源名称"
>
<el-input v-model="resetForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="currentVersion"
label="当前版本"
>
<el-input v-model="resetForm.currentVersion" :disabled="true" />
</el-form-item>
<el-form-item
prop="resetVersion"
label="回退版本"
required
>
<el-select v-model="resetForm.resetVersion">
<el-option
label="#2"
value="#2"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitReset"> </el-button>
</div>
</el-dialog>
<el-dialog title="编辑服务" :visible.sync="dialogASVisible">
<el-form ref="asForm" :model="asForm">
<el-form-item
prop="name"
label="名称"
>
<el-input v-model="asForm.name" :disabled="true" />
</el-form-item>
<el-form-item
prop="kind"
label="访问类型"
>
<el-alert
:closable="false"
title="通过集群内部IP来访问服务Virtual IP"
show-icon
type="info"
/>
</el-form-item>
<el-form-item
prop="selector"
label="选择器"
>
<el-input v-model="asForm.cpuTargetUsagePer" />
</el-form-item>
<el-form-item
prop="port"
label="端口"
>
<el-input v-model="asForm.cpuTargetUsage" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitAS"> </el-button>
</div>
</el-dialog>
<el-dialog title="编辑配置文件" :visible.sync="dialogEditSettingVisible">
<codemirror v-model="code" class="code-mirror" :options="cmOption" />
<div slot="footer" class="dialog-footer">
<el-button @click="dialogEditSettingVisible = false"> </el-button>
<el-button type="primary" @click="submitSettingEdit"> </el-button>
</div>
</el-dialog>
<FormData :data="formData" :data-map="dataMap" />
<el-tabs v-model="activeName" @tab-click="switchTab">
<el-tab-pane key="resource-status" label="资源状态" />
<el-tab-pane key="revision-control" label="版本记录" />
<el-tab-pane key="monitors" label="监控" />
</el-tabs>
<router-view />
</el-card>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
import { getWorkloadDetails } from '@/api/second-class-page/workloadInfo'
// import path from 'path'
export default {
components: { FormData },
data() {
return {
code: ``,
cmOption: {
autoCloseBrackets: true,
tabSize: 4,
styleActiveLine: true,
lineNumbers: true,
line: true,
mode: 'text/x-yaml',
theme: 'mbo'
// keyMap: "emacs"
},
dataMap: {
cluster: '集群',
namespace: '项目',
application: '应用',
createTime: '创建时间',
updateTime: '更新时间',
creator: '创建者'
},
formData: {
cluster: 'bj-member2',
namespace: '-',
application: '-',
createTime: '-',
updateTime: '-',
creator: '-'
},
dialogFormVisible: false,
dialogResetVisible: false,
dialogASVisible: false,
dialogEditSettingVisible: false,
asForm: {},
editInfoForm: {},
resetForm: {},
activeName: '',
tabList: {
'0': 'resource-status',
'1': 'revision-control',
'2': 'monitors'
}
}
},
watch: {
$route(route) {
if (route.path.search('resource-status') !== -1) {
this.getFormData()
}
}
},
created() {
for (const i in Object.keys(this.tabList)) {
if (this.$route.path.split('/')[3] === this.tabList[i]) {
this.activeName = i
}
}
this.getFormData()
},
methods: {
goBack() {
this.$router.push({ path: '/' + this.$route.path.split('/')[1] + '/' + this.$route.path.split('/')[3] })
},
switchTab(e) {
const tab = this.tabList[e.index]
if (this.$route.path.indexOf(tab) === -1) {
this.$router.push(tab)
}
},
getFormData() {
const customurl = this.$route.path.split('/')[2] + '/statefulsets/' + this.$route.path.split('/')[4]
getWorkloadDetails(customurl).then(res => {
this.formData.namespace = res.metadata.namespace
this.formData.application = (res.metadata.labels['app.kubernetes.io/name'] != null) ? res.metadata.labels['app.kubernetes.io/name'] : '-'
this.formData.createTime = res.metadata.creationTimestamp
this.formData.updateTime = (res.status.conditions != null) ? res.status.conditions[1].lastUpdateTime : res.metadata.creationTimestamp
})
},
editInfo() {
this.dialogFormVisible = true
},
submitInfoEdit() {
this.dialogFormVisible = false
this.$message.success('修改成功')
},
submitReset() {
this.dialogResetVisible = false
this.goBack()
},
submitAS() {
this.dialogASVisible = false
this.$message.success('回退成功')
},
submitSettingEdit() {
},
handleCommand(command) {
switch (command) {
case 'reset' :
this.dialogResetVisible = true
break
case 'editService' :
this.dialogASVisible = true
break
case 'editTemplate' :
break
case 'editSetting' :
this.dialogEditSettingVisible = true
break
case 'redeploy' :
this.$alert(`您即将重新部署工作负载 ${this.$route.params.name} (部署) , 容器组将根据更新策略进行重新部署,您的业务可能会被暂时中断。`, '确认重新部署 ?', {
confirmButtonText: '确定',
callback: () => {
this.$message.success('重新部署成功')
}
})
break
case 'deleteDeployment':
break
}
}
}
}
</script>
<style lang="scss" scoped>
.code-mirror{
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div>
<h5>
副本运行状态
</h5>
<FormData :column="4" :data="formData" :data-map="dataMap" />
<el-alert
:closable="false"
title="有状态副本集 (StatefulSet) 用来描述有状态应用,比如副本之间有主从关系,数据需要做持久化。与部署 (Deployment) 相同的是,有状态副本集创建的副本也是完全相同的,不同的是每个副本有个固定且唯一的标识,即使副本被重新调度了,标识也不会发生变化。您可以用有状态副本集来实现应用的有序部署,有序的删除,有序的滚动更新。"
show-icon
type="info"
/>
<h5>
端口
</h5>
<h5>
容器组
</h5>
<div>
<el-table :data="tableData" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<div v-for="(item, key) in props.row.container" :key="key">
<el-form-item label="容器名称">
<span>{{ item.name }}</span>
</el-form-item>
<el-form-item label="容器镜像">
<span>{{ item.image }}</span>
</el-form-item>
<el-form-item label="状态">
<span>{{ item.status }}</span>
</el-form-item>
<el-form-item label="重启次数">
<span>{{ item.restart }}</span>
</el-form-item>
<el-form-item label="端口">
<span>{{ item.port }}</span>
</el-form-item>
</div>
</el-form>
</template>
</el-table-column>
<el-table-column label="Pod名称" prop="pod" />
<el-table-column label="所属节点" prop="node" />
<el-table-column label="容器组IP" prop="ip" />
<el-table-column label="CPU监控" prop="cpu" />
<el-table-column label="内存监控" prop="memory" />
</el-table>
</div>
</div>
</template>
<script>
import { FormData } from '@/components/FormData'
// import * as echarts from 'echarts'
export default {
components: { FormData },
data() {
return {
dataMap: {
wantedCopy: '期望副本',
realityCopy: '实际运行副本'
},
formData: {
wantedCopy: '1',
realityCopy: '1'
},
tableData: [{
pod: 'kubectl-nudt-785fd767c5-jg9vp',
node: 'jcc-txy-003(10.206.0.15)',
ip: '10.244.2.13',
cpu: '',
memory: '',
container: [
{
name: 'kubectl',
image: 'kubesphere/kubectl:v1.19.0',
status: '运行中',
restart: '0',
port: '-'
}
]
}],
dataMap1: {
cpuUsage: 'CPU 请求',
storageUsage: 'CPU 限制',
podUsage: '内存请求',
localStorage: '内存限制'
},
formData1: {
cpuUsage: '0.787 Core (39%)',
storageUsage: '10.4 Core (520%)',
podUsage: '1.225 Gi (31%)',
localStorage: '20.857 Gi (543%)'
},
lineChartOption: {
title: {
subtext: 'CPU使用率'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [
'09:57:32',
'10:06:32',
'10:15:32',
'10:24:32',
'10:33:32',
'10:42:32',
'10:57:32'
]
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value}%'
}
},
series: [
{
name: 'CPU使用率',
type: 'line',
data: [10, 11, 13, 11, 12, 12, 9]
}
]
}
}
},
mounted() {
// this.$nextTick(() => {
// const lineChart = echarts.init(this.$refs.lineChart, 'dark')
// lineChart.setOption(this.lineChartOption)
// })
}
}
</script>
<style lang="scss" scoped>
#lineChart{
width:100%;
height: 200px;
}
</style>

View File

@ -39,32 +39,32 @@ module.exports = {
proxy: {
'/oauth': {
ws: false,
// target: 'http://192.168.0.243:30881/'
// target: 'http://124.71.196.205:30881/'
// target: 'http://119.3.157.144:30881/',
target: 'http://119.45.100.73:30881/',
// target: 'http://124.71.196.205:30881/' /* EduCoder */
// target: 'http://119.3.157.144:30881/', /* KubeX */
target: 'http://119.45.100.73:30881/', /* Host */
// target: 'http://39.103.233.49:30881/', /* BJ-Member2 */
},
'/kapis': {
ws: false,
// target: 'http://192.168.0.243:30881/'
// target: 'http://124.71.196.205:30881/'
// target: 'http://119.3.157.144:30881/',
target: 'http://119.45.100.73:30881/',
// target: 'http://124.71.196.205:30881/' /* EduCoder */
// target: 'http://119.3.157.144:30881/', /* KubeX */
target: 'http://119.45.100.73:30881/', /* Host */
// target: 'http://39.103.233.49:30881/', /* BJ-Member2 */
// changeOrigin: true,
},
'/prom': {
ws: false,
target: 'http://119.3.157.144:9090/',
target: 'http://119.3.157.144:9090/', /* KubeX */
pathRewrite: {
'^/prom': ''
}
},
'/api': {
ws: false,
// target: 'http://192.168.0.243:30881/'
// target: 'http://124.71.196.205:30881/'
// target: 'http://119.3.157.144:30881/',
target: 'http://119.45.100.73:30881/',
// target: 'http://124.71.196.205:30881/' /* EduCoder */
// target: 'http://119.3.157.144:30881/', /* KubeX */
target: 'http://119.45.100.73:30881/', /* Host */
// target: 'http://39.103.233.49:30881/', /* BJ-Member2 */
// changeOrigin: true,
}
},

View File

@ -4936,6 +4936,11 @@
"resolved" "https://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz?cache=0&sync_timestamp=1595428045324&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-levenshtein%2Fdownload%2Ffast-levenshtein-2.0.6.tgz"
"version" "2.0.6"
"fast-xml-parser@^3.19.0":
"integrity" "sha1-y2N+w/OZn1FAbdj/Dm/E2D5SDQE="
"resolved" "https://registry.npm.taobao.org/fast-xml-parser/download/fast-xml-parser-3.19.0.tgz"
"version" "3.19.0"
"faye-websocket@^0.11.3":
"integrity" "sha1-fw2Sdc/dhqHJY9yLZfzEUe3Lsdo="
"resolved" "https://registry.nlark.com/faye-websocket/download/faye-websocket-0.11.4.tgz"
@ -6552,6 +6557,13 @@
"resolved" "https://registry.nlark.com/is-string/download/is-string-1.0.6.tgz?cache=0&sync_timestamp=1620448217105&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-string%2Fdownload%2Fis-string-1.0.6.tgz"
"version" "1.0.6"
"is-svg@^4.3.1":
"integrity" "sha1-jGPsjGfIx/Co3gpxyMfVjsz0QGs="
"resolved" "https://registry.npm.taobao.org/is-svg/download/is-svg-4.3.1.tgz"
"version" "4.3.1"
dependencies:
"fast-xml-parser" "^3.19.0"
"is-symbol@^1.0.2", "is-symbol@^1.0.3":
"integrity" "sha1-ptrJO2NbBjymhyI23oiRClevE5w="
"resolved" "https://registry.nlark.com/is-symbol/download/is-symbol-1.0.4.tgz?cache=0&sync_timestamp=1620501182675&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-symbol%2Fdownload%2Fis-symbol-1.0.4.tgz"