pod的基本介绍| harbor仓库的搭建 tomcat镜像拉取

news2024/11/20 13:37:08

pod的基本介绍| harbor仓库的搭建 tomcat镜像拉取

  • 一 Pod基础概念:
  • 二 通常把Pod分为两类:
  • 三 Pod容器的分类:
  • 四 应用容器(Maincontainer)
  • 五 镜像拉取策略(image PullPolicy)
  • 六 部署 harbor 创建私有项目
    • 6.1 安装docker和harbor仓库 192.168.10.40
    • 6.2 在node节点 192.168.10.20,192.168.10.30
    • 6.3 在master节点上192.168.10.10

一 Pod基础概念:

Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的,例如,用于管理Pod运行的StatefulSet和Deployment等控制器对象,用于暴露Pod应用的Service和Ingress对象,为Pod提供存储的PersistentVolume存储资源对象等。

//在Kubrenetes集群中Pod有如下两种使用方式:
●一个Pod中运行一个容器。“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,你可以把Pod想象成是单个容器的封装,kuberentes管理的是Pod而不是直接管理容器。

●在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位,比如一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。

一个Pod下的容器必须运行于同一节点上。现代容器技术建议一个容器只运行一个进程,该进程在容器中PID命令空间中的进程号为1,可直接接收并处理信号,进程终止时容器生命周期也就结束了。若想在容器内运行多个进程,需要有一个类似Linux操作系统init进程的管控类进程,以树状结构完成多进程的生命周期管理。运行于各自容器内的进程无法直接完成网络通信,这是由于容器间的隔离机制导致,k8s中的Pod资源抽象正是解决此类问题,Pod对象是一组容器的集合,这些容器共享Network、UTS及IPC命令空间,因此具有相同的域名、主机名和网络接口,并可通过IPC直接通信。

Pod资源中针对各容器提供网络命令空间等共享机制的是底层基础容器pause,基础容器(也可称为父容器)pause就是为了管理Pod容器间的共享操作,这个父容器需要能够准确地知道如何去创建共享运行环境的容器,还能管理这些容器的生命周期。为了实现这个父容器的构想,kubernetes中,用pause容器来作为一个Pod中所有容器的父容器。这个pause容器有两个核心的功能,一是它提供整个Pod的Linux命名空间的基础。二来启用PID命名空间,它在每个Pod中都作为PID为1进程(init进程),并回收僵尸进程。

//pause容器使得Pod中的所有容器可以共享两种资源:网络和存储。
●网络:
每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。

●存储:
Pod可以指定多个共享的Volume。Pod中的所有容器都可以访问共享的Volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。

//总结:
每个Pod都有一个特殊的被称为“基础容器”的Pause容器。Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或者多个紧密相关的用户应用容器。

//kubernetes中的pause容器主要为每个容器提供以下功能:
●在pod中担任Linux命名空间(如网络命令空间)共享的基础;
●启用PID命名空间,开启init进程。

//Kubernetes设计这样的Pod概念和特殊组成结构有什么用意?????
●原因一:在一组容器作为一个单元的情况下,难以对整体的容器简单地进行判断及有效地进行行动。比如,一个容器死亡了,此时是算整体挂了么?那么引入与业务无关的Pause容器作为Pod的基础容器,以它的状态代表着整个容器组的状态,这样就可以解决该问题。

●原因二:Pod里的多个应用容器共享Pause容器的IP,共享Pause容器挂载的Volume,这样简化了应用容器之间的通信问题,也解决了容器之间的文件共享问题。

二 通常把Pod分为两类:

●自主式Pod 
这种Pod本身是不能自我修复的,当Pod被创建后(不论是由你直接创建还是被其他Controller),都会被Kuberentes调度到集群的Node上。直到Pod的进程终止、被删掉、因为缺少资源而被驱逐、或者Node故障之前这个Pod都会一直保持在那个Node上。Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。

●控制器管理的Pod
Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。

三 Pod容器的分类:

