部署dashboard之前,先确保traefik https方式部署成功,这样就可以通过 https 域名的方式访问dashboard,无需kube-proxy转发了。假设traefik-ingress https部署完成。

下载dashboard yaml文件

wget https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/alternative/kubernetes-dashboard.yaml

由于k8s开启了rbac认证,因此需要添加serviceaccount

[root@node-01 ~]# cat kubernetes-dashboard.yaml
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.# ------------------- Dashboard Secrets ------------------- #apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-certsnamespace: kube-system
type: Opaque---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-csrfnamespace: kube-system
type: Opaque
data:csrf: ""---
# ------------------- Dashboard Service Account ------------------- #apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kube-system---
# ------------------- Dashboard Role & Role Binding ------------------- ##kind: Role
#apiVersion: rbac.authorization.k8s.io/v1
#metadata:
#  name: kubernetes-dashboard-minimal
#  namespace: kube-system
#rules:
#  # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
#- apiGroups: [""]
#  resources: ["secrets"]
#  verbs: ["create"]
#  # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
#- apiGroups: [""]
#  resources: ["configmaps"]
#  verbs: ["create"]
#  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
#- apiGroups: [""]
#  resources: ["secrets"]
#  resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
#  verbs: ["get", "update", "delete"]
#  # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
#- apiGroups: [""]
#  resources: ["configmaps"]
#  resourceNames: ["kubernetes-dashboard-settings"]
#  verbs: ["get", "update"]
#  # Allow Dashboard to get metrics from heapster.
#- apiGroups: [""]
#  resources: ["services"]
#  resourceNames: ["heapster"]
#  verbs: ["proxy"]
#- apiGroups: [""]
#  resources: ["services/proxy"]
#  resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
#  verbs: ["get"]---
apiVersion: rbac.authorization.k8s.io/v1
#kind: RoleBinding
kind: ClusterRoleBinding
metadata:name: kubernetes-dashboard-minimalnamespace: kube-system
roleRef:apiGroup: rbac.authorization.k8s.io
#  kind: Rolekind: ClusterRole
#  name: kubernetes-dashboard-minimalname: cluster-admin
subjects:
- kind: ServiceAccountname: kubernetes-dashboardnamespace: kube-system---
# ------------------- Dashboard Deployment ------------------- #kind: Deployment
apiVersion: apps/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kube-system
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:k8s-app: kubernetes-dashboardtemplate:metadata:labels:k8s-app: kubernetes-dashboardspec:containers:- name: kubernetes-dashboardimage: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1ports:- containerPort: 8443protocol: TCPargs:- --auto-generate-certificates# Uncomment the following line to manually specify Kubernetes API server Host# If not specified, Dashboard will attempt to auto discover the API server and connect# to it. Uncomment only if the default does not work.# - --apiserver-host=http://my-address:port
        volumeMounts:- name: kubernetes-dashboard-certsmountPath: /certs# Create on-disk volume to store exec logs- mountPath: /tmpname: tmp-volumelivenessProbe:httpGet:scheme: HTTPSpath: /port: 8443initialDelaySeconds: 30timeoutSeconds: 30volumes:- name: kubernetes-dashboard-certssecret:secretName: kubernetes-dashboard-certs- name: tmp-volumeemptyDir: {}serviceAccountName: kubernetes-dashboard# Comment the following tolerations if Dashboard must not be deployed on mastertolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedule---
# ------------------- Dashboard Service ------------------- #kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kube-system
spec:ports:- port: 443targetPort: 8443selector:k8s-app: kubernetes-dashboard

配置ingress

[root@node-01 ~]# cat kubernetes-dashboard-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: kube-uinamespace: kube-system
spec:rules:- host: k8sui.ptengine.jphttp:paths:- path: '/'backend:serviceName: kubernetes-dashboardservicePort: 443

添加本地host,测试。

1、使用kubernetes-dashboard-token的tocken登陆,先获取tocken,令牌方式登陆 
[root@node-01 ~]# kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kubernetes-dashboard-token|awk '{print $1}')|grep token:|awk '{print $2}'

