Kubernetes 集群使用 NFS 网络文件存储

2023-10-26

1、NFS 介绍

Kubernetes PersistentVolumes 持久化存储方案中,提供两种 API 资源方式: PersistentVolume(简称 PV) 和 PersistentVolumeClaim(简称 PVC)。PV 可理解为集群资源,PVC 可理解为对集群资源的请求,Kubernetes 支持很多种持久化卷存储类型。NFS 是网络文件存储系统,它允许网络中的计算机之间通过 TCP/IP 网络共享资源。通过 NFS,我们本地 NFS 的客户端应用可以透明地读写位于服务端 NFS 服务器上的文件,就像访问本地文件一样方便。

2、环境、软件准备

本次演示环境,我是在虚拟机上安装 Linux 系统来执行操作,通过虚拟机完成 NFS 服务搭建以及 Kubernetes HA 集群的搭建,以下是安装的软件及版本:

  • Oracle VirtualBox: 5.1.20 r114628 (Qt5.6.2)
  • System: CentOS Linux release 7.3.1611 (Core)
  • rpcbind: 0.2.0-38.el7.x86_64
  • nfs-utils: 1.3.0-0.54.el7.x86_64
  • kubernetes: 1.12.1
  • docker: 18.06.1-ce
  • etcd: 3.3.8
  • Keepalived: v1.3.5
  • HaProxy: version 1.5.18
  • cfssl version 1.2.0

注意:这里我着重描述一下 Kubernetes 集群如何使用 NFS 来实现持久化存储,所以需要提前搭建好 Kubernetes 集群和 NFS 文件存储服务,具体搭建过程可参考之前文章 国内使用 kubeadm 在 Centos7 搭建 Kubernetes 集群Linux 环境下 NFS 服务安装及配置使用。这里提一下,使用上边方案搭建 Kubernetes 集群亦可以使用 NFS 网络文件存储,但是集群为单主多节点方式,本次演示如何快速搭建 Kubernetes HA 高可用集群(多主多节点、Etcd HA、LB + VIP),来使用 NFS 网络文件存储。

3、Kubernetes HA 集群搭建

Kubernetes HA 集群搭建,主要包含 Etcd HA 和 Master HA。Etcd HA 这个很容易办到,通过搭建 Etcd 集群即可(注意 Etcd 集群只能有奇数个节点)。Master HA 这个稍微麻烦一些,多主的意思就是多个 Kubernetes Master 节点组成,任意一个 Master 挂掉后,自动切换到另一个备用 Master,而且整个集群 Cluster-IP 不发生变化,从而实现高可用。而实现切换时 Cluster-IP 不变化,目前采用最多的方案就是 haproxy + keepalived 实现负载均衡,然后使用 VIP(虚地址) 方式来实现的。

这里推荐使用 kubeasz 项目,该项目致力于提供快速部署高可用 k8s 集群的工具,它基于二进制方式部署和利用 ansible-playbook 实现自动化安装,同时集成了很多常用插件,而且都有对应的文档说明,非常方便操作。它提供了单节点、单主多节点、多主多节点、在公有云上部署等方案,通过它很容易就能完成各种类型版本 k8s 集群的搭建。我觉得非常好的一点就是,他同时提供了搭建 k8s 集群所需要的离线资源下载,这对于国内网络用户来说,简直是太方便了,有木有。本人亲测过,确实可行。

本次,我们要搭建的就是多主多节点 HA 集群,请参照 kubeasz 文档 来执行,非常方便,亲测可行,这里就不在演示了。说明一下:同时由于本机内存限制,共开启了 4 个虚拟机节点,每个节点都分别充当了一个或多个角色。

高可用集群节点配置:

  • 部署节点 x 1: 10.222.77.86
  • etcd 节点 x 3: 10.222.77.130、10.222.77.132、10.222.77.134
  • master 节点 x 2: 10.222.77.130、10.222.77.134
  • lb 节点 x 2: 10.222.77.134(主)、10.222.77.130(备)
  • node 节点 x 2 : 10.222.77.132、10.222.77.86
  • nfs 节点 x 1: 10.222.77.86

