云与虚拟化结课报告

云与虚拟化结课报告

引言

  • 介绍Docker和虚拟化技术的背景和重要性
  • 概述本次课程的实验内容和目标
  • dayi在讲自己的经历)

引言1——dayi

虽然之前运维比赛平台,出过一些网络安全的题目和容器,对Docker有一定的了解,因为经常折腾也写了不少的Dockerfile,但是超级有收获的!

虚拟化这个东东,真的超级上头,但是这个东东折腾起来也是无休止无止境的,而且会越来越多。

还记得我在家里第一弄的时候也就是一个小平板,但到现在已经是超级大电牛了(一天电费接近2度,而且内存、磁盘越塞越多),塞到现在甚至已经忘了最初的目的,但是没关系,继续总会有学习和收货滴。

对,说起这个,京东京造的盘真的好烂1T的NVME3.0,写入量300G,连续开了3个月就坏掉了,而且还有0E错误,真的超级超级烂!不适合在服务器上用(虽然我觉得他也没想到我会这么个用法hhhh)

  • ESXI

虚拟化真的超级爽,之前去过医院实习,看到80多个节点,300多个处理核心,还有HA之类的,超厉害。

之所以选esxi没有选KVM是因为远程运维真的是一个技术活,教妈妈如何去开电脑真的超级艰难,虽然多次之后,我妈妈好像也学会了一点点的运维的技巧,但是还是求稳定,虽然用的许可证不是正版的许可证,但是这个也是有免费许可证的,只不过开的虚拟机数量偏少,功能偏少。

我觉得,如果学习用的话,还是临时用一点“学习版”的许可证,试试更多的新东西,在之后一定可以用得到。

说道这里,又想起来,ESXI目前还是不支持同一 HOST里有不同的CPU。之前买了个5900X,买了个主板,超级超级不稳定,隔一段时间就不知道为什么关机,也有可能是积热过多。也不是很清楚。

后来一气之下,直接买了个12700K(压岁钱全塞上了),后来又整了个E5-2680v4的双路28核56线程的洋垃圾(这东西真的很便宜),就是耗电有点多,现在一套(不带电源也就1k出头),但是发现其实虽然是不知道几手的垃圾,但是服务器CPU还是稳定,X99芯片组虽然开机慢,但是还是蛮稳定的。

ESXI开机的时候因为12代的CPU有E核心和P核心,就会导致开机的时候报Kernel错误,于是可以禁用检查:

但是如果禁用检查,可以正常进入系统,但是会导致超线程无法使用,而且系统也不是很稳定,于是尝试在BIOS里把E核心全部禁用,是可以的,性能就稍微有点衰减,但没关系!之后技好了之后就可以用LINUX KVM PVE之类的方案啦。

当时的教程其实是非常少的,当时新处理器刚出,在国外的Reddit上找到了解决的方案,试了试是可以的。后来关注了帖子,老外又找到了这一篇国内的文章。真的是蛮有戏剧性的。

不过Esxi面向的群体也不一样,服务器一般是没有小核心的,所以到现在也没有进行兼容(估计如果兼容的话要写巨量的代码),按照VMWARE的性格,我感觉他可能更想去兼容来抢占市场,这也许对他们更重要一点点(毕竟许可证真的很搞笑,一个序列号用到DEAD)。

VMware有个克隆软件,可以把物理机变成虚拟机,然后变成虚拟机之后就可以各种格式的虚拟机相互转换啦,这个软件是免费的,不是很稳定,经常报错,但是确实可以把正在运行的机子变成虚拟机,从这个方面来说,还是不错的。

PVE:

现在放到1A那边的屋子里,换了个降噪的风扇,几乎没有影响到别人,也没有光,缺点没有公网IP,只能直接内网打洞,因为是NAT4还经常打不好哈哈哈哈。

打洞确实不太稳定,最稳定的方法还是公网FRP这样TCP是最稳定的。

FRP虽然有点烂,但是可靠性还是说得过去的。

引言2——dayi的絮絮念

docker成功的原因感觉还是因为镜像仓库的大,之前docker hub还没有限制流量的时候,镜像站都被用来开电影院,但是现在的镜像,因为限制的比较严重,所以到现在,也不是很常见了。

至于之后的发展,不是很好说,但是目前来说,大家还是都在用Docker Hub的东西,现在结课啦。还是想吐槽一下,除了当年在WSL1(windows的LINUX装Docker没有成功之外),现在WSL2可以正常装啦(因为直接用了Hyper-V虚拟机)。

Docker还是挺稳定的。相比于K8S,几乎至少不会出现Centos可以正常使用,但是Debian就不是很稳定(本来打算直接用Debian部署,结果发现真的好多好奇怪的问题,也不知道是包管理器的事情还是别的事情,不是这个启动失败就是那个healthz检查失败。)Debian的包虽然也没红帽系的稳定,但是也不应该开始就无法初始化集群,真的很炸心态。索性后面换了K3S,一个是省资源,第二个也是文档相对多一点点。

其实最后还是把Kube部署成功啦(虽然还有点小毛刺,但是估计已经可以用啦,还是挺满意的)。

引言3——平台运维

之前参与了某个安全比赛,也出了一些题目,也运维了不少内容,因为为了反抄袭,所以用了Docker容器来启动和生成文件,对于Web题目肯定是要用容器的,但是关键还是可以用动态的FLAG,把动态的FLAG当做环境变量传入到容器里,然后容器可以在运行的时候把这个环境变量解析成FLAG。

具体的话其实也没什么要说的,写一个entrypoint.sh脚本,容器启动的时候开一下就好啦。

这是第二届啦,其实当时第一届参与的更多,今年事情比较多,而且也挺放心他们的就有点放了一下。

这里用了Docker的容器代理,也就是平台(.NET ASP dll 访问数据库和容器网络,然后转发出来),这样就可以让一堆容器用一个平台(端口)啦,用了西电的转发器。

其实当时还打算PR点代码,无奈自己前端能力过弱,而且ASP的代码也比较不一样,理解也需要点时间..

不过跟作者也提过一点点,那时候这个平台还没有那么普遍,于是自己有幸挂在了readme.md上面。

题目

一些小题目

这里还有道GPT的题目:

把秘密放到SYSTEM PROMPT里面,然后让GPT不要告诉任何人,实际上还是被23级的新生找到了。

一道OJ题目,flask写了一个OJ

这里是entrypoint脚本,后面是通用的啦。

当然对于题目来说,实际上上传system("cat xxx")的函数,就可以来达到“骇入”的目的。

说起这个如果DOCKER容器权限设置的不好

就容易被找到漏洞。

昨天另外一个比赛,有个题目也是Docker,但是是直接给的ssh,进入之后,因为提权之后是在容器里的root账号,一开始以为没网,穿了个busybox之后发现可以ping通223.5.5.5,于是发现是/etc/resolv.conf被改了,改了之后直接apt装包,然后转发。

还nmap扫了扫,结果是,直接通过容器访问到了他服务器集群的ikuai路由器上了。

嘘~

之后一起买的服务器过期了,就把服务器迁移到1A那边

现在平台还正常运行着https://ctf.dayi.ink

docker迁移就是爽,把docker-compose down 一下,然后把docker-comose 挂载到目录的文件打压缩包带走就可以啦。

然后到另外的机子上去解包就好。

