首页 > 互联网 > k8s无用的副本集占空间吗

k8s无用的副本集占空间吗

互联网 2024-04-02

18.k8s中部署harbor registry blobs占用空间大

现象:在删除掉镜像后,下图依旧空间没有减少
解决:使用admin,点击 系统管理-->垃圾清理

Docker&k8s(一)

​ 容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界” 。对于 Docker 等大多数 Linux 容器来说, Cgroups 技术 是用来制造约束的主要手段,而 Namespace 技术 则是用来修改进程视图的主要方法。
其实只是 Linux 创建新进程的一个可选参数。我们知道,在 Linux 系统中创建线程的系统调用是 clone(),比如:
​ 这个系统调用就会为我们创建一个新的进程,并且返回它的进程号 pid。而当我们用 clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数,比如:
​ 这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID 是 1。之所以说“看到”,是因为这只是一个“障眼法”,在宿主机真实的进程空间里,这个进程的 PID 还是真实的数值,比如 100。
​ 而 除了 PID Namespace,Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace,用来对各种不同的进程上下文进行“障眼法”操作。
​ 比如,Mount Namespace,用于让被隔离进程只看到当前 Namespace 里的挂载点信息;Network Namespace,用于让被隔离进程看到当前 Namespace 里的网络设备和配置。
​ 这,就是 Linux 容器最基本的实现原理了。所以说,容器,其实是一种特殊的进程而已。Namespace 技术实际上修改了应用进程看待整个计算机“视图”,即它的“视线”被操作系统做了限制,只能“看到”某些指定的内容 。
优势:更加的轻量且没有损耗资源。弊端:隔离不彻底
Cgroups(Linux Control Group) 就是 Linux 内核中用来为进程设置资源限制的一个重要功能。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等
Cgroups 给用户暴露出来的操作接口是文件系统
比如,向 container 组里的 cfs_quota 文件写入 20 ms(20000 us):
意味着在每 100 ms 的时间里,被该控制组限制的进程只能使用 20 ms 的 CPU 时间,也就是说这个进程只能使用到 20% 的 CPU 带宽。
把被限制的进程的 PID 写入 container 组里的 tasks 文件,上面的设置就会对该进程生效了:
除 CPU 子系统外,Cgroups 的每一项子系统都有其独有的资源限制能力,比如:
Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。容器是一个“单进程”模型。
​ Mount Namespace 修改的,是容器进程对文件系统“挂载点”的认知。Mount Namespace 跟其他 Namespace 的使用略有不同的地方:它对容器进程视图的改变,一定是伴随着挂载操作(mount)才能生效。实际上,Mount Namespace 正是基于对 chroot 的不断改良才被发明出来的,它也是 Linux 操作系统里的第一个 Namespace。
​ 而这个挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统,就是所谓的“容器镜像”。它还有一个更为专业的名字,叫作:rootfs(根文件系统)。
对 Docker 项目来说,它最核心的原理实际上就是为待创建的用户进程:
​ rootfs 只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。在 Linux 操作系统中,这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像。
容器的 rootfs 由如下图所示的三部分组成:
第一部分,只读层 :它是这个容器的 rootfs 最下面的五层,对应的正是 ubuntu:latest 镜像的五层,挂载方式都是只读的(ro+wh,即 readonly+whiteout)
这些层,都以增量的方式分别包含了 Ubuntu 操作系统的一部分
第二部分,可读写层。 (rw)
​ 在没有写入文件之前,这个目录是空的。而一旦在容器里做了写操作,你修改产生的内容就会以增量的方式出现在这个层中。如果要删除AuFS 会在可读写层创建一个 whiteout 文件,把只读层里的文件“遮挡”起来。
专门用来存放你修改 rootfs 后产生的增量,原先的只读层里的内容则不会有任何变化
第三部分,Init 层。
​ 有些文件本来属于只读的 Ubuntu 镜像的一部分,但是用户往往需要在启动容器时写入一些指定的值比如 hostname,所以就需要在可读写层对它们进行修改。可是,这些修改往往只对当前的容器有效,我们并不希望执行 docker commit 时,把这些信息连同可读写层一起提交掉。所以,Docker 做法是,在修改了这些文件之后,以一个单独的层挂载了出来。而用户执行 docker commit 只会提交可读写层,所以是不包含这些内容的。可以参考git ignore的思想。
Dockerfile :
ENTRYPOINT:entrypoint才是正统地用于定义容器启动以后的执行体的,其实我们从名字也可以理解,这个是容器的“入口”。
CMD:cmd给出的是一个容器的默认的可执行体。也就是容器启动以后,默认的执行的命令。如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么,就会使用cmd指定的默认的执行命令执行如果你不额外指定,那么就执行cmd的命令,否则呢?只要你指定了,那么就不会执行cmd,也就是cmd会被覆盖。
docker commit,实际上就是在容器运行起来后,把最上层的“可读写层”,加上原先容器镜像的只读层,打包组成了一个新的镜像。当然,下面这些只读层在宿主机上是共享的,不会占用额外的空间。
而由于使用了联合文件系统,你在容器里对镜像 rootfs 所做的任何修改,都会被操作系统先复制到这个可读写层,然后再修改。这就是所谓的:Copy-on-Write。
​ 一个进程的每种 Linux Namespace,都在它对应的 /proc/[进程号]/ns 下有一个对应的虚拟文件,并且链接到一个真实的 Namespace 文件上。
​ 这也就意味着:一个进程,可以选择加入到某个进程已有的 Namespace 当中,从而达到“进入”这个进程所在容器的目的,这正是 docker exec 的实现原理。
Volume 机制,允许你将宿主机上指定的目录或者文件,挂载到容器里面进行读取和修改操作。
​ 当容器进程被创建之后,尽管开启了 Mount Namespace,但是在它执行 chroot(或者 pivot_root)之前,容器进程一直可以看到宿主机上的整个文件系统。所以在 rootfs 准备好之后,在执行 chroot 之前,把 Volume 指定的宿主机目录(比如 /home 目录),挂载到指定的容器目录(比如 /test 目录)在宿主机上对应的目录(即 /var/lib/docker/aufs/mnt/[可读写层 ID]/test)上,这个 Volume 的挂载工作就完成了。
​ 由于执行这个挂载操作时,“容器进程”已经创建了,也就意味着此时 Mount Namespace 已经开启了。所以,这个挂载事件只在这个容器里可见。你在宿主机上,是看不见容器内部的这个挂载点的。这就 保证了容器的隔离性不会被 Volume 打破 。
​ 而这里要使用到的挂载技术,就是 Linux 的 绑定挂载(bind mount)机制 。它的主要作用就是,允许你将一个目录或者文件,而不是整个设备,挂载到一个指定的目录上。并且,这时你在该挂载点上进行的任何操作,只是发生在被挂载的目录或者文件上,而原挂载点的内容则会被隐藏起来且不受影响。绑定挂载实际上是一个 inode 替换的过程。在 Linux 操作系统中,inode 可以理解为存放文件内容的“对象”,而 dentry,也叫目录项,就是访问这个 inode 所使用的“指针”。
​ 所以,在一个正确的时机,进行一次绑定挂载,Docker 就可以成功地将一个宿主机上的目录或文件,不动声色地挂载到容器中。