别看上边显示了一堆 IP,其实就 4 个节点,交叉使用,建议生产环境下,每个节点充当一个角色,这样既方便排查问题,也利于集群稳定性。如果上边 IP 看的不直观的话,那么就看下下边这个 k8s HA 集群架构图吧!
kubernetes-HA

部署完成后,通过如下命令查看下是否部署成功。

$ kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
scheduler            Healthy   ok                  
etcd-2               Healthy   {"health":"true"}   
etcd-1               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"} 

$ kubectl get nodes
NAME            STATUS                     ROLES    AGE   VERSION
10.222.77.130   Ready,SchedulingDisabled   master   1h    v1.12.1
10.222.77.132   Ready                      node     1h    v1.12.1
10.222.77.134   Ready,SchedulingDisabled   master   1h    v1.12.1
10.222.77.86    Ready                      node     1h    v1.12.1

4、直接挂载 NFS

k8s 集群已搭建完毕,我们来演示一下直接挂载 NFS 到 Pod 的方式,这种方式最直接。首先,我们去 NFS 服务端机器(10.222.77.86)创建一个 /data/nfs0 目录作为远端共享文件存储目录。

$ mkdir -p /data/nfs0
# 修改配置
$ vim /etc/exports
/data/nfs0 *(rw,sync,insecure,no_subtree_check,no_root_squash)

# 使配置生效
$ exportfs -r

# 服务端查看下是否生效
$ showmount -e localhost
Export list for localhost:
/data/nfs0  *
/data/share 10.222.77.0/24

说明一下,我们要挂载 NFS,那么需要先到 NFS 服务端创建好对应目录,否则将挂载不成功。此处 NFS 操作及配置如果不清楚,请参考之前 Linux 环境下 NFS 服务安装及配置使用 这篇文章。

接下来,直接创建一个挂载该 NFS 路径的 Pod,yaml 文件如下:

$ vim nfs-busybox.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nfs-busybox
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nfs-busybox
  template:
    metadata:
      labels:
        name: nfs-busybox
    spec:
      containers:
      - image: busybox
        command:
          - sh
          - -c
          - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep 10m; done'
        imagePullPolicy: IfNotPresent
        name: busybox
        volumeMounts:
          - name: nfs
            mountPath: "/mnt"
      volumes:
      - name: nfs
        nfs:
          path: /data/nfs0
          server: 10.222.77.86

简单说下,该 Deployment 使用 busybox 作为镜像,挂载 nfs 的 /data/nfs0 卷到容器 /mnt 目录,并输出系统当前时间及 hostname 到 /mnt/index.html 文件中。那么来创建一下该 Deployment。

$ kubectl apply -f nfs-busybox.yaml 
deployment.apps/nfs-busybox created

$ kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP           NODE            NOMINATED NODE
nfs-busybox-5c98957964-g7mps   1/1     Running   0          2m    172.20.3.2   10.222.77.132   <none>

创建成功,这里提一下,如果不确认写的 yaml 文件是否有问题,可以加上 --validate 参数验证一下,如果不想验证就可加上 --validate=false。最后,进入容器内验证一下是否成功挂载吧!

$ kubectl exec -it nfs-busybox-5c98957964-g7mps /bin/sh
/ $ df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      2.4G     29.6G   7% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
10.222.77.86:/data/nfs0  27.0G     10.8G     16.1G  40% /mnt
......

/ $ cat /mnt/index.html 
Tue Nov  6 12:54:11 UTC 2018
nfs-busybox-5c98957964-g7mps

我们看到成功挂载到指定路径并生成了文件,NFS 服务端也验证一下吧!

