一、配置管理

1.1 ConfigMap的创建和使用

使用 kubectl create configmap -h 查看示例,构建 configmap 对象

kubectl create cm  -h  

#test是文件夹,使用文件夹创建
kubectl create cm test-dir-config --from-file=test/


#spring-boot-test-yaml是文件
kubectl create cm spring-boot-test-yaml --from-file=./application.yaml


#给配置文件的名字修改为app.yml
kubectl create cm spring-boot-alis-test-yaml --from-file=app.yml=./application.yaml


kubectl create cm test-key-value-config --from-literal=username=root  --from-literal=passwordd=1232456
创建configmap
kubectl create cm test-env-config  --from-literal=JAVA_OPTS_TEST='-Xms512m -Xmx=512m' --from-literal=APPNAME=springboot-env-test


创建pod之前创建configmap
apiVersion: v1
kind: Pod
metadata: 
  name: test-env-cm-pod
spec:
  containers:
    - name: env-test
      image: alpine
      command: ["/bin/sh","-c","env;sleep 3600"]
      imagePullPolicy: IfNotPresent
      env:
      - name: JAVA_VM_OPTS
        valueFrom:
          configMapKeyRef:
            name: test-env-config #configMap的名字
            key: JAVA_OPTS_TEST #表示从name的configMap中获取名字为key的value 将value赋值给本地环境变量JAVA_VM_OPTS
      - name: APP
        valueFrom:
          configMapKeyRef:
            name: test-env-config
            key: APPNAME
  restartPolicy: Never

 指定configmap中的db.properties

apiVersion: v1
kind: Pod
metadata: 
  name: test-config-cm-pod
spec:
  containers:
    - name: config-test
      image: alpine
      command: ["/bin/sh","-c","sleep 3600"]
      imagePullPolicy: IfNotPresent
      env:
      - name: JAVA_VM_OPTS
        valueFrom:
          configMapKeyRef:
            name: test-env-config #configMap的名字
            key: JAVA_OPTS_TEST #表示从name的configMap中获取名字为key的value 将value赋值给本地环境变量JAVA_VM_OPTS
      - name: APP
        valueFrom:
          configMapKeyRef:
            name: test-env-config
            key: APPNAME
      volumeMounts: #加载数据卷
      - name: db-config #表示加载volumes属性中哪个数据卷
        mountPath: "/usr/local/mysql/conf" #表示想要将数据卷中的文件加载到哪个目录下
        readOnly: true  #是否只读      
  volumes:  #数据卷挂载,configMap、secret
    - name: db-config
      configMap:  #数据卷类型为configMap
        name: test-dir-config #configMap的名字
        items: #对configMap中的key 进行映射 如果不指定 默认会将configMap中的所有key 全部转换为一个个同名的文件
        - key: "db.properties"  #configMap中的 key
          path: "db.properties" #将该key的值 转换为文件
  restartPolicy: Never

1.2 加密数据配置 Secret

使用提示:kubectl create secret -h

kubectl create secret  generic orig-secret --from-literal=username=admin --from-literal=password="123456"



create secret docker-registry  habbor-secret --docker-username=admin --docker-password=123456 --docker-email=java_ht@163.com

k8s主机路径创建的pv挂载后容器内创建的目录在本地没有 k8s存储挂载权限_Pod

1.3 subPath的使用

使用 ConfigMap 或 Secret 挂载到目录的时候,会将容器中源目录给覆盖掉。此时我们可能只想覆盖目录中的某一个文件。但是这样的操作会覆盖整个文件,因此需要使用到 SubPath

配置方式:定义 volumes 时需要增加 items 属性,配置 key 和 path,且 path 的值不能从 / 开始
在容器内的 volumeMounts 中增加 subPath 属性,该值与 volumes 中 items.path 的值相同


containers:
  ......
  volumeMounts:
  - mountPath: /etc/nginx/nginx.conf # 挂载到哪里
    name: config-volume # 使用哪个 configmap 或 secret
    subPath: etc/nginx/nginx.conf # 与 volumes.[0].items.path 相同
volumes:
- configMap:
  name: nginx-conf # configMap 名字
  items: # subPath 配置
    key: nginx.conf # configMap 中的文件名
    path: etc/nginx/nginx.conf # subPath 路径

1.4 配置的热更新

我们通常会将项目的配置文件作为 configmap 然后挂载到 pod。那么如果更新 configmap 中的配置,会不会更新到 pod 中呢?

