我想创建 100 个虚拟服务器。它们将用于测试,因此它们应该易于创建和销毁。
ssh I.P.n.o例如ssh 10.0.0.99(IPv4 或 IPv6,私有地址空间可以,端口转发不是 - 所以这可能涉及设置桥接)给定的最快方法(挂钟时间)是什么:
我应该运行的实际命令/应该创建的文件是什么?
我有一种感觉,如果采用正确的技术,这是一项可以在几分钟内完成的 50 条生产线作业。
这几行大概可以分成几个 bash 函数:
install() {
# Install needed software once
}
setup() {
# Configure the virtual servers
}
start() {
# Start the virtual servers
# After this it is possible to do:
# ssh 10.0.0.99
# from another physical server
}
stop() {
# Stop the virtual servers
# After there is no running processes on the host server
# and after this it is no longer possible to do:
# ssh 10.0.0.99
# from another physical server
# The host server returns to the state before running `start`
}
destroy() {
# Remove the setup
# After this the host server returns to the state before running `setup`
}
Run Code Online (Sandbox Code Playgroud)
背景
为了开发 GNU Parallel,我需要一种简单的方法来测试在 100 台机器上并行运行。
对于其他项目,能够创建一堆虚拟机,测试一些竞争条件,然后再次销毁机器也很方便。
换句话说:这不适用于生产环境,安全性不是问题。
基于以下@danielleontiev 的注释:
install() {
# Install needed software once
sudo apt -y install docker.io
sudo groupadd docker
sudo usermod -aG docker $USER
# Logout and login if you were not in group 'docker' before
docker run hello-world
}
setup() {
# Configure the virtual servers
mkdir -p my-ubuntu/ ssh/
cp ~/.ssh/id_rsa.pub ssh/
cat ssh/*.pub > my-ubuntu/authorized_keys
cat >my-ubuntu/Dockerfile <<EOF
FROM ubuntu:bionic
RUN apt update && \
apt install -y openssh-server
RUN mkdir /root/.ssh
COPY authorized_keys /root/.ssh/authorized_keys
# run blocking command which prevents container to exit immediately after start.
CMD service ssh start && tail -f /dev/null
EOF
docker build my-ubuntu -t my-ubuntu
}
start() {
testssh() {
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@"$1" echo "'$1'" '`uptime`'
}
export -f testssh
# Start the virtual servers
seq 100 |
parallel 'docker run -d --rm --name my-ubuntu-{} my-ubuntu; docker inspect my-ubuntu-{}' |
# After this it is possible to do:
# ssh 10.0.0.99
# from another physical server
perl -nE '/"IPAddress": "(\S+)"/ and not $seen{$1}++ and say $1' |
parallel testssh
docker ps
}
stop() {
# Stop the virtual servers
# After there is no running processes on the host server
# and after this it is no longer possible to do:
# ssh 10.0.0.99
# from another physical server
# The host server returns to the state before running `start`
seq 100 | parallel docker stop my-ubuntu-{}
docker ps
}
destroy() {
# Remove the setup
# After this the host server returns to the state before running `setup`
rm -rf my-ubuntu/
docker rmi my-ubuntu
}
full() {
install
setup
start
stop
destroy
}
$ time full
real 2m21.611s
user 0m47.337s
sys 0m31.882s
Run Code Online (Sandbox Code Playgroud)
这总共需要 7 GB RAM来运行 100 个虚拟服务器。因此,您甚至不需要有足够的 RAM 来执行此操作。
它最多可扩展到 1024 个服务器,之后 docker 网桥抱怨(可能是由于每个网桥设备最多可以有 1024 个端口)。
现在唯一缺少的是使 docker 网桥与以太网通信,因此可以从另一台物理服务器访问容器。
基于以下@Martin 的注释:
install() {
# Install needed software once
sudo apt install -y vagrant virtualbox
}
setup() {
# Configure the virtual servers
mkdir -p ssh/
cp ~/.ssh/id_rsa.pub ssh/
cat ssh/*.pub > authorized_keys
cat >Vagrantfile <<'EOF'
Vagrant.configure("2") do |config|
config.vm.box = "debian/buster64"
(1..100).each do |i|
config.vm.define "vm%d" % i do |node|
node.vm.hostname = "vm%d" % i
node.vm.network "public_network", ip: "192.168.1.%d" % (100+i)
end
end
config.vm.provision "shell" do |s|
ssh_pub_key = File.readlines("authorized_keys").first.strip
s.inline = <<-SHELL
mkdir /root/.ssh
echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
apt-get update
apt-get install -y parallel
SHELL
end
end
EOF
}
start() {
testssh() {
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@"$1" echo "'$1'" '`uptime`'
}
export -f testssh
# Start the virtual servers
seq 100 | parallel --lb vagrant up vm{}
# After this it is possible to do:
# ssh 192.168.1.111
# from another physical server
parallel testssh ::: 192.168.1.{101..200}
}
stop() {
# Stop the virtual servers
# After there is no running processes on the host server
# and after this it is no longer possible to do:
# ssh 10.0.0.99
# from another physical server
# The host server returns to the state before running `start`
seq 100 | parallel vagrant halt vm{}
}
destroy() {
# Remove the setup
# After this the host server returns to the state before running `setup`
seq 100 | parallel vagrant destroy -f vm{}
rm -r Vagrantfile .vagrant/
}
full() {
install
setup
start
stop
destroy
}
Run Code Online (Sandbox Code Playgroud)
start 给出了很多警告:
NOTE: Gem::Specification.default_specifications_dir is deprecated; use Gem.default_specifications_dir instead. It will be removed on or after 2020-02-01.
Run Code Online (Sandbox Code Playgroud)
stop 给出这个警告:
NOTE: Gem::Specification.default_specifications_dir is deprecated; use Gem.default_specifications_dir instead. It will be removed on or after 2020-02-01.
Gem::Specification.default_specifications_dir called from /usr/share/rubygems-integration/all/gems/vagrant-2.2.6/lib/vagrant/bundler.rb:428.
NOTE: Gem::Specification.default_specifications_dir is deprecated; use Gem.default_specifications_dir instead. It will be removed on or after 2020-02-01.
Gem::Specification.default_specifications_dir called from /usr/share/rubygems-integration/all/gems/vagrant-2.2.6/lib/vagrant/bundler.rb:428.
/usr/share/rubygems-integration/all/gems/vagrant-2.2.6/plugins/kernel_v2/config/vm.rb:354: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/usr/share/rubygems-integration/all/gems/vagrant-2.2.6/plugins/kernel_v2/config/vm_provisioner.rb:92: warning: The called method `add_config' is defined here
/usr/share/rubygems-integration/all/gems/vagrant-2.2.6/lib/vagrant/errors.rb:103: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/usr/share/rubygems-integration/all/gems/i18n-1.8.2/lib/i18n.rb:195: warning: The called method `t' is defined here
Run Code Online (Sandbox Code Playgroud)
每个虚拟机在主机系统上占用 0.5 GB 的 RAM。
启动速度比上面的 Docker 机器慢得多。最大的区别在于 Vagrant 机器不必运行与主机相同的内核,而是完整的虚拟机。
我认为 docker 满足您的要求。
1) 安装 docker ( https://docs.docker.com/engine/install/ ) 确保您已完成 linux 后安装步骤 ( https://docs.docker.com/engine/install/linux-postinstall/ )
2)我假设你有以下目录结构:
.
??? my-ubuntu
??? Dockerfile
??? id_rsa.pub
1 directory, 2 files
Run Code Online (Sandbox Code Playgroud)
id_rsa.pub是你的公钥,Dockerfile我们将在下面讨论
3) 首先,我们将构建docker 镜像。它就像我们将要运行的容器模板。每个集装箱会是这样的物化我们的形象。
4)要构建图像,我们需要一个模板。它是Dockerfile:
FROM ubuntu:bionic
RUN apt update && \
apt install -y openssh-server
RUN mkdir /root/.ssh
COPY id_rsa.pub /root/.ssh/authorized_keys
CMD service ssh start && tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)
FROM ubuntu:bionic定义我们的基础镜像。您可以在 hub.docker.com 上找到 Arch、Debian、Apline、Ubuntu 等的基础apt install 部分安装ssh服务器COPY from to 将我们的公钥复制到它将在容器中的位置RUN语句来执行其他操作:安装软件、创建文件等...5) docker build my-ubuntu -t my-ubuntu- 建立形象。此命令的输出:
Sending build context to Docker daemon 3.584kB
Step 1/5 : FROM ubuntu:bionic
---> c3c304cb4f22
Step 2/5 : RUN apt update && apt install -y openssh-server
---> Using cache
---> 40c56d549c0e
Step 3/5 : RUN mkdir /root/.ssh
---> Using cache
---> c50d8b614b21
Step 4/5 : COPY id_rsa.pub /root/.ssh/authorized_keys
---> Using cache
---> 34d1cf4e9f69
Step 5/5 : CMD service ssh start && tail -f /dev/null
---> Using cache
---> a442db47bf6b
Successfully built a442db47bf6b
Successfully tagged my-ubuntu:latest
Run Code Online (Sandbox Code Playgroud)
6)让我们跑my-ubuntu。(再次my-ubuntu是图像的名称)。以my-ubuntu-1从my-ubuntu图像派生的名称启动容器:
docker run -d --rm --name my-ubuntu-1 my-ubuntu
选项:
-d 妖魔化在 bg 中运行容器--rm在容器停止后擦除容器。这很重要,因为当您处理大量容器时,它们会很快污染您的 HDD。--name 容器名称my-ubuntu 我们从图像开始7) 图像正在运行。docker ps可以证明这一点:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee6bc20fd820 my-ubuntu "/bin/sh -c 'service…" 5 minutes ago Up 5 minutes my-ubuntu-1
Run Code Online (Sandbox Code Playgroud)
8)在容器运行中执行命令:
docker exec -it my-ubuntu-1 bash- 进入容器的bash. 可以提供任何命令
9) 如果上面的方式运行命令还不够 dodocker inspect my-ubuntu-1和 grepIPAddress字段。对我来说是172.17.0.2。
ssh root@172.17.0.2
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 5.6.15-arch1-1 x86_64)
Run Code Online (Sandbox Code Playgroud)
10)停止容器: docker stop my-ubuntu-1
11) 现在可以运行 100 个容器:
Sending build context to Docker daemon 3.584kB
Step 1/5 : FROM ubuntu:bionic
---> c3c304cb4f22
Step 2/5 : RUN apt update && apt install -y openssh-server
---> Using cache
---> 40c56d549c0e
Step 3/5 : RUN mkdir /root/.ssh
---> Using cache
---> c50d8b614b21
Step 4/5 : COPY id_rsa.pub /root/.ssh/authorized_keys
---> Using cache
---> 34d1cf4e9f69
Step 5/5 : CMD service ssh start && tail -f /dev/null
---> Using cache
---> a442db47bf6b
Successfully built a442db47bf6b
Successfully tagged my-ubuntu:latest
Run Code Online (Sandbox Code Playgroud)
我的docker ps:
... and so on ...
ee2ccce7f642 my-ubuntu "/bin/sh -c 'service…" 46 seconds ago Up 45 seconds my-ubuntu-20
9fb0bfb0d6ec my-ubuntu "/bin/sh -c 'service…" 47 seconds ago Up 45 seconds my-ubuntu-19
ee636409a8f8 my-ubuntu "/bin/sh -c 'service…" 47 seconds ago Up 46 seconds my-ubuntu-18
9c146ca30c9b my-ubuntu "/bin/sh -c 'service…" 48 seconds ago Up 46 seconds my-ubuntu-17
2dbda323d57c my-ubuntu "/bin/sh -c 'service…" 48 seconds ago Up 47 seconds my-ubuntu-16
3c349f1ff11a my-ubuntu "/bin/sh -c 'service…" 49 seconds ago Up 47 seconds my-ubuntu-15
19741651df12 my-ubuntu "/bin/sh -c 'service…" 49 seconds ago Up 48 seconds my-ubuntu-14
7a39aaf669ba my-ubuntu "/bin/sh -c 'service…" 50 seconds ago Up 48 seconds my-ubuntu-13
8c8261b92137 my-ubuntu "/bin/sh -c 'service…" 50 seconds ago Up 49 seconds my-ubuntu-12
f8eec379ee9c my-ubuntu "/bin/sh -c 'service…" 51 seconds ago Up 49 seconds my-ubuntu-11
128894393dcd my-ubuntu "/bin/sh -c 'service…" 51 seconds ago Up 50 seconds my-ubuntu-10
81944fdde768 my-ubuntu "/bin/sh -c 'service…" 52 seconds ago Up 50 seconds my-ubuntu-9
cfa7c259426a my-ubuntu "/bin/sh -c 'service…" 52 seconds ago Up 51 seconds my-ubuntu-8
bff538085a3a my-ubuntu "/bin/sh -c 'service…" 52 seconds ago Up 51 seconds my-ubuntu-7
1a50a64eb82c my-ubuntu "/bin/sh -c 'service…" 53 seconds ago Up 51 seconds my-ubuntu-6
88c2e538e578 my-ubuntu "/bin/sh -c 'service…" 53 seconds ago Up 52 seconds my-ubuntu-5
1d10f232e7b6 my-ubuntu "/bin/sh -c 'service…" 54 seconds ago Up 52 seconds my-ubuntu-4
e827296b00ac my-ubuntu "/bin/sh -c 'service…" 54 seconds ago Up 53 seconds my-ubuntu-3
91fce445b706 my-ubuntu "/bin/sh -c 'service…" 55 seconds ago Up 53 seconds my-ubuntu-2
54c70789d1ff my-ubuntu "/bin/sh -c 'service…" 2 minutes ago Up 2 minutes my-ubuntu-1
Run Code Online (Sandbox Code Playgroud)
我可以执行 fe docker inspect my-ubuntu-15,获取其 IP 并连接到 ssh 或使用 docker exec。
可以ping从容器中获取容器(安装iputils-ping以复制):
root@5cacaf03bf89:~# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=1.19 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.158 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.160 ms
^C
--- 172.17.0.2 ping statistics ---
Run Code Online (Sandbox Code Playgroud)
NB 从 bash 运行容器是快速解决方案。如果您想要可扩展的方法,请考虑使用kubernetes或swarm
PS 有用的命令:
docker psdocker statsdocker container lsdocker image ls
docker stop $(docker ps -aq) - 停止所有正在运行的容器
此外,请遵循 docs.docker.com 中的基础知识 - 花费 1 小时的时间以获得更好的容器使用体验
额外的:
示例中的基本图像实际上是最小的图像。它没有 DE 甚至 xorg。您可以手动安装它(将包添加到RUN apt install ...部分)或使用已经拥有您需要的软件的图像。快速谷歌搜索给了我这个(https://github.com/fcwu/docker-ubuntu-vnc-desktop)。我从未尝试过,但我认为它应该有效。如果您确实需要 VNC 访问权限,我应该尝试一下并在答案中添加信息
暴露给本地网络:
这个可能很棘手。我相信它可以通过一些晦涩的端口转发来完成,但直接的解决方案是按如下方式更改运行脚本:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee6bc20fd820 my-ubuntu "/bin/sh -c 'service…" 5 minutes ago Up 5 minutes my-ubuntu-1
Run Code Online (Sandbox Code Playgroud)
之后,您将能够使用主机 IP 访问您的容器:
ssh root@localhost -p 10001
The authenticity of host '[localhost]:10001 ([::1]:10001)' can't be established.
ECDSA key fingerprint is SHA256:erW9kguSvn1k84VzKHrHefdnK04YFg8eE6QEH33HmPY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:10001' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 5.6.15-arch1-1 x86_64)
Run Code Online (Sandbox Code Playgroud)
创建虚拟网络
或通过使用搬运工,例如:docker
network create --driver=bridge --ip-range=10.0.190.0/24
--subnet=10.0.0.0/16 --aux-address='ip1=10.0.190.1' --aux-address='ip2=10.0.190.2' --aux-address='ip3=10.0.190.3' -o "com.docker.network.bridge.name=br0" br0)
如果你想要 virtualbox/kvm :
准备一个pxe/http服务器和一个像SLAX或Alpine Linux这样的发行
版,使用 slax 和savechanges你在云中构建一个系统,其中所有软件都预先打包,另一方面,这会产生很多开销,但是使用Cluster SSH 之类的工具你可以触发你的命令同时通过运行
cssh root@10.0.190.{04..254} -p 22
使用 docker 时:通过 docker-compose 或手动将所有容器附加到命名网络,dropbear如果您想要 ssh 访问,您还可以修改 CMD 以运行
您可以使用Vagrant来启动您的测试环境。一旦你写了一个Vagrantfile定义要运行的发行版、网络配置等,你可以通过运行来启动机器,vagrant up <vmname>或者只是vagrant up启动它们。Vagrant 支持各种虚拟化提供商,包括 Virtual Box、VMware、KVM、AWS、Docker …… Vagrant 能够快速启动开发环境,因为它利用了预先构建的“box”文件,而不是从头开始安装每个系统。同时,Vagrant 允许您使用Ansible、Puppet、Chef、CFEngine为每个 VM运行自定义配置或者只是一个简短的 shell 脚本。您可以在同一个 Vagrantfile 中混合和匹配不同的发行版。SSH 访问是自动设置的。您可以通过运行来访问机器vagrant ssh <vmname>。同步文件夹可以轻松地将文件从您的主机系统带入您的测试环境。
以下是详细步骤:
下载并安装 Vagrant 和你最喜欢的虚拟化提供商:
$ sudo apt install -y vagrant virtualbox
Run Code Online (Sandbox Code Playgroud)使用以下内容创建 Vagrantfile:
$ sudo apt install -y vagrant virtualbox
Run Code Online (Sandbox Code Playgroud)启动虚拟机:
$ parallel vagrant up ::: vm{001..100}
Run Code Online (Sandbox Code Playgroud)SSH 到 VM:Vagrant 方式(使用 Vagrant 生成的密钥):
$ vagrant ssh vm001
Run Code Online (Sandbox Code Playgroud)
使用您自己的密钥(我们在配置阶段安装到 VM 中):
$ ssh vagrant@<IP>
Run Code Online (Sandbox Code Playgroud)
或者获取 root 访问权限:
$ ssh root@<IP>
Run Code Online (Sandbox Code Playgroud)您可以通过运行暂停虚拟机,vagrant suspend并在几天后启动它们以继续测试 ( vagrant up)。如果您有许多测试环境但只有有限的磁盘空间,您可以销毁一些虚拟机并在以后重新创建它们。
销毁 VM 并删除配置:
vagrant destroy -f
rm -rf Vagrantfile .vagrant
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1497 次 |
| 最近记录: |