k8s中的Mysql数据库持久化存储


一、配置:
环境:
CentOS7 
VMware
笔者配置了四台虚拟机:
K8S-Master节点: 3GB内存   2核CPU   20GB硬盘空间
K8S-node1节点:  2GB内存   2核CPU   30GB硬盘空间
K8S-node2节点:  2GB内存   2核CPU   30GB硬盘空间
镜像仓库节点:      2GB内存   2核CPU   50GB硬盘空间
二、节点规划:
使用三台虚拟机搭建K8S集群,使用一台虚拟机搭建镜像仓库。
每台虚拟机配置两块网卡,其中一块为“NAT模式”,用于拉取镜像等功能。
另外一块网卡为“仅主机模式”,用于集群节点间的通信。归划如下:
K8s-master节点:
仅主机模式:10.10.10.200
NAT模式:  192.168.200.130
K8S-node1节点:
仅主机模式:10.10.10.201
NAT模式:  192.168.200.131
K8S-node2节点:
仅主机模式:10.10.10.202
NAT模式:  192.168.200.132
镜像仓库节点:
仅主机模式:10.10.10.101
NAT模式:  192.168.200.150
三、版本信息
Linux内核版本:
Linux version 3.10.0-862.el7.x86_64 (builder@kbuilder.dev.centos.org)
(gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) )
 #1 SMP Fri Apr 20 16:44:24 UTC 2018