这得分成几种情况:
默认方式:会更新,更新周期是更新时间 + 缓存时间
subPath:不会更新
变量形式:如果 pod 中的一个变量是从 configmap 或 secret 中得到,同样也是不会更新的

对于 subPath 的方式,我们可以取消 subPath 的使用,将配置文件挂载到一个不存在的目录
避免目录的覆盖,然后再利用软连接的形式,将该文件链接到目标位置

但是如果目标位置原本就有文件,可能无法创建软链接
此时可以基于前面讲过的 postStart 操作执行删除命令,将默认的删除即可

两种方式更新:
1. 通过 edit 命令直接修改 configmap


2.前半部分会生成一个yaml文件 后半部分使用生成的文件去替换
kubectl create cm test-cm-dir --from-file=./test/  --dry-run=client -o yaml  | kubectl  replace -f-

1.5 不可变的 Secret 和 ConfigMap

对于一些敏感服务的配置文件,在线上有时是不允许修改的,此时在配置 configmap 时可以设置 immutable: true 来禁止修改

二、持久化存储

2.1 Volumes

2.1.1 HostPath

HostPath: 将节点上的文件或目录挂载到 Pod 上,此时该目录会变成持久化存储目录,即使 Pod 被删除后重启,也可以重新加载到该目录,该目录下的文件不会丢失。注意:不能跨机器

HostPath

apiVersion: v1
kind: Pod
metadata:
  name: test-volume-pd
spec:
  containers:
  - image: nginx
    name: nginx-volume
    volumeMounts:
    - mountPath: /test-pd # 挂载到容器的哪个目录
      name: test-volume # 挂载哪个 volume
  volumes:
  - name: test-volume
    hostPath: #与主机共享目录,加载主机中的指定目录到容器中
      path: /data # 节点中的目录
      type: DirectoryOrCreate # 检查类型,在挂载前对挂载目录做什么检查操作,有多种选项,默认为空字符串,不做任何检查



类型:
空字符串:默认类型,不做任何检查

DirectoryOrCreate:如果给定的 path 不存在,就创建一个 755 的空目录
Directory:这个目录必须存在
FileOrCreate:如果给定的文件不存在,则创建一个空文件,权限为 644
File:这个文件必须存在
Socket:UNIX 套接字,必须存在
CharDevice:字符设备,必须存在
BlockDevice:块设备,必须存在

2.1.2 EmptyDir

EmptyDir:   EmptyDir 主要用于一个 Pod 中不同的 Container 共享数据使用的
由于只是在 Pod 内部使用,因此与其他 volume 比较大的区别是
当 Pod 如果被删除了,那么 emptyDir 也会被删除。

存储介质可以是任意类型,如 SSD、磁盘或网络存储。
可以将 emptyDir.medium 设置为 Memory 让 k8s 使用 tmpfs(内存支持文件系统)
速度比较快,但是重启 tmpfs 节点时,数据会被清除,且设置的大小会计入到 Container 的内存限制中。

k8s主机路径创建的pv挂载后容器内创建的目录在本地没有 k8s存储挂载权限_kubernetes_02

apiVersion: v1
kind: Pod
metadata:
  name: empty-dir-pd
spec:
  containers:
  - image: alpine
    name: nginx-emptydir1
    command: ["/bin/sh","-c","sleep 3600;"]
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - image: alpine
    name: nginx-emptydir2
    command: ["/bin/sh","-c","sleep 3600;"]
    volumeMounts:
    - mountPath: /opt
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}


两个container共享一个目录 说白了就是容器间数据共享  但是pod删除了 这个文件也会被删除

 2.2 NFS 挂载

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

# 安装 nfs
yum install nfs-utils -y

# 启动 nfs
systemctl start nfs-server

# 查看 nfs 版本
cat /proc/fs/nfsd/versions

# 创建共享目录
mkdir -p /data/nfs
cd /data/nfs
mkdir rw
mkdir ro

# 设置共享目录 export
vim /etc/exports
/data/nfs/rw 192.168.20.11/24(rw,sync,no_subtree_check,no_root_squash)
/data/nfs/ro 192.168.20.11/24(ro,sync,no_subtree_check,no_root_squash)

# 重新加载
exportfs -f
systemctl reload nfs-server

# 到其他测试节点安装 nfs-utils 并加载测试
mkdir -p /mnt/nfs/rw
mount -t nfs 192.168.20.11:/data/nfs/rw /mnt/nfs/rw
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: test-container
    volumeMounts:
    - mountPath: /my-nfs-data
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: my-nfs-server.example.com # 网络存储服务地址
      path: /my-nfs-volume # 网络存储路径
      readOnly: true # 是否只读

