kubernetes-存储卷(十二)
为了保证数据的持久性,必须保证数据在外部存储在docker
容器中,为了实现数据的持久性存储,在宿主机和容器内做映射,可以保证在容器的生命周期结束,数据依旧可以实现持久性存储。但是在k8s
中,由于pod
分布在各个不同的节点之上,并不能实现不同节点之间持久性数据的共享,并且,在节点故障时,可能会导致数据的永久性丢失。为此,k8s
就引入了外部存储卷的功能。
Volume
https://kubernetes.io/docs/concepts/storage/volumes/
Kubernetes中的Volume提供了在容器中挂载外部存储的能力
Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume
k8s的存储类型
[root@k8s-master ~]# kubectl explain pod.spec.volumes #查看k8s支持的存储类型
KIND: Pod
VERSION: v1 常用分类:
emptyDir(临时目录):Pod删除,数据也会被清除,这种存储成为emptyDir,用于数据的临时存储。
hostPath(宿主机目录映射):
本地的SAN(iSCSI,FC)、NAS(nfs,cifs,http)存储
分布式存储(glusterfs,rbd,cephfs)
云存储(EBS,Azure Disk)
emptyDir
一个emptyDir 第一次创建是在一个pod被指定到具体node的时候,并且会一直存在在pod的生命周期当中,正如它的名字一样,它初始化是一个空的目录,pod中的容器都可以读写这个目录,这个目录可以被挂在到各个容器相同或者不相同的的路径下。当一个pod因为任何原因被移除的时候,这些数据会被永久删除。注意:一个容器崩溃了不会导致数据的丢失,因为容器的崩溃并不移除pod.
emptyDir 磁盘的作用:
(1)普通空间,基于磁盘的数据存储
(2)作为从崩溃中恢复的备份点
(3)存储那些那些需要长久保存的数据,例web服务中的数据
默认的,emptyDir 磁盘会存储在主机所使用的媒介上,可能是SSD,或者网络硬盘,这主要取决于你的环境。当然,我们也可以将emptyDir.medium的值设置为Memory来告诉Kubernetes 来挂在一个基于内存的目录tmpfs,因为
tmpfs速度会比硬盘块度了,但是,当主机重启的时候所有的数据都会丢失。
创建emptyDir示例
[root@k8s-master1 volume]# vim pod-vol-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort:
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: html
mountPath: /data/
command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
volumes:
- name: html
emptyDir: {} [root@k8s-master1 volume]# kubectl apply -f pod-vol-demo.yaml
pod/pod-demo configured
[root@k8s-master1 volume]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-demo / Running 15m 172.17.32.3 192.168.0.125 <none> <none>
在上面,我们定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。如下访问验证:
[root@k8s-node01 ~]# curl 172.17.73.3
Wed Dec :: UTC
Wed Dec :: UTC
Wed Dec :: UTC
Wed Dec :: UTC
Wed Dec :: UTC
Wed Dec :: UTC
Wed Dec :: UTC
Wed Dec :: UTC
hostPath
hostPath宿主机路径,就是把pod所在的宿主机之上的脱离pod中的容器名称空间的之外的宿主机的文件系统的某一目录和pod建立关联关系,在pod删除时,存储数据不会丢失。
[root@k8s-master1 volume]# vim pod-hostpath-vol.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-hostpath
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
hostPath:
path: /data/pod/volume1
type: DirectoryOrCreate [root@k8s-master1 volume]# kubectl apply -f pod-hostpath-vol.yaml
pod/pod-vol-hostpath created
[root@k8s-master1 volume]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-vol-hostpath / Running 39s 172.17.73.3 192.168.0.126 <none> <none>
访问测试
[root@k8s-node02 ~]# echo "test hostpath" > /data/pod/volume1/index.html
[root@k8s-node02 ~]# curl 172.17.73.3
test hostpath
nfs共享存储卷
nfs使的我们可以挂在已经存在的共享到的我们的Pod中,和emptyDir不同的是,emptyDir会被删除当我们的Pod被删除的时候,但是nfs不会被删除,仅仅是解除挂在状态而已,这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递.并且,nfs可以同时被多个pod挂在并进行读写
准备nfs服务
[root@localhost ~]# yum install -y nfs-utils
[root@localhost ~]# mkdir /data/volumes -p
[root@localhost ~]# vim /etc/exports
/data/volumes 192.168.0.0/(rw,no_root_squash)
[root@localhost ~]# systemctl start nfs
[root@localhost ~]# showmount -e
Export list for localhost.localdomain:
/data/volumes 192.168.0.0/ node测试挂载
[root@k8s-node01 ~]# yum install -y nfs-utils
[root@k8s-node01 ~]# mount -t nfs 192.168.0.122:/data/volumes /mnt
[root@k8s-node01 ~]# mount
. . . . .
192.168.0.122:/data/volumes on /mnt type nfs4 (rw,relatime,vers=4.1,rsize=,wsize=,namlen=,hard,proto=tcp,timeo=,retrans=,sec=sys,clientaddr=192.168.0.125,local_lock=none,addr=192.168.0.122)
[root@k8s-node01 ~]# umount /mnt
使用nfs存储卷示例
[root@k8s-master1 volume]# vim pod-nfs-vol.yaml apiVersion: v1
kind: Pod
metadata:
name: pod-vol-nfs
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
path: /data/volumes
server: 192.168.0.122 [root@k8s-master1 volume]# kubectl apply -f pod-nfs-vol.yaml
pod/pod-vol-nfs created
[root@k8s-master1 volume]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-vol-hostpath / Running 29m 172.17.73.3 192.168.0.126 <none> <none>
pod-vol-nfs / Running 13s 172.17.73.4 192.168.0.126 <none> <none> 在nfs创建index.html,访问测试
[root@localhost ~]# cat /data/volumes/index.html
<h1>nfs test</h1>
[root@k8s-node01 ~]# curl 172.17.73.4
<h1>nfs test</h1>
PVC和PV的概念
Kubernetes支持持久卷的存储插件:https://kubernetes.io/docs/concepts/storage/persistent-volumes/
kubernetes提供那么多存储接口,但是首先kubernetes的各个Node节点能管理这些存储,但是各种存储参数也需要专业的存储工程师才能了解,由此我们的kubernetes管理变的更加复杂的。由此kubernetes提出了PV和PVC的概念,这样开发人员和使用者就不需要关注后端存储是什么,使用什么参数等问题。如下图:
PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。 集群中的资源就像一个节点是一个集群资源。 PV是诸如卷之类的卷插件,但是具有独立于使用PV的任何单个pod的生命周期。 该API对象捕获存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统。
PersistentVolumeClaim(PVC)是用户存储的请求。PVC的使用逻辑:在pod中定义一个存储卷(该存储卷类型为PVC),定义的时候直接指定大小,pvc必须与对应的pv建立关系,pvc会根据定义去pv申请,而pv是由存储空间创建出来的。pv和pvc是kubernetes抽象出来的一种存储资源。
PV是集群中的资源。 PVC是对这些资源的请求,也是对资源的索赔检查。 PV和PVC之间的相互作用遵循这个生命周期:
Provisioning(配置)---> Binding(绑定)--->Using(使用)---> Releasing(释放) ---> Recycling(回收)
Provisioning
这里有两种PV的提供方式:静态或者动态
静态-->直接固定存储空间:
集群管理员创建一些 PV。它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费。
动态-->通过存储类进行动态创建存储空间:
当管理员创建的静态 PV 都不匹配用户的 PVC 时,集群可能会尝试动态地为 PVC 配置卷。此配置基于 StorageClasses:PVC 必须请求存储类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。
Binding
在动态配置的情况下,用户创建或已经创建了具有特定数量的存储请求和特定访问模式的PersistentVolumeClaim。 主机中的控制回路监视新的PVC,找到匹配的PV(如果可能),并将 PVC 和 PV 绑定在一起。 如果为新的PVC动态配置PV,则循环将始终将该PV绑定到PVC。 否则,用户总是至少得到他们要求的内容,但是卷可能超出了要求。 一旦绑定,PersistentVolumeClaim绑定是排他的,不管用于绑定它们的模式。
如果匹配的卷不存在,PVC将保持无限期。 随着匹配卷变得可用,PVC将被绑定。 例如,提供许多50Gi PV的集群将不匹配要求100Gi的PVC。 当集群中添加100Gi PV时,可以绑定PVC。
Using
Pod使用PVC作为卷。 集群检查声明以找到绑定的卷并挂载该卷的卷。 对于支持多种访问模式的卷,用户在将其声明用作pod中的卷时指定所需的模式。
一旦用户有声明并且该声明被绑定,绑定的PV属于用户,只要他们需要它。 用户通过在其Pod的卷块中包含PersistentVolumeClaim来安排Pods并访问其声明的PV。
Releasing
当用户完成卷时,他们可以从允许资源回收的API中删除PVC对象。 当声明被删除时,卷被认为是“释放的”,但是它还不能用于另一个声明。 以前的索赔人的数据仍然保留在必须根据政策处理的卷上.
Reclaiming
PersistentVolume的回收策略告诉集群在释放其声明后,该卷应该如何处理。 目前,卷可以是保留,回收或删除。 保留可以手动回收资源。 对于那些支持它的卷插件,删除将从Kubernetes中删除PersistentVolume对象,以及删除外部基础架构(如AWS EBS,GCE PD,Azure Disk或Cinder卷)中关联的存储资产。 动态配置的卷始终被删除
Recycling
如果受适当的卷插件支持,回收将对卷执行基本的擦除(rm -rf / thevolume / *),并使其再次可用于新的声明。
静态创建nfs类型的pv示例
创建pv
[root@k8s-master1 volume]# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
path: /data/volumes/wwwroot
server: 192.168.0.122 [root@k8s-master1 volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
my-pv 5Gi RWX Retain Available 8s 创建容器应用
[root@k8s-master1 volume]# cat pod-nfs-pvc.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas:
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort:
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: my-pvc ---
定义pvc:卷需求模板
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi [root@k8s-master1 volume]# kubectl apply -f pod-nfs-pvc.yaml
deployment.apps/nginx-deployment created
persistentvolumeclaim/my-pvc created
[root@k8s-master1 volume]# kubectl get pv,pvc #查看pvc绑定
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/my-pv 5Gi RWX Retain Bound default/my-pvc 11m NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/my-pvc Bound my-pv 5Gi RWX 9s
[root@k8s-master1 volume]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-57fbd964dc-f5qx9 / Running 22s 172.17.32.3 192.168.0.125 <none> <none>
nginx-deployment-57fbd964dc-hrlq9 / Running 22s 172.17.32.4 192.168.0.125 <none> <none>
nginx-deployment-57fbd964dc-qqmh9 / Running 22s 172.17.73.3 192.168.0.126 <none> <none> 访问测试
[root@localhost volumes]# cat /data/volumes/wwwroot/index.html
hello world!
[root@k8s-node01 ~]# curl 172.17.32.3
hello world!
[root@k8s-node01 ~]# curl 172.17.32.4
hello world!
[root@k8s-node01 ~]# curl 172.17.73.3
hello world!
动态生成nfs类型的pv示例
Dynamic Provisioning机制工作的核心在于StorageClass的API对象。
StorageClass声明存储插件,用于自动创建PV。
参考文档:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client/deploy/objects
创建storageclass
[root@k8s-master1 volume]# vim storageclass-nfs.yaml
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: fuseim.pri/ifs [root@k8s-master1 volume]# kubectl apply -f storageclass-nfs.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
创建rbac授权
[root@k8s-master1 volume]# cat rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner --- kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"] --- kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io [root@k8s-master1 volume]# kubectl apply -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
运行nfs-client-provisioner
[root@k8s-master1 volume]# cat deployment-nfs.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nfs-client-provisioner
spec:
replicas:
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
imagePullSecrets:
- name: registry-pull-secret
serviceAccount: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: lizhenliang/nfs-client-provisioner:v2.0.0
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 192.168.0.122
- name: NFS_PATH
value: /data/volumes
volumes:
- name: nfs-client-root
nfs:
server: 192.168.0.122
path: /data/volumes [root@k8s-master1 volume]# kubectl apply -f deployment-nfs.yaml
deployment.apps/nfs-client-provisioner created
[root@k8s-master1 volume]# kubectl get storageclass
NAME PROVISIONER AGE
managed-nfs-storage fuseim.pri/ifs 65s
[root@k8s-master1 volume]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-f69cd5cf-wvwlq / Running 21s
nginx-deployment-57fbd964dc-f5qx9 / Running 7m42s
nginx-deployment-57fbd964dc-hrlq9 / Running 7m42s
nginx-deployment-57fbd964dc-qqmh9 / Running 7m42s
创建deployment示例
[root@k8s-master1 volume]# cat deployment-demo.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment2
spec:
replicas:
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort:
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: my-pvc2 --- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc2
spec:
accessModes:
- ReadWriteMany
storageClassName: managed-nfs-storage
resources:
requests:
storage: 5Gi [root@k8s-master1 volume]# kubectl apply -f deployment-demo.yaml
deployment.apps/nginx-deployment2 created
persistentvolumeclaim/my-pvc2 created
[root@k8s-master1 volume]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-f69cd5cf-wvwlq / Running 6m14s
nginx-deployment-57fbd964dc-f5qx9 / Running 13m
nginx-deployment-57fbd964dc-hrlq9 / Running 13m
nginx-deployment-57fbd964dc-qqmh9 / Running 13m
nginx-deployment2-8685f649c9-82zgg / Running 52s
nginx-deployment2-8685f649c9-tjbdm / Running 52s
nginx-deployment2-8685f649c9-tkrwq / Running 52s
[root@k8s-master1 volume]# kubectl get pv,pvc #查看自动生成my-pvc2
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/default-my-pvc2-pvc-c9c9861f-09b4-11e9-b58a-000c298a2b5f 5Gi RWX Delete Bound default/my-pvc2 managed-nfs-storage 79s
persistentvolume/my-pv 5Gi RWX Retain Bound default/my-pvc 24m NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/my-pvc Bound my-pv 5Gi RWX 14m
persistentvolumeclaim/my-pvc2 Bound default-my-pvc2-pvc-c9c9861f-09b4-11e9-b58a-000c298a2b5f 5Gi RWX managed-nfs-storage 79s
#查看nfs自动生成的目录
[root@localhost ~]# ll /data/volumes/
total
drwxrwxrwx root root Dec : default-my-pvc2-pvc-c9c9861f-09b4-11e9-b58a-000c298a2b5f
-rw-r--r-- root root Dec : index.html
drwxr-xr-x root root Dec : wwwroot
kubernetes-存储卷(十二)的更多相关文章
- kubernetes 存储卷
kubernetes 存储卷 数据卷用于实现容器持久化数据,Kubernetes对于数据卷重新定义,提供了丰富强大的功能.在Kubernetes系统中,当Pod重建的时候,数据卷会丢失,Kube ...
- (九)Kubernetes 存储卷
Kubernetes存储卷概述 Pod本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,kubelet会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态:第二,当很多容器在同一 ...
- Kubernetes 学习12 kubernetes 存储卷
一.概述 1.我们此前讲过根据应用本身是否需要持久存储数据以及某一次请求和之前的请求是否有联系,可以分为四类应用 a.有状态,要存储 b.有状态,无持久存储 c.无状态,要存储 d.无状态,无持久存储 ...
- Kubernetes 存储卷管理 PV&PVC(十)
目录 一.emptyDir 二.hostPath 三.PV & PVC 1.NFS PersistentVolume 2.创建 PVC 3.创建 Pod 进行挂载 为了持久化保存容器的数据,可 ...
- Kubernetes 配置管理 ConfigMap(十二)
目录 一.背景 二.创建 ConfigMap 2.1.通过 --from-literal 2.2.通过 --from-file 2.3.通过--from-env-file 2.4.YAML 配置文件 ...
- Kubernetes 存储卷详解
转载自:https://mp.weixin.qq.com/s/Ywx3ju6FP0IShOgI757XYA Volumes 默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问 ...
- Spark RDD概念学习系列之Spark的数据存储(十二)
Spark数据存储的核心是弹性分布式数据集(RDD). RDD可以被抽象地理解为一个大的数组(Array),但是这个数组是分布在集群上的. 逻辑上RDD的每个分区叫一个Partition. 在Spar ...
- Hive压缩和存储(十二)
压缩和存储 1. Hadoop压缩配置 1) MR支持的压缩编码 压缩格式 工具 算法 文件扩展名 是否可切分 DEFAULT 无 DEFAULT .deflate 否 Gzip gzip DEFAU ...
- 从零开始入门 K8s | Kubernetes 存储架构及插件使用
本文整理自<CNCF x Alibaba 云原生技术公开课>第 21 讲. 导读:容器存储是 Kubernetes 系统中提供数据持久化的基础组件,是实现有状态服务的重要保证.Kubern ...
- 第21 章 : Kubernetes 存储架构及插件使用
Kubernetes 存储架构及插件使用 本文将主要分享以下三方面的内容: Kubernetes 存储体系架构: Flexvolume 介绍及使用: CSI 介绍及使用. Kubernetes 存储体 ...
随机推荐
- mac 终端命令kill掉某个指定端口
用mac电脑开发时,有时候会遇到端口占用的问题,导致我们,不得不去结束这个端口. 第一步在终端命令输入: lsof -i : 端口号(如:lsof -i:8080) 第二步: kill -9 PID ...
- 毕马威&阿里:通向智能制造的转型之路
文章发布于公号[数智物语] (ID:decision_engine),关注公号不错过每一篇干货. 2019 年 4 月 17 日,毕马威与阿里研究院携手举办了智能经济主题报告发布会,从技术.制造.组织 ...
- 防止表单submit或按钮button多次连续点击提交
如上例子:当我点击提交按钮触发submitQuartz()函数 防止用户连续点击提交操作 方法一:获取当时点击时间,根据时间差判断 $scope.submitQuartz=function () { ...
- Docker存储卷
六.Docker 存储卷(volume) COW:写时复制 Bind mount volume:手动mount绑定的卷 # docker run --name centos-3 -it -v /dat ...
- springboot和Druid整合配置数据源
@Configuration public class DruidConfiguration { @ConfigurationProperties(prefix = "spring.data ...
- angularJs1.x 版本中 uib-tabset 如何默认激活不同的标签页
<uib-tabset> 默认有个active属性,根据官方文档,active的默认值是0,也就是说,默认显示索引为0的标签页,可以通过修改这个值来默认显示不同的索引的标签页. 示例: ...
- P3823_[NOI2017]蚯蚓排队 哈希+脑子
之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$ 观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$).我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数, ...
- docker exit status 255解决
一 windows开发整docker就是痛苦,在公司win7电脑想拿起几年没再用的docker 结果直接报错 Error getting IP address: ssh command error: ...
- FormsAuthentication IsAuthenticated一直为false
解决办法: 在Web.Config中添加一下红框的内容
- java.sql.SQLException: Zero date value prohibited 报错分析
今天在使用 iReview 复习词条时,发现 review 页面始终不会跳到下一个词条,应该是前台或者后台出现 BUG 了. 查看浏览器控制台,看到 500 报错,那应该是后台的问题. 登录后台,先查 ...