至于已经build容器,因为空间比较少(现在看这个决策有点不是很明智),于是装了个ZFS(这个东西跟linux的许可证还不兼容),然后把docker的文件目录塞到ZFS分区,启动压缩(寻思能少占用点硬盘资源,但其实占了更多的内存)。

然后7z打包过来,记得备份下tag!!当时差点没备份导致前功后弃。

引言4——诶说起这个

之前在GITHUB上有个QQ机器人的小项目,虽然不大但是也有680的Star了,虽然Star水分比较大,但是还算是可以的。当时我记得是因为用甲骨文的ARM机子,没有成功启动二进制,我觉得这不行,于是就本地写了个脚本,fork了一下下,改了点点代码。其实还是蛮开心的,毕竟是第一次PR。

而且PR了一个GITHUBACTION 和一个entrypoint,当然也修改了下Dockerfile 其实还是蛮满意的。

这个项目:

https://github.com/SAGIRI-kawaii/sagiri-bot

相关的PR:

https://github.com/SAGIRI-kawaii/sagiri-bot/pull/400

虽然没做什么大事,但是PR进去还是蛮开心的。

entrypoint.sh

引言5——讲真docker-compose真的蛮好用的

有些时候,把文件塞Docker里,经常会因为不小心删掉容器,然后数据就没了,虽然可以-v来映射目录,但是说实在的,不是特别方便。而且特别是要迁移服务器或者服务器要重新格式化文件的时候就会有点点问题。

比如这个网站https://cmd.dayi.ink

真的是蛮方便的,虽然说,上次我尝试迁移(从arm64->amd64)好像数据库容易崩溃,隔一段时间就502(NGINX反代),但是还是能正常运行,到时候只需要把pgsql的数据库导出下,然后迁移一下就可以,估计是生成的文件不是很兼容。

走的时候打个包,就可以啦

就比如这些,当时迁移的时候超简单!

文件:

gzctf

引言6——docker还是不错的

其实我感觉docker最好的就是(但是要Dockerfile开源的前提)就是省去了大家的时间,虽然确实是用了更多的空间(之前挂QQ机器人的时候总是把我硬盘吃满,特别是LOG文件!一定要限制大小,不然会超级惨),但是在一样的容器,其实是更省空间的。

空间换时间,这在算法设计上是一个很常见的操作,正因为如此,感觉docker最大的好处就是可以省超多的时间,在硬盘空间足够的情况下,直接下镜像,跑起来,分发和部署超级方便。

PLANTUML生成了点图显得没那么空。

Kube 部署实训项目

docker-compose 部署实训内容

差不多这个图:

  • 数据库mysql
  • 数据库管理器 phpmyadmin
  • 闸瓦!项目(MVN先编译为jar就好)
  • 然后mysql挂载到本地目录(docker卷),持久化存储!

docker-compose.yaml

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile
# ports:
# - 14101:8080
depends_on:
- db
- phpmyadmin
environment:
- mysql_host=db
- mysql_database=product
restart: always
networks:
my_network:
ipv4_address: 192.168.188.2 # 指定容器的IP地址

db:
image: mysql:8.0.34-oracle
environment:
- MYSQL_ROOT_PASSWORD=123456
volumes:
- ./_data:/var/lib/mysql
- ./sql.sql:/docker-entrypoint-initdb.d/sql.sql
restart: always
networks:
my_network:
ipv4_address: 192.168.188.3 # 指定容器的IP地址

phpmyadmin:
image: arm64v8/phpmyadmin
# ports:
# - 14102:80
depends_on:
- db
environment:
- PMA_HOST=db
- PMA_USER=root
- PMA_PASSWORD=123456
restart: always
networks:
my_network:
ipv4_address: 192.168.188.4 # 指定容器的IP地址

networks:
my_network:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.188.0/24

