十二、K8S-配置管理ConfigMap、Secret

目录

一、ConfigMap

1、概念:

2、作用:

3、ConfigMap使用

4、如何将这些configmap对象与 Pod 一起使用。

5、把configMap挂载到容器中充当配置文件

二、Secret

1、创建Secret

 2、如何使用Secret

三、总结:


一、ConfigMap

1、概念:

        是k8s的一种资源对象,可以将配置一key-value的形式传递,用来保存不需要加密的配置信息,使用时,Pod可以将其用作环境变量、命令行参数或者存储卷中的配置文件,如果想保存需要加密的数据,使用Secret

2、作用:

        使用ConfigMap将配置数据和应用程序代码分开

3、ConfigMap使用

        官网示例:k8s-configMap

        创建方式:可以使用kuberctl create configmap 命令基于目录、文件、或者键值对来创建ConfigMap

  1. 基于键值对创建ConfigMap,即命令行指定ConfigMap参数。使用 --from-liternal
  2. 基于指定文件创建,即将一个配置文件创建为一个ConfigMap,使用 --from-file=(file)
  3. 基于指定目录创建,即将一个目录下所有配置文件创建为一个ConfigMap,使用 --from-file=(Directory)
  4. 基于指定写好的ConfigMap资源的yaml文件,使用 kubectl create -f 创建
1、通过目录,创建configMap,先创建目录
[root@k8s-master-1 test]# mkdir -p configmap/configure-pod-container/configmap/将示例文件下载到目录下
wget https://kubernetes.io/examples/configmap/game.properties --no-check-certificate -O /k8s/kubernetes/cfg/test/configmap/configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties --no-check-certificate -O /k8s/kubernetes/cfg/test/configmap/configure-pod-container/configmap/ui.properties#创建ConfigMap
[root@k8s-master-1 configmap]# kubectl create configmap game-config --from-file=/k8s/kubernetes/cfg/test/configmap/configure-pod-container/configmap/
\configmap/game-config created[root@k8s-master-1 configmap]# kubectl get cm
NAME          DATA   AGE
game-config   2      11s可以看到刚才两个文件的内容被写到configmap里,就可以把configmap挂在到容器里使用[root@k8s-master-1 configmap]# kubectl describe cm game-config
Name:         game-config
Namespace:    default
Labels:       <none>
Annotations:  <none>Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNiceEvents:  <none>2、------通过单个文件创建configMap-----[root@k8s-master-1 configmap]# kubectl create cm game-ui-cm --from-file=/k8s/kubernetes/cfg/test/configmap/configure-pod-container/configmap/ui.properties
configmap/game-ui-cm created[root@k8s-master-1 configmap]# kubectl get cm
NAME          DATA   AGE
game-config   2      10m
game-ui-cm    1      12s#创建成功,可以看到configmap里只有ui的配置内容
[root@k8s-master-1 configmap]# kubectl describe cm game-ui-cm  也可以使用[root@k8s-master-1 configmap]# kubectl get cm game-config -oyaml查看
Name:         game-ui-cm
Namespace:    default
Labels:       <none>
Annotations:  <none>Data
====
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice可以修改data部分的键名:--from-file=<我的键名>=<文件路径>,如果不指定名称是按照文件名来命名的。kubectl create cm game-ui-cm --from-file=ui-pro=/k8s/kubernetes/cfg/test/configmap/configure-pod-container/configmap/ui.properties3、----也可以通过env环境变量来创建,使用 --from-env-file 创建 在k8s1.23版本之前使用多指定--from-env-file 创建的话,第二个文件会把第一个文件的env替换调,
1.23版本之后,就会叠加到一起,不在被替换调。再此不做演示可以查看官网示例4、------基于写好的ConfigMao文件创建configmap------# 创建包含 ConfigMapGenerator 的 kustomization.yaml 文件[root@k8s-master-1 configmap]# vim kustomization.yaml
configMapGenerator:
- name: game-config-4labels:game-config: config-4files:- configure-pod-container/configmap/game.properties或者指定一个键名:比如名为  asd-asd=configure-pod-container/configmap/game.properties
使用 kubectl apply -f .  来创建5、------  基于字面创建configmap ------
[root@k8s-master-1 configmap]# vim kustomization.yamlconfigMapGenerator:- name: special-config-2literals:- special.how=very- special.type=charm6、基于键值对创建 :使用--from-literal参数,指定键值对内容,可以有多个
语法:
kubectl create cm cm_name --from-literal=key1=valus1 --from-literal=key2=value2
示例:kubectl create cm cm_name --from-literal=prot=3306 --from-literal=hostname=root7、清理configmap
[root@k8s-master-1 configmap]# kubectl delete configmap game-config-env-file

