Kubernetes

给kubernetes cluster安装可视化界面dashboard

一 背景说明

这是一个跑在3台Linux服务器上的kubernetes cluster,1个master(172.16.11.106),2个worker node(172.16.11.148和172.16.11.161)。

OS信息:

[root@master-node ~]# cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core)
[root@master-node ~]# uname -rm
3.10.0-862.el7.x86_64 x86_64
[root@master-node ~]#

kubernetes信息:

[root@master-node ~]# kubectl get nodes
NAME         STATUS   ROLES                 AGE     VERSION
master-node   Ready   control-plane,master   5d23h   v1.22.3
node-1       Ready   <none>                 5d23h   v1.22.3
node-2       Ready   <none>                 5d23h   v1.22.3
[root@master-node ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:41:28Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:35:25Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
[root@master-node ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:40:11Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
[root@master-node ~]#

现在,考虑给这个kubernetes cluster配置1个可视化的图形管理界面dashboard。

二 安装流程

1 获取资源文件recommended.yaml

kubernetes官网,或者GitHub上都有说明,如何安装配置dashboard。通过一个命令即可完成:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml

问题麻烦在文件https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.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.

apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard

---

apiVersion: v1
kind: ServiceAccount
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard

---

kind: Service
apiVersion: v1
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
  - port: 443
    targetPort: 8443
selector:
  k8s-app: kubernetes-dashboard

---

apiVersion: v1
kind: Secret
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque

---

apiVersion: v1
kind: Secret
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""

---

apiVersion: v1
kind: Secret
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque

---

kind: ConfigMap
apiVersion: v1
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
 # 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.
- apiGroups: [""]
  resources: ["services"]
  resourceNames: ["heapster", "dashboard-metrics-scraper"]
  verbs: ["proxy"]
- apiGroups: [""]
  resources: ["services/proxy"]
  resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
  verbs: ["get"]

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
 # Allow Metrics Scraper to get metrics from the Metrics server
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list", "watch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

---

kind: Deployment
apiVersion: apps/v1
metadata:
labels:
  k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
  matchLabels:
    k8s-app: kubernetes-dashboard
template:
  metadata:
    labels:
      k8s-app: kubernetes-dashboard
  spec:
    containers:
      - name: kubernetes-dashboard
        image: kubernetesui/dashboard:v2.3.1
        imagePullPolicy: Always
        ports:
          - containerPort: 8443
            protocol: TCP
        args:
          - --auto-generate-certificates
          - --namespace=kubernetes-dashboard
           # 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-certs
            mountPath: /certs
             # Create on-disk volume to store exec logs
          - mountPath: /tmp
            name: tmp-volume
        livenessProbe:
          httpGet:
            scheme: HTTPS
            path: /
            port: 8443
          initialDelaySeconds: 30
          timeoutSeconds: 30
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsUser: 1001
          runAsGroup: 2001
    volumes:
      - name: kubernetes-dashboard-certs
        secret:
          secretName: kubernetes-dashboard-certs
      - name: tmp-volume
        emptyDir: {}
    serviceAccountName: kubernetes-dashboard
    nodeSelector:
      "kubernetes.io/os": linux
     # Comment the following tolerations if Dashboard must not be deployed on master
    tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule

---

kind: Service
apiVersion: v1
metadata:
labels:
  k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
  - port: 8000
    targetPort: 8000
selector:
  k8s-app: dashboard-metrics-scraper

---

kind: Deployment
apiVersion: apps/v1
metadata:
labels:
  k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
  matchLabels:
    k8s-app: dashboard-metrics-scraper
template:
  metadata:
    labels:
      k8s-app: dashboard-metrics-scraper
    annotations:
      seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
  spec:
    containers:
      - name: dashboard-metrics-scraper
        image: kubernetesui/metrics-scraper:v1.0.6
        ports:
          - containerPort: 8000
            protocol: TCP
        livenessProbe:
          httpGet:
            scheme: HTTP
            path: /
            port: 8000
          initialDelaySeconds: 30
          timeoutSeconds: 30
        volumeMounts:
        - mountPath: /tmp
          name: tmp-volume
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsUser: 1001
          runAsGroup: 2001
    serviceAccountName: kubernetes-dashboard
    nodeSelector:
      "kubernetes.io/os": linux
     # Comment the following tolerations if Dashboard must not be deployed on master
    tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
    volumes:
      - name: tmp-volume
        emptyDir: {}
2 master上执行安装dashboard
[root@master-node ~]# kubectl apply -f dashboard.yaml 
namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
Warning: spec.template.metadata.annotations[seccomp.security.alpha.kubernetes.io/pod]: deprecated since v1.19; use the "seccompProfile" field instead
deployment.apps/dashboard-metrics-scraper created
[root@master-node ~]#

查看新创建的dashboard资源:

[root@master-node ~]# kubectl get pods -A
NAMESPACE             NAME                                         READY   STATUS             RESTARTS   AGE
default               nginx-6799fc88d8-dg6d9                       1/1     Running             0         6d
kube-system           coredns-7f6cbbb7b8-mrsgg                     1/1     Running             0         6d
kube-system           coredns-7f6cbbb7b8-wvd4x                     1/1     Running             0         6d
kube-system           etcd-master-node                             1/1     Running             0         6d
kube-system           kube-apiserver-master-node                   1/1     Running             0         6d
kube-system           kube-controller-manager-master-node          1/1     Running             0         6d
kube-system           kube-flannel-ds-ndp9g                        1/1     Running             0         6d
kube-system           kube-flannel-ds-nxjzc                        1/1     Running             0         6d
kube-system           kube-flannel-ds-v2d5t                        1/1     Running             0         6d
kube-system           kube-proxy-5wmch                             1/1     Running             0         6d
kube-system           kube-proxy-95l4w                             1/1     Running             0         6d
kube-system           kube-proxy-xq77j                             1/1     Running             0         6d
kube-system           kube-scheduler-master-node                   1/1     Running             0         6d
kubernetes-dashboard   dashboard-metrics-scraper-856586f554-l4bpm   1/1     Running             0         22s
kubernetes-dashboard   kubernetes-dashboard-67484c44f6-xqftl        0/1     ContainerCreating   0         22s
[root@master-node ~]#
3修改kubernetes-dashboard的端口映射

修改之前:

[root@master-node ~]# kubectl get svc -A
NAMESPACE             NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                 AGE
default               kubernetes                 ClusterIP   10.96.0.1     <none>        443/TCP                 6d
default               nginx                       NodePort    10.108.50.59   <none>        80:30769/TCP             6d
kube-system           kube-dns                   ClusterIP   10.96.0.10     <none>        53/UDP,53/TCP,9153/TCP   6d
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.102.0.17   <none>        8000/TCP                 9m7s
kubernetes-dashboard   kubernetes-dashboard       ClusterIP   10.97.131.98   <none>        443/TCP                 9m7s
[root@master-node ~]#

看到资源kubernetes-dashboard的端口在443。

执行命令,进行修改:

[root@master-node ~]# kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.

将其中的,type: ClusterIP修改成type: NodePort,保存退出即可。

修改之后:

[root@master-node ~]# kubectl get svc -A
NAMESPACE             NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                 AGE
default               kubernetes                 ClusterIP   10.96.0.1     <none>        443/TCP                 6d
default               nginx                       NodePort    10.108.50.59   <none>        80:30769/TCP             6d
kube-system           kube-dns                   ClusterIP   10.96.0.10     <none>        53/UDP,53/TCP,9153/TCP   6d
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.102.0.17   <none>        8000/TCP                 15m
kubernetes-dashboard   kubernetes-dashboard       NodePort    10.97.131.98   <none>        443:30838/TCP           15m
[root@master-node ~]#

看到kubernetes-dashboard 服务暴露在端口30838。

Chrome浏览器访问:https://172.16.11.106:30838/ 弹出警告,修改浏览器安全级别即可。这里,直接用Firefox来访问:https://172.16.11.106:30838/

其实,此时可以通过该kubernetes cluster中的任意节点来访问这个dashboard:

$ telnet 172.16.11.106 30838
Trying 172.16.11.106...
Connected to 172.16.11.106.
Escape character is '^]'.
^]
telnet> quit
Connection closed.

asher at MacBook-Air-3 in ~
$ telnet 172.16.11.148 30838
Trying 172.16.11.148...
Connected to 172.16.11.148.
Escape character is '^]'.
^]  
telnet> quit
Connection closed.