# NFS 服务器查看
$ ll /data/nfs0/
total 4
-rw-r--r-- 1 root root 58 Nov  7 14:16 index.html

5、PV & PVC 方式使用 NFS

我们知道 k8s 提供了两种 API 资源方式:PersistentVolume 和 PersistentVolumeClaim 来解决 Pod 删除掉,挂载 volume 中的数据丢失的问题,PV 拥有独立与 Pod 的生命周期,即使 Pod 删除了,但 PV 还在,PV 上的数据依旧存在,而 PVC 则定义用户对存储资源 PV 的请求消耗。接下来,来演示下如何使用 PV & PVC 方式使用 NFS。同样,我们也需要去 NFS 服务端机器(10.222.77.86)创建一个 /data/nfs1 目录作为远端共享文件存储目录。

$ mkdir -p /data/nfs1
# 修改配置
$ vim /etc/exports
/data/nfs1 *(rw,sync,insecure,no_subtree_check,no_root_squash)

# 使配置生效
$ exportfs -r

# 服务端查看下是否生效
$ showmount -e localhost
Export list for localhost:
/data/nfs1  *
/data/nfs0  *
/data/share 10.222.77.0/24

然后,分别创建 PV 和 PVC,yaml 文件如下:

$ vim nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  nfs:
    path: /data/nfs1
    server: 10.222.77.86

$ vim nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "slow"
  resources:
    requests:
      storage: 1Gi

说明一下,这里 PV 定义了 accessModesReadWriteMany 即多次读写模式,NFS 是支持三种模式的 ReadWriteOnce、ReadOnlyMany、ReadWriteMany,详细可参考 这里 查看,实际使用中,按需配置,待会下边验证一下该类型是否支持多次读写。接下来,创建并验证一下 PV & PVC 是否成功。

$ kubectl create -f nfs-pv.yaml 
persistentvolume/nfs-pv created
$ kubectl create -f nfs-pvc.yaml 
persistentvolumeclaim/nfs-pvc created

$ kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
nfs-pv   1Gi        RWX            Recycle          Bound    default/nfs-pvc   slow                    51s
$ kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc   Bound    nfs-pv   1Gi        RWX            slow           46s

OK,成功创建,并处于 Bound 状态。接下来,创建一个挂载该 PVC 的 Pod,yaml 文件如下:

$ vim nfs-busybox-pvc.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nfs-busybox-pvc
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nfs-busybox-pvc
  template:
    metadata:
      labels:
        name: nfs-busybox-pvc
    spec:
      containers:
      - image: busybox
        command:
          - sh
          - -c
          - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep 10m; done'
        imagePullPolicy: IfNotPresent
        name: busybox
        volumeMounts:
          - name: nfs
            mountPath: "/mnt"
      volumes:
      - name: nfs
        persistentVolumeClaim:
          claimName: nfs-pvc

这里就不多分析了,跟上边的 Deployment 类似,只是更换了挂载卷方式为 PVC。然后,创建一下该 Deployment。

$ kubectl create -f nfs-busybox-pvc.yaml 
deployment.apps/nfs-busybox-pvc created
$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nfs-busybox-pvc-5d5597d976-8lkvs   1/1     Running   0          12s

创建成功。接着,验证一下是否成功挂载吧。

$ kubectl exec -it nfs-busybox-pvc-5d5597d976-8lkvs /bin/sh
/ $ df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      2.4G     29.6G   7% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
10.222.77.86:/data/nfs1  27.0G     10.8G     16.1G  40% /mnt
......

/ $ cat /mnt/index.html 
Tue Nov  6 13:28:36 UTC 2018
nfs-busybox-pvc-5d5597d976-8lkvs

最后,验证一下多次读写模式是否可行。

# nfs-busybox-pvc 容器内操作
/ $ echo "This message is from nfs-busybox-pvc." > /mnt/message.txt

