learn.lianglianglee.com/专栏/Kubernetes 从上手到实践/20 扩展增强:Dashboard.md.html
2022-05-11 19:04:14 +08:00

730 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>20 扩展增强Dashboard.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/Kubernetes 从上手到实践/01 开篇: Kubernetes 是什么以及为什么需要它.md.html">01 开篇: Kubernetes 是什么以及为什么需要它.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/02 初步认识Kubernetes 基础概念.md.html">02 初步认识Kubernetes 基础概念.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/03 宏观认识:整体架构.md.html">03 宏观认识:整体架构.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/04 搭建 Kubernetes 集群 - 本地快速搭建.md.html">04 搭建 Kubernetes 集群 - 本地快速搭建.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/05 动手实践:搭建一个 Kubernetes 集群 - 生产可用.md.html">05 动手实践:搭建一个 Kubernetes 集群 - 生产可用.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/06 集群管理:初识 kubectl.md.html">06 集群管理:初识 kubectl.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/07 集群管理:以 Redis 为例-部署及访问.md.html">07 集群管理:以 Redis 为例-部署及访问.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/08 安全重点 认证和授权.md.html">08 安全重点 认证和授权.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/09 应用发布:部署实际项目.md.html">09 应用发布:部署实际项目.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/10 应用管理:初识 Helm.md.html">10 应用管理:初识 Helm.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/11 部署实践:以 Helm 部署项目.md.html">11 部署实践:以 Helm 部署项目.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/12 庖丁解牛kube-apiserver.md.html">12 庖丁解牛kube-apiserver.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/13 庖丁解牛etcd.md.html">13 庖丁解牛etcd.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/14 庖丁解牛controller-manager.md.html">14 庖丁解牛controller-manager.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/15 庖丁解牛kube-scheduler.md.html">15 庖丁解牛kube-scheduler.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/16 庖丁解牛kubelet.md.html">16 庖丁解牛kubelet.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/17 庖丁解牛kube-proxy.md.html">17 庖丁解牛kube-proxy.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/18 庖丁解牛Container Runtime Docker.md.html">18 庖丁解牛Container Runtime Docker.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/19 Troubleshoot.md.html">19 Troubleshoot.md.html</a>
</li>
<li>
<a class="current-tab" href="/专栏/Kubernetes 从上手到实践/20 扩展增强Dashboard.md.html">20 扩展增强Dashboard.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/21 扩展增强CoreDNS.md.html">21 扩展增强CoreDNS.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/22 服务增强Ingress.md.html">22 服务增强Ingress.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/23 监控实践:对 K8S 集群进行监控.md.html">23 监控实践:对 K8S 集群进行监控.md.html</a>
</li>
<li>
<a href="/专栏/Kubernetes 从上手到实践/24 总结.md.html">24 总结.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>20 扩展增强Dashboard</h1>
<h2>整体概览</h2>
<p>通过前面的介绍,想必你已经迫不及待的想要将应用部署至 K8S 中,但总是使用 <code>kubectl</code> 或者 <code>Helm</code> 等命令行工具也许不太直观,你可能想要一眼就看到集群当前的状态,或者想要更方便的对集群进行管理。</p>
<p>本节将介绍一个 Web 项目 <a href="https://github.com/kubernetes/dashboard"><code>Dashboard</code></a> 可用于部署容器化的应用程序,管理集群中的资源,甚至是排查和解决问题。</p>
<p>当然它和大多数 Dashboard 类的项目类似,也为集群的状态提供了一个很直观的展示。</p>
<p><img src="assets/167d6b6e66c60e89" alt="img" /></p>
<h2>如何安装</h2>
<p>要想使用 Dashboard首先我们需要安装它而 Dashboard 的安装其实也很简单。不过对于国内用户需要注意的是需要解决网络问题,或替换镜像地址等。</p>
<p>这里我们安装当前最新版 <code>v1.10.1</code> 的 Dashboard</p>
<ul>
<li>
<p>对于已经解决网络问题的用户:</p>
<p>可使用官方推荐做法进行安装,以下链接是使用了我提交了 path 的版本,由于官方最近的一次更新导致配置文件中的镜像搞错了。</p>
<pre><code>master $ kubectl apply -f https://raw.githubusercontent.com/tao12345666333/dashboard/67970554aa9275cccec1d1ee5fbf89ae81b3b614/aio/deploy/recommended/kubernetes-dashboard.yaml
secret/kubernetes-dashboard-certs created
serviceaccount/kubernetes-dashboard created
role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created
</code></pre>
</li>
<li>
<p>也可使用我修改过的这份(使用 Docker Hub 同步了镜像)仓库地址 <a href="https://github.com/tao12345666333/k8s-dashboard">GitHub</a>, 国内 <a href="https://gitee.com/K8S-release/k8s-dashboard">Gitee</a></p>
<pre><code>master $ kubectl apply -f https://gitee.com/K8S-release/k8s-dashboard/raw/master/kubernetes-dashboard.yaml
secret/kubernetes-dashboard-certs created
serviceaccount/kubernetes-dashboard created
role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created
</code></pre>
</li>
</ul>
<p>当已经执行完以上步骤后,可检查下是否安装成功:</p>
<pre><code>master $ kubectl -n kube-system get all -l k8s-app=kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
pod/kubernetes-dashboard-67896bc598-dhdpz 1/1 Running 0 3m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes-dashboard ClusterIP 10.109.92.207 &lt;none&gt; 443/TCP 3m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/kubernetes-dashboard 1 1 1 1 3m
NAME DESIRED CURRENT READY AGE
replicaset.apps/kubernetes-dashboard-67896bc598 1 1 1 3m
</code></pre>
<p>可以看到 <code>Pod</code> 已经在正常运行,接下来便是访问 Dashboard.</p>
<h2>访问 Dashboard</h2>
<p>以当前的部署方式,<code>Service</code> 使用了 <code>ClusterIP</code> 的类型,所以在集群外不能直接访问。我们先使用 <code>kubectl</code> 提供的 <code>port-forward</code> 功能进行访问。</p>
<pre><code>master $ kubectl -n kube-system port-forward pod/kubernetes-dashboard-67896bc598-dhdpz 8443
Forwarding from 127.0.0.1:8443 -&gt; 8443
Forwarding from [::1]:8443 -&gt; 8443
</code></pre>
<p>还记得,我们在第 5 节时候安装过一个名为 <code>socat</code> 的依赖项吗? <code>socat</code> 的主要功能便是端口转发。</p>
<p>现在在浏览器打开 <a href="https://127.0.0.1:8443/"><code>https://127.0.0.1:8443</code></a> 便可看到如下的登录界面。</p>
<p><img src="assets/167d6b787d0a2779" alt="img" /></p>
<p>对于我们的 <strong>新版本</strong> 而言,我们 <strong>使用令牌登录</strong> 的方式。</p>
<h3>查找 Token</h3>
<pre><code>master $ kubectl -n kube-system get serviceaccount -l k8s-app=kubernetes-dashboard -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{&quot;apiVersion&quot;:&quot;v1&quot;,&quot;kind&quot;:&quot;ServiceAccount&quot;,&quot;metadata&quot;:{&quot;annotations&quot;:{},&quot;labels&quot;:{&quot;k8s-app&quot;:&quot;kubernetes-dashboard&quot;},&quot;name&quot;:&quot;kubernetes-dashboard&quot;,&quot;namespace&quot;:&quot;kube-system&quot;}}
creationTimestamp: 2018-12-20T17:27:14Z
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
resourceVersion: &quot;1400&quot;
selfLink: /api/v1/namespaces/kube-system/serviceaccounts/kubernetes-dashboard
uid: 7e01ddda-047c-11e9-b55c-0242ac11002a
secrets:
- name: kubernetes-dashboard-token-6ck2l
kind: List
metadata:
resourceVersion: &quot;&quot;
selfLink: &quot;&quot;
</code></pre>
<p>首先,我们查看刚才创建出的 <code>serviceaccount</code> 可以看到其中有配置 <code>secrets</code></p>
<p>查看该 <code>secret</code> 详情获得 Token</p>
<pre><code>master $ kubectl -n kube-system describe secrets kubernetes-dashboard-token-6ck2l
Name: kubernetes-dashboard-token-6ck2l
Namespace: kube-system
Labels: &lt;none&gt;
Annotations: kubernetes.io/service-account.name=kubernetes-dashboard
kubernetes.io/service-account.uid=7e01ddda-047c-11e9-b55c-0242ac11002a
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 11 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi02Y2sybCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjdlMDFkZGRhLTA0N2MtMTFlOS1iNTVjLTAyNDJhYzExMDAyYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.WZ5YRUkGlKRSpkBFCk3BrZ6p2t1qVxEs7Kb18DP5X2C2lfMhDrB931PeN05uByLD6biz_4IQvKh4xmvY2RqekfV1BLCfcIiMUbc1lcXGbhH4g4vrsjYx3NZifaBh_5HuBlEL5zs5e_zFkPEhhIqjsY3KueFEuGwxTAsqGBQwawc-v6wqzB3Gzb01o1iN5aTb37PVG5gTTE8cQLih_urKhvdNEKBSRg_zHQlYjFrtUUWYRYMlYz_sWmamYVXHy_7NvKrBfw44WU5tLxMITkoUEGVwROBnHf_BcWVedozLg2uLVontB12YvhmTfJCDEAJ8o937bS-Fq3tLfu_xM40fqw
</code></pre>
<p>将此处的 token 填入输入框内便可登录,<strong>注意这里使用的是 describe。</strong></p>
<p><img src="assets/167d6b926b4eed4d" alt="img" /></p>
<h3>修正权限</h3>
<p>但是我们注意到这里有很多提示 <code>configmaps is forbidden: User &quot;system:serviceaccount:kube-system:kubernetes-dashboard&quot; cannot list resource &quot;configmaps&quot; in API group &quot;&quot; in the namespace &quot;default&quot;</code> 。根据我们前面的介绍,这很明显就是用户权限不足。</p>
<p>我们已经知道,当前我们的集群是开启了 <code>RBAC</code> 的,所以这里我们还是以前面学到的方法创建一个用户并进行授权。</p>
<ul>
<li>
<p>创建 ServiceAccount</p>
<pre><code>apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system
</code></pre>
</li>
<li>
<p>创建 RoleBinding: 这里为了方便直接绑定了 <code>cluster-admin</code> 的 ClusterRole ,但是生产环境下,请按照实际情况进行授权,参考前面第 8 节相关的内容。</p>
<pre><code>apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kube-system
</code></pre>
</li>
</ul>
<p>使用以上配置创建了用户和绑定,然后还是同样的办法获取 Token。</p>
<p>点击 Dashboard 右上角,退出登录后,重新使用新的 Token 进行登录。登录完成后便可看到如下图:</p>
<p><img src="assets/167d6b9e22f03343" alt="img" /></p>
<h2>部署应用</h2>
<p>点击右上角的 <strong>+创建</strong> 可进入创建页面,现在支持三种模式:从文本框输入;从文件创建;直接创建应用。</p>
<p>我们仍然以我们的示例项目 <a href="https://github.com/tao12345666333/saythx">SayThx</a> 为例。先 <code>clone</code> 该项目,并进入项目的 <code>deploy</code> 目录中。将 <code>namespace.yaml</code> 的内容复制进输入框,点击上传按钮,便可创建名为 <code>work</code><code>Namespace</code> 了。</p>
<p>通过以下命令验证:</p>
<pre><code>master $ kubectl get ns
NAME STATUS AGE
default Active 2h
kube-public Active 2h
kube-system Active 2h
work Active 10s
</code></pre>
<p>可以看到 Namespace 已经创建成功。或者刷新下网页,点击左侧的命名空间即可看到当前的所有 <code>Namespace</code></p>
<p><img src="assets/167d6ba21937e5ca" alt="img" /></p>
<p>我们先将左侧的命名空间选择为 <strong>全部命名空间</strong><strong>work</strong> (当刷新过网页后) ,接下来继续点击右上角的 <strong>+创建</strong> 按钮,将 <code>redis-deployment.yaml</code> 的内容复制进输入框,点击上传按钮,部署 Redis 。</p>
<p>部署成功后,点击 部署 ,点击刚才的 <code>saythx-redis</code> 便可看到其详情。</p>
<p><img src="assets/167d6ba5e9d8d5a9" alt="img" /></p>
<p>点击左侧的容器组,便可看到刚才部署的 Pod</p>
<p><img src="assets/167d6ba94e0db733" alt="img" /></p>
<p>在此页面的右上角,可以点击命令行按钮,打开新标签页进入其内部执行命令。</p>
<p><img src="assets/167d6bac91d8f387" alt="img" /></p>
<p>或者是点击日志按钮,可打开新标签页,查看日志。</p>
<p><img src="assets/167d6bafed569ab1" alt="img" /></p>
<h2>总结</h2>
<p>本节我们介绍了 <code>Kubernetes Dashboard</code> 的基本功能,以及如何安装和使用它。</p>
<p>Dashboard 相比 <code>kubectl</code> 为用户提供了一种相对直观的 Web 端操作方式,但是并不能完全取代 <code>kubectl</code>,这两者应该是相辅相成的。</p>
<p>如果你所需的功能相对简单或是想要给某些用户提供一种通过 Web 操作的方式,那便推荐使用 Dashboard。Dashboard 的后端使用了 K8S 的 <a href="https://github.com/kubernetes/client-go"><code>client-go</code></a> ,前端主要使用了 <a href="https://angular.io/">Angular</a>,有兴趣可以大致看看其源代码,对于开发基于 K8S 的云平台会有些启发。</p>
<p>下节,我们将介绍用于 DNS 和服务发现的插件 <a href="https://coredns.io/">CoreDNS</a>,学习如何利用它完成这些需求。并且它在 K8S 1.13 版本中,已经成为了默认的 DNS server。</p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/Kubernetes 从上手到实践/19 Troubleshoot.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/Kubernetes 从上手到实践/21 扩展增强CoreDNS.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997251de933d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>