4、如何将这些configmap对象与 Pod 一起使用。

1、#示例:
#通过命令行方式先创建一个configmap,使用参数:--from-literal
[root@k8s-master-1 configmap]# kubectl create configmap special-config --from-literal=special.how=very
configmap/special-config created2、#创建一个包含多个键值对的 ConfigMap。
apiVersion: v1kind: ConfigMapmetadata:name: special-confignamespace: defaultdata:SPECIAL_LEVEL: verySPECIAL_TYPE: charm------------使用envFrom 将所有 ConfigMap 的数据定义为容器环境变量,ConfigMap 中的键成为 Pod 中的环境变量名称
apiVersion: v1kind: Podmetadata:name: dapi-test-podspec:nodeName: k8s-node-2 #指定到node-2节点containers:- name: test-containerimage: busyboximagePullPolicy: IfNotPresentcommand: [ "/bin/sh", "-c", "env" ]envFrom:- configMapRef:name: special-config #configMap 名称env:   - - - #或者在pod中直接定义环境变量
- - - - name: testvalue: test-value- name: mysqlHostvalue: 10.10.10.10- name: portvalue: "3306"restartPolicy: Never创建完成查看日志就可以看到输出一下环境变量[root@k8s-master-1 configmap]# kubectl logs -f dapi-test-pod
SPECIAL_LEVEL=very
SPECIAL_TYPE=charm
test=test-value
mysqlHost=10.10.10.10
port=3306

5、把configMap挂载到容器中充当配置文件

        在 Pod 规约的 volumes 部分下添加 ConfigMap 名称。 这会将 ConfigMap 数据添加到 volumeMounts.mountPath 所指定的目录 (在本例中为 /etc/config)。 command 部分列出了名称与 ConfigMap 中的键匹配的目录文件。

1、使用上边的configMap2、创建pod env的多种编写方式[root@k8s-master-1 configmap]# vim pod-config-volume.yaml
apiVersion: v1
kind: Pod
metadata:name: dapi-test-pod
spec:nodeName: k8s-node-2containers:- name: test-containerimage: busybox:1.28.4imagePullPolicy: IfNotPresentcommand: [ "sleep", "3600" ]volumeMounts:- name: config-volume #这个是下边自定义的volumes的名字mountPath: /mnt- name: xxx mountPath: /mntenvFrom:- configMapRef:name: special-configenv:#定义环境变量- name: SPECIAL_LEVEL # 请注意这里和 ConfigMap 中的键名是不一样的valueFrom:configMapKeyRef:name: special-config # 这个值来自 ConfigMapkey:  special_level- name: SPECIAL_TYPE # 请注意这里和 ConfigMap 中的键名是不一样的valueFrom:configMapKeyRef:name: special-config # 这个值来自 ConfigMapkey: special_type                                                                                       env:- name: testvalue: test-value- name: mysqlHostvalue: 10.10.10.10- name: portvalue: "3306"restartPolicy: Nevervolumes:- name: config-volume #自定义configMap:name: special-config # 提供你想要挂载的 ConfigMap 的名字#将 ConfigMap 数据添加到卷中的特定路径,在这里,ConfigMap 中键 SPECIAL_LEVEL 的内容将挂载在 config-volume 卷中 /mnt/keys 文件中。items:- key: SPECIAL_LEVELpath: keys
#可以挂载多个- name: config-volume2 #自定义configMap:name: xxx[root@k8s-master-1 configmap]# kubectl apply -f pod-config-volume.yaml 
pod/dapi-test-pod created#创建完成进入容器查看
[root@k8s-master-1 configmap]# kubectl exec -it dapi-test-pod sh
/ # cd mnt/
/mnt # cat SPECIAL_TYPE 
charm/mnt #显示的是SPECIAL_TYPE 的值