2、创建一个名为admin的ServiceAccount并绑定名为cluster-admin的ClusterRole角色(该角色拥有集群最高权限),使用下面的yaml文件创建admin用户并赋予他管理员权限,然后可以通过token登陆dashbaord。这种认证方式本质上是通过ServiceAccount的身份认证加上Bearer token请求API server的方式实现。
[root@node-01 ~]# cat admin-token.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: adminannotations:rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:kind: ClusterRolename: cluster-adminapiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccountname: adminnamespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:name: adminnamespace: kube-systemlabels:kubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcile

[root@node-01 ~]# kubectl create -f admin-token.yaml
[root@node-01 ~]# kubectl get secret -n kube-system | grep admin
admin-token-422fl                                kubernetes.io/service-account-token   3      17s

通过如下的命令来获取admin ServiceAccount的token:
[root@node-01 ~]# kubectl describe secret/admin-token-422fl -n kube-system
Name:         admin-token-422fl
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: adminkubernetes.io/service-account.uid: ec5caa59-7142-11e9-aa9a-fad20acb9b00Type:  kubernetes.io/service-account-tokenData
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi10b2tlbi00MjJmbCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImVjNWNhYTU5LTcxNDItMTFlOS1hYTlhLWZhZDIwYWNiOWIwMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphZG1pbiJ9.gXi0mToE0sct0soTeR_TLcDC5Xnr2xCZpvEn-VhE_hZX_QtzhqmgCcUy2wQmpjPoF6eku59dpQVp9WyBYY_rJaAY6HzB3Nzr3pZmDvNdj5Qe1QwxJadp38cqGs7Ao6EZg82wKoXqGI3481rU59BgbcbMeOO75d_e8iN7s64ErpJ25AAWIhfnNvHIJJUP0HoNU8uWbtrcCpceqm-gBY2-hKyqFH5dekMEdoz6GOH9w2xTYeF8Cl6d5xpQ8WcBJ60b7bSVV0PPlhVsswxkA0v95gDGj18rjrLoLJTc0rBOL4FwXOpMeyIO5y7HGXnHWWIL9gMInwoxGloxQJf7RWCRZw

如上,我们得到了该用户的token,dashboard登陆即可。


部署heapster

kubernetes 获取性能参数,默认使用 metric server 获取,通过修改kube-controller-manager.yaml,可以修改获取方式。此处介绍heapster。
1、 修改 /etc/kubernetes/manifests/kube-controller-manager.yaml 添加
--horizontal-pod-autoscaler-use-rest-clients=false

master节点需要全部修改。修改完后,重启kube-controller-manager,如果是kubeadm部署,容器会自动重启。

2、 部署的应用需要添加resource限制
resources:limits:cpu: 200mmemory: 30Mirequests:cpu: 100mmemory: 20Mi

3、 整合heapster 和 influxdb

在没有配置heapster和influxdb的情况下,pod的metric信息是无法获取到的,而早前版本K8S的HPA特性依赖的metric数据来源恰巧就是heapster和influxdb。heapster会在后面的版本中废弃。

准备yaml文件

# cat heapster-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: heapsternamespace: kube-system

# cat heapster-rbac.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: heapster
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: system:heapster
subjects:
- kind: ServiceAccountname: heapsternamespace: kube-system

# cat heapster-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: heapsternamespace: kube-system
spec:replicas: 1template:metadata:labels:task: monitoringk8s-app: heapsterspec:serviceAccountName: heapstercontainers:- name: heapsterimage: k8s.gcr.io/heapster-amd64:v1.4.2imagePullPolicy: IfNotPresentcommand:- /heapster- --source=kubernetes:https://kubernetes.default- --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086

上面配置source和influxdb有问题,下面会修改。

# cat heapster-service.yaml
apiVersion: v1
kind: Service
metadata:labels:task: monitoringkubernetes.io/cluster-service: 'true'kubernetes.io/name: Heapstername: heapsternamespace: kube-system
spec:ports:- port: 80targetPort: 8082selector:k8s-app: heapster