K8s集群版本为1.15.0版本:
四、基于StatefulSet与PV/PVC的MySql持久化存储实验
1. 在每个节点安装nfs服务
在“镜像仓库”节点,执行以下命令:
yum install -y nfs-common nfs-utils rpcbind
在k8s集群,执行以下命令:
yum install -y nfs-utils rpcbind
2. 在“镜像仓库”节点下,配置nfs服务器
mkdir /nfs_mysql
Chmod 777 /nfs_mysql/
(在测试环境中,为了不考虑用户属性,暂时赋予777权限,但在生产环境不推荐这样做)
Chown nfsnobody /nfs_mysql/
echo “/nfs_mysql *(rw,no_root_squash,no_all_squash,sync)” >> /etc/exports
cat /etc/exports
/nfs_mysql *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs
3. 测试nfs服务是否可用
mkdir /test
showmount -e 10.10.10.101
可见/nfs_mysql *已暴露于共享目录,接下来测试挂载是否可用:
在master节点下执行:
mount -t nfs 10.10.10.101:/nfs_mysql /test/
echo "hello-world">>/test/1.txt
在镜像仓库节点下查看1.txt是否存在,若存在则挂载成功:
可见nfs服务可以正常使用,接下来删除test目录和1.txt
在镜像仓库下:
[root@hub nfs_mysql]# rm -f 1.txt
在Master节点下:
[root@k8s-master ~]# umount /test/
[root@k8s-master ~]# rm -rf /test/
同理,依照以上步骤同时创建:(提供多个mysql副本进行挂载)
nfs_mysql1
nfs_mysql2
完成后需要重启nfs服务
systemctl restart rpcbind
systemctl restart nfs
最终效果:
4. 将nfs封装成pv
创建mysql_test文件夹,将yaml文件统一保存在此目录下
mkdir mysql_test
cd mysql_test
vim mysql-pv.yml
mysql-pv.yml配置如下:
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    -  ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfs_mysql
    server: 10.10.10.101
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv1
spec:
  capacity:
    storage: 5Gi
  accessModes:
    -  ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfs_mysql1
    server: 10.10.10.101
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv2
spec:
  capacity:
    storage: 5Gi
  accessModes:
    -  ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfs_mysql2
    server: 10.10.10.101
注意:
在k8s集群15版本中recycle回收策略已被删除,只能用retain策略或者Delete策略。这里我们使用 persistentVolumeReclaimPolicy: Retain
 
执行命令:
kubectl create -f mysql-pv.yml
kubectl get pv
如图所示,即为Pv创建成功。
5. 部署MySQL,在mysql_test目录下编写mysql.yml,配置文件如下
apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  ports:
  - port: 3306
    name: mysql
  clusterIP: None
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  serviceName: "mysql"
  replicas: 3
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.6
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-persistent-storage
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "nfs"
      resources:
        requests:
          storage: 1Gi  
执行以下命令,部署mysql服务:
kubectl create -f mysql.yml
如图可知,mysql按StatefulSet依次创建了mysql-0 mysql-1 mysql-2
查看各个Pod部在哪个节点:
6. 通过创建临时容器,使用MySQL客户端发送测试请求给MySQL master节点
注意:
主机名为mysql-0.mysql;跨命名空间的话,主机名请使用mysql-0.mysql. [NAMESPACE_NAME].如果没有指定命名空间,默认为default,即 mysql-0.mysql. default。
   
这里笔者打算关闭node2节点来模拟node2宕机,来测试是否实现数据的持久化存储,
所以我们向node2上的mysql1写入数据。
 
执行以下命令,访问mysql1:
kubectl run mysql-client --image=mysql:5.6 -it --rm --restart=Never -- mysql -h mysql-1.mysql.default -p password
创建数据库demo,并向messages表中写入hello-world
CREATE DATABASE demo; 
CREATE TABLE demo.messages (message VARCHAR(250)); 
INSERT INTO demo.messages VALUES ('hello-world');
如图所示
接下来我们来关闭k8s-node2虚拟机,模拟宕机
查看nodes的运行状态,可知node2的状态已转变为NotReady
一段时间后,k8s将Pod MySql -1迁移到节点k8s-node1
由于时间过长,笔者把三个Pod都删除重启后,验证数据:
MySQL服务恢复,数据完好无损!

K8s -- StatefulSet

RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群等。
StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为 GA 版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。
在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP(所以无法负载均衡),解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,这个域名的格式为:
StatefulSet适用于具有以下特点的应用:
接下来看一些示例,演示下上面所说的特性,以加深理解。
通过该配置文件,可看出StatefulSet的三个组成部分:
为什么需要 headless service 无头服务?
在用Deployment时,每一个Pod名称是没有顺序的,是随机字符串,因此是Pod名称是无序的,但是在statefulset中要求必须是有序 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。而pod IP是变化的,所以是以Pod名称来识别。pod名称是pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称 。
为什么需要volumeClaimTemplate?
对于有状态的副本集都会用到持久存储,对于分布式系统来讲,它的最大特点是数据是不一样的,所以各个节点不能使用同一存储卷,每个节点有自已的专用存储,但是如果在Deployment中的Pod template里定义的存储卷,是所有副本集共用一个存储卷,数据是相同的,因为是基于模板来的 ,而statefulset中每个Pod都要自已的专有存储卷,所以statefulset的存储卷就不能再用Pod模板来创建了,于是statefulSet使用volumeClaimTemplate,称为卷申请模板,它会为每个Pod生成不同的pvc,并绑定pv, 从而实现各pod有专用存储。这就是为什么要用volumeClaimTemplate的原因。
创建:
看下这三个Pod创建过程:
根据volumeClaimTemplates自动创建的PVC
如果集群中没有StorageClass的动态供应PVC的机制,也可以提前手动创建多个PV、PVC,手动创建的PVC名称必须符合之后创建的StatefulSet命名规则:(volumeClaimTemplates.name)-(pod_name)
Statefulset名称为web 三个Pod副本: web-0,web-1,web-2,volumeClaimTemplates名称为:www,那么自动创建出来的PVC名称为www-web[0-2],为每个Pod创建一个PVC。
规律总结:
Statefulset的启停顺序:
Statefulset Pod管理策略:
在v1.7以后,通过允许修改Pod排序策略,同时通过.spec.podManagementPolicy字段确保其身份的唯一性。
StatefulSet使用场景:
在Kubernetes 1.7及更高版本中,通过.spec.updateStrategy字段允许配置或禁用Pod、labels、source request/limits、annotations自动滚动更新功能。
OnDelete :通过.spec.updateStrategy.type 字段设置为OnDelete,StatefulSet控制器不会自动更新StatefulSet中的Pod。用户必须手动删除Pod,以使控制器创建新的Pod。
RollingUpdate :通过.spec.updateStrategy.type 字段设置为RollingUpdate,实现了Pod的自动滚动更新,如果.spec.updateStrategy未指定,则此为默认策略。
StatefulSet控制器将删除并重新创建StatefulSet中的每个Pod。它将以Pod终止(从最大序数到最小序数)的顺序进行,一次更新每个Pod。在更新下一个Pod之前,必须等待这个Pod Running and Ready。
Partitions :通过指定 .spec.updateStrategy.rollingUpdate.partition 来对 RollingUpdate 更新策略进行分区,如果指定了分区,则当 StatefulSet 的 .spec.template 更新时,具有大于或等于分区序数的所有 Pod 将被更新。
具有小于分区的序数的所有 Pod 将不会被更新,即使删除它们也将被重新创建。如果 StatefulSet 的 .spec.updateStrategy.rollingUpdate.partition 大于其 .spec.replicas,则其 .spec.template 的更新将不会传播到 Pod。在大多数情况下,不需要使用分区。

如何清除电脑中的无用文件释放存储空间3?

清除电脑中的无用文件释放存储空间可以通过以下几种方式:
1. 使用磁盘清理工具:在Windows中,可以使用系统自带的Disk Cleanup工具,它可以扫描磁盘中的临时文件、垃圾文件、已删除文件等,并清除这些文件来释放存储空间。
2. 卸载不需要的程序:不再需要的应用程序可能占用了大量的存储空间。在控制面板中找到Programs and Features菜单,选择卸载不需要的软件。
3. 删除大文件:使用Windows自带的文件浏览器,可以搜索文件大小超过一定大小的文件,逐一查看是否需要保存,如果不需要可以删除这些大文件。
4. 清理浏览器缓存:浏览器缓存可能会占用大量的存储空间,清理浏览器缓存可以释放存储空间。在浏览器的设置菜单中,选择Clear browsing data,勾选要删除的项目,然后点击Clear data按钮即可。
5. 清理邮件附件:邮件附件可能会占用大量的存储空间,可以打开邮件客户端,查找附件文件,并删除不需要的附件文件。
6. 清理下载文件夹:下载文件夹也是文件堆积的地方,可以打开下载文件夹,删除不需要的下载文件。
7. 使用云存储:存储一些文件可以使用云存储,将文件上传到云存储中,可以释放本地存储空间。
8. 使用外接存储设备:使用外接存储设备,将不常用的文件保存到外接存储设备中,可以释放本地存储空间。
除了以上方法,还可以使用一些第三方清理工具来清除电脑中的无用文件,但要注意选择可靠的工具,以避免误删重要文件。同时,定期清理电脑中的垃圾文件和释放存储空间可以帮助电脑保持高效运行并节省存储空间。

标签:未分类 计算机 电脑网络 数据 生活

大明白知识网 Copyright © 2020-2022 www.wangpan131.com. Some Rights Reserved. 京ICP备11019930号-18