2.3 PV 与 PVC

2.3.1 生命周期

2.3.1.2 静态构建
集群管理员创建若干 PV 卷。这些卷对象带有真实存储的细节信息, 并且对集群用户可用(可见)。PV 卷对象存在于 Kubernetes API 中,可供用户消费(使用)。
2.3.1.3 动态构建
如果集群中已经有的 PV 无法满足 PVC 的需求,那么集群会根据 PVC 自动构建一个 PV,该操作是通过 StorageClass 实现的。



想要实现这个操作,前提是 PVC 必须设置 StorageClass,否则会无法动态构建该 PV,可以通过启用 DefaultStorageClass 来实现 PV 的构建。
2.3.1.4 绑定
当用户创建一个 PVC 对象后,主节点会监测新的 PVC 对象,并且寻找与之匹配的 PV 卷,找到 PV 卷后将二者绑定在一起。

如果找不到对应的 PV,则需要看 PVC 是否设置 StorageClass 来决定是否动态创建 PV,若没有配置,PVC 就会一致处于未绑定状态,直到有与之匹配的 PV 后才会申领绑定关系。
2.3.1.5 使用
Pod 将 PVC 当作存储卷来使用,集群会通过 PVC 找到绑定的 PV,并为 Pod 挂载该卷。

Pod 一旦使用 PVC 绑定 PV 后,为了保护数据,避免数据丢失问题,PV 对象会受到保护,在系统中无法被删除。
2.3.1.6 回收策略
当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除, 从而允许该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群, 当其被从申领中释放时如何处理该数据卷。 目前,数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)。




保留(Retain)

回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"。 由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:
删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在。
根据情况,手动清除所关联的存储资产上的数据。
手动删除所关联的存储资产。
如果你希望重用该存储资产,可以基于存储资产的定义创建新的 PersistentVolume 卷对象。



删除(Delete)

对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。 动态制备的卷会继承其 StorageClass 中设置的回收策略, 该策略默认为 Delete。管理员需要根据用户的期望来配置 StorageClass; 否则 PV 卷被创建之后必须要被编辑或者修补。


回收(Recycle)

警告: 回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备。

如果下层的卷插件支持,回收策略 Recycle 会在卷上执行一些基本的擦除 (rm -rf /thevolume/*)操作,之后允许该卷用于新的 PVC 申领。

2.3.2  PV

2.3.2.1 状态
Available:空闲,未被绑定

Bound:已经被 PVC 绑定

Released:PVC 被删除,资源已回收,但是 PV 未被重新使用

Failed:自动回收失败
2.3.2.2 配置文件
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 5Gi # pv 的容量
  volumeMode: Filesystem # 存储类型为文件系统
  accessModes: # 访问模式:ReadWriteOnce、ReadWriteMany、ReadOnlyMany
    - ReadWriteOnce # 可被单节点独写
  persistentVolumeReclaimPolicy: Recycle # 回收策略
  storageClassName: slow # 创建 PV 的存储类名,需要与 pvc 的相同
  mountOptions: # 加载配置
    - hard
    - nfsvers=4.1
  nfs: # 连接到 nfs
    path: /data/nfs/rw/test-pv # 存储路径
    server: 192.168.20.11 # nfs 服务地址

2.3.3 PVC

2.3.3.1 Pod 绑定 PVC
在 pod 的挂载容器配置中,增加 pvc 挂载
containers:
  ......
  volumeMounts:
    - mountPath: /tmp/pvc
      name: nfs-pvc-test
volumes:
  - name: nfs-pvc-test
    persistentVolumeClaim:
      claimName: nfs-pvc # pvc 的名称
2.3.3.2 配置文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteOnce # 权限需要与对应的 pv 相同
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi # 资源可以小于 pv 的,但是不能大于,如果大于就会匹配不到 pv
  storageClassName: slow # 名字需要与对应的 pv 相同
#  selector: # 使用选择器选择对应的 pv
#    matchLabels:
#      release: "stable"
#    matchExpressions:
#      - {key: environment, operator: In, values: [dev]}

2.3.4 StorageClass

k8s 中提供了一套自动创建 PV 的机制,就是基于 StorageClass 进行的,通过 StorageClass 可以实现仅仅配置 PVC,然后交由 StorageClass 根据 PVC 的需求动态创建 PV。