# cat influxdb-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: monitoring-influxdbnamespace: kube-system
spec:replicas: 1template:metadata:labels:task: monitoringk8s-app: influxdbspec:containers:- name: influxdbimage: k8s.gcr.io/heapster-influxdb-amd64:v1.3.3volumeMounts:- mountPath: /dataname: influxdb-storagevolumes:- name: influxdb-storageemptyDir: {}

# cat influxdb-service.yaml
apiVersion: v1
kind: Service
metadata:labels:task: monitoringkubernetes.io/cluster-service: 'true'kubernetes.io/name: monitoring-influxdbname: monitoring-influxdbnamespace: kube-system
spec:ports:- port: 8086targetPort: 8086selector:k8s-app: influxdb

检查heapster日志

[root@node-01 hpa]# kubectl logs -f heapster-76b4794779-d2vph -n kube-system
I0508 06:16:51.944854       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-bjksx
I0508 06:16:51.944890       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-q4vjz
E0508 06:17:05.003857       1 kubelet.go:231] error while getting containers from Kubelet: failed to get all container stats from Kubelet URL "http://172.19.8.114:10255/stats/container/": Post http://172.19.8.114:10255/stats/container/: dial tcp 172.19.8.114:10255: getsockopt: connection refused

通过kubectl top 命令也获取不到结果

[root@node-01 ~]# kubectl top pod
W0508 15:25:57.588871    8939 top_pod.go:259] Metrics not available for pod default/my-nginx-6785b88976-7rrll, age: 3h32m13.588851424s
error: Metrics not available for pod default/my-nginx-6785b88976-7rrll, age: 3h32m13.588851424s
[root@node-01 ~]# kubectl top node
error: metrics not available yet

解决办法:

#在heapster-deployment.yaml 清单文件中进行如下修改
- --source=kubernetes:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true
- --sink=influxdb:http://monitoring-influxdb.kube-system.svc.cluster.local:8086

然后删除heapster重建

kubectl delete -f heapster-deployment.yaml
kubectl apply -f heapster-deployment.yaml

继续 。。。。。发现新问题

遇到403错误

[root@node-01 hpa]# kubectl logs -f heapster-699c6b684d-8sj2q -n kube-system
I0508 06:20:33.630699       1 heapster.go:72] /heapster --source=kubernetes:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true --sink=influxdb:http://monitoring-influxdb.kube-system.svc.cluster.local:8086
I0508 06:20:33.630780       1 heapster.go:73] Heapster version v1.4.2
I0508 06:20:33.631200       1 configs.go:61] Using Kubernetes client with master "https://kubernetes.default" and version v1
I0508 06:20:33.631235       1 configs.go:62] Using kubelet port 10250
I0508 06:20:33.657061       1 influxdb.go:278] created influxdb sink with options: host:monitoring-influxdb.kube-system.svc.cluster.local:8086 user:root db:k8s
I0508 06:20:33.657100       1 heapster.go:196] Starting with InfluxDB Sink
I0508 06:20:33.657111       1 heapster.go:196] Starting with Metric Sink
I0508 06:20:33.666165       1 heapster.go:106] Starting heapster on port 8082
I0508 06:20:38.888431       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-bjksx
I0508 06:20:38.888461       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-q4vjz
I0508 06:20:54.158646       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-q4vjz
I0508 06:20:54.158676       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-bjksx
E0508 06:21:05.018631       1 kubelet.go:231] error while getting containers from Kubelet: failed to get all container stats from Kubelet URL "https://172.19.8.113:10250/stats/container/": request failed - "403 Forbidden", response: "Forbidden (user=system:serviceaccount:kube-system:heapster, verb=create, resource=nodes, subresource=stats)"

解决办法:
查看ClusterRole: system:heapster的权限,发现的确没有针对Resource: nodes/stats 的create权限
[root@node-01 hpa]# kubectl describe clusterrole system:heapster
Name:         system:heapster
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:Resources               Non-Resource URLs  Resource Names  Verbs---------               -----------------  --------------  -----events                  []                 []              [get list watch]namespaces              []                 []              [get list watch]nodes                   []                 []              [get list watch]pods                    []                 []              [get list watch]deployments.extensions  []                 []              [get list watch]

