baby sword‘s blog baby sword‘s blog
首页
  • java基础
  • java进阶
大数据
  • mysql

    • mysql索引
    • mysql日志
  • redis

    • 单机下的redis
    • 集群下的redis
  • Spring
  • springboot
  • RPC
  • netty
  • mybatis
  • maven
  • 消息队列
  • kafka
  • zookeeper
  • rocketmq
  • 七大设计原则
  • 创建型模式
  • 结构型模式
  • 行为型模式
  • SpringCloud

    • eureka
  • SpringCloud Alibaba

    • nacos
  • 计算机网络
  • 操作系统
  • 算法
  • 个人项目
  • 个人面试面经
  • 八股记忆
  • 工作积累
  • 逻辑题
  • 面试

    • 百度后端实习二面
GitHub (opens new window)

zhengjian

不敢承担失去的风险,是不可能抓住梦想的
首页
  • java基础
  • java进阶
大数据
  • mysql

    • mysql索引
    • mysql日志
  • redis

    • 单机下的redis
    • 集群下的redis
  • Spring
  • springboot
  • RPC
  • netty
  • mybatis
  • maven
  • 消息队列
  • kafka
  • zookeeper
  • rocketmq
  • 七大设计原则
  • 创建型模式
  • 结构型模式
  • 行为型模式
  • SpringCloud

    • eureka
  • SpringCloud Alibaba

    • nacos
  • 计算机网络
  • 操作系统
  • 算法
  • 个人项目
  • 个人面试面经
  • 八股记忆
  • 工作积累
  • 逻辑题
  • 面试

    • 百度后端实习二面
GitHub (opens new window)
  • 华仔聊技术

  • 业务设计

  • 场景设计

  • 运维

  • 安全

  • 面试

  • mac相关工具推荐

  • 开发工具

  • 人工智能

  • 推荐

  • 阅读

  • 工具

  • 计划

  • 产品

  • 云原生

  • go

  • QVM

    • OpenStack

    • K8S

      • 扣丁狼k8s(一)
      • 扣丁狼k8s(二)
      • k8s中的网络(一)
      • k8s中的网络(二)
      • 扣丁狼k8s(三)存储与配置
        • 配置管理
          • ConfigMap
          • 创建
          • 使用
          • secret
        • subPath
          • 配置的热更新
          • 不可变的Secret和condigmap
        • 容器中的容器卷技术
        • NFS挂载
          • 不同的机器之间使用nfs
          • 在容器中使用nfs
        • PV和PVC
          • 生命周期
          • PV
          • PVC
          • storageClass
      • k8s高级调度
      • k8s分享
      • 常用命令
      • k8s集群搭建
      • 搭建过程bug记录
      • 什么是k8s的CRD
      • OpenStack Kubernetes kubevirt
      • k8s-go-client
      • kubeconfig详解
    • kubevirt

  • 软件设计师

  • 极客时间

  • 单元测试

  • 其他
  • QVM
  • K8S
xugaoyi
2023-09-03
目录

扣丁狼k8s(三)存储与配置

image-20230904093356552

# 配置管理

# ConfigMap

# 创建

例如我们先创建一个配置文件db.properties

username=root
password=123456
1
2

Redis.properties

port=6379
host=localhost
1
2

将上面的两个文件放到同一个test/中

root@openstackTest-1:~/yamlPackage/configMap/test# ls
mysql.properties  redis.properties
1
2
  • kubectl create configmap <configname> --from-file=<dirpath> 基于文件夹进行创建
root@openstackTest-1:~/yamlPackage/configMap# kubectl create cm mytestconfig --from-file=test/
configmap/mytestconfig created
root@openstackTest-1:~/yamlPackage/configMap# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      37h
mytestconfig       2      5s
1
2
3
4
5
6

查看详细信息

root@openstackTest-1:~/yamlPackage/configMap# kubectl describe cm mytestconfig
Name:         mytestconfig
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
redis.properties:
----
host=127.0.0.1
port=6379

mysql.properties:
----
username=root
password=123456


BinaryData
====

Events:  <none>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

从上面可以看到我们具体设置的信息,通过文件夹的方式,将某个文件夹下面所有的文件的写进了配置

  • kubectl create cm <cnname> --from-file=key1=filepath --from-file=key2=filepath基于文件进行创建【key如果不指定,默认使用文件的名字】

我们创建一个配置文件application.yaml

spring:
	application:
	  name: test
server:
	port: 8080
