在K8S中,容器本身是非持久化的,当容器崩溃后,kubelet将以镜像的初始状态重新启动容器,但是此时之前容器的数据已经丢失,我们该如何保护好容器的数据呢?

在同一Pod中的容器往往需要共享一些数据,此时我们又该如何实现呢?

这个时候就需要存储来解决这两个问题。

一、ConfigMap

ConfigMap功能在 Kubernetes1.2版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。 ConfigMap API给我们提供了向容器中注入配置信息的机制, ConfigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON二进制大对象。

1.1 ConfigMap 的创建

① 使用目录创建


[root@master configmap]
apple=8.0
orange=3.5
[root@master configmap]
beef=55.0
pork=28.0 [root@master configmap]
configmap/shop-config created [root@master configmap]
NAME DATA AGE
shop-config 2 8s [root@master configmap]
[root@master configmap]

② 使用文件创建

[root@master configmap]
tea=3.0
coffee=4.0 [root@master configmap]
configmap/drink-config created [root@master configmap]

③ 使用字面值创建

使用文字值创建,利用 --from-literal参数传递配置信息,该参数可以使用多次,格式如下:

[root@master configmap]
configmap/snacks-config created [root@master configmap]

1.2 使用 ConfigMap

使用 ConfigMap有三种方式,一种是通过环境变量的方式,直接传递 pod,另一种是通过在 pod的命令行下运行的方式,第三种是使用 volume的方式挂载入到 pod内。

① 使用 ConfigMap 来替代环境变量


[root@master configmap]
apiVersion: v1
kind: ConfigMap
metadata:
name: animal-config
namespace: default
data:
cat: cute
dog: lovely [root@master configmap]
configmap/animal-config created [root@master configmap]
apiVersion: v1
kind: Pod
metadata:
name: use-configmap-pod
spec:
containers:
- name: test-container
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "env" ]
env:
- name: animal-config-cat
valueFrom:
configMapKeyRef:
name: animal-config
key: cat
- name: animal-config-coffee
valueFrom:
configMapKeyRef:
name: animal-config
key: dog
envFrom:
- configMapRef:
name: snacks-config
restartPolicy: Never [root@master configmap]
pod/use-configmap-pod created [root@master configmap]

② 用 ConfigMap 设置命令行参数

apiVersion: v1
kind: Pod
metadata:
name: use--configmap-pod2
spec:
containers:
- name: test-container
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "echo $(animal-config-cat) $(animal-config-dog)" ]
env:
- name: animal-config-cat
valueFrom:
configMapKeyRef:
name: animal-config
key: cat
- name: animal-config-dog
valueFrom:
configMapKeyRef:
name: animal-config
key: dog
restartPolicy: Never

③ 通过数据卷插件使用 ConfigMap

在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。

apiVersion: v1
kind: Pod
metadata:
name: use-configmap-pod3
spec:
containers:
- name: test-container
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "ls /etc/config" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: animal-config
restartPolicy: Never

1.3 ConfigMap 热更新


[root@master configmap]
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: hub.hc.com/library/myapp:v1
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: snacks-config [root@master configmap]
deployment.extensions/my-nginx created
[root@master configmap]
NAME READY STATUS RESTARTS AGE
my-nginx-bc7499bd8-hrgl9 1/1 Running 0 2s [root@master configmap]
6.9 [root@master configmap] [root@master configmap]
8.8

二、Secret

Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret 可以以 Volume 或者环境变量的方式使用

Secret有三种类型:

  • Service Account:用来访问 Kubernetes API,由 Kubernetes自动创建,并且会自动挂载到 Pod/run/secrets/kubernetes.io/serviceaccount目录中
  • Opaquebase64编码格式的 Secert,用来存储密码、密钥等
  • kubernetes.io/dockerconfigjson:用来存储私有 docker registry的认证信息

2.1 Service Account

[root@master ~]

ca.crt	namespace  token

2.2 Opaque

Opaque类型的数据是一个 map类型,要求 valuebase64编码格式:

[root@master ~]
YWRtaW4=
[root@master ~]
MWYyZDFlMmU2N2Rm

创建 Opaque类型的 secret:

[root@master secert]
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm [root@master secert]
secret/mysecret created
[root@master secert]
NAME TYPE DATA AGE
mysecret Opaque 2 93s