修改ClusterRole: system:heapster的权限

生成清单文件

kubectl get clusterrole system:heapster -o yaml > heapster_modify.yaml

修改文件,增加verbs:create权限,增加resources:nodes/stats

[root@node-01 hpa]# cat heapster_modify.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:annotations:rbac.authorization.kubernetes.io/autoupdate: "true"creationTimestamp: "2019-05-06T06:24:10Z"labels:kubernetes.io/bootstrapping: rbac-defaultsname: system:heapsterresourceVersion: "50"selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/system%3Aheapsteruid: 8f773f30-6fc7-11e9-991a-fa982e6ff600
rules:
- apiGroups:- ""resources:- events- namespaces- nodes- pods- nodes/stats  # 增加verbs:- create   #增加- get- list- watch
- apiGroups:- extensionsresources:- deploymentsverbs:- get- list- watch

执行

kubectl apply -f heapster_modify.yaml

删除heapster重新部署

kubectl delete -f heapster-deployment.yaml
kubectl apply -f heapster-deployment.yaml

再次检查heapster日志

[root@node-01 hpa]# kubectl logs -f heapster-699c6b684d-n2ggr -n kube-system
I0508 06:39:28.987133       1 heapster.go:72] /heapster --source=kubernetes:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true --sink=influxdb:http://monitoring-influxdb.kube-system.svc.cluster.local:8086
I0508 06:39:28.987229       1 heapster.go:73] Heapster version v1.4.2
I0508 06:39:28.987560       1 configs.go:61] Using Kubernetes client with master "https://kubernetes.default" and version v1
I0508 06:39:28.987589       1 configs.go:62] Using kubelet port 10250
I0508 06:39:29.012055       1 influxdb.go:278] created influxdb sink with options: host:monitoring-influxdb.kube-system.svc.cluster.local:8086 user:root db:k8s
I0508 06:39:29.012098       1 heapster.go:196] Starting with InfluxDB Sink
I0508 06:39:29.012120       1 heapster.go:196] Starting with Metric Sink
I0508 06:39:29.021905       1 heapster.go:106] Starting heapster on port 8082
I0508 06:40:05.166962       1 influxdb.go:241] Created database "k8s" on influxDB server at "monitoring-influxdb.kube-system.svc.cluster.local:8086”
I0508 06:39:54.519349       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-q4vjz
I0508 06:40:04.062180       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-bjksx
I0508 06:40:04.062246       1 handlers.go:215] No metrics for pod default/nginx-deployment-6d6fdc59f7-q4vjz

heapster默认30秒检查一次,因此需要等上30s才会收集到数据

[root@node-01 ~]# kubectl top nodes
NAME      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
node-01   305m         7%     2421Mi          31%
node-02   242m         6%     1906Mi          24%
node-03   224m         5%     1760Mi          22%
node-04   77m          1%     693Mi           8%
node-05   82m          2%     848Mi           10%
node-06   87m          2%     677Mi           8%
[root@node-01 ~]# kubectl top pods
NAME                                CPU(cores)   MEMORY(bytes)
my-nginx-6785b88976-7rrll           0m           1Mi
nginx-deployment-6d6fdc59f7-bjksx   0m           1Mi
nginx-deployment-6d6fdc59f7-q4vjz   0m           1Mi

此时登录dashboard,可以单独内存、CPU信息。

转载于:https://www.cnblogs.com/cptao/p/10912392.html