# NFS 服务端操作,nfs 端写入,客户端查看
$ cat /data/nfs1/message.txt 
This message is from nfs-busybox-pvc.
$ echo "This message is from nfs-server." >> /data/nfs1/message.txt 

# nfs-busybox-pvc 容器内操作
/ $ cat /mnt/message.txt 
This message is from nfs-busybox-pvc.
This message is from nfs-server.

6、StorageClasses 动态创建 PV 方式使用 NFS

PV 支持 Static 静态请求,即提前准备好固定大小的资源。但是每次都需要管理员手动去创建对应的 PV资源,确实不方便。还好 PV 同时支持 Dynamic 动态请求,k8s 提供了 provisioner 来动态创建 PV,不仅大大节省了时间,而且还可以根据不同的 StorageClasses 封装不同类型的存储供 PVC 使用。接下来,我们演示下如何配置 NFS 类型的 StorageClasses 来动态创建 PV。

这里要说一下,k8s 默认内部 provisioner 支持列表中,是不支持 NFS 的,如果我们要使用该 provisioner 该怎么办呢?方案就是使用外部 provisioner,这里可参照 kubernetes-incubator/external-storage 这个来创建,跟之前 初试 Kubernetes 集群使用 Ceph RBD 块存储 文章中演示类似,参照这个项目,可以提供外部 provisioner 来支持动态创建 PV 的功能。

在开始创建之前,我们还是需要去 NFS 服务端(10.222.77.86)创建一个 /data/nfs2 共享存储目录,后续动态创建的 PV 卷目录都在该目录下。

$ mkdir -p /data/nfs2
# 修改配置
$ vim /etc/exports
/data/nfs2 *(rw,sync,insecure,no_subtree_check,no_root_squash)

# 使配置生效
$ exportfs -r

# 服务端查看下是否生效
$ showmount -e localhost
Export list for localhost:
/data/nfs2  *
/data/nfs1  *
/data/nfs0  *
/data/share 10.222.77.0/24

然后,我们参照 external-storage/nfs-client 文档来完成自定义外部 nfs-provisioner 的创建。参照文档,NFS-Client Provisioner 可以使用 Helm 部署非 Helm 部署方式,采用 Helm 部署非常方便,只需要一条命令即可。

$ helm install stable/nfs-client-provisioner --set nfs.server=x.x.x.x --set nfs.path=/exported/path

如果采用非 helm 部署方式,稍微麻烦一些,不过也不是很难,这里就演示下这种方式吧!首先,我们需要 Clone 下该项目到本地。

$ git clone https://github.com/kubernetes-incubator/external-storage.git
$ tree external-storage/nfs-client/deploy/
external-storage/nfs-client/deploy/
├── class.yaml
├── deployment-arm.yaml
├── deployment.yaml
├── objects
│   ├── README.md
│   ├── class.yaml
│   ├── clusterrole.yaml
│   ├── clusterrolebinding.yaml
│   ├── deployment-arm.yaml
│   ├── deployment.yaml
│   ├── role.yaml
│   ├── rolebinding.yaml
│   └── serviceaccount.yaml
├── rbac.yaml
├── test-claim.yaml
└── test-pod.yaml

我们用到的文件就在 external-storage/nfs-client/deploy/ 该目录下,然后修改 class.yamldeployment.yaml,注意:这两个文件也可以不修改,使用默认值也可以,只不过生成的 provisioner 名称为 fuseim.pri/ifs,我们可以修改成自定义的名称,同时修改下 nfs-client-provisioner 镜像为国内可拉取镜像,以及 nfs 配置信息。

# class.yaml 文件修改前后对比
-  name: managed-nfs-storage
-provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
+  name: my-nfs-storage-class
+provisioner: my-nfs-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'

# deployment.yaml 文件修改前后对比
-          image: quay.io/external_storage/nfs-client-provisioner:latest
+          image: jmgao1983/nfs-client-provisioner:latest
           env:
             - name: PROVISIONER_NAME