文件目录

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
35
root@k3s-master-ovo-2:~/java-spring/java-spring# tree -L 5
.
|-- Dockerfile
|-- LICENSE
|-- README.md
|-- docker-compose.yaml
|-- docs
| `-- Rabbit.md
|-- pom.xml
|-- sql.sql
|-- src
| |-- main
| | |-- java
| | | |-- com
| | | | `-- test
| | | `-- net
| | | `-- dabbit
| | `-- resources
| | |-- application.yml
| | |-- generatorConfig.xml
| | `-- static
| | |-- css
| | |-- dist
| | |-- images
| | |-- js
| | |-- pages
| | |-- plugins
| | |-- static_small_23_9_19.zip
| | `-- welcome
| `-- test
| `-- java
`-- tools
`-- sql_fix.sql

21 directories, 11 files

Dockerfile

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
FROM maven:latest as builder
WORKDIR /app
COPY ./src /app/src
COPY pom.xml /app/pom.xml
# RUN mvn package
# 国内源构建
RUN echo '<?xml version="1.0" encoding="UTF-8"?>\
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"\
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0\
https://maven.apache.org/xsd/settings-1.0.0.xsd">\
<mirrors>\
<mirror>\
<id>aliyunmaven</id>\
<mirrorOf>central</mirrorOf>\
<name>Aliyun Central</name>\
<url>https://maven.aliyun.com/repository/central</url>\
</mirror>\
</mirrors>\
</settings>' > /app/settings.xml && mvn -s /app/settings.xml package


FROM openjdk:8u342-jdk-oracle
WORKDIR /opt/dayi/
COPY --from=builder /app/target/skd21_dayi_springboot.jar /opt/dayi/skd21_dayi_springboot.jar
CMD ["java", "-jar","skd21_dayi_springboot.jar"]

容器技术

容器技术的核心原理是基于Linux内核的Namespace和Cgroups功能,这些功能允许将操作系统资源进行隔离和限制,从而实现了用户空间的分割,创造了轻量级、独立的容器。

其实LXC也是容器哦。

LXC也挺好用的。也是一种容器技术。

Namespace

Linux的Namespace是一种内核功能,它允许将不同的系统资源隔离开来,使得每个容器看起来像拥有自己独立的操作系统环境。不同类型的Namespace用于隔离不同的资源,例如:

  1. PID Namespace:每个容器拥有独立的进程ID命名空间,使得容器内的进程看起来是在一个隔离的进程环境中运行,不受其他容器的影响。

  2. Mount Namespace:容器可以有自己的文件系统挂载点,使得容器内的文件系统与宿主系统分开,提高了文件系统的隔离性。

  3. Network Namespace:每个容器拥有独立的网络命名空间,可以有自己的网络接口、IP地址和路由表,使得容器可以创建自己的网络拓扑。

  4. User Namespace:用户命名空间允许容器内的用户和组映射到宿主系统的不同用户和组,增加了安全性和隔离性。

  5. IPC Namespace:进程间通信(IPC)命名空间隔离了容器内的进程间通信资源,如消息队列和信号量。

Cgroups

Cgroups(Control Groups)是Linux内核的另一个关键功能,它允许对系统资源进行限制和管理,以确保容器之间的资源隔离。Cgroups可以用来限制CPU、内存、磁盘I/O、网络带宽等资源的使用。通过Cgroups,容器可以被限制在分配的资源范围内,避免了资源争用和不合理的资源占用。

容器的优势

容器技术带来了许多优势,包括但不限于:

  1. 轻量级:由于容器共享宿主操作系统内核,它们比传统虚拟机更轻量,启动更快,占用更少的内存和磁盘空间。

  2. 隔离性:通过Namespace和Cgroups,容器提供了良好的隔离,每个容器看起来像一个独立的操作系统环境,避免了应用之间的干扰。

  3. 可移植性:容器可以在不同的环境中轻松部署,因为它们包含了应用程序和所有依赖项,不受宿主系统的影响。

  4. 高效管理:容器可以使用编排工具(如Docker Compose、Kubernetes等)进行集中管理,简化了应用的部署和扩展。

  5. 资源利用率:容器可以更好地利用宿主系统的资源,因为它们可以在同一物理服务器上运行多个容器,共享资源。

容器技术已经成为现代应用开发和部署的重要组成部分,它们使得开发者能够更快速地交付应用程序,提高了基础设施的利用率,并促进了微服务架构和云计算的发展。通过合理使用Namespace和Cgroups,容器技术提供了一种强大的方式来实现应用隔离和资源管理。

虚拟化技术

虚拟化技术指的是一种通过组合或分区现有的计算机资源,使得这些资源表现为一个或多个操作环境,从而提供优于原有资源配置的访问方式的技术[1]。虚拟化技术在云计算环境中有着极其重要的作用,其能够对云计算平台中的全部资源进行有效的管理和利用,虚拟化技术分为完全虚拟化技术和半虚拟化技术两种,两种虚拟化技术的操作方式有所不同,完全虚拟化技术是整体整合物理资源后进行资源分配管理,而半虚拟化技术则首先对物理资源进行分割,而后在各自分割领域内进行资源的管理和利用。虚拟化技术是云计算平台发挥作用的关键所在,云计算平台中的大量数据均需要通过虚拟化技术来进行保存、分配、整理,因此随着云计算数据分析需求不断提高,也要不断优化虚拟化技术的性能,这样才能更好地推动云计算平台的应用和发展。

① 基于硬件的虚拟化:也称为传统的虚拟化技术,是通过模拟宿主机底层硬件环境,在硬件物理资源的基础上,虚拟出多个OS,然后在OS的基础上构建相对独立的程序运行环境,如常见的VMware Workstation、VirtualBox、QEMU 就是使用这种技术。通过这种技术虚拟出来的OS称为虚拟机,由于虚拟机是模拟硬件搭建操作系统,实现虚拟出来的各操作系统之间的隔离,所以隔离级别更高、安全性更强。但由于虚拟机模拟的是完整的操作系统,体积大、对宿主机的系统资源占用多、启动慢、不方便迁移。

② 基于软件的虚拟化:操作系统的内核通过创建多个虚拟的操作系统实例(内核和库)来隔离不同的进程。Docker容器技术就是在操作系统层面上实现虚拟化,直接复用宿主机的操作系统,因此更加轻量级。与传统的虚拟化技术相比,启动和停止速度更快、对系统资源需求很少、以及灵活的类似Git设计理念的操作和Docker镜像的自动化创建和部署机制,在生产实践中能够大幅度提高工作效率并使流程标准化。

实验相关

实验1: 安装和使用Docker

  • 讨论Docker的基本概念和架构
  • 总结Docker的安装步骤和基本使用方法

Docker的基本概念和背景

Docker是一种容器化平台,它允许开发者将应用程序和所有相关的依赖项打包到一个独立的容器中。这个容器包括应用程序代码、运行时环境、系统工具、库和配置文件,确保应用在不同的环境中能够一致运行。以下是Docker的基本概念:

  1. 容器:Docker容器是一个轻量级、独立的执行单元,可以在任何支持Docker的环境中运行。它们隔离了应用程序和其宿主系统,因此可以确保应用的可移植性和一致性。

  2. 镜像:Docker镜像是容器的模板,包含了应用程序的所有组件和依赖项。它们是只读的,可以用来创建容器实例。镜像的分发和共享使得应用程序部署变得非常简单。

  3. Docker引擎:Docker引擎是Docker平台的核心组件,负责构建、运行和管理容器。它包括Docker守护进程、REST API和命令行工具。

  4. Docker Hub:Docker Hub是一个在线的镜像仓库,允许用户分享和获取Docker镜像。这使得开发者可以轻松地找到和使用已有的容器镜像。

Docker的背景是,它在应用程序开发和部署中引入了革命性的变化。传统的虚拟化技术需要完整的操作系统,而Docker使用容器技术,允许多个容器共享同一个操作系统内核,从而更加高效地利用资源。这使得开发者可以更快速、可靠地构建、交付和运行应用程序,促进了DevOps文化的发展,提高了应用程序的可移植性和可伸缩性。

虚拟化技术的基本概念和背景

虚拟化技术是一种将硬件资源抽象成多个虚拟环境的技术,使多个操作系统和应用程序能够在同一物理服务器上并行运行。以下是虚拟化技术的基本概念:

  1. 虚拟机(VM):虚拟机是一种完整的虚拟操作系统实例,包括独立的内核、内存、磁盘和网络接口。虚拟机使得多个操作系统可以同时运行在同一物理服务器上。

  2. 宿主机:宿主机是物理服务器,它托管了一个或多个虚拟机。它的操作系统被称为宿主操作系统。

  3. Hypervisor:Hypervisor是虚拟化软件,允许多个虚拟机在宿主机上并行运行。它有两种类型:Type 1(裸机)Hypervisor在硬件上直接运行,而Type 2 Hypervisor在宿主操作系统上运行。

虚拟化技术的背景是,它解决了服务器资源利用率低下和资源隔离的问题。通过虚拟化,可以更灵活地管理和分配资源,降低硬件成本,提高数据中心的效率。虚拟化技术也为云计算提供了基础,使得云服务提供商能够提供虚拟机实例,供用户按需使用。

Docker和虚拟化技术都在现代应用程序部署和管理中发挥着关键作用。Docker通过容器化技术提供了轻量级的应用隔离和部署解决方案,而虚拟化技术提供了更广泛的硬件虚拟化和资源管理能力。这两种技术的结合使得应用程序的构建、交付和运行更加高效和可靠。

实验2: Docker镜像常用命令的使用

其实我觉得比较值得说的就是OVERLAY了

这个文件系统bia,说好,确实分层挺好的,说不好,估计是很多小的overlay就会叠一起,稍微有点差别就再建立一层。

Docker镜像是容器的基础构建块,它包含了一个应用程序及其依赖项的文件系统。

常用Docker镜像命令:

  1. **docker pull <image_name>[:tag]**:从Docker Hub或其他镜像仓库拉取指定镜像。

  2. docker images:列出本地已经下载的镜像列表,包括镜像名称、标签、大小等信息。

  3. **docker rmi <image_name>[:tag]**:删除本地的镜像。

  4. **docker inspect <image_name>[:tag]**:查看有关特定镜像的详细信息,包括元数据、历史、依赖关系等。

  5. **docker history <image_name>[:tag]**:查看镜像的构建历史,包括每个镜像层的详细信息。

  6. **docker save <image_name>[:tag] -o <output_file.tar>**:将镜像保存为tar文件,用于导出和共享。

  7. **docker load -i <input_file.tar>**:从tar文件中加载镜像。

  8. **docker build -t <image_name>[:tag] <Dockerfile_path>**:使用Dockerfile构建新的镜像。

overlay2 文件系统

overlay2是Docker默认使用的存储驱动程序之一,用于管理和组织镜像和容器的文件系统。它是overlay存储驱动的改进版本,并提供了更高的性能和更好的稳定性。以下是有关overlay2的详细内容:

  1. 分层存储:overlay2使用分层文件系统来存储容器和镜像的文件。每个镜像都可以看作是一个或多个只读层的叠加,以及一个可写层(容器层)。这种分层结构使得容器共享相同的只读层,从而节省磁盘空间。

  2. 镜像层叠加:当一个容器使用某个镜像时,Docker会创建一个新的容器层,叠加在该镜像的只读层上。这个新容器层是可写的,容器可以在其中进行文件修改和添加。

  3. 性能和效率:overlay2相对于其它存储驱动,如aufs和overlay,具有更好的性能和效率。它能够更快速地构建和启动容器,并且能够更有效地管理文件系统层。

  4. 多层叠加:overlay2支持多个镜像层的叠加,这使得容器可以同时引用多个基础镜像,而不需要在磁盘上复制相同的内容。

  5. **Copy-On-Write (COW)**:overlay2使用写时复制(Copy-On-Write)策略,当容器对文件进行修改时,它只会复制被修改的文件,而不是整个镜像层,这降低了I/O开销。

  6. 容器隔离:overlay2确保每个容器的文件系统都是独立的,容器之间不会相互影响,从而实现了文件系统的隔离。

overlay2是Docker默认的存储驱动程序之一,它提供了高性能、有效的文件系统管理,是Docker生态系统中的重要组成部分,确保了容器的隔离和效率。

实验3: 搭建Docker私有仓库

其实docker能把仓库下发,真的超级不错,虽然你往上面塞也没人管哈哈哈哈。

  1. 安全性:

    • 私有仓库允许你存储和管理敏感或专有的镜像,而无需将其公开在Docker Hub或其他公共注册表上。这对于包含敏感信息或专有代码的应用程序非常重要。
  2. 控制版本和发布:

    • 私有仓库使团队能够完全掌控镜像的版本和发布。这对于确保在生产环境中使用的镜像是经过审查和测试的稳定版本非常重要。
  3. 性能优化:

    • 使用私有仓库可以减少与公共注册表之间的网络传输,提高拉取和推送镜像的性能。在大型团队中,这对于加快构建和部署过程非常重要。
  4. 离线支持:

    • 私有仓库允许在没有互联网连接的情况下使用Docker镜像。这对于在封闭网络环境中工作的场景非常关键。
  5. 定制化和自动化:

    • 通过搭建私有仓库,你可以定制镜像的构建流程,并集成自动化流水线。这有助于确保每个构建的一致性和可重复性。
  6. 节省带宽成本:

    • 对于大型组织而言,使用私有仓库可以降低带宽成本,因为团队成员不必从公共注册表中拉取相同的镜像,而是可以从内部仓库中获取。

搭建的话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 步骤 1: 安装Docker Registry
docker run -d -p 5000:5000 --restart=always --name registry registry:2

# 步骤 2: 配置TLS(可选)
mkdir -p certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
docker run -d -p 5000:5000 --restart=always --name registry -v $(pwd)/certs:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key registry:2

# 步骤 3: 配置访问控制(可选)
mkdir auth
htpasswd -Bbn your_username your_password > auth/htpasswd
docker run -d -p 5000:5000 --restart=always --name registry -v $(pwd)/certs:/certs -v $(pwd)/auth:/auth -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -e REGISTRY_AUTH=htpasswd -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry:2

# 步骤 4: 测试私有仓库
docker pull hello-world
docker tag hello-world localhost:5000/hello-world
docker push localhost:5000/hello-world
docker pull localhost:5000/hello-world

后面K8S因为没有dockerfile的构建,所以其实也需要一个镜像库,如果你不是很希望把image塞网上的话。

实验4: 构建自定义镜像

自定义镜像的构建原理是通过编写Dockerfile文件来定义镜像的构建过程。Dockerfile是一个文本文件,其中包含一系列指令,Docker引擎会根据这些指令来创建一个新的镜像。每个指令都会在一个新的临时容器中执行,并生成一个新的容器层。这些容器层叠加在一起,最终形成一个镜像。

以下是一些常见的Dockerfile指令和其原理:

  1. FROM:指定基础镜像,新镜像将基于该基础镜像构建。

  2. RUN:在临时容器中执行命令,通常用于安装软件包、配置环境等。

  3. COPY:将本地文件复制到容器中的指定路径。

  4. ADD:类似于COPY,但支持更多功能,如从URL复制文件并自动解压缩。

  5. WORKDIR:设置容器中的工作目录,后续指令将在该目录下执行。

  6. EXPOSE:声明容器运行时监听的端口。

  7. CMD:指定容器启动后要执行的默认命令或应用程序。

  8. ENTRYPOINT:类似于CMD,但不可被覆盖,可以作为容器的主要执行入口点。

当Docker引擎构建镜像时,它会按照Dockerfile中的顺序执行这些指令,每个指令都会生成一个新的镜像层。这些镜像层会被缓存,如果没有发生变化,将会被重复使用,从而提高构建效率。

最终,Docker引擎将所有镜像层叠加在一起,形成一个完整的镜像,包含了所有定义在Dockerfile中的配置和文件。这个自定义镜像可以用于创建容器实例,并运行用户指定的应用程序或服务。

自定义镜像的构建原理是基于Dockerfile中的指令来定义构建过程,每个指令都会生成一个新的容器层,最终组合成一个完整的镜像,用于容器的部署和运行。这个过程是可重复、自动化的,使得镜像的构建和管理变得高效和可靠。

技巧和注意事项:

  1. 多阶段构建:
    如果你需要减小最终镜像的大小,可以考虑使用多阶段构建。在单个Dockerfile中定义多个FROM指令,每个指令代表一个构建阶段。这可以通过减少镜像层数来降低最终镜像的大小。

  2. 利用.dockerignore文件:
    创建一个名为.dockerignore的文件,类似于.gitignore,用于指定在构建镜像时要排除的文件和目录。这有助于减小上下文(构建上下文)的大小,加快构建过程。

  3. 复制文件和目录:
    使用COPY指令将本地文件和目录复制到镜像中。这是将应用程序代码、配置文件等添加到镜像的常见方式。

  4. 选择合适的基础镜像:
    选择适合你应用程序需求的基础镜像。不同的基础镜像提供了不同的环境和工具,选择适当的基础镜像有助于减小镜像大小并提高安全性。

  5. 使用构建缓存:
    Docker使用构建缓存以加快构建过程。确保在Dockerfile中更改的步骤尽可能地位于文件中的后面,以充分利用构建缓存。

相关内容:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# 步骤 1: 拉取镜像并安装SSH,生成自定义镜像

# 拉取CentOS 7镜像
docker pull centos:7

# 创建并启动一个容器
docker run -itd --name centos_sshd centos:7 bash

# 进入容器
docker exec -it centos_sshd bash

# 在容器内切换镜像源到CERNET
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.cernet.edu.cn/centos|g' \
-i.bak \
/etc/yum.repos.d/CentOS-*.repo

# 安装SSH服务和其他工具
yum -y install openssh-server net-tools
mkdir -pv /var/run/sshd

# 创建SSH启动脚本
echo "/usr/sbin/sshd -D" > /auto_sshd.sh
chmod +x /auto_sshd.sh

# 设置root密码
echo "root:123456" | chpasswd

# 生成SSH密钥
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key

# 生成更多的SSH密钥(可选)
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

# 退出容器
exit

# 构建自定义镜像
docker commit centos_sshd centos7_sshd:1.0

# 步骤 1.2: 测试容器是否可用

# 启动一个新容器
docker run -itd --name centos_7.0-1 centos7_sshd:1.0

# 查看容器是否运行
docker ps

# 测试SSH连接(需要填写实际容器的IP)
ssh root@172.17.0.6
# 输入密码:123456

# 步骤 1.4: 查看镜像和容器信息
docker inspect centos7_sshd:1.0

# 步骤 2: 删除全部容器(可选)
docker rm -f $(docker ps -aq)

# 删除SSH无法连接的known_hosts文件(可选)
rm -rf ~/.ssh/known_hosts

# 步骤 3.1: 创建Dockerfile文件

# 创建一个目录
mkdir -pv /opt/centos_sshd
cd /opt/centos_sshd

# 创建Dockerfile文件并编辑
vi Dockerfile

# 在Dockerfile中添加以下内容:
# 使用CERNET镜像源的CentOS 7作为基础镜像
FROM centos:7
MAINTAINER dayi
# 切换镜像源到CERNET
RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.cernet.edu.cn/centos|g' \
-i.bak \
/etc/yum.repos.d/CentOS-*.repo
# 安装必要的软件包
RUN yum -y install openssh-server net-tools && \
mkdir -pv /var/run/sshd && \
echo "/usr/sbin/sshd -D && nohup" > /auto_sshd.sh && \
chmod +x /auto_sshd.sh && \
echo "root:123456" | chpasswd && \
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && \
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N '' && \
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''
# 暴露SSH端口
EXPOSE 22
# 启动SSH服务
CMD ["bash","/auto_sshd.sh"]

# 步骤 3.2: 构建自定义镜像

# 切换到Dockerfile所在目录
cd /opt/centos_sshd

# 构建自定义镜像
docker build -t centos7_sshd:2.0 .

# 查看已构建的镜像
docker images

# 步骤 3.3: 启动容器

# 启动新容器
docker run -itd --name centos7_ssh_2 centos7_sshd:2.0

# 查看容器IP地址
docker exec -it centos7_ssh_2 ifconfig

# 步骤 3.4: 启动失败(如果需要重新启动)

# 删除全部容器
docker rm -f $(docker ps -aq)

# 删除SSH无法连接的known_hosts文件
rm -rf ~/.ssh/known_hosts

实验5: Docker容器常用命令的使用

  • containerd 的作用和关键概念

在Docker容器常用命令的实验中,了解和掌握容器的关键概念和管理方法是非常重要的。其中,containerd 是一个关键的组件,它在 Docker 中扮演着重要的角色。

containerd 的作用和关键概念

containerd 是一个基于开放标准的容器运行时管理器,它负责在容器生命周期中执行核心容器操作,如创建、运行、停止和删除容器。以下是关于 containerd 的重要信息:

  1. 容器运行时:containerd 充当容器运行时的核心组件,它负责与容器引擎(如 Docker)协同工作,管理容器的生命周期。

  2. OCI 标准:containerd 遵循 Open Container Initiative(OCI)标准,这是一个开放的行业标准,用于定义容器的格式和运行时规范。这意味着容器d 使用 OCI 标准来创建和管理容器。

  3. 容器镜像:containerd 使用 OCI 标准的容器镜像格式,这与 Docker 镜像兼容。容器镜像包括文件系统层、元数据和运行时配置。

  4. 容器快照:containerd 使用容器快照(snapshots)来创建容器的文件系统视图。这允许多个容器共享相同的只读文件系统层,并为每个容器提供一个独立的可写层,从而实现了容器的隔离。

  5. 容器任务:containerd 使用容器任务(tasks)来表示容器实例。每个容器任务包括一个容器进程和相关的资源配置,如 CPU 和内存限制。

  6. 容器标签:容器可以通过标签进行分类和组织,这有助于管理和识别容器实例。

containerd 是一个用于管理容器的守护进程,它提供了容器的核心功能,包括容器的创建、运行、停止和删除。以下是 containerd 的关键概念和作用:

containerd 和 Docker

在 Docker 中,Docker 引擎使用 containerd 作为其底层容器运行时。Docker CLI(命令行界面)通过 Docker REST API 与 Docker 引擎通信,而 Docker 引擎使用 containerd 来实际执行容器操作。这种架构将容器管理与高级 Docker 功能(如构建镜像、编排和服务管理)分开,使容器管理更加模块化和可扩展。

相关实验步骤

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
35
# 步骤 1: 创建和启动容器CentosTest
docker pull centos:7
docker create -it --name CentosTest centos:7

# 步骤 2: 启动容器并执行命令
docker start CentosTest
docker exec -it CentosTest /bin/bash
ls
exit

# 步骤 3: 查看容器状态
docker ps -a

# 步骤 4: 创建并启动Nginx容器NginxTest,映射到80端口
docker run -dit -p 80:80 --name NginxTest nginx:latest

# 步骤 5: 替换容器内的index.html
echo "欢迎使用Docker容器" >> index.html
docker cp index.html NginxTest:/usr/share/nginx/html

# 步骤 6: 导出容器为tar文件
docker export -o nginxtest.tar NginxTest
ls

# 步骤 7: 导入容器为新镜像
docker import nginxtest.tar nginx:v1.0
docker images

# 步骤 8: 输出容器和宿主机的端口映射关系
docker inspect -f {{.NetworkSettings.Ports}} NginxTest
docker port NginxTest

# 步骤 9: 删除容器NginxTest和CentosTest
docker rm -f NginxTest CentosTest

实验6: Docker资源控制

以下是实验步骤和总结的简要总结代码块:

常用命令的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建和启动容器
docker pull centos:7
docker run -dit --name CentosTest centos:7

# 在容器内执行命令
docker exec -it CentosTest /bin/bash

# 替换容器内的文件
docker cp index.html NginxTest:/usr/share/nginx/html

# 导出和导入容器
docker export -o nginxtest.tar NginxTest
docker import nginxtest.tar nginx:v1.0

# 删除容器
docker rm -f NginxTest CentosTest

Docker资源控制

1
2
3
4
5
6
7
8
9
10
11
12
13
# 限制CPU使用率
docker run -dit --name centos1 centos:7 /bin/bash
docker run -dit --name centos2 --cpu-quota 20000 centos:7 /bin/bash

# 设置CPU权重
docker run -dit --name=centos3 --cpu-shares 512 centos:7 /bin/bash
docker run -dit --name=centos4 --cpu-shares 1024 centos:7 /bin/bash

# 监控资源使用情况
docker stats

# 查看内存限制
cat /sys/fs/cgroup/memory/docker/<容器编号>/memory.limit_in_bytes

总结
这两个实验,我学到了如何使用Docker来管理容器和控制资源。这些技能对于实际应用和系统管理非常有帮助。我期待将来能够在云计算和容器化技术领域取得更多的成就。

实验7: Docker网络管理应用

  • 探讨Docker网络的不同类型和用途

1. 桥接网络(Bridge Network):

  • 用途: 桥接网络是 Docker 默认的网络模式,它使得容器可以相互通信,并且容器与宿主机之间也可以通信。
  • 创建命令:
    1
    docker network create my-bridge-network
  • 特点: 桥接网络在同一宿主机上的容器之间提供了隔离,并且容器可以使用容器名称进行通信。

2. 主机网络(Host Network):

  • 用途: 容器直接使用宿主机的网络命名空间,与宿主机共享网络。这样容器就可以直接使用宿主机的网络接口,无需进行端口映射。
  • 创建命令:
    1
    docker run --network host my-container
  • 特点: 主机网络模式提供了最大的网络性能,但失去了容器间网络隔离的优势。

3. 覆盖网络(Overlay Network):

  • 用途: 覆盖网络允许跨多个宿主机的容器通信,适用于在集群中运行的应用程序。常用于 Docker Swarm 和 Kubernetes 集群。
  • 创建命令:
    1
    docker network create --driver overlay my-overlay-network
  • 特点: 覆盖网络通过在宿主机之间创建虚拟网络来实现容器间通信,支持容器跨宿主机部署。

4. None 网络:

  • 用途: 在 None 网络模式下,容器不会加入到任何网络中。这意味着容器无法通过网络与外部通信。
  • 创建命令:
    1
    docker run --network none my-container
  • 特点: 容器内部只能使用本地回环接口,适用于一些特殊场景,如需要完全隔离容器的情况。

5. Macvlan 网络:

  • 用途: Macvlan 网络允许容器获得物理网络上的独立 MAC 地址,使得容器可以直接与物理网络交互,就像是物理设备一样。
  • 创建命令:
    1
    docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 my-macvlan-network
  • 特点: 适用于需要容器直接连接到物理网络的场景,每个容器都会获得物理网络上的 IP 地址。

实验8: 利用Docker实现容器互连

  • 解释容器互连的概念和需求
  • 演示如何通过Docker实现容器之间的互连

实验目的
本实验旨在探索和理解 Docker 容器之间的网络互连。通过创建和配置容器,在两个不同的虚拟机上建立网络通信,以满足容器间互连的需求。

实验步骤

  1. 准备工作:

    • 克隆两个虚拟机(node-a 和 node-b)并为它们分配静态 IP 地址。
    • 确保虚拟机的网络配置正确。
  2. 创建和配置容器:

    • 在 node-a 上创建自定义网络网桥 node1-br0 和容器 node1_busybox,并分配 IP 地址 172.100.0.10。
    • 在 node-b 上创建自定义网络网桥 node2-br0 和容器 node2_busybox,并分配 IP 地址 172.100.1.10。
    • 测试容器是否能够访问各自的网桥。
  3. 测试容器间网络连通性:

    • 初始测试结果显示容器无法直接通信。
    • 解决意外的网络通信问题,如关闭 tun 网卡。
  4. 配置路由和 iptables:

    • 在 node-a 和 node-b 上添加路由规则,以实现容器间通信。
    • 清除 iptables 规则,并设置默认策略为接受,以确保网络连通。
  5. 最终测试:

    • 在路由和 iptables 配置之后,再次测试,确保容器能够成功地相互通信。

实验总结

  1. 网络互连挑战:实验展示了在不同 Docker 网络环境下建立容器间通信的复杂性,尤其是涉及不同主机上的容器时。
  2. 网络配置的重要性:正确配置路由和 iptables 规则对于容器间的网络连通至关重要。
  3. Docker 网络理解:通过本实验,加深了对 Docker 网络概念的理解,包括自定义网络、网桥和建立不同 Docker 网络之间连接的方法。
  4. 排错经验:提高了排错能力,特别是处理网络相关问题时的技能。

理解 Docker 容器网络互连提供了基础,提升了网络配置和排错技能,为在云计算和虚拟化领域的未来学习和工作打下坚实的基础。

实验9: Docker数据卷和数据卷容器应用

  • 强调数据卷的重要性和用途
  • 提供数据卷和数据卷容器的实际应用场景

实验目的
本实验旨在掌握 Docker 数据卷和数据卷容器的使用方法。数据卷是 Docker 容器中用于数据持久化和共享的一种机制。通过创建数据卷、挂载宿主机文件或目录到容器数据卷,以及创建和使用数据卷容器,加深对这些概念的理解。

实验步骤

  1. 创建数据卷:

    • 创建一个名为 mycentos 的容器,并为该容器添加一个数据卷,位于容器内的目录 /opt/data。
    • 在数据卷中创建文件,并在宿主机上查找数据卷目录以验证数据的一致性。
  2. 挂载宿主机文件或目录到容器数据卷:

    • 挂载宿主机的文件到容器中,并设置为只读模式,验证容器内部无法修改只读挂载的数据。
    • 挂载宿主机目录到容器中,并在容器内部添加文件,确认这些文件同时出现在宿主机的对应目录中。
  3. 创建数据卷容器:

    • 创建一个包含两个数据卷 /opt/volume1 和 /opt/volume2 的容器 my_container。
    • 创建另一个容器 my_centos,并从 my_container 容器中挂载这两个数据卷,验证数据卷容器的有效性。

实验总结

  1. 数据卷的重要性:
    • 数据卷为 Docker 容器提供了有效的数据持久化和共享机制,对于保证数据的持续性和安全性至关重要,尤其在生产环境中。
  2. 挂载的灵活性:
    • 实验展示了如何挂载宿主机的文件和目录到容器中,可以设置为只读或读写模式,增加了 Docker 在处理不同应用场景时的灵活性。
  3. 数据卷容器的作用:
    • 数据卷容器方便了多个容器之间的数据共享和维护。通过从一个容器挂载数据卷到另一个容器,可以轻松地实现数据的共享和管理。

强调了 Docker 数据卷和数据卷容器的实际应用场景,以及它们在容器化环境中的重要性。

实验10: Compose编排工具应用

  • 介绍Docker Compose的作用和基本用法
  • 演示如何使用Compose编排多个容器应用

实验目的
本实验的目的是介绍 Docker Compose 编排工具的作用和基本用法,以及演示如何使用 Compose 编排多个容器应用。

实验内容与步骤

  1. 安装 Docker Compose:

    • 确保实验主机能够连接外网,已经安装 Docker CE 版本 18.03.0-ce,并关闭了防火墙和 SELinux。
    • 下载并安装 Docker Compose,然后测试安装结果。
  2. 使用 Docker Compose 编排启动镜像:

    • 创建一个文件目录用于存放配置文件。
    • 编写 Docker Compose 配置文件,定义多个服务以编排容器应用。
    • 启动服务,并通过浏览器访问应用程序以测试。

实验总结

  1. Docker Compose 的便利性:

    • Docker Compose 是一个方便的工具,可以简化多容器应用的配置和管理。通过配置文件定义整个应用的结构和配置,使得管理容器化应用更加便捷。
  2. 实际操作中的学习:

    • 通过实践,加深了对容器化技术和服务之间相互作用的理解。配置文件中的各个参数有特定的用途,如环境变量设置、卷挂载等。
  3. 问题解决能力的提升:

    • 在实验中,学会了解决一些常见问题,如服务依赖关系、端口映射等,提升了问题解决能力。

这次实验不仅增强了对 Docker Compose 的理解,还提升了在实际环境中部署和管理多容器应用的能力。通过这种实践积累了宝贵的经验,为应对更复杂的项目打下了基础。

实验12: Rancher平台部署应用

  • 简介Rancher平台的特点和功能
  • 演示如何使用Rancher部署和管理容器应用

实验步骤

  1. 拉取Rancher镜像:

    • 使用命令 docker pull rancher/server:stable 拉取Rancher服务器镜像。
  2. 利用Rancher镜像生成Rancher容器:

    • 使用命令 docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:stable 启动Rancher容器。
  3. 复制Rancher脚本代码到主机:

    • 使用命令 sudo docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.11 http://192.168.5.100:8080/v1/scripts/33363BDEA2105F76C889:1577750400000:7pDzaq5dOUcHCFdLqfZ2lyvGex0 复制Rancher脚本代码到主机。
  4. 添加主机成功:

    • 进入Rancher平台,点击底部的”创建”按钮,添加主机。

总结
Rancher平台是一个用于部署和管理容器应用的强大工具。通过拉取Rancher镜像、生成Rancher容器,并复制Rancher脚本代码到主机,可以创建一个Rancher集群并添加主机。然后,您可以使用Rancher平台来部署、管理和监控容器应用,实现容器化应用程序的轻松部署和维护。

实验13: Jenkins持续化部署工具应用

  • 介绍Jenkins作为持续集成和持续部署工具的角色
  • 展示如何利用Jenkins实现容器化持续部署
  1. Jenkins 的作用:

    • Jenkins 是一个强大的持续集成和持续部署工具,可以自动化构建、测试和部署应用程序,提高开发团队的效率和质量。
  2. 持续化部署的重要性:

    • 持续化部署能够实现快速、可靠的应用程序交付,减少人为错误,提高应用程序的可靠性和稳定性。
  3. Jenkins 的配置和扩展:

    • Jenkins 可以根据项目的需求进行灵活配置和扩展,通过插件和脚本可以满足各种不同的构建和部署场景。

这次实验介绍了 Jenkins 作为持续化部署工具的应用,加深了对持续集成和持续部署的理解,为实际项目中的自动化构建和部署提供了基础。

这里也部署了一个

这个工具还是蛮好用的。

实验14 &15: Kubernetes部署 和 Kubectl常用命令使用

  • 简要介绍Kubernetes的背景和特点
  • 解释Kubernetes在容器编排中的作用
  • 提供Kubectl命令的概述
  • 指导如何使用Kubectl管理Kubernetes集群

实验14 & 15: Kubernetes部署 和 Kubectl常用命令使用

实验背景和特点
Kubernetes是一个用于自动化容器部署、扩展和管理的开源平台。它具有以下特点:

  • 自动化容器编排:Kubernetes可以自动部署、伸缩和管理容器,使应用程序在容器中运行变得更加容易。
  • 高可用性:Kubernetes支持多节点集群,确保应用程序的高可用性和冗余。
  • 自动负载均衡:Kubernetes可以自动分发流量,确保负载均衡,提高应用程序的稳定性。
  • 自我修复:Kubernetes可以自动检测和修复容器故障,减少了人工干预的需要。
  • 伸缩性:Kubernetes支持水平和垂直伸缩,根据负载自动调整容器的数量。
  • 丰富的生态系统:Kubernetes有一个庞大的生态系统,包括插件、工具和服务,可以满足不同需求的应用程序。

Kubernetes在容器编排中的作用
Kubernetes在容器编排中起到了关键的作用,它负责以下任务:

  • 调度容器:Kubernetes将容器分配到可用的节点上,确保资源的合理利用和负载均衡。
  • 自动伸缩:Kubernetes可以根据负载自动伸缩容器,以满足应用程序的需求。
  • 网络管理:Kubernetes提供了网络解决方案,允许容器之间进行通信,并支持服务发现。
  • 存储管理:Kubernetes提供了持久化存储选项,以确保数据的持久性和可靠性。
  • 自我修复:Kubernetes可以监控容器的健康状态,并在容器故障时自动修复。
  • 配置管理:Kubernetes支持配置文件和环境变量的管理,使容器的配置更加灵活。
  • 负载均衡:Kubernetes可以自动分发流量,确保负载均衡,提高应用程序的稳定性。
  • 扩展性:Kubernetes支持集群的横向和纵向扩展,以应对不同规模的应用程序。

Kubectl命令概述
Kubectl是Kubernetes的命令行工具,用于管理Kubernetes集群。以下是一些常用的Kubectl命令:

  • kubectl get pods:获取所有Pod的列表。
  • kubectl create -f <yaml文件>:从YAML文件创建资源。
  • kubectl delete <资源类型> <资源名称>:删除指定的资源。
  • kubectl scale deployment <部署名称> --replicas=<副本数>:扩展或缩减Deployment的副本数。
  • kubectl describe <资源类型> <资源名称>:获取资源的详细信息。
  • kubectl logs <Pod名称>:查看Pod的日志。
  • kubectl exec -it <Pod名称> -- <命令>:在Pod内执行命令。
  • kubectl apply -f <yaml文件>:应用YAML文件的更改。
  • kubectl port-forward <Pod名称> <本地端口>:<远程端口>:将本地端口映射到Pod的端口。
  • kubectl get nodes:获取所有节点的列表。

使用Kubectl管理Kubernetes集群
要使用Kubectl管理Kubernetes集群,需要首先安装Kubectl,并配置Kubectl与Kubernetes集群的连接。然后可以使用Kubectl执行各种管理任务,包括创建、删除、扩展、监视和调试容器应用程序。

Kubernetes是一个强大的容器编排平台,Kubectl是管理Kubernetes集群的关键工具。通过学习Kubectl命令和实践,您可以更好地理解和管理Kubernetes集群中的容器应用程序。

通过一系列详细的步骤,包括创建Debian模板、设置Master和Node节点、安装和配置Containerd、安装Kubernetes、初始化集群、网络和安全配置、加入节点和验证,成功搭建了一个工作正常的Kubernetes集群。

K3S部署实训项目

基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#安装docker
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable docker
sudo systemctl start docker

# 关闭selinux
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config


yum install ntpdate -y
ntpdate time.windows.com

yum install containerd -y
systemctl start containerd && systemctl enable containerd

#防火墙
sudo systemctl stop firewalld
sudo systemctl disable firewalld

安装K3S

1
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --flannel-backend none" K3S_TOKEN=2bf45f98-8e0a-11ee-86c0-27c7514cb965 sh -s -
1
2
3
4
5
6
7
8
9
10
11
Complete!
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Skipping /usr/local/bin/ctr symlink to k3s, command exists in PATH at /usr/bin/ctr
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
1
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="agent" K3S_TOKEN="2bf45f98-8e0a-11ee-86c0-27c7514cb965" sh -s - --server https://k3s.dayi.fun

检查

1
2
kubectl get nodes
k3s check-config

启动参数添加:

1
user_namespace.enable=1

vim /etc/default/grub

然后发现1G内存的小鸡子寄了,带不动这个玩意。

获得token

1
cat /var/lib/rancher/k3s/server/node-token

从节点

1
2
3
4
5
6

K1031de9d755e087bb9524c7cc72a109f6985a7bad3733aa3bb5cadf49c700fd1f6::server:41a8b3813c91595999fb186af203cbba


curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://k3s-zt-cloud.dayi.fun:6443 K3S_TOKEN=K1031de9d755e087bb9524c7cc72a109f6985a7bad3733aa3bb5cadf49c700fd1f6::server:41a8b3813c91595999fb186af203cbba sh -

隧道

1
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://k3s-zt-cloud.dayi.fun:6443 K3S_TOKEN=K1031de9d755e087bb9524c7cc72a109f6985a7bad3733aa3bb5cadf49c700fd1f6::server:41a8b3813c91595999fb186af203cbba sh -

欧耶

用的tailscile!

安装面板:

1
2
3
4
5
6
mkdir ~/k3s-dashboard
cd ~/k3s-dashboard
GITHUB_URL=https://github.com/kubernetes/dashboard/releases
VERSION_KUBE_DASHBOARD=$(curl -w '%{url_effective}' -I -L -s -S ${GITHUB_URL}/latest -o /dev/null | sed -e 's|.*/||')
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

又加了一个节点:

1
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://k3s-zt-cloud.dayi.fun:6443 K3S_TOKEN=K1031de9d755e087bb9524c7cc72a109f6985a7bad3733aa3bb5cadf49c700fd1f6::server:41a8b3813c91595999fb186af203cbba sh -

上传镜像

先登录docker hub

1
2
3
4
5
6
7
root@k3s-master-ovo-2:~/java-spring/java-spring# docker push yumibiao/dayi-spring-emis:1.0
The push refers to repository [docker.io/yumibiao/dayi-spring-emis]
An image does not exist locally with the tag: yumibiao/dayi-spring-emis
root@k3s-master-ovo-2:~/java-spring/java-spring# docker tag yumibiao/dayi-spring-emis:1.0 dayi-spring-emis:1.0
Error response from daemon: No such image: yumibiao/dayi-spring-emis:1.0
root@k3s-master-ovo-2:~/java-spring/java-spring# docker tag dayi-spring-emis:1.0 yumibiao/dayi-spring-emis:1.0
root@k3s-master-ovo-2:~/java-spring/java-spring#

配置文件:

文件1 emis.yaml

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
apiVersion: v1
kind: Namespace
metadata:
name: emis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: yumibiao/dayi-spring-emis:1.0
ports:
- containerPort: 8080
env:
- name: MYSQL_HOST
value: "db"
- name: MYSQL_DATABASE
value: "product"


---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi # 修改为你需要的大小


---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- protocol: TCP
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db-deployment
spec:
replicas: 1
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: db
image: mysql:8
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: sql-init-script
mountPath: /docker-entrypoint-initdb.d/sql.sql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data-pvc
- name: sql-init-script
configMap:
name: sql-script-configmap
---
apiVersion: v1
kind: Service
metadata:
name: db
spec:
selector:
app: db
ports:
- protocol: TCP
port: 3306
targetPort: 3306
---
apiVersion: v1
kind: ConfigMap
metadata:
name: phpmyadmin-config
data:
PMA_HOST: "db"
PMA_USER: "root"
PMA_PASSWORD: "123456"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: phpmyadmin-deployment
spec:
replicas: 2
selector:
matchLabels:
app: phpmyadmin
template:
metadata:
labels:
app: phpmyadmin
spec:
containers:
- name: phpmyadmin
image: phpmyadmin/phpmyadmin
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: phpmyadmin-config
---
apiVersion: v1
kind: Service
metadata:
name: phpmyadmin-service
spec:
selector:
app: phpmyadmin
ports:
- protocol: TCP
port: 80
targetPort: 80

文件2 emis_sql.yaml

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
35
36
37
38
39
40
41
42
43
44
45
46
47
apiVersion: v1
kind: ConfigMap
metadata:
name: sql-script-configmap
data:
init.sql: |
DROP DATABASE IF EXISTS ovo;
CREATE DATABASE ovo;
use ovo;

/*
Navicat Premium Data Transfer

Source Server : dayi_spr_bo_em
Source Server Type : MySQL
Source Server Version : 50740
Source Host : a.dayiyi.top:3306
Source Schema : dayi_spr_bo_em

Target Server Type : MySQL
Target Server Version : 50740
File Encoding : 65001

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for class
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`faculty_id` int(11) NULL DEFAULT NULL,
`major_id` int(11) NULL DEFAULT NULL,
`class_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES (1, 1, 1, '2001班');
INSERT INTO `class` VALUES (2, 1, 1, '2002班');
INSERT INTO `class` VALUES (3, 2, 3, '2001班');
INSERT INTO `class` VALUES (4, 2, 2, '2001班');
INSERT INTO `class` VALUES (5, 4, 5, '9998班班');
INSERT INTO `class` VALUES (6, 4, 5, '9999班');