kubernetes之部署dashboard 和heapster相关推荐

  1. K8S部署Dashboard和Heapster

    K8S部署Dashboard和Heapster 0.前言 文章使用的k8s版本为1.10.0,dashboard版本为v1.8.3 系统为CentOS7 总共有三台机器: Name IP Role c ...

  2. kubernetes1.30集群部署+dashboard+heapster

    v2.1 1.系统配置 1.1.禁用防火墙.禁用selinux #防火墙禁用 systemctl stop firewalld systemctl disable firewalld#SELinux禁 ...

  3. 部署Kubernetes集群+Dashboard可视化页面-1.18.6版本

    Kubeadm 部署 Kubernetes1.18.6 集群 一.环境说明 主机名 IP地址 角色 系统 k8s-master 192.168.182.150 k8s-master Centos7.6 ...

  4. Kubernetes Dashboard集成Heapster

    默认安装后的Kubernetes dashboard 如下图所示,是无法图形化展现集群度量指标 信息的: 图形化展示度量指标的实现需要集成k8s的另外一个Addons组件: Heapster . He ...

  5. Heapster -- Kubernetes Dashboard集成Heapster

    原始kubernetes dashboard的界面中仅显示了pod一些配置信息,无法图形化展现集群度量指标信息.原始图如下(此处从网上找了一个图..): 而如果要展示图形化的集群度量指标信息,就需要安 ...

  6. kubernetes1.9部署metrics-server0.3.1、dashboard、heapster

    简介 K8S从1.8版本开始,CPU.内存等资源的metrics信息可以通过 Metrics API来获取,用户可以直接获取这些metrics信息(例如通过执行kubect top命令),HPA使用这 ...

  7. 安装部署 Kubernetes 仪表板(Dashboard)

    简介 Kubernetes 仪表板(Dashboard)是基于网页的 Kubernetes 用户界面. 你可以使用仪表板: 展示了 Kubernetes 集群中的资源状态信息和所有报错信息. 把容器应 ...

  8. kubernetes部署dashboard可视化插件

    Dashboard简介 在 Kubernetes 社区中,有一个很受欢迎的 Dashboard 项目,它可以给用户提供一个可视化的 Web 界面来查看当前集群的各种信息.用户可以用 Kubernete ...

  9. 第五篇:kubernetes部署dashboard(图形化界面)

    说明: 总的目标是在k8s集群部署gitlab.jenkins,并且在本地提交代码到gitlab后jenkin流水线可以自动编译打包成为docker镜像然后部署到k8s中并实现客户端外部域名访问,在文 ...

最新文章

  1. Python3.5源码分析-List概述
  2. 二十、Threaded I/O模型
  3. SVN错误:Attempted to lock an already-locked dir
  4. VS2010中添加lib库引用
  5. linux十字符木马,Linux系统随机10字符病毒的清除
  6. 蓄水池抽样(Reservoir Sampling)
  7. java逆序对距离之和,七天刷完剑指offer-【第27道-第37道】
  8. WINDOWS上传文件到LINUX中文乱码
  9. HDU1013 POJ1519 Digital Roots(解法二)【废除!!!】
  10. Linux 命令学习(1): head和tail
  11. C语言编译程序的顺序,C语言函数定义顺序
  12. 哔哩哔哩电脑版怎么下载视频?
  13. [ 江枫]关于ORA_ROWSCN
  14. 傅里叶描述子、HOG特征描述子原理及matlab代码
  15. 中国联通广州软件研究院 软件开发岗二面(技术面)
  16. 鸿蒙王者荣耀想要转区吗,王者荣耀开放转区 转区转角色服务要求条件汇总
  17. MCMC_calibration
  18. vivado+vscode
  19. 基于 Paraview 扩展与实现——(2)
  20. 在Java中将excel文件转换成pdf文件

热门文章

  1. 北邮博导孙松林:5G 新物种开启新时代
  2. VS2012C语言有编译按钮在哪,VS2012的使用
  3. 跑跑手游显示服务器异常,跑跑卡丁车手游测试资格异常处理方法 有资格进不去怎么办...
  4. 应用软件-财务管理系统开发
  5. 智能门锁里的大市场,凯迪仕签署上市辅导协议,冲击A股上市
  6. 上海天旦网络携CrossFlow最新网络性能管理产品参加2012中国国际金融展
  7. 蓝桥杯试题 算法训练 进击的青蛙 python
  8. 函数stdlib.h应用举例
  9. NTKO在线office控件使用实例
  10. 如何快速实现完美身材,告别减肥烦恼?分享这些高效减肥方法,让你事半功倍达成健康目标!