-              value: fuseim.pri/ifs
+              value: my-nfs-provisioner
             - name: NFS_SERVER
-              value: 10.10.10.60
+              value: 10.222.77.86
             - name: NFS_PATH
-              value: /ifs/kubernetes
+              value: /data/nfs2

           nfs:
-            server: 10.10.10.60
-            path: /ifs/kubernetes
+            server: 10.222.77.86
+            path: /data/nfs2

提一下,这里的 rbac.yaml 当 k8s 开启了 rbac 认证时使用,默认是 default 命名空间,如果非 default,则需要修改为对应命名空间,这里我就是使用 default,就不用修改了。然后,创建一下这些资源。

$ kubectl create -f class.yaml 
storageclass.storage.k8s.io/my-nfs-storage-class created
$ kubectl create -f rbac.yaml 
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
$ kubectl create -f deployment.yaml 
serviceaccount/nfs-client-provisioner created
deployment.extensions/nfs-client-provisioner created

创建完毕,查看下是否创建成功。

$ kubectl get sc
NAME                   PROVISIONER          AGE
my-nfs-storage-class   my-nfs-provisioner   1m27s
$ kubectl get pods 
NAME                                     READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-6787dcc59-tgcc5   1/1     Running   0          2m19s

最后,我们需要提供一下使用 my-nfs-storage-class 的 PVC 资源以及使用挂载该 PVC 资源的 Pod。PVC 的 yaml 文件如下:

$ vim nfs-sc-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nfs-sc-pvc
  annotations:
    volume.beta.kubernetes.io/storage-class: "my-nfs-storage-class"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

创建一下,看下是否能够创建成功,是否能够动态创建 PV。

$ kubectl create -f nfs-sc-pvc.yaml 
persistentvolumeclaim/nfs-sc-pvc created

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS           REASON   AGE
pvc-176dbc3b-e1d6-11e8-ac77-0800272ff396   1Gi        RWX            Delete           Bound    default/nfs-sc-pvc   my-nfs-storage-class            60s

$ kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS           AGE
nfs-sc-pvc   Bound    pvc-176dbc3b-e1d6-11e8-ac77-0800272ff396   1Gi        RWX            my-nfs-storage-class   15s

可以看到,成功的动态创建了 PV,达到预期效果。NFS 服务端查看下是否已创建该 PV 对应的卷目录。

# NFS 服务器上操作
$ ll /data/nfs2/
total 0
drwxrwxrwx 2 root root 6 Nov  7 16:22 default-nfs-sc-pvc-pvc-176dbc3b-e1d6-11e8-ac77-0800272ff396

自动创建了,非常方便了,有没有!最后创建挂载 PVC 的 Deployment,yaml 文件如下:

$ vim nfs-busybox-sc-pvc.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nfs-busybox-sc-pvc
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nfs-busybox-sc-pvc
  template:
    metadata:
      labels:
        name: nfs-busybox-sc-pvc
    spec:
      containers:
      - image: busybox
        command:
          - sh
          - -c
          - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep 10m; done'
        imagePullPolicy: IfNotPresent
        name: busybox
        volumeMounts:
          - name: nfs
            mountPath: "/mnt"
      volumes:
      - name: nfs
        persistentVolumeClaim:
          claimName: nfs-sc-pvc

创建一下该 Deployment。

$ kubectl create -f nfs-busybox-sc-pvc.yaml
deployment.apps/nfs-busybox-sc-pvc created
$ kubectl get pods
NAME                                     READY   STATUS    RESTARTS   AGE
nfs-busybox-sc-pvc-5f8d5b4b96-fwh6b      1/1     Running   0          7s
nfs-client-provisioner-6787dcc59-tgcc5   1/1     Running   0          8m57s

创建成功,最后验证一下是否成功挂载吧。