后面省略了

部署:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@k3s-master-ovo-2:~/k3s-ovo/emis# kubectl apply -f emis_sql.yaml 
configmap/sql-script-configmap unchanged
root@k3s-master-ovo-2:~/k3s-ovo/emis# kubectl apply -f emis.yaml
namespace/emis unchanged
deployment.apps/web-deployment created
persistentvolumeclaim/mysql-data-pvc unchanged
service/web-service unchanged
deployment.apps/db-deployment created
service/db unchanged
configmap/phpmyadmin-config unchanged
deployment.apps/phpmyadmin-deployment created
service/phpmyadmin-service unchanged
root@k3s-master-ovo-2:~/k3s-ovo/emis#

SQL:

排错

部署之后发现不能解析db

要用services

1
2
3
4
5
6
7
8
9
10
ping: db: Name or service not known
root@k3s-master-ovo-2:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 23h
mysql-service ClusterIP 10.43.151.82 <none> 3306/TCP 74m
web-service ClusterIP 10.43.4.120 <none> 8080/TCP 34m
db-service ClusterIP 10.43.43.192 <none> 3306/TCP 34m
phpmyadmin-service ClusterIP 10.43.121.42 <none> 80/TCP 34m
root@k3s-master-ovo-2:~#

这样子:

成功啦