1
2
3
4
5
root@openstackTest-1:~/yamlPackage/configMap# kubectl create cm spring-yaml --from-file=application.yaml=test/spring.yaml
configmap/spring-yaml created
root@openstackTest-1:~/yamlPackage/configMap# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      37h
mytestconfig       2      12m
spring-yaml        1      6s
root@openstackTest-1:~/yamlPackage/configMap# kubectl describe cm spring-yaml
Name:         spring-yaml
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
application.yaml:
----
spring:
  application:
    name: test
server:
  port: 8080


BinaryData
====

Events:  <none>
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
  • kubectl create cm <cmname> --from-literal=key1=config1 --from-literal=key2=config2

当参数比较少时,可以用这个方法

root@openstackTest-1:~/k8s1# kubectl create cm keyvalueconfig --from-literal=key1=value1 --from-literal=key2=value2
configmap/keyvalueconfig created
root@openstackTest-1:~/k8s1# kubectl get cm keyvalueconfig
NAME             DATA   AGE
keyvalueconfig   2      14s
root@openstackTest-1:~/k8s1# kubectl describe cm keyvalueconfig
Name:         keyvalueconfig
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
key2:
----
value2
key1:
----
value1

BinaryData
====

Events:  <none>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 使用

首先我们先创建一个我们想要使用的配置

kubectl create cm test-env-config --from-literal=JAVA_OPTS_TEST='-Xms512m -Xmx512m' --from-literal=APP_NAEM=springboot-test
1
root@openstackTest-1:~/k8s1# kubectl create cm test-env-config --from-literal=JAVA_OPTS_TEST='-Xms512m -Xmx512m' --from-literal=APP_NAEM=springboot-test
configmap/test-env-config created
root@openstackTest-1:~/k8s1# kubectl describe cm test-env-config
Name:         test-env-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
APP_NAEM:
----
springboot-test
JAVA_OPTS_TEST:
----
-Xms512m -Xmx512m

BinaryData
====

Events:  <none>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

实现在容器中打印出对应的配置

  • 创建我们对应的一个容器
apiVersion: v1
kind: Pod
metadata:
  name: test-env-pod
spec:
  restartPolicy: Never
  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
            key: JAVA_OPTS_TEST
      - name: APP
        valueFrom:
          configMapKeyRef:
            name: test-env-config
            key: APP_NAME
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

我们使用命令查看容器的日志:

root@openstackTest-1 ~/y/pod# kubectl logs -f test-env-pod
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=test-env-pod
SHLVL=1
HOME=/root
NGINX_SERVICE_PORT_80_TCP=tcp://10.98.194.204:80
JAVA_VM_OPTS=-Xms512m -Xmx512m
APP=springboot-test
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_SERVICE_SERVICE_HOST=10.98.194.204
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
NGINX_SERVICE_SERVICE_PORT=80
NGINX_SERVICE_PORT=tcp://10.98.194.204:80
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
NGINX_SERVICE_PORT_80_TCP_ADDR=10.98.194.204
NGINX_SERVICE_PORT_80_TCP_PORT=80
NGINX_SERVICE_PORT_80_TCP_PROTO=tcp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

可以看到这个容器确实拿到了我们的对应的数据了。

另一种配置的方式,通过挂载的方式将某个配置文件加载到容器中

apiVersion: v1
kind: Pod
metadata:
  name: test-env-pod
