1. 虚拟机
虚拟机(VM)是共享一个服务器的物理资源的操作系统。它是主机硬件上的Guest,因此也被称为Guest虚拟机。
虚拟机由几层组成。支持虚拟化的层是hypervisor。hypervisor是一种虚拟化服务器的软件。
优势
虚拟机可减少在服务器设备上的支出,可以利用一个物理服务器资源切分成多个独立的虚拟机来完成许多工作。
由于只有一台主机,因此可以利用虚拟机管理程序的集中功能高效地管理所有虚拟环境。这些系统完全相互独立,这意味着你可以在不同的虚拟机里安装不同的系统环境。
最重要的是,虚拟机与主机操作系统隔离,是进行实验和开发应用程序的安全场所。
劣势
虚拟机可能占用主机的大量系统资源,虚拟机的大小为数GB。在虚拟服务器上运行单个应用程序意味着还要运行Guest OS以及Guest OS运行所需的所有硬件的虚拟副本。这样很快就增加了很多RAM和CPU资源消耗。
迁移虚拟机上运行的应用程序的过程也可能很复杂,因为它始终附加在操作系统上。因此,必须同时迁移应用程序和操作系统。同样,在创建虚拟机时,系统管理程序会分配专用于VM的硬件资源。不过与运行单独的实体服务器相比,这仍然是经济的。
2. 容器
容器是一个不依赖于操作系统,运行应用程序的环境。它通过Linux的Namespaces和Cgroups技术对应用程序进程进行隔离和限制的,Namespace的作用是隔离,它让应用进程只能看到该Namespace内的世界;而Cgroups 的作用是限制分配给进程的宿主机资源。但对于宿主机来说,这些被“隔离”了的进程跟其他进程并没有太大区别。
容器只是运行在宿主机上的一种特殊的进程,多个容器之间使用的还是同一个宿主机的操作系统内核。
原理
Namespace的作用是隔离,它让应用进程只能看到该Namespace内的世界;而Cgroups的作用是限制,它给这个世界围上了一圈看不见的墙。通过Mount Namespace可以修改容器进程对自己的文件系统 “挂载点"的认知。在容器进程启动之前重新挂载它的整个根目录”/"(通过pivot_root系统调用改变进程的文件系统,如果系统不支持,则使用chroot),而由于Mount Namespace的存在,这个挂载对宿主机不可见的。这个挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统,就是所谓的“容器镜像”。它还有一个更为专业的名字,叫做:rootfs(根文件系统)。rootfs只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。
所以说,rootfs 只包括了操作系统的 “躯壳”,并没有包括操作系统的内核。同一台机器上的所有容器,都会共享宿主机操作系统的内核。
这就意味着,如果容器里的应用程序需要配置内核参数、跟内核进行直接的交互,这些都是操作的宿主机操作系统的内核,它对于该机器上的所有容器来说是一个“全局变量”,牵一发而动全身。这也是容器相比于虚拟机的主要缺陷之一:毕竟虚拟机有模拟出来的硬件机器充当沙盒,而且每个虚拟机里还运行着一个完整Guest OS让应用随便折腾。不过由于rootfs里打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起。这就赋予了容器所谓的一致性:无论在本地、云端,还是在一台任何地方的机器上,用户只需要解压打包好的容器镜像,那么这个应用运行所需要的完整的执行环境就能被重现出来。
优势
容器占用的大小比虚拟机小很多,甚至可以小到10MB,可以轻松限制容器的内存和CPU使用率。与部署应用需要部署整个操作系统的虚拟机相比,容器非常轻巧且启动迅速。这样让我们可以快速扩展容器并添加相同的容器。同样,容器对于持续集成和持续部署(CI / CD)实施也是极好的选择。他们通过在开发人员之间分发和合并镜像来促进协作开发。
劣势
容器仍无法提供与虚拟机相同的安全性和稳定性。由于它们共享主机的内核,因此不能像虚拟机一样完全隔离。容器是进程级的隔离,一个容器可以通过影响宿主机内核的稳定性来影响其他容器。一旦容器执行了任务,它就会关闭并删除其中的所有数据。如果希望数据保留下来,则必须使用"数据卷"进行保存,这需要在主机上进行手动配置。
3. Docker
Docker 是 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。
组成
- 具有长时间运行的守护进程的服务器dockerd。
- API,用于指定程序可以用来与Docker守护程序进行对话和指示的接口。
- 命令行界面(CLI)客户端docker。
CLI使用Docker API通过脚本或直接CLI命令来控制Docker守护程序或与Docker守护程序进行交互。许多其他Docker应用程序都使用基础API和CLI。守护程序创建和管理Docker对象,例如镜像,容器,网络和存储卷。
安装
参考官方文档 https://docs.docker.com/engine/install/
镜像
Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
特点
- 镜像是分层(Layer)的:即一个镜像可以多个中间层组成,多个镜像可以共享同一中间层,我们也可以通过在镜像添加多一层来生成一个新的镜像。在 Dockerfile 中, 每一条指令都会创建一个镜像层,继而会增加整体镜像的大小。
- 镜像是只读的(read-only):镜像在构建完成之后,便不可以再修改,而上面我们所说的添加一层构建新的镜像,这中间实际是通过创建一个临时的容器,在容器上增加或删除文件,从而形成新的镜像,因为容器是可以动态改变的。
Docker中与镜像操作相关的命令都在docker image这条子命令下,通过docker image --help这条命令,可以看到docker image子命令的详细文档,如下:
root@k8s-node-01:~# docker image --help
Usage: docker image COMMAND
Manage images
Commands:
build Build an image from a Dockerfile
history Show the history of an image
import Import the contents from a tarball to create a filesystem image
inspect Display detailed information on one or more images
load Load an image from a tar archive or STDIN
ls List images
prune Remove unused images
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rm Remove one or more images
save Save one or more images to a tar archive (streamed to STDOUT by default)
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
Run 'docker image COMMAND --help' for more information on a command.
示例
root@k8s-node-01:~# cat Dockerfile
FROM centos:7
LABEL maintainer=lqy \
mail=lqy7575@163.com
RUN yum -y install gcc make pcre-devel zlib-devel tar zlib wget \
&& yum clean all \
&& wget http://nginx.org/download/nginx-1.20.0.tar.gz -P /usr/local/src \
&& cd /usr/local/src \
&& tar -zxvf ./nginx-1.20.0.tar.gz \
&& cd ./nginx-1.20.0 \
&& ./configure --prefix=/usr/local/nginx \
&& make -j 4 \
&& make install \
&& ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
EXPOSE 80
ENTRYPOINT nginx -g "daemon off;"
# 启动容器
root@k8s-node-01:~# docker run -dti --name test-nginx -p 10080:80 nginx:v1
e71633e7897b5a1b8a1279aa01cb245590ad14697107cfa8be7ad912fd097c96
# 验证 测试
root@k8s-node-01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e71633e7897b nginx:v1 "/bin/sh -c 'nginx -…" 2 seconds ago Up 1 second 0.0.0.0:10080->80/tcp test-nginx
root@k8s-node-01:~# curl localhost:10080 -I
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Fri, 23 Apr 2021 09:42:01 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Fri, 23 Apr 2021 08:27:10 GMT
Connection: keep-alive
ETag: "608284de-264"
Accept-Ranges: bytes
仓库
仓库(Repository)是集中存储镜像的地方。
公共仓库
公共仓库一般是指Docker Hub,前面我们已经多次介绍如何从Docker Hub获取镜像,除了获取镜像外,我们也可以将自己构建的镜像存放到Docker Hub,这样,别人也可以使用我们构建的镜像。
私有仓库
有时候自己部门内部有一些镜像要共享时,如果直接导出镜像拿给别人又比较麻烦,使用像Docker Hub这样的公共仓库又不是很方便,这时候我们可以自己搭建属于自己的私有仓库服务,用于存储和分布我们的镜像。
Docker官方提供了registry这个镜像,可以用于搭建私有仓库服务,也可以自行部署Harbor。
Harbor搭建
# 安装docker-compose pip安装
root@k8s-node-01:~# apt install python-pip -y
root@k8s-node-01:~# pip install docker-compose
# 安装docker-compose github直接下载,上传后添加执行权限
# https://github.com/docker/compose/releases
root@k8s-node-01:/usr/local/sbin# chmod +x docker-compose-Linux-x86_64
root@k8s-node-01:/usr/local/sbin# mv docker-compose-Linux-x86_64 docker-compose
root@k8s-node-01:/usr/local/sbin# docker-compose -v
docker-compose version 1.28.5, build c4eb3a1f
# 下载Harbor安装包 https://github.com/goharbor/harbor/releases
root@k8s-node-01:/usr/local/src# tar -zxvf harbor-offline-installer-v2.2.1.tgz
root@k8s-node-01:/usr/local/src# cd harbor/
root@k8s-node-01:/usr/local/src/harbor# ls
common.sh harbor.v2.2.1.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
root@k8s-node-01:/usr/local/src/harbor# vim harbor.yml.tmpl
# 修改配置文件 hostname为本机地址 并注释https
root@k8s-node-01:/usr/local/src/harbor# cp harbor.yml.tmpl harbor.yml
# 执行安装脚本
root@k8s-node-01:/usr/local/src/harbor# ./install.sh
···
[Step 5]: starting Harbor ...
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating harbor-portal ... done
Creating registryctl ... done
Creating redis ... done
Creating harbor-db ... done
Creating registry ... done
Creating harbor-core ... done
Creating nginx ... done
Creating harbor-jobservice ... done
✔ ----Harbor has been installed and started successfully.----
# 配置文件填写错误可以重新修改后执行prepare再次安装
root@k8s-node-01:/usr/local/src/harbor# vim harbor.yml
root@k8s-node-01:/usr/local/src/harbor# ./prepare
root@k8s-node-01:/usr/local/src/harbor# ./install.sh
# 登录验证