1、基础容器(infrastructure container)
维护整个 Pod 网络和存储空间
node 节点中操作
启动一个Pod时,k8s会自动启动一个基础容器
cat /opt/kubernetes/cfg/kubelet
......
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"

//每次创建 Pod 时候就会创建,运行的每一个Pod都有一个 pause-amd64 的基础容器自动会运行,对于用户是透明的
docker ps -a
registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0   "/pause"

2、初始化容器(initcontainers)
Init容器必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以Init容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法。
Init 容器与普通的容器非常像,除了以下两点:
●Init 容器总是运行到成功完成为止

●每个 Init 容器都必须在下一个 Init 容器启动之前成功完成启动和退出
如果 Pod 的 Init 容器失败,k8s 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的重启策略(restartPolicy)为 Never,它不会重新启动。

lnit 的容器作用
因为init容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:
●Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。例如,没有必要仅为了在安装过程中使用类似 sed、 awk、 python 或 dig 这样的工具而去FROM 一个镜像来生成一个新的镜像。

●Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。

●应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。

●Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此,Init容器可具有访问 Secrets 的权限,而应用容器不能够访问。

●由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,
直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。

四 应用容器(Maincontainer)



官网示例:
https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/init-containers/

vim myapp-pod-01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

这个例子是定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 myservice 启动, 第二个等待 mydb 启动。 一旦这两个 Init容器都启动完成,Pod 将启动 spec 中的应用容器。

在这里插入图片描述

1应用yaml文件  
kubectl apply -f myapp-pod-01.yaml 
2 
kubectl describe pod myapp-pod

kubectl logs myapp-pod -c init-myservice

请添加图片描述
请添加图片描述

1 编辑myserver.yaml文件
vim myservice.yaml
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
2 创建myservice的pod	
kubectl create -f myservice.yaml
3 查看svc
kubectl get svc

kubectl get pods -n kube-system
4 查看pod节点
kubectl get pods

在这里插入图片描述
请添加图片描述

1 编辑mydb.yaml文件
vim mydb.yaml
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377
2 运行yaml文件	
kubectl create -f mydb.yaml

3 获取pod信息
kubectl get pods

在这里插入图片描述
请添加图片描述

五 镜像拉取策略(image PullPolicy)

Pod 的核心是运行容器,必须指定容器引擎,比如 Docker,启动容器时,需要拉取镜像,k8s 的镜像拉取策略可以由用户指定:
1、IfNotPresent:在镜像已经存在的情况下,kubelet 将不再去拉取镜像,仅当本地缺失时才从仓库中拉取,默认的镜像拉取策略
2、Always:每次创建 Pod 都会重新拉取一次镜像;
3、Never:Pod 不会主动拉取这个镜像,仅使用本地镜像。
注意:对于标签为“:latest”的镜像文件,其默认的镜像获取策略即为“Always”;而对于其他标签的镜像,其默认策略则为“IfNotPresent”。

官方示例:
https://kubernetes.io/docs/concepts/containers/images

1 创建测试案例
mkdir /opt/demo
cd /opt/demo

vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test1
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]
2 创建pod
kubectl create -f pod1.yaml

3 查看pod节点状态
kubectl get pods -o wide

4 kubectl describe pod pod-test1

请添加图片描述
请添加图片描述
请添加图片描述

1 修改 pod1.yaml 文件
cd /opt/demo
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test1
spec:
  containers:
    - name: nginx
      image: nginx:1.14							#修改 nginx 镜像版本
      imagePullPolicy: Always
      #command: [ "echo", "SUCCESS" ]			#删除

2 删除原有的资源
kubectl delete -f pod1.yaml 

3 更新资源
kubectl apply -f pod1.yaml 

4 查看 Pod 状态
kubectl get pods -o wide

请添加图片描述
请添加图片描述

六 部署 harbor 创建私有项目

6.1 安装docker和harbor仓库 192.168.10.40