$ kubectl exec -it nfs-busybox-sc-pvc-5f8d5b4b96-fwh6b /bin/sh
/ $ df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      2.4G     29.6G   8% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
10.222.77.86:/data/nfs2/default-nfs-sc-pvc-pvc-176dbc3b-e1d6-11e8-ac77-0800272ff396
                         27.0G     10.9G     16.1G  40% /mnt
......

/ $ cat /mnt/index.html 
Tue Nov  6 15:14:04 UTC 2018
nfs-busybox-sc-pvc-5f8d5b4b96-fwh6b

# NFS 服务器端验证
$ cat /data/nfs2/default-nfs-sc-pvc-pvc-176dbc3b-e1d6-11e8-ac77-0800272ff396/index.html 
Tue Nov  6 15:14:04 UTC 2018
nfs-busybox-sc-pvc-5f8d5b4b96-fwh6b

最后,多提一点,上边动态创建 PV 方式,只能动态创建到 nfs-client-provisioner 指定挂载的目录里面,如果我们想根据不同的服务分别动态创建到不同的 NFS 共享目录里面的话,可以多创建几个 nfs-client-provisioner,每个 provisioner 指定挂载不同的 NFS 存储路径即可。

参考资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kubernetes 集群使用 NFS 网络文件存储 的相关文章