二、Secret

        Secret:用于存储和管理一些敏感数据,它把想要访问的加密数据存放到Etcd中,然后用户就可以通过在Pod的容器里挂载Volume的方式或者环境变量的方式访问到这些Secret里保存的信息了。

类型:3种

  • Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱
  • kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息
  • kubernetes.io/service-account-token:用于被serviceaccount引用,serviceaccount创建时kubernetes会默认创建对应的secret。Pod如果使用了serviceaccount,对应的secret会自动挂载到Pod的 /run/secrets/kubernetes.io/serviceaccount 目录中

 Secret 特殊字符处理

特殊字符(例如 $、\、*、= 和 !)因此需要转义。在大多数 Shell 中,对密码进行转义的最简单方式是用单引号(')将其括起来,

例如:password='S!B\*d$zDsb='无需转义 或者使用转义字符\ :password="S!B\\\*d\$zDsb="

1、创建Secret

#创建Secret的几种方式  generic:通用的,一般的加密方式1、使用命令创建 --from-literal
kubectl create secret generic  mysecret1 --from-literal=username=admin --from-literal=password=123456
[root@k8s-master-1 secret]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-6xh94   kubernetes.io/service-account-token   3      41d
mysecret1             Opaque                                2      7s
#查看yaml文件,可以看到已加密
[root@k8s-master-1 secret]# kubectl get secret mysecret1 -oyaml
apiVersion: v1
data:password: MTIzNDU2username: YWRtaW4=2、通过from-file(文件)创建
[root@k8s-master-1 secret]# echo -n 'admin' > ./username.txt
[root@k8s-master-1 secret]# 
[root@k8s-master-1 secret]# echo -n '123456' > ./password.txt
[root@k8s-master-1 secret]# kubectl create secret generic mysecret2 --from-file=username.txt --from-file=password.txt
secret/mysecret2 created
#创建成功  结果同上3、通过--from-env-file创建
创建一个文件,写入信息
[root@master secret]#vim env.txt 
username=admin
password=123456
[root@k8s-master-1 secret]# kubectl create secret generic mysecret3 --from-env-file=env.txt
secret/mysecret3 created
#创建成功,查询结果同上4、通过yaml文件创建4.1把需要保存的数据加密[root@k8s-master-1 secret]# echo admin |base64YWRtaW4K4.2编写secret 的yaml文件。如果你不希望执行 base64 编码转换,可以使用 stringData 字段代替,如果同时写了data和stringData,则stringData的优先级高,data会被忽略
[root@k8s-master-1 secret]# vim mysecret4.yaml apiVersion: v1kind: Secretmetadata:name: mysecret4data:username: YWRtaW4=password: MTIzNDU2
#或者使用stringDatastringData:username: adminpassword: "123456" #注意一定要加引号,不然报错,规范问题

 2、如何使用Secret

1、以volume挂载的方式使用Secret
Secret可以作为数据卷挂载或者作为环境变量暴露给Pod中的容器使用,也可以被系统中的其他资源使用。
在Pod中以文件形式使用secret1、创建一个Secret,多个Pod可以应用一个Secret2、修改Pod的定义,在spec.volumes[]加一个volume,给这个volume起个名字,spec.volumes[].volume.secretName记录的是要引用Secret的名字3、在每个需要使用Secret的容器中添加一项spec.containers[].columeMounts[],指定spec.containers[].volumeMounts[].readOnly=true,spec.containers[].columeMounts[].mountPath要指向一个未被使用的系统路径4、修改镜像或者命令行使系统可以找到上一步指定的路径,此时Secret中data字段的每一个key都是指定路径下的一个文件名创建yaml文件
apiVersion: v1
kind: Pod
metadata:name: secret-test-pod
spec:nodeName: k8s-node-2containers:- name: test-containerimage: busybox:1.28.4imagePullPolicy: IfNotPresentcommand: [ "/bin/sh", "-c", "sleep 3600" ]volumeMounts:- name: secret-test #这个是自定义的volumes的名字mountPath: /mntreadOnly: true #是否只读restartPolicy: Nevervolumes:- name: secret-test #自定义secret:secretName: mysecret2 #要使用的Secret名字[root@k8s-master-1 secret]# kubectl apply -f secret-pod.yaml
创建完成  进入容器,在/mnt下就可以看到两个文件
/mnt # ls
password.txt  username.txt#测试是否为只读
/mnt # echo admin > username.txt 
sh: can't create username.txt: Read-only file system1.1 自定义容器中的目录
volumes:
- name: secret-test #自定义secret:secretName: mysecret2 #要使用的Secret名字items:- key: usernamepath: my-group/my-username   #自定义的容器中的目录- key: passwordpath: my-group/my-password   #自定义的容器中的目录
1.2 如果,现在将secret资源内保存的数据进行更新,那么,使用次数据的应用内,数据是否也会被更新?会实时更新示例:更新mysecret2文件,把密码改成admin然后在进入使用secret的容器secret-test-pod 中,看看密码是否被更新[root@k8s-master-1 secret]# kubectl edit secret mysecret2secret/mysecret2 edited[root@k8s-master-1 secret]# kubectl exec -it secret-test-pod -- sh/mnt # cat password.txt admin/mnt #此时密码已经被更新了

imagePullSecrets:Pod拉去私有镜像仓库时使用的账户密码,里边的账户信息,会传递给kubelet,然后kubelet就可以拉取有密码仓库里面的镜像

[root@k8s-master-1 secret]# kubectl create secret docker-registry docker-secret \
>   --docker-server=hub.docker.com \
>   --docker-username=DOCKER_USER \
>   --docker-password=DOCKER_PASSWORD \
>   --docker-email=DOCKER_EMAIL
secret/docker-secret created
[root@k8s-master-1 secret]# kubectl get secret
NAME                  TYPE                                  DATA   AGEdocker-secret         kubernetes.io/dockerconfigjson        1      8s使用:
在pod中加入imagePullSecrets 和containers是同级
containers:
imagePullSecrets:- name: docker-secret #创建的docker-registry 名字
2、以环境变量的方式创建secret,多个Pod可以引用同一个Secret,修改Pod的定义,定义环境变量并使用env[].valueFrom.secretKeyRef指定secret和相应的KEY
[root@k8s-master-1 secret]# vim env-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: env-secret-pod
spec:nodeName: k8s-node-2containers:- name: test-containerimage: busybox:1.28.4imagePullPolicy: IfNotPresentcommand: [ "/bin/sh", "-c", "sleep 3600" ]env:- name: SECRET_USERNAMEvalueFrom:secretKeyRef:name: mysecret3key: username- name: SECRET_PASSWORDvalueFrom:secretKeyRef:name: mysecret3key: passwordd
创建成功,进入容器查看环境变量
[root@k8s-master-1 secret]# kubectl exec -it env-secret-pod -- sh
/ #echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
123456
此时  修改secret文件的内容,在进入容器查看的时候,发现容器的信息并没有被更新

三、总结:

        如果引用Secret数据的应用,会随着secret资源对象内保存的数据的更新,而实时更新,那么应该使用volumes挂载的方式引用资源,因为环境变量的方式引用不会实时更新数据。

ConfigMap和Secret的区别:

相同点:

  1. key/value的形式
  2. 属于某个特定的namespaces
  3. 可以导出到环境变量
  4. 可以通过目录/文件形式挂载
  5. 通过volume挂载的配置均可热更新

不同点:

  1. Secret 可以被 ServerAccount 关联
  2. Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
  3. Secret 支持 Base64 加密
  4. Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/643896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UDS Flash刷写流程介绍

一、刷写流程介绍 1.1刷写包含以下三个步骤&#xff1a;预编程&#xff0c;编程&#xff0c;后编程 1.2预编程步骤 此步骤是保证能够正常进入编程&#xff08;10 02&#xff09;会话下。 &#xff08;1&#xff09;如果无特殊要求&#xff0c;只保证刷写能够正常进行&#x…

Fluent 技巧:查找并修改隐藏的设置

绝大部分 Fluent 设置可以通过图形界面或者命令行内置的命令按照提示处理。少部分设置因为种种原因被隐藏&#xff0c;需要在命令行中使用 scheme 语句进行处理。例如关闭温度的二阶梯度&#xff0c;需要在命令行中完整输入如下 scheme 语句&#xff08;包括英文括号部分&#…

编译安装Nginx健康检查模块和echo模块

1、编译安装Nginx健康检查模块和echo模块 -rw-r--r-- 1 root root 482 1月 20 09:51 1.sh -rw-------. 1 root root 1060 11月 26 09:12 anaconda-ks.cfg -rw-r--r-- 1 root root 370929 1月 16 18:02 bash.txt drwxrwxr-x 5 root root 174 8月 1 2022 ec…

网站将http升级到https大概要多少费用

随着网络安全意识的不断提升&#xff0c;越来越多的网站正从传统的HTTP协议转向更安全的HTTPS协议。这一转变的核心在于部署SSL&#xff08;Secure Sockets Layer&#xff09;或TLS&#xff08;Transport Layer Security&#xff09;证书&#xff0c;以实现数据加密传输&#x…

【算法专题】动态规划之路径问题

动态规划2.0 动态规划 - - - 路径问题1. 不同路径2. 不同路径Ⅱ3. 珠宝的最高价值4. 下降路径最小和5. 最小路径和6. 地下城游戏 动态规划 - - - 路径问题 1. 不同路径 题目链接 -> Leetcode -62.不同路径 Leetcode -62.不同路径 题目&#xff1a;一个机器人位于一个 m …

论 Solon 开源框架的意义!

Solon 是一个国产的生态级 Java 应用开发框架&#xff08;已发具备全球第二级别的生态&#xff09;。七年时间打磨。14 万行代码。两三百个生态扩展呢。 国内第一个 从零开始构建&#xff0c;有自己的标准规范与开放生态。尤其没有使用 javaee 的接口规范&#xff08;它改包名…

srs5.0.205编译启动

官方有教程了&#xff0c;但是我编译的时候出了很多错误&#xff0c;记录一下。 官方文档&#xff1a;https://ossrs.net/lts/zh-cn/docs/v4/doc/getting-started-build 拉取源码 git clone -b 4.0release https://gitee.com/ossrs/srs.git进入文件夹 cd srs/trunk配置 ./c…

【apollo在springboot中运行原理】

系列文章目录 Springboot源码分析之apollo配置 文章目录 系列文章目录前言一、apollo是如何完成初始化的,拉取配置的呢1. apollo的初始化阶段2.初始化RemoteConfigRepository3.同步远程配置4.发布ConfigFileChangeEvent事件 总结 前言 配置中心我相信有一年开发经验的程序员都…

【STM32】STM32F4中USB的CDC虚拟串口(VCP)使用方法

文章目录 一、前言二、STM32CubeMX生成代码2.1 选择芯片2.2 配置相关模式2.3 设置时钟频率2.4 生成代码2.5 编译并下载代码2.6 结果2.7 问题 三、回环测试3.1 打开工程3.2 添加回环代码3.3 编译烧录并测试 四、出现问题和解决方法4.1 烧录总是要自己插拔USB4.2 自己生成的工程没…

【win】Windows下MSI Afterburner如何让其不在某个软件中显示帧数

本文首发于 慕雪的寒舍 Windows下MSI Afterburner如何让其不在某个软件中显示帧数 1.问题说明 总所周知&#xff0c;MSI Afterburner这个软件可以在游戏里面展示你当前电脑的各项生命体征&#xff0c;包括GPU/CPU功耗频率温度&#xff0c;内存占用&#xff0c;当前帧数等等数据…

java重写与重载的区别详细讲解通俗易懂

重写&#xff08;Override&#xff09;和重载&#xff08;Overload&#xff09;是Java中的两个重要概念&#xff0c;它们都涉及到方法的使用和定义。下面我会通俗易懂地解释它们的区别。 重写&#xff08;Override&#xff09;指的是在子类中重新定义父类中已经存在的方法&…

OpenKruiseGame × KubeSphere 联合发布游戏服运维控制台,推动云原生游戏落地

作者&#xff1a;云原生游戏社区 近日&#xff0c;云原生游戏开源社区旗下 OpenKruiseGame&#xff08;以下简称&#xff1a;OKG&#xff09;基于 KubeSphere 4.0 LuBan 架构开发的游戏服运维控制台 OKG Dashboard 正式发布&#xff01;现已上架 KubeSphere Marketplace 云原生…

32、WEB攻防——通用漏洞文件上传二次渲染.htaccess变异免杀

文章目录 一、点过滤二、文件删除三、二次渲染四、.htaccess五、过滤php关键函数 一、点过滤 不能写带文件后缀的文件名&#xff1b;IP转数字 二、文件删除 文件依据规则进行删除&#xff0c;删除有两种删除的类型&#xff1a; 什么文件都删除&#xff0c;条件竞争进行绕过…

宠物热潮席卷欧美:探秘宠物经济的蓬勃发展与增长动力

近年来&#xff0c;宠物经济在欧美地区蓬勃发展&#xff0c;成为经济体系中一股不可忽视的力量。从宠物食品到医疗护理&#xff0c;从宠物用品到服务业&#xff0c;整个产业链日益完善&#xff0c;呈现出多元化、高度专业化的趋势&#xff0c;不仅满足了宠物主人的需求&#xf…

Node.JS CreateWriteStream(大容量写入文件流优化)

Why I Need Node.JS Stream 如果你的程序收到以下错误&#xff0c;或者需要大容量写入很多内容(几十几百MB甚至GB级别)&#xff0c;则必须使用Stream文件流甚至更高级的技术。 Error: EMFILE, too many open files 业务场景&#xff0c;我们有一个IntradayMissingRecord的补…

LeetCode2865. Beautiful Towers I

文章目录 一、题目二、题解 一、题目 You are given a 0-indexed array maxHeights of n integers. You are tasked with building n towers in the coordinate line. The ith tower is built at coordinate i and has a height of heights[i]. A configuration of towers i…

TDengine 十大行业案例汇总,总有一款适合你!

伴随着产品的六载创新与发展&#xff0c;TDengine 的全球用户实例以日增 500 例在持续扩大。截至 2024 年初&#xff0c;TDengine 全球运行的实例数已经超过了 46 万&#xff0c;在物联网、车联网、工业互联网等多个领域都有了广泛的应用&#xff0c;越来越多的企业和组织选择使…

Java数据结构与算法:图算法之深度优先搜索(DFS)

Java数据结构与算法&#xff1a;图算法之深度优先搜索&#xff08;DFS&#xff09; 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;一个热爱编程的程序猿。今天&#xff0c;让我们一起探索图算法中的深度优先搜索&#xff08;DFS&…

《WebKit 技术内幕》学习之十二(1):安全机制

第12章 安全机制 安全机制对于浏览器和渲染引擎来说至关重要。一个不考虑安全机制的HTML5规范体系肯定不会受到广泛地使用&#xff0c;同时一个不安全的浏览器也不会得到广大用户的青睐。本章介绍的安全机制分成两个不同的部分&#xff0c;第一个部分是网页的安全&#xff0c;…

详解Mockito

详解Mockito 1. Mockito简介 在我们的编程世界中&#xff0c;测试是一个非常重要的环节&#xff0c;它能帮助我们确保代码的质量和稳定性。而在众多的测试方法中&#xff0c;Mock测试是一种非常有效的手段。 1.1 什么是 Mock 测试 Mock测试&#xff0c;顾名思义&#xff0c;…