1 在 Docker harbor 节点(192.168.10.40)上操作
systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0

yum install -y yum-utils device-mapper-persistent-data lvm2 
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
yum install -y docker-ce
systemctl start docker.service
systemctl enable docker.service
docker version

2 上传 docker-compose 和 harbor-offline-installer-v1.2.2.tgz 到 /opt 目录中
cd /opt
chmod +x docker-compose
mv docker-compose /usr/local/bin/

3 部署 Harbor 服务
tar zxvf harbor-offline-installer-v1.2.2.tgz -C /usr/local/
vim /usr/local/harbor/harbor.cfg
--5行--修改,设置为Harbor服务器的IP地址或者域名
hostname = 192.168.10.40

cd /usr/local/harbor/
在配置好了 harbor.cfg 之后,执行 ./prepare 命令,为 harbor 启动的容器生成一些必要的文件(环境)
./install.sh

5 在 Harbor 中创建一个新项目
(1)浏览器访问:http://192.168.10.40 登录 Harbor WEB UI 界面,默认的管理员用户名和密码是 admin/Harbor12345
(2)输入用户名和密码登录界面后可以创建一个新项目。点击“+项目”按钮
(3)填写项目名称为“kgc-project”,点击“确定”按钮,创建新项目

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
在这里插入图片描述

6.2 在node节点 192.168.10.20,192.168.10.30

1 在每个 node 节点配置连接私有仓库(注意每行后面的逗号要添加)
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
  "insecure-registries":["192.168.10.40"]
}
EOF

systemctl daemon-reload
systemctl restart docker

2 在每个 node 节点登录 harbor 私有仓库
docker login -u admin -p Harbor12345 http://192.168.10.40 

3 在一个 node 节点下载 Tomcat 镜像进行推送
docker pull tomcat:8.0.52
docker images

docker tag tomcat:8.0.52 192.168.10.40/kgc-project/tomcat:v1
docker images

docker push 192.168.10.40/kgc-project/tomcat:v1

请添加图片描述
请添加图片描述
请添加图片描述

node节点查看登陆凭据
cat /root/.docker/config.json | base64 -w 0			#base64 -w 0:进行 base64 加密并禁止自动换行

在这里插入图片描述

6.3 在master节点上192.168.10.10

1 创建 harbor 登录凭据资源清单,用于 K8S 访问 Harbor 私服拉取镜像所需要的密钥权限凭证 secret 资源
vim harbor-pull-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: harbor-pull-secret
data:
.dockerconfigjson:ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEwLjQwIjogewoJCQkiYXV0aCI6ICJZV1J0YVc0NlNHRnlZbTl5TVRJek5EVT0iCgkJfQoJfQp9
type: kubernetes.io/dockerconfigjson


2 创建 secret 资源
kubectl create -f harbor-pull-secret.yaml

3 查看 secret 资源
kubectl get secret

请添加图片描述
请添加图片描述

创建资源从 harbor 中下载镜像
cd /opt/demo
vim tomcat-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-tomcat
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-tomcat
  template:
    metadata:
      labels:
        app: my-tomcat
    spec:
      imagePullSecrets:						#添加 K8S 访问 Harbor 私服拉取镜像所需要的 secret 资源选项
      - name: harbor-pull-secret			#指定 secret 资源名称
      containers:
      - name: my-tomcat
        image: 192.168.10.40/kgc-project/tomcat:v1		#指定 harbor 中的镜像名
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-tomcat
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 31111
  selector:
    app: my-tomcat

在这里插入图片描述

1 删除之前在 node 节点192.168.10.30下载的 Tomcat 镜像
docker rmi tomcat:8.0.52
docker rmi 192.168.10.40/kgc-project/tomcat:v1
docker images


2 matser192.168.10.10创建资源
kubectl create -f tomcat-deployment.yaml

3 查看资源
kubectl get pods

4 查看 Pod 的描述信息,可以发现镜像时从 harbor 下载的
kubectl describe pod my-tomcat-6464c6bdf6