asher at MacBook-Air-3 in ~
$ telnet 172.16.11.161 30838
Trying 172.16.11.161...
Connected to 172.16.11.161.
Escape character is '^]'.
6通过yaml配置文件创建访问dashboard的用户:
#创建访问账号,准备一个yaml文件; vi dash.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
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: kubernetes-dashboard
[root@master-node ~]# kubectl apply -f dash-user.yaml 
serviceaccount/admin-user created
clusterrolebinding.rbac.authorization.k8s.io/admin-user created
[root@master-node ~]#
7创建访问token,master执行
[root@master-node ~]# kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
eyJhbGciOiJSUzI1NiIsImtpZCI6Imp3aEZfMTF2UVczM2xyOVZGNnZ6Wnc2RWFEVVk2czR2dTZWUkNNMXZGWWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWZwdHJrIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI4ZWM3ZjM4MS05MjZiLTQxYTUtOWVjNi1hNzYyMTMyNDhmZjIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.W-0gUXFsxGq0p9h33Lzsx-etr4Ywngz5LWs_Esa16tFGAF4IflL9M_V1o4lg-iMby8F3AGT4CSi8OApMHAIs2NXDiUCu-uBCh4MaMUhEppNR3S_Jd45JF6R6WaX-0tEtgo7-C2OB30dLKq31IUQeCsXvakj0TWiAzdgVkx09tC40RbTIx3917qJhe8xKrvmwUVpsiD6vCSyfHCy9cBp9GepHrku6ZJRyMLPgQxCjjQbWZc1JXerdXSvrK21OSf5FIWIv7VHt6Lv32z15EQjzRcXccIIw7yqb0q06GD0ZQ4WjZLw3akPcpJkIOlS5-kyyrdoOJrSBNIn-jWfwLhikIA
[root@master-node ~]#
8 登录dashboard

登录界面,输入上述令牌。

上述,6/7步骤,可以参考GitHub:https://github.com/kubernetes/dashboard

三小结

通过创建dashboard可以友好的通过图形界面对kubernetes cluster进行查看,管理。

相关阅读:如何在CentOS 7安装配置kubernetes cluster v1.22