结构图

结论

  • 总结本次课程的关键收获和重要观点
  • 强调Docker云与虚拟化技术在现代应用部署中的重要性和应用前景

其实课上还是学到了不少内容,包括实验过程启动了一大堆虚拟机

这个过程可以说有辛苦也有收获啦,

展望

  • 简要展望未来Docker和虚拟化技术的发展趋势
  • 提出可能的进一步学习和研究方向

参考文献

1
2
3
4
5
6
7
8
[1]                      郑可飚.            虚拟化技术在云计算环境下的性能优化与资源管理研究[J].      数字通信世界,      2023,            (05):      50-52.            
摘要:随着各种先进技术的愈加成熟,云计算技术在各行各业中也不断有了愈加重要的应用。虚拟化技术作为云计算技术中重要的组成技术之一,其能够对网络信息资源进行有效的管理。随着网络资源管理市场需求的不断增多,云计算环境下的虚拟化技术也应当不断地优化各方面性能,提高资源管理的效率和质量。文章从虚拟化技术、服务器虚拟化、云计算环境下的虚拟化资源管理模型、虚拟化技术在云计算环境下的性能优化以及资源管理的具体策略等几个方面对其进行了具体的研究分析。



[1] 邱建新. 基于Docker容器技术的Linux在线实验环境设计[J]. 信息技术, 2022, (02): 48-52+58.
摘要:基于Docker容器的虚拟技术在云计算、大数据环境中被大规模的使用,针对Linux操作系统实验环境使用受限的问题,设计了基于Docker容器技术的在线实验环境,描述了实验环境构建的大致过程,对服务器端Docker容器的创建方法进行了分类分析和服务器压力测试,结果表明,所设计的Linux在线实验环境能够满足线上及线下教学的需要,提高了教学效果和效率。