5 登录web页面查看harbor镜像的下载次数 发现增加了

请添加图片描述

请添加图片描述
请添加图片描述

请添加图片描述

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

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

相关文章

无序列表标签<ul>和<li>

HTML5中提供了3种列表。 无序列表 无序列表是没有刻意顺序的列表。 比如我们如果想去超市买东西&#xff0c;想买的东西又比较多&#xff0c;为了避免忘记漏买某些东西&#xff0c;就会列一个购物清单&#xff0c;购物清单就是一个无序列表&#xff0c;因为要买的东西只要没有…

如何为博客选择目标受众(+例子)

要创建免费网站和博客&#xff1f;从易服客建站平台开始 500M免费空间&#xff0c;可升级为20GB电子商务网站 创建免费网站 您是否正在寻找为您的博客选择目标受众的最佳实践&#xff1f; 选择目标受众可以让您创建更好的内容&#xff0c;引起用户的共鸣。这有助于您获得更…

[学习笔记]解决因C#8.0的语言特性导致EFCore实体类型映射的错误

今天下午在排查一个EF问题时&#xff0c;遇到了个很隐蔽的坑&#xff0c;特此记录。 问题 使用ef执行Insert对象到某表时报错&#xff0c;此对象的Address为空&#xff1a; 不能将值 NULL 插入列 Address&#xff0c;表 dbo.xxx&#xff1b;列不允许有 Null 值。INSERT 失败。…

基于云服务器的博客和靶场搭建-经验教训

搭这两个东西还是走了很多弯路 我就不给你们讲方法过程了&#xff0c;直接参考我给的链接&#xff0c;我主要说经验教训 博客搭建参考&#xff1a;https://zhuanlan.zhihu.com/p/37896471 靶场搭建参考&#xff1a;https://zhuanlan.zhihu.com/p/86409304 https://www.free…

LAMP搭建Discuz

文章目录 一、关闭防火墙二、安装apache三、安装Mysql四、安装PHP五、安装Discuz 一、关闭防火墙 [rootlocalhost ~]# systemctl status firewalld.service还要关闭selinux&#xff0c;要不然后面web页安装Discuz时会过不去。 [rootlocalhost ~]# setenforce 0编辑 /etc/seli…

堆排序——我欲修仙(功法篇)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️我欲修仙】 学习名言&#xff1a;学习和研究好比爬梯子&#xff0c;要一步一步地往上爬&#xff0c;企图一脚跨上四五步&#xff0c;平地登天&#xff0c;那就必须会摔跤了。——华罗庚 系列文章目录…

国产游戏引擎,竟然用来搞民航

​本文源自量子位 | 公众号 QbitAI 只是给飞行员做个“装备”&#xff0c;竟然突破了国内民用航空领域的一大技术难题&#xff1f;&#xff01; 这是一群游戏技术开发者的真实经历。 他们用自研游戏引擎开发了一个飞行模拟软件&#xff0c;能够第一视角模拟飞行员起飞、着陆…

Html中使用jquery通过Ajax请求WebService接口以及跨域问题解决

场景 VS2019新建WebService/Web服务/asmx并通过IIS实现发布和调用&#xff1a; VS2019新建WebService/Web服务/asmx并通过IIS实现发布和调用_霸道流氓气质的博客-CSDN博客 在上面实现发布WebService的基础上&#xff0c;怎样在html中通过jquery对接口发起 请求和解析数据。…

【航空和卫星图像中检测建筑物】使用gabor特征和概率的城市区域和建筑物检测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

领域驱动设计DDD架构解析和绘图模板分享

DDD整洁架构 DDD整洁架构为了解决强调用的关系&#xff0c;出现了洋葱架构&#xff08;六边形&#xff09;架构&#xff0c;就是为了实现依赖倒置 它的思想就是把领域模型放到核心的位置&#xff0c;领域模型是独立的&#xff0c;不会直接强依赖其他层&#xff0c;而通过适配…

