由于之前docker的数据卷都是每个容器挂在至外部,但是不可能一百个容器创建100个的数据卷,所以k8s就抽象了一个存储层;在每一个节点都有一个存储目录,然后各个节点的存储的数据都会通过NFS(网路文件系统)同步。存储层的框架不止NFS,只是这里学习用NFS。
不同节点的NFS都是数据同步的,即使其中一个宕机了,也会在其他机器拉起来,然后数据同步过去。
安装NFS:
1、所有节点
#所有机器安装
yum install -y nfs-utils
2、主节点
#nfs主节点
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports#在主节点以非安全,可读写,无权限下/nfs/data/暴露,所有节点都可以同步这个目录
mkdir -p /nfs/data
systemctl enable rpcbind --now #启动远程绑定服务
systemctl enable nfs-server --now #启动NFS服务端(enable开机自己启动)
#配置生效
exportfs -r
3、从节点
showmount -e 172.31.0.2 #检查这个ip的服务器哪些目录可以挂载,这个ip是私有地址
#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data
mount -t nfs 172.31.0.2:/nfs/data /nfs/data
# 写入一个测试文件
echo "hello nfs server" > /nfs/data/test.txt
原生方式对pod进行数据挂载,这里有一个yaml文件:
apiVersion: apps/v1
kind: Deployment #这是一个deployment部署
metadata:
labels:
app: nginx-pv-demo
name: nginx-pv-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- image: nginx
name: nginx #容器的名字
volumeMounts: #卷挂载
- name: html #挂在外面叫的名字
mountPath: /usr/share/nginx/html #在pod里面挂载的目录
volumes: #在这里开始是外部挂载的信息
- name: html #挂载名
nfs: #以nfs方式挂载
server: 172.31.0.2 #网络文件系统的服务端(是个内网地址)
path: /nfs/data/nginx-pv #挂载外部的路径
以上的yaml文件其实就是这个内容:
启动这个应用:kubectl apply -f deploy.yaml
发现失败原来是服务器的/nfs/data路径上没有nginx-pv ,所以要先创建这个文件夹,然后删除原先的deployment部署kubectl delete -f deploy.yaml
,因为使用yaml文件部署的,所以使用yaml删除;然后重新启动该应用。
接着是测试:
在外部创建一个文件:
在可视化操作界面即可看到:
原生方式挂载的话自己本地的文件夹需要自己先创建;pod删除了,数据卷还存在;然后对于pod的产生的数据量大小没有做限制;
1、PV&PVC
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置
PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格
1、创建pv池
静态供应
#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
创建PV,yaml文件如下:
apiVersion: v1
kind: PersistentVolume #资源类型:持久化卷
metadata:
name: pv01-10m #名字
spec:
capacity: #限制了他的容量
storage: 10M #容量大小是10M
accessModes:
- ReadWriteMany #可读可写,多节点都可以操作的
storageClassName: nfs #这里随便写,这里写nfs
nfs:
path: /nfs/data/01
server: 172.31.0.2 #下行的3个短横线代表分割一个文档
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02-1gi
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
server: 172.31.0.2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3gi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
server: 172.31.0.2 #nfs服务端所在机器的内网地址
然后应用:kubectl apply -f pv.yaml
,创建成功:
2、PVC创建与绑定
创建PVC(写申请书),yaml文件:
kind: PersistentVolumeClaim #资源类型:PVC的写法
apiVersion: v1
metadata:
name: nginx-pvc #申请书的名字随便
spec: #这里就是PVC的申请空间内容
accessModes:
- ReadWriteMany #可读可写,多节点都可以操作的
resources:
requests:
storage: 200Mi #申请大小
storageClassName: nfs #注意:这里的storageClassName:命名需要和创建pv的是一样的
然后应用:kubectl apply -f pvc.yaml
,创建成功:可以看到pv被我们刚刚创建的PVC绑定了;
创建Pod绑定PVC,yaml文件内容:
apiVersion: apps/v1
kind: Deployment #资源类型:Deployment(部署pod的)
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2 #副本2个
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html #还是把这个目录挂出去
volumes:
- name: html
persistentVolumeClaim:
claimName: nginx-pvc #PVC的名称,是把内部的空间与申请书申请的空间绑定。
然后应用:kubectl apply -f deploy02.yaml
,创建成功,在/nfs/data/02目录下创建一个文件:
在pod里面验证成功:
拓展:PV池还有动态供应,自动创建一个相对大小的PV。
ConfigMap:抽取应用配置,并且可以自动更新
这个是一些应用或者中间件的配置文件的配置集,管理这些应用的配置的。
1、redis示例
1、把之前的配置文件创建为配置集
# 创建配置,redis保存到k8s的etcd;
kubectl create cm redis-conf --from-file=redis.conf
先做一个小测试:创建一个redis.conf的文件(用命令形式创建ConfigMap):
appdenonly yes #代表redis的数据需要持久化存储
然后用kubectl create cm redis-conf --from-file=redis.conf
命令,把redis.conf做成一个叫redis-conf的配置集,如图新建成功:
配置集的内容都会存储在etcd了,只要k8s或者这个配置集就会存在,etcd类似一个档案库。
查看redis-conf配置集,以yaml形式输出:kubectl get cm redis-conf -oyaml
以下的yaml是我们上面创建redis-conf配置集经过up主精简的yaml文件,所以我们要想创建和上面的一样配置集文件,运行这个yaml文件即可;
apiVersion: v1
data: #data是配置文件的所有真正的数据,key:默认是文件名(redis.conf) value:配置文件的内容(appendonly yes)
redis.conf: |
appendonly yes
kind: ConfigMap #资源的类型:ConfigMap
metadata:
name: redis-conf #是我们这个资源的名字
namespace: default
2、创建Pod
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
command:
- redis-server #redis启动的时候使用我们自定义启动命令,接着加载我们的配置文件,我们的配置文件是这个"/redis-master/redis.conf";然后是在下面mountPath的。
- "/redis-master/redis.conf" #指的是redis容器内部的位置(redis启动加载这配置文件)
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config #这里对应pod的mountPath下的name,然后这些下面就是对我们配置集的配置
configMap:
name: redis-conf
items:
- key: redis.conf#这里对应我们上面做的配置集(redis-conf)的key:默认是文件名(redis.conf)
path: redis.conf #这里对应我们上面做的配置集 value:配置文件的内容,然后他会映射到我们这个yaml文件中的 "/redis-master/redis.conf" 这里
以上对pod的yaml文件解读如下图:
接下来我们就开始应用启动这个pod:kubectl apply -f redis.yaml
创建成功:
使用k8s做出来的配置集另一个优点就是我们在外部修改配置集的内容,我们pod里面也会变化;接下来我们修改这个配置集:kubectl edit cm redis-conf
,下图是进入配置集的内容:
接着我们看看pod里的redis配置文件的内容:内容是变化了,但是,接着看后面。。。。
3、检查默认配置
如果在linux服务器的话就先执行kubectl exec -it redis -- redis-cli
,但是在可视化操作那就直接进入pod然后redis-cli
,然后输入
127.0.0.1:6379> CONFIG GET appendonly
127.0.0.1:6379> CONFIG GET requirepass
为什么我们requirepass没有‘yes’呢?
原因:我们的Pod部署的中间件自己本身没有热更新能力
因此,检查指定文件内容已经更新,修改了CM。Pod里面的配置文件会跟着变,这里是redis自己的问题。
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。
kubectl create secret docker-registry zhanglong-docker \
--docker-username=zlxwl \
--docker-password=***** \
--docker-[email protected]
##命令格式zlxwl
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
然后在此处可以下载私人的
apiVersion: v1
kind: Pod
metadata:
name: private-nginx
spec:
containers:
- name: private-nginx
image: leifengyang/guignginx:v1.0 #私有镜像名称
imagePullSecrets:
- name: leifengyang-docker #这里用上面secret创建的名称