spec:
  restartPolicy: Never
  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
            key: JAVA_OPTS_TEST
      - name: APP
        valueFrom:
          configMapKeyRef:
            name: test-env-config
            key: APP_NAME
			volumeMounts:
			- name: db-config
			  mountPath: "/usr/local/mysql/conf"
			  readOnly: true
	volumes: 
	  - name: db-config
	    configMap:
	      name: test-dir-config
	      items:
	      - key: "db.properties"
	        path: "db.properties"
	restartPolicy: Never
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
  1. metadata: 这是用于定义 Pod 元数据的部分。

    • name: test-env-pod: 这里定义了 Pod 的名称。
  2. spec: 这是用于定义 Pod 规范的部分。

    • restartPolicy: Never: 这表示 Pod 的重启策略是 "Never",即不会自动重启。一旦容器退出,它将永远保持在非运行状态。

    • containers: 这是一个容器列表,这里定义了一个容器。

      • name: env-test: 容器的名称是 "env-test"。
      • image: alpine: 使用 Alpine Linux 镜像作为容器的基础镜像。
      • command: 定义容器启动时执行的命令。在这里,容器将打印环境变量 (env) 的内容,并然后休眠 3600 秒。
      • imagePullPolicy: IfNotPresent: 这表示如果本地没有这个容器镜像,才从远程仓库拉取,否则使用本地镜像。
    • env: 这里定义了容器的环境变量。

      • name: JAVA_VM_OPTS: 环境变量的名称是 "JAVA_VM_OPTS"。

      • valueFrom
        
        1

        : 这表示环境变量的值来自于其他资源。

        • configMapKeyRef
          
          1

          : 环境变量的值是从 ConfigMap 中获取的。

          • name: test-env-config: 这是 ConfigMap 的名称。
          • key: JAVA_OPTS_TEST: 这是 ConfigMap 中的键,它的值将赋给 "JAVA_VM_OPTS" 变量。
      • name: APP: 另一个环境变量的名称是 "APP"。

      • valueFrom
        
        1

        : 同样,这个环境变量的值也来自于 ConfigMap。

        • configMapKeyRef
          
          1

          : 它引用了同一个 ConfigMap,但使用了不同的键。

          • name: test-env-config: 这是相同的 ConfigMap。
          • key: APP_NAME: 这是不同的键,其值将赋给 "APP" 变量。
    • volumes: 这是一个用于定义卷的部分,这里定义了一个卷。

      • name: db-config: 卷的名称是 "db-config"。

      • configMap
        
        1

        : 这表示这个卷是一个 ConfigMap 类型的卷。

        • name: test-dir-config: 这是 ConfigMap 的名称,它将被挂载到容器中。

        • items
          
          1

          : 这里定义了 ConfigMap 中的哪些键值对将被挂载到容器中。

          • key: "db.properties": 这是 ConfigMap 中的键。
          • path: "db.properties": 这是挂载到容器中的路径。
    • 最后的 restartPolicy: Never 与之前的相同,表示 Pod 的重启策略是 "Never",容器退出后不会自动重启。

# secret

主要是可以配置一些加密的信息,不过这个加密是base64,加密性不高

创建方式和secret差不多

例如:

kubectl create secret generic orig-secret --from-literal=username=admin --from-literal=password=ds@!3-/

上面创建语句没有问题,但是ds@!3-/这种有特殊字符的数据进行创建,可能会出现一些特殊的问题,导致我们保存的数据不是我们实际想要的数据

更多用在docker私有仓库等。

# subPath

subPath 是 Kubernetes 中用于挂载卷内部文件或目录到容器的特定路径的设置。它通常在 Pod 的 volumes 和容器的 volumeMounts 中使用。

假设你有一个卷(例如 ConfigMap 或者 Secret),其中包含多个文件或目录,而你只想将其中的一部分挂载到容器内的特定路径,你可以使用 subPath 来实现这一点。

下面是一个示例:

yamlCopy code
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
    volumeMounts:
    - name: my-volume
      mountPath: /path/in/container
      subPath: my-file.txt
  volumes:
  - name: my-volume
    configMap:
      name: my-configmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在这个示例中,我们有一个 Pod,其中包含一个容器(my-container)和一个卷(my-volume),卷使用了 ConfigMap(my-configmap)。我们希望将 ConfigMap 中的 my-file.txt 文件挂载到容器中的 /path/in/container 路径上。这就是通过在容器的 volumeMounts 中使用 subPath 来实现的。这将只挂载 ConfigMap 中的 my-file.txt 文件到指定路径,而不是整个 ConfigMap。

这在某些情况下非常有用,因为你可以选择性地将卷的特定部分挂载到容器中,而不必将整个卷都挂载进来。

image-20230904143721193

意思就是将我们configMap中的的nginx.conf个文件挂在到容器中/etc/nginx/的目录下。但是这里有一个关键点,挂在时,如果容器中对应的目录存在则覆盖,不存在则新建,这样会导致我们所有的nginx的该目录下原本的文件消失,我们是不想要这样的。

这个时候,我们就要使用到subpath这个概念。

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

image-20230904145206474

# 配置的热更新

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

默认方式:会更新,更新周期是更新时间+缓存时间

subpath: 不会更新

变量形式: 如果pod中的一个变量从condigmap或者secret中得到,同样也不会更新的

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

image-20230904151614412

更新方式:

  • 通过edit命令直接修改configmap
  • 通过replace替换

image-20230904152012060

# 不可变的Secret和condigmap

一些线上的配置文件,我们并不想改变,更具有稳定性

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

image-20230904152838042

# 容器中的容器卷技术

  1. 空白目录(EmptyDir)卷示例:

    主要目的不是为了持久化,而是为了管理一个pod上面有多个容器的情况

    image-20230904154439331

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-container
        image: nginx:1.19
        volumeMounts:
        - name: my-volume
          mountPath: /data
      volumes:
      - name: my-volume
        emptyDir: {}
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  2. 主机路径(HostPath)卷示例:

    将节点上的文件或目录挂在到pod上,此时该目录会变成持久化存储目录,即使pod被删除后重启,也可以重新加载到该目录,该目录下的文件不会丢失

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-container
        image: nginx:1.19
        volumeMounts:
        - name: my-volume
          mountPath: /data
      volumes:
      - name: my-volume
        hostPath:
          path: /path/on/host
          type: Directory
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    image-20230904153608701