mmtrack mmdet mmcv环境安装 版本匹配 2023.5.18

一、参考官网&#xff1a; https://mmtracking.readthedocs.io/zh_CN/latest/install.html# mmtracking&#xff0c;mmcv&#xff0c;mmdetection版本匹配关系&#xff1a; MMTracking versionMMCV versionMMDetection versionmastermmcv-full>1.3.17, \<2.0.0MMDetec…

100 个 Go 错误以及如何避免:9~12

协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【OpenDocCN 饱和式翻译计划】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 真相一旦入眼&#xff0c;你就再也无法视而不见。——《黑客帝国》 九、并发实践 本章涵盖 防止 …

vue3的学习【超详细】

目录 一、vue3的优点1、vue3的优点 二、常用的API1、setup&#xff08;Composition API&#xff09;2、生命周期&#xff08;Composition API&#xff09;3、ref函数和reactive函数用法和区别&#xff08;Composition API&#xff09;1、ref2、reactive3、ref和reactive的区别 …

linux + ros 使用 catkin 从源码编译安装并运行 rocon_rtsp_camera_relay 订阅 rtsp 视频流

1. rocon_rtsp_camera_relay 介绍 最主要的功能在于把相机的 rtsp 视频流 转换为 ros topic 发布出来&#xff0c;使其他节点可以通过订阅的形式获取视频流数据。 2. 编译安装 注&#xff1a;官网的安装命令 sudo apt-get install ros-<distro>-rocon-rtsp-camera-rel…

leetcode 1557. Minimum Number of Vertices to Reach All Nodes(到达所有顶点的最少顶点集)

给出一个有向无环图&#xff08;DAG&#xff09;&#xff0c;顶点有n个&#xff1a;0&#xff5e;n - 1, 边[from, to]为从顶点from到to的边。 找出最小的顶点集合&#xff0c;从这些顶点出发能到达图中的所有顶点&#xff08;集合里不一定每个点都能到达所有顶点&#xff0c;而…

kettle——处理缺失值

目录 一、删除缺失值 1、文本文件输入 2、字段选择 3、过滤记录 4、输出excel文件 5、运行 二、填充缺失值 1、添加文件 2、过滤记录 3、替换NULL值 4、合并记录 5、替换NULL值2 6、字段选择 7、Excel输出 8、运行并查看执行结果 一、删除缺失值 1、文本文件输入…

MMOE - 经典多任务模型(谷歌)

文章目录 1、动机&#xff1a;2、模型结构&#xff1a; Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Expertsmmoe: Multi-gate Mixture-of-Expertsmmoe由谷歌发表在KDD-2018【和阿里的ESMM同年发表&#xff0c;SIGIR-2018】&#xff1b;模…

华为手环8添加门禁卡操作指导

不得不说&#xff0c;华为基于手机/手环NFC和蓝牙等技术应用&#xff0c;结合门禁卡灵活、安全、便利的优势&#xff0c;给社区场景提供更优质和更多样的技术支持与服务&#xff0c;为广大用户创造美好的数字化生活体验。 目前华为手环8支持模拟市面上未经加密过的、频率为13.5…

服务发现原理与grpc源码解析

一 服务发现基础概念 为什么需要服务发现 在微服务架构中&#xff0c;在生产环境中服务提供方都是以集群的方式对外提供服务&#xff0c;集群中服务的IP随时都可能发生变化&#xff0c;如服务重启&#xff0c;发布&#xff0c;扩缩容等&#xff0c;因此我们需要及时获取到对应…

ThreadLocal使用和原理

ThreadLocal是线程本地变量&#xff0c;用来解决并发下数据隔离性的问题&#xff0c;不能解决共享。 他可以将一个变量拷贝的线程内&#xff0c;线程调用时再线程内进行使用&#xff0c;相当于给每个线程复制一个副本供各个线程使用。 ThreadLocal简单使用 他的目的很简单&a…