随机推荐

  • Halcon (64位)无法卸载或者卸载不彻底,没法再次安装?

    以管理员身份 切换到cmd 1 删除安装目录 rmdir S HALCONROOT 2 查询安装的Halcon版本 reg query HKLM SOFTWARE Wow6432Node MVTec HALCON Windows x64 3
  • 面试常用算法归纳

    面试常用算法归纳 算法时间复杂度 二叉查找树的时间复杂度 递归和分治 递归思维 汉诺塔问题 排序算法 最长子串 子序列 一维dp 有断层 最长递增子序列 最大子数组和 无重复字符的最长子串 买卖股票的最佳时机 二维dp 组合 子集 和排列
  • YOLOv5改进算法之添加CA注意力机制模块

    目录 1 CA注意力机制 2 YOLOv5添加注意力机制 送书活动 1 CA注意力机制 CA Coordinate Attention 注意力机制是一种用于加强深度学习模型对输入数据的空间结构理解的注意力机制 CA 注意力机制的核心思想是引
  • Atmel Studio 7.0 快速上手指南(基于ASF)

    Atmel Studio 7 0 快速上手指南 基于ASF 程序员大本营 pianshen com
  • 【Kubernetes部署篇】K8s图形化管理工具Dasboard部署及使用

    文章目录 一 Dashboard简介 二 Dashboard部署安装 三 配置Dashboard登入用户 1 通过Token令牌登入 2 通过kubeconfig文件登入 四 Dashboard创建容器 五 扩展 一 Dashboard简介
  • switch...case...和if...else...区别

    switch 和 if 都是用来处理分支语句的 那么使用的时候 考虑到代码效率问题 就必须先来了解他们有什么区别 先来看看这两个语句的使用格式 if else if 表达式1 语句1 else if 表达式2 语句2 else if 表达式
  • Altium Designer (AD) 元器件出现绿色叉叉报错的解决办法

    出现报错的原因 元器件的安全间距小于设定的安全间距 但通常情况下 这个问题并不严重 可以理解为是一个警告 不去处理也可以 解决办法 点击菜单栏的工具 T 再点击复位错误标志 M 即可解决报错
  • 一个爬虫代码价值 7000 万

    一个爬虫代码价值 7000 亿 这样的代码你听说过吗 这是一个爬取比特币密钥的代码 比特币相信大家都有听说过 尤其最近比特币价格还突破了 5 万美元大关 现在1 枚比特币就价值 35 万人民币 难怪有句说 币圈一天 人间一年 最近朋友圈关于
  • 登录,注册HTML页面,详细过程

    1 页面说明 登录和注册切换按钮 当点击登录按钮时 显示登录表单 当点击注册按钮时 显示注册表单 每个表单都有对应的 JavaScript 校验函数 校验用户名 邮箱和密码是否为空 如果为空 会弹出警告框 2 效果图展示 3 代码部分 3
  • 手把手教你快速上手人体姿态估计(MMPose)

    最近在研究如何快速实现图像中人体姿态的估计 也就是常见的pose estimation任务 花了些时间 实际对比了AlphaPose BlazePose和MMPose BlazePose主要为移动端设计 AlphaPose安装配置比较麻烦
  • 服务器显卡驱动重装系统,windows7旗舰版系统重装显卡驱动的方法

    在windows7旗舰版电脑中 我们都是需要安装显卡驱动 但是如果显卡驱动安装不合适的话 就会容易导致电脑出现问题 所以如果有碰到安装到不合适的显卡驱动的话我们可以通过重装显卡驱动来解决 那么该怎么操作呢 为此小编这就给大家讲解一下wind
  • 图片 url blob base64 互转

    待补充 url to blob export const urlToBlob async url string gt return new Promise resolve gt fetch url then res gt res blob
  • Nginx

    HTTP和反向代理web服务器 Nginx是一个高性能的HTTP和反向代理web服务器 同时也提供了IMAP POP3 SMTP服务 Nginx是一款轻量级的Web服务器反向代理服务器及电子邮件 IMAP POP3 代理服务器 nginx反
  • 结合 服务器+后端+前端,完成 vue项目 后台管理系统

    目录 以上是项目的服务器php 后端 前端 已经可以正常运行 一 登录 登录页进度条 戳这里Vue项目电商后台管理系统 nprogress 进度条 活在风浪里的博客 CSDN博客 二 侧导航 三 列表页源码 四 角色分配 五 权限页面开发
  • 多线程实现Runable接口和Callable接口的区别

    先看源码callable接口 返回泛型v 可以抛出异常 Runable接口是抽象方法run 没有返回值 不能抛出异常 有异常在run方法内部处理 总结 区别1 两者最大的区别 实现Callable接口的任务线程能返回执行结果 而实现Runn
  • 交换机电口、光口、网络速率的基本概念总结

    电口和光口 千兆网 万兆网 POE 包转发率 背板带宽 交换容量 光纤跳线 电口和光口 电口 电口也即RJ45口 插双绞线的端口 网线 一般速率为10M或100M 即为百兆工业交换机 部分支持1000M 即为千兆交换机 光口 工业以太网交换
  • python sklearn 梯度下降法_Python与机器学习:梯度下降

    梯度下降 Gradient Descent 梯度下降法不是一个机器学习算法 是一种基于搜索的最优化算法 目的是最小化一个损失函数 同样 梯度上升法用于最大化一个效用函数 求解损失函数的最小值有两种方法 1 正规方程求解 上一章已经讲使用线性
  • java多线程和高并发系列三 & Synchronized锁详解

    目录 设计同步器的意义 如何解决线程并发安全问题 同步器的本质就是加锁 synchronized原理详解 synchronized底层原理 Monitor监视器锁 什么是monitor 对象的内存布局 对象头 对象头分析工具 锁的膨胀升级过
  • Python入门教学——多进程和多线程

    目录 一 线程和进程 1 线程和进程的基本概念 2 线程和进程的关系 3 串行 并行和并发 二 创建多个线程 1 线程相关的模块 2 创建线程 2 1 通过Thread类构造器来创建新线程 2 2 通过继承于Thread类来创建新线程 三
  • Kubernetes 集群使用 NFS 网络文件存储

    文章目录 1 NFS 介绍 2 环境 软件准备 3 Kubernetes HA 集群搭建 4 直接挂载 NFS 5 PV PVC 方式使用 NFS 6 StorageClasses 动态创建 PV 方式使用 NFS 1 NFS 介绍 Kub