Secret 挂载到 Volume 中:

[root@master secert]
apiVersion: v1
kind: Pod
metadata:
labels:
name: secret-test
name: secret-test
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- image: hub.hc.com/library/myapp:v1
name: db
volumeMounts:
- name: secrets
mountPath: /etc/config [root@master secert]
pod/secret-test created
[root@master secert]
/ /etc/config
1f2d1e2e67df
admin

Secret 导出到环境变量中:

[root@master secert]
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: pod-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
containers:
- name: pod-1
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "env" ]
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password [root@master secert]
deployment.extensions/pod-deployment created

2.3 kubernetes.io/dockerconfigjson


[root@master secert]
secret "myregistrykey" created [root@master secert]
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: roc/awangyang:v1
imagePullSecrets:
- name: myregistrykey

三、Volume

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时, kubelet会重启它,但是容器中的文件将丢失,容器以干净的状态(镜像最初的状态)重新启动。其次,在 Pod中同时运行多个容器时,这些容器之间通常需要共享文件。 Kubernetes中的 Volume抽象就很好的解决了这些问题。

Kubernetes中的卷( Volume)有明确的寿命,与封装它的 Pod相同。所f以,卷的生命比 Pod中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当 Pod不再存在时,卷也将不复存在。 Kubernetes支持多种类型的卷, Pod可以同时使用任意数量的卷。

3.1 emptyDir

Pod被分配给节点时,首先创建 emptyDir卷,并且只要该 Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。 Pod中的容器可以读取和写入 emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod时, emptyDir中的数据将被永久删除。

emptyDir 的用法有:

  • 暂存空间,例如用于基于磁盘的合并排序
  • 用作长时间计算崩溃恢复时的检查点
  • Web服务器容器提供数据时,保存内容管理器容器提取的文件

[root@master volume]
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: hub.hc.com/library/myapp:v1
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
- image: busybox
name: test-container2
imagePullPolicy: IfNotPresent
command: ['/bin/sh','-c','sleep 3600']
volumeMounts:
- mountPath: /test
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {} [root@master volume] [root@master volume]
'NAME READY STATUS RESTARTS AGE
test-pd 2/2 Running 0 8m32s [root@master volume]
/
/cache
/cache
Wed Aug 12 07:43:08 UTC 2020 [root@master ~]
/
/test
Wed Aug 12 07:43:08 UTC 2020

3.2 hostPath

hostPath卷将主机节点的文件系统中的文件或目录挂载到集群中

hostPath 的用途如下:

  • 运行需要访问 Docker内部的容器;使用 /var/lib/dockerhostPath
  • 在容器中运行 cAdvisor;使用 /dev/cgroupshostPath

除了所需的 path属性之外,用户还可以为 hostPath卷指定 type

值行为空空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查DirectoryOrCreate如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为0755,与Kubelet具有相同的组和所有权。Directory给定的路径下必须存在目录FileOrCreate如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为0644,与Kubelet具有相同的组和所有权。File给定的路径下必须存在文件Socket给定的路径下必须存在UNIX套接字CharDevice给定的路径下必须存在字符设备BlockDevice给定的路径下必须存在块设备

使用这种卷类型时请注意:

  • 由于每个节点上的文件都不同,具有相同配置(例如从 podTemplate创建的)的 pod在不同节点上的行为可能会有所不同
  • Kubernetes按照计划添加资源感知调度时,将无法考虑 hostPath使用的资源
  • 在底层主机上创建的文件或目录只能由 root写入。您需要在特权容器中以 root身份运行进程,或修改主机上的文件权限以便写入 hostPath
[root@master volume]
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: hub.hc.com/library/myapp:v1
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath: path: /data type: Directory [root@master volume]
[root@master volume]
/
/test-pd [root@worker1 data] [root@worker2 data]
2020年 08月 12日 星期三 17:52:43 CST

四、PV-PVC

4.1 相关概念

① PersistentVolume(PV)

是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样, PV也是集群中的资源。 PVVolume之类的卷插件,但具有独立于使用 PVPod的生命周期。此 API对象包含存储实现的细节,即 NFSiSCSI或特定于云供应商的存储系统

② PersistentVolumeClaim(PVC)