需要注意的是,我们创建了一个挂载的容器后,我们首先需要知道这个容器挂在到了哪个node节点,对应的node节点上的主机目录才是对应的挂在目录

image-20230904155052921

如何进入到一个pod中的指定的一个容器:

kubectl exec -it empty-dir-pod -c nginx-emptydir1 -- sh

可以进入到两个容器中,在对应的目录查看文件的共享

没有持久化的能力,pod被删除,对应的数据最终也会被删除

  1. 持久卷声明(PersistentVolumeClaim)示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-container
        image: nginx:1.19
        volumeMounts:
        - name: my-volume
          mountPath: /data
      volumes:
      - name: my-volume
        persistentVolumeClaim:
          claimName: my-pvc
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  2. 配置映射(ConfigMap)卷示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-container
        image: nginx:1.19
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
      - name: config-volume
        configMap:
          name: my-config
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  3. 密钥和证书卷示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-container
        image: nginx:1.19
        volumeMounts:
        - name: tls-volume
          mountPath: /etc/tls
      volumes:
      - name: tls-volume
        secret:
          secretName: my-tls-secret
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

这些示例演示了不同类型的容器卷配置,包括空白目录卷、主机路径卷、持久卷声明、配置映射卷以及密钥和证书卷。你可以根据需要选择适当的卷类型并根据你的应用程序要求进行配置。

# NFS挂载

# 不同的机器之间使用nfs

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

因为会存在网络通信,所以不建议存储在频繁读写的情况,例如不适用于mysql。

参考: 安装和原理教程 (opens new window)

下载nfs-server,apt install nfs-server

选定一台机器作为服务器,创建目录/nfs/ro和/nfs/rw

配置文件/etc/exports

/nfs/rw 10.10.10.0/24(rw,sync,no_subtree_check,no_root_squash)
/nfs/ro 10.10.10.0/24(ro,sync,no_subtree_check,no_root_squash)
1
2

注意上面的配置,只有对应网段的的机器才可以挂载到这里

重新加载nfs配置exportfs -f

重启服务systemctl reload nfs-server

可以在ro当中写一个文件,便于等会在客户端查看

在客户端安装好nfs-utils

apt install nfs-common

在客户端创建一个用于挂载的目录:mkdir -p /mnt/nfs/rw/

挂载:mount -t nfs 10.10.10.7:/nfs/rw /mnt/nfs/rw

挂载后查看对应的目录发现有可用的文件

# 在容器中使用nfs

同样是通过volume配置的方式进行运用

image-20230904174456434

apiVersion: v1
kind: pod
metadata:
  name: nfs-test-pod1
spec:
  containers:
  - image: nginx
    name: test-container
    volumeMount:
    - mountPath: /usr/share/nginx/html
      name: test-volume
  volumes:
  - name: test-volume
    nfs: 
      server: 10.10.10.7
      path: /nfs/rw
      readOnly: false
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

curl podip可以看到返回对应的内容

当我们删除掉这两个pod后,nfs服务器上的资源还是存在的

# PV和PVC

image-20230904180137431

为了解决远程存储的不统一

PV就是对其做一个抽象,屏蔽其底层的细节。

PVC用于描写每个pod服务需要多少的数据资源

image-20230904180748017

# 生命周期

构建

  • 静态构建

集群管理员创建若干pv卷,这些卷对象带有真实存储的细节信息,并且对集群用户可见,pv卷存在于k8s api中,可以供用户消费

  • 动态构建

image-20230904181202351

绑定

image-20230904181424050

使用

pod与pvc关联

image-20230904181458505

回收策略

  • Retain
  • delete
  • recycle

# PV

配置文件

image-20230904182042073

pv的状态

available 空闲:未被绑定

bound 已被pvc绑定

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

Failed: 自动回收失败

# PVC

image-20230904183110866

创建后,看pvc就可以看到bound状态

image-20230904183155770

最后我们再来绑定pod

image-20230904183349258

# storageClass

编辑 (opens new window)
上次更新: 2024/02/22, 14:03:19
k8s中的网络(二)
k8s高级调度

← k8s中的网络(二) k8s高级调度→

最近更新
01
spark基础
02-22
02
mysql读写分离和分库分表
02-22
03
数据库迁移
02-22
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式