k8s 存储抽象
- 在docker中, 为了数据安全, 会将容器的数据挂载到宿主机的磁盘上
- 问题: 当集群中有的容器挂掉之后, 集群在其他主机上重新拉起的容器不能访问上一台宿主机磁盘上的数据.
- 在k8s集群中, 会将存储层抽象出来, 所有的pod数据全部挂载到存储层, k8s自动管理存储层
- 存储层技术: NFS(网络存储),Glusterfs, CephFS
架构图
NFS网络存储系统会在某一台节点上(NFS的主节点)创建一个
/nfs/data
数据目录,在其他节点(NFS从节点)上创建/bak/bada
, 任意一个节点对文件修改都会在所有节点上同步, 实现数据一致
# 安装存储系统
存储层技术: NFS(网络存储),Glusterfs, CephFS, 这里使用NFS
所有节点 安装nfs
yum install -y nfs-utils
1主节点
#nfs主节点 echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports mkdir -p /nfs/data systemctl enable rpcbind --now systemctl enable nfs-server --now #配置生效 exportfs -r
1
2
3
4
5
6
7
8从节点
showmount -e 10.120.11.35 #执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount mkdir -p /nfs/data mount -t nfs 10.120.11.35:/nfs/data /nfs/data # 写入一个测试文件 echo "hello nfs server" > /nfs/data/test.txt
1
2
3
4
5
6
7
8
# k8s原生方式数据挂载
- 问题:
- 在pod中修改了文件, nfs数据卷中的数据不会更新, 反之也是如此
- 需要手动创建nfs数据卷文件夹
- 推荐使用PV|VC
apiVersion: apps/v1
kind: 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: # pod数据卷
- name: html
mountPath: /usr/share/nginx/html
volumes: # nfs 数据卷
- name: html
nfs:
server: 10.120.11.35
path: /nfs/data/nginx-pv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# PV&PVC
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置 场地
PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格, 场地申请书
PV&PVC配合使用: pod中修改了数据卷中的数据, pv池中的数据也会更新
PV 可以静态供应也可以动态供应:
- 静态供应: 一次性分配空间
- 动态供应: 动态分配空间
PV&PVC挂载目录, ConfigMap挂载配置文件
# a. 创建PV池
创建数据卷(静态供应)
#nfs主节点 mkdir -p /nfs/data/01 mkdir -p /nfs/data/02 mkdir -p /nfs/data/03
1
2
3
4创建PV
apiVersion: v1 kind: PersistentVolume metadata: name: pv01-10m spec: capacity: storage: 10M accessModes: - ReadWriteMany storageClassName: nfs # 存储名称,分组, 可以随便写, 上下要统一 nfs: path: /nfs/data/01 server: 10.120.11.35 --- apiVersion: v1 kind: PersistentVolume metadata: name: pv02-1gi spec: capacity: storage: 1Gi accessModes: - ReadWriteMany storageClassName: nfs nfs: path: /nfs/data/02 server: 10.120.11.35 --- apiVersion: v1 kind: PersistentVolume metadata: name: pv03-3gi spec: capacity: storage: 3Gi accessModes: - ReadWriteMany storageClassName: nfs nfs: path: /nfs/data/03 server: 10.120.11.35
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# b. PVC创建与绑定
创建PVC
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nginx-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 200Mi # 申请200M空间, hu storageClassName: nfs # 指定分组, pv存储名称
1
2
3
4
5
6
7
8
9
10
11创建Pod绑定PVC
apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx-deploy-pvc name: nginx-deploy-pvc spec: replicas: 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申请书名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# ConfigMap
- PV&PVC挂载目录, ConfigMap挂载配置文件
- 抽取应用配置,并且可以自动更新
下面以redis示例, 使用ConfigMap
创建redis.conf
appendonly yes
1把redis.conf 配置文件创建为配置集
# 从conf文件创建配置,redis 保存到k8s的etcd; kubectl create cm redis-conf --from-file=redis.conf
1
2# yaml创建configmap apiVersion: v1 data: #data是所有真正的数据,key:默认是文件名 value:配置文件的内容 redis.conf: | appendonly yes kind: ConfigMap metadata: name: redis-conf namespace: default
1
2
3
4
5
6
7
8
9创建pod并指定ConfigMap
apiVersion: v1 kind: Pod metadata: name: redis spec: containers: - name: redis image: redis command: - redis-server - "/redis-master/redis.conf" # 指的是redis容器内部的位置 ports: - containerPort: 6379 volumeMounts: - mountPath: /data # configmap 挂载路径 name: data - mountPath: /redis-master # redis pod内部路径 name: config volumes: - name: data emptyDir: {} # k8s会自动分配目录(configmap 挂载路径) - name: config configMap: name: redis-conf # 名称为 redis-conf 的 configmap items: # 名称为 redis-conf 的 configmap 下的所有配置集 - key: redis.conf # 获取名称为 redis-conf 的 configmap 下key为redis.conf的value path: redis.conf # redis pod 内部文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27检查默认配置
# kubectl get configmap redis-conf -o yaml apiVersion: v1 data: redis.conf: | appendonly yes kind: ConfigMap
1
2
3
4
5
6修改configmap, redis pod中的配置文件也会自动更新
kubectl edit configmap redis-config
apiVersion: v1 kind: ConfigMap metadata: name: example-redis-config data: redis-config: | maxmemory 2mb maxmemory-policy allkeys-lru
1
2
3
4
5
6
7
8检查配置是否更新
kubectl exec -it redis -- redis-cli 127.0.0.1:6379> CONFIG GET maxmemory 127.0.0.1:6379> CONFIG GET maxmemory-policy
1
2
3
4
修改了CM。Pod里面的配置文件会跟着变, 但是redis 中的配置值未更改,因为需要重新启动 Pod 才能从关联的 ConfigMap 中获取更新的值。
原因:我们的Pod部署的中间件自己本身没有热更新能力
# Secret
- Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod (opens new window)的定义或者 容器镜像 (opens new window) 中来说更加安全和灵活。
- docker仓库有些私有镜像, 需要登录或者提供镜像秘钥, pod在拉取镜像时指定秘钥信息即可
kubectl create secret docker-registry leifengyang-docker \
--docker-username=leifengyang \
--docker-password=Lfy123456 \
--docker-email=534096094@qq.com
## 命令格式
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: private-nginx
spec:
containers:
- name: private-nginx
image: leifengyang/guignginx:v1.0
imagePullSecrets:
- name: leifengyang-docker # 指定秘钥
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
上次更新: 2023/06/02, 19:38:12