是用户存储的请求,它与 Pod相似。 Pod消耗节点资源, PVC消耗 PV资源。 Pod可以请求特定级别的资源( CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或只读多次模式挂载)

③ 静态 pv

集群管理员创建一些 PV,它们带有可供群集用户使用的实际存储的细节。它们存在于 Kubernetes API中,可用于消费

④ 动态

当管理员创建的静态 PV都不匹配用户的 PersistentVolumeClaim时,集群可能会尝试动态地为 PVC创建卷。此配置基于 StorageClassesPVC必须请求 [存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为""可以有效地禁用其动态配置要启用基于存储级别的动态存储配置,集群管理员需要启用 API server上的 DefaultStorageClass[准入控制器]。例如,通过确保 DefaultStorageClass位于 API server组件的 --admission-control标志,使用逗号分隔的有序值列表中,可以完成此操作

⑤ 绑定
master中的控制环路监视新的 PVC,寻找匹配的 PV(如果可能),并将它们绑定在一起。如果为新的 PVC动态调配 PV,则该环路将始终将该 PV绑定到 PVC。否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦 PVPVC绑定后, PersistentVolumeClaim绑定是排他性的,不管它们是如何绑定的。 PVCPV绑定是一对一的映射

4.2 PV说明

PVC的保护
PVC保护的目的是确保由 pod正在使用的 PVC不会从系统中移除,因为如果被移除的话可能会导致数据丢失当启用 PVC保护 alpha功能时,如果用户删除了一个 pod正在使用的 PVC,则该 PVC不会被立即删除。 PVC的删除将被推迟,直到 PVC不再被任何 pod使用

PV演示代码

apiVersion: v1
kind: PersistentVolumemeta
data:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2

PV类型
PV类型以插件形式实现。 K8S目前支持以下插件类型:



PV访问模式
PV可以以资源提供者支持的任何方式挂载到主机上。如下表所示,供应商具有不同的功能,每个 PV的访问模式都将被设置为该卷支持的特定模式。例如, NFS可以支持多个读/写客户端,但特定的 NFS PV可能以只读方式导出到服务器上。每个 PV都有一套自己的用来描述特定功能的访问模式:

  • ReadWriteOnce:该卷可以被单个节点以读/写模式挂载
  • ReadOnlyMany:该卷可以被多个节点以只读模式挂载
  • ReadWriteMany:该卷可以被多个节点以读/写模式挂载

在命令行中,访问模式缩写为

  • RWOReadWriteOnce
  • ROXReadOnlyMany
  • RWXReadWriteMany



回收策略

  • Retain(保留)——手动回收
  • Recycle(回收)——基本擦除( rm -rf /thevolume/*
  • Delete(删除)——关联的存储资产(例如 AWS EBSGCE PDAzure DiskOpenStack Cinder卷)将被删除

当前,只有 NFSHostPath支持回收策略。 AWS EBSGCE PDAzure DiskCinder卷支持删除策略

状态

卷可以处于以下的某种状态:

  • Available(可用)——一块空闲资源还没有被任何声明绑定
  • Bound(已绑定)——卷已经被声明绑定
  • Released(已释放)——声明被删除,但是资源还未被集群重新声明
  • Failed(失败)——该卷的自动回收失败

命令行会显示绑定到 PVPVC的名称

4.3 持久化演示说明 - NFS

① 安装 NFS 服务器

[root@master ~]
[root@master ~]
[root@master ~]
/nfs *(rw,no_root_squash,no_all_squash,sync)
[root@master ~] [root@worker1 ~]
[root@worker1 ~]
Export list for 192.168.182.100:
/nfs *
[root@worker1 ~]
[root@worker1 /]

② 部署 PV

[root@master pv]
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs
server: 192.168.182.100
[root@master pv]
persistentvolume/nfs-pv1 created
[root@master pv]
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv1 1Gi RWO Retain Available nfs 5s

③ 创建服务并使用 PVC


[root@master /]
[root@master /]
[root@master /]
/nfs *(rw,no_root_squash,no_all_squash,sync)
/nfs2 *(rw,no_root_squash,no_all_squash,sync)
/nfs3 *(rw,no_root_squash,no_all_squash,sync) [root@master pv] [root@master pv]
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs
server: 192.168.182.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv2
spec:
capacity:
storage: 5Gi
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs2
server: 192.168.182.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv3
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: slow
nfs:
path: /nfs3
server: 192.168.182.100
[root@master pv] NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv1 1Gi RWO Retain Available nfs 23s
nfs-pv2 5Gi ROX Retain Available nfs 23s
nfs-pv3 1Gi RWX Retain Available slow 23s [root@master pv]
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: hub.hc.com/library/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi [root@master pv]
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 7s
web-1 0/1 Pending 0 5s [root@master pv]
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv1 1Gi RWO Retain Bound default/www-web-0 nfs 4m40s
nfs-pv2 5Gi ROX Retain Available nfs 4m40s
nfs-pv3 1Gi RWO Retain Bound default/www-web-1 nfs 4m40s
[root@master pv]
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 15m 10.244.2.84 worker2 <none> <none>
web-1 1/1 Running 0 15m 10.244.1.58 worker1 <none> <none> [root@master pv]
Hello PV
[root@master pv]
Hello PV
[root@master pv]
pod "web-0" deleted
[root@master pv]
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 3s 10.244.2.85 worker2 <none> <none>
web-1 1/1 Running 0 18m 10.244.1.58 worker1 <none> <none> [root@master pv]
Hello PV

4.4 关于 StatefulSet

  • 匹配 Pod name ( 网络标识 ) 的模式为: $(statefulset名称)-$(序号),比如上面的示例: web-0web-1
  • StatefulSet为每个 Pod副本创建了一个 DNS域名,这个域名的格式为: $(podname).(headless servername),也就意味着服务间是通过 Pod域名来通信而非 Pod IP,因为当 Pod所在 Node发生故障时, Pod会被飘移到其它 Node上, Pod IP会发生变化,但是 Pod域名不会有变化
  • StatefulSet使用 Headless服务来控制 Pod的域名,这个域名的 FQDN为: $(servicename).$(namespace).svc.cluster.local,其中, cluster.local指的是集群的域名
  • 根据 volumeClaimTemplates,为每个 Pod创建一个 pvcpvc的命名规则匹配模式: (volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=wwwPodname=web-[0-2],因此创建出来的 PVCwww-web-0www-web-1
  • 删除 Pod不会删除其 pvc,手动删除 pvc将自动释放 pv

Statefulset 的启停顺序:

  • 有序部署:部署 StatefulSet时,如果有多个 Pod副本,它们会被顺序地创建(从 0N-1)并且,在下一个 Pod运行之前所有之前的 Pod必须都是 RunningReady状态
  • 有序删除:当 Pod被删除时,它们被终止的顺序是从 N-10
  • 有序扩展:当对 Pod执行扩展操作时,与部署一样,它前面的 Pod必须都处于 RunningReady状态

StatefulSet 使用场景:

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于 PVC来实现
  • 稳定的网络标识符,即 Pod重新调度后其 PodNameHostName不变
  • 有序部署,有序扩展,基于 init containers来实现
  • 有序收缩

微信搜一搜 : 全栈小刘 ,获取文章 pdf 版本

8. 老板 不加薪,我用了 这篇 加了 3K的更多相关文章

  1. [No000046]为什么跳槽加薪会比内部调薪要高?

    有网友在知乎提问: 最近在思考一个问题,为什么跳槽往往意味着加薪? 如果一个人确有价值,为什么在原来的公司没有在薪水上体现出来?如果没有价值,为什么跳槽以后就会加薪?还是可以单纯的解释为,应聘者和招聘 ...

  2. 老板让只懂Java基本语法的我,基于AQS实现一个锁

    10 点整,我到了公司,又成为全组最后一个到的员工. 正准备刷刷手机摸摸鱼,看见老板神秘兮兮地走了过来. 老板:闪客呀,你写个工具,基于 AQS 实现一个锁,给咱们组其他开发用 我:哦好的 老板:你多 ...

  3. 学习CSS的瓶颈

    何为学习瓶颈 学习到了一定的阶段,就很难继续提高水平的一种现象 这是很多人都正面对的,但同时自己并未意识到. 既然是瓶颈,那么一旦突破了,就是广阔天空! 你是否经常面对这样的情景: 遇到一个奇葩问题, ...

  4. 2天驾驭DIV+CSS (实战篇)(转)

     这是去年看到的一片文章,感觉在我的学习中,有不少的影响.于是把它分享给想很快了解css的兄弟们.本文是实战篇. 基础篇[知识一] “DIV+CSS” 的叫法是不准确的[知识二] “DIV+CSS” ...

  5. 最全的ORACLE-SQL笔记

    -- 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott account unloc ...

  6. Android 开发者,如何提升自己的职场竞争力?

    前言 该文章是笔者参加 Android 巴士线下交流会成都站 的手写讲稿虚拟场景,所以大家将就看一下. 开始 大家好,我是刘世麟,首先感谢安卓巴士为我们创造了这次奇妙的相遇.现场的氛围也让我十分激动. ...

  7. 【工作感悟】Android 开发者,如何提升自己的职场竞争力?

    前言 该文章是笔者参加 Android 巴士线下交流会成都站 的手写讲稿虚拟场景,所以大家将就看一下. 开始 大家好,我是刘世麟,首先感谢安卓巴士为我们创造了这次奇妙的相遇.现场的氛围也让我十分激动. ...

  8. 怎样从Javaproject师成长为架构师?

      工作1-5年.当我们向老板提出加薪的时候,或者跳槽去"捡"offer的时候.我们底气够吗? 敢不敢不给涨薪就"挥一挥衣袖.不带走一个bug"?是不是提出要求 ...

  9. Android 四大组件学习之ContentProvider二

    上节学习了什么是ContentProvider.以及ContentProvider的作用.以及什么是URL.本节就对上节学习的知识做一个实践,也就是定义自己的ContentProvider 好.实践是 ...

随机推荐

  1. 教你用Vegas Pro制作视频的遮罩转场特效

    很多小伙伴在接触了Vegas之后,都想利用Vegas制作出各种酷炫的特效.小编也是一样. 今天,小编就和大家分享一下,小编近期学会的遮罩转场特效. 首先想要制作遮罩转场效果,需要的素材有:至少两个图片 ...

  2. css3系列之详解border-image

     border-image border-image呢,是给 边框加上背景图片的.没错,就是平常那一小小条的边框,也能加图片. 参数: border-image-source border-image ...

  3. 5w 字 | 172 图 | 超级赛亚级 Spring Cloud 实战

    一.PassJava 项目简介 PassJava-Learning 项目是 PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. PassJava 是一款 Java 面试刷题 的 ...

  4. 【模板】【P1182】数列分段II——二分答案

    题意:给定一列数,分成m段,使每段和的最大值最小. 考虑二分最小段和size,答案显然满足单调性.可以在每次check中累加数列元素判断当前组的总和是否在size以内.由于序列元素均为非负整数,前缀和 ...

  5. CentOS7.X 下安装MySQL8.0(附文件)

    这是64位的安装包.如果需要32位的可以去官网下载哦.步骤一样 1 获取安装资源包 mysql-8.0.18-1.el7.x86_64.rpm-bundle.tar 链接: https://pan.b ...

  6. LeetCode周赛#203 题解

    1561. 你可以获得的最大硬币数目 #贪心 题目链接 题意 有 3n 堆数目不一的硬币,你和你的朋友们打算按以下方式分硬币: 每一轮中,你将会选出 任意 3 堆硬币(不一定连续). Alice 将会 ...

  7. Ubuntu\Linux 下编写及调试C\C++

    一.在Ubuntu\Linux 下编写及调试C\C++需要配置基本的环境,即配置gcc编译器.安装vim编译器,具体配置安装步骤我在这里就不多说了. 二.基本环境配置完了我们就可以进入自己的程序编写了 ...

  8. Spring Boot 集成 MQTT

    本文代码有些许问题,处理方案见:解决 spring-integration-mqtt 频繁报 Lost connection 错误 一.添加配置 spring: mqtt: client: usern ...

  9. 第15.22节 PyQt(Python+Qt)入门学习:Model/View架构详解

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.简介 在PyQt和Qt中,Model/View架构是图形界面开发时用于管理数据和界面展现方式的关 ...

  10. 从Linux源码看Socket(TCP)的accept

    从Linux源码看Socket(TCP)的accept 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就从Linux源码的角度看下Serve ...