100台の仮想サーバーを作成したいと思います。テストに使用されるため、作成と削除が簡単になります。
- 他の物理システムからSSHを介してアクセスできる必要があります(公開SSHキーを提供)。
- 独自のIPアドレスが必要で、他の物理ホストからアクセスできる必要があります
ssh I.P.n.o
(たとえば、ssh 10.0.0.99
IPv4またはIPv6、プライベートアドレススペースは許可され、ポート転送は不可能であるため、ブリッジ設定が必要になる場合があります)。 - デフォルトのUNIXツールがインストールされている必要があります(完全展開を推奨)。
- /proc/cpuinfo、rootユーザー、およびネットワークカードが必要です(マシンが完全に仮想化されていない場合にのみ関連する可能性があります)。
- リモート接続可能なXサーバーを実行することができる場合(VNCまたは同様の使用)ボーナス
与えられた最速の方法(壁時計の時間)は何ですか?
- ホストシステムはUbuntu 20.04を実行し、十分なRAMとCPUを備えています。
- LANにはDHCPサーバーがあります(事前定義されたIP範囲も利用可能です)。
- どんな無料の仮想化技術を使用しても構いません(他の要件を満たしていればコンテナ化も問題ありません)
どの実際のコマンドを実行し、どのファイルを生成する必要がありますか?
私の考えでは、正しいスキルを使えば、この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`
}
背景
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() {
# start container number x..y
servers_min=$1
servers_max=$2
testssh() {
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/tmp/known root@"$1" echo "'$1'" '`uptime`'
}
export -f testssh
setup_bridge() {
# OMG why is this so hard
# Default interface must have IP-addr removed
# bridge must have IP-addr + routing copied from $dif, so it takes over default interface
# Why on earth could we not just: brctl addif dock0 $dif - and be done?
default_interface=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)')
dif=$default_interface
gw=$(ip -4 route ls | grep default | grep -Po '(?<=via )(\S+)')
dif_ip=$(ip -4 route ls | grep default | grep -Po '(?<=src )(\S+)')
echo Add bridge
docker network create --driver bridge --subnet=172.20.0.0/16 --opt com.docker.network.bridge.name=dock0 net0
# $dif must be up, but with no ip addr
sudo ip addr flush dev $dif
sudo brctl addif dock0 $dif
sudo ifconfig dock0:ext $dif_ip
sudo route add -net 0.0.0.0 gw $gw
}
# Start the containers
startone() {
id=$1
net=$2
docker run -d --rm --name ubuntu-$id-$net --network $net my-ubuntu
docker inspect ubuntu-$id-$net
}
export -f startone
setup_bridge
echo Start containers
seq $servers_min $servers_max | parallel startone {} net0 |
# 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' |
# Keep a list of the IP addresses in /tmp/ipaddr
tee /tmp/ipaddr |
parallel testssh
docker ps
route -n
}
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`
echo Stop containers
docker ps -q | parallel docker stop {} |
perl -pe '$|=1; s/^............\n$/./'
echo
echo If any containers are remaining it is an error
docker ps
# Take down bridge
docker network ls|G bridge net|field 1| sudo parallel docker network rm
# Re-establish default interface
dif=$default_interface
sudo ifconfig $dif $dif_ip
# Routing takes a while to be updated
sleep 2
route -n
}
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
これは7GBのRAMを占めます。みんな100台の仮想サーバーを実行している場合。したがって、これを行うのに十分なRAMは必要ありません。
1024台のサーバーに拡張され、その後、ドッカーブリッジは文句を言います(おそらく次の理由で)。各ブリッジデバイスには最大1024のポートがあります。)。
このスクリプトは6000個のコンテナを実行するように調整できます(1024を超えるドッカーコンテナを実行しています)、しかし6055ではブロックされます(https://serverfault.com/questions/1091520/docker-blocks-when-running-multiple-containers)。
徒歩旅行者
以下の@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
}
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.
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
各仮想マシンはホストシステムで0.5 GBのRAMを使用します。
起動は上記のDockerマシンよりはるかに遅いです。主な違いは、Vagrantマシンがホストマシンと同じカーネルを実行する必要がなく、仮想マシン全体を実行する必要がないことです。
答え1
私はドッカーがあなたの要件を満たしていると思います。
1) ドッカーの取り付け(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
id_rsa.pub
公開鍵です。これについてはDockerfile
以下で説明します。
3) まず、構築しなければなりません。桟橋労働者イメージ。テンプレートだと思いますコンテナ私たちは走らなければなりません。すべてのコンテナは次のとおりです。具体化する私たちのビデオ。
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
FROM ubuntu:bionic
私たちを定義する基本イメージ。 Hub.docker.comで、Arch、Debian、Apline、Ubuntuなどの基本を見つけることができます。apt install
部分的にSSHサーバーをインストールするCOPY from to
公開鍵をコンテナの場所にコピーします。RUN
ここで他のタスク(ソフトウェアのインストール、ファイルの生成など)を実行するためのより多くのステートメントを追加できます。- 最後はトリッキーです。パート1 SSHサーバーの起動コンテナを起動するときこれは明らかですが、2番目は重要です。コンテナが起動後すぐに終了するのを防ぐブロックコマンドを実行します。
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
6)走りましょうmy-ubuntu
。 (my-ubuntu
名前をもう一度ビデオ)。my-ubuntu-1
イメージから派生した名前でコンテナを起動しますmy-ubuntu
。
docker run -d --rm --name my-ubuntu-1 my-ubuntu
オプション:
-d
悪魔化するbgでコンテナを実行している場合--rm
停止したら容器を拭きます。大量のコンテナを扱うと、ハードドライブが急速に汚染される可能性があるため、これは重要です。--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
8) コンテナでコマンドを実行します。
docker exec -it my-ubuntu-1 bash
- コンテナを入力してくださいbash
。どのコマンドでも入力できます。
9)上記の方法でコマンドを実行するだけでは不十分な場合は、そのフィールドを実行してdocker inspect my-ubuntu-1
grepしますIPAddress
。私にとってはそうです172.17.0.2
。
ssh [email protected]
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 5.6.15-arch1-1 x86_64)
10)コンテナを停止します。docker stop my-ubuntu-1
11)これで100個のコンテナを実行できるようになりました。
#!/bin/bash
for i in $(seq 1 100); do
docker run -d --rm --name my-ubuntu-$i my-ubuntu
done
私のもの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
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 ---
Bashでコンテナを実行するにはクイック解決策。拡張可能なアプローチが必要な場合、kubernetes
またはswarm
PS便利なコマンド:
docker ps
docker stats
docker container ls
docker image ls
docker stop $(docker ps -aq)
- 実行中のすべてのコンテナを停止します。
また、docs.docker.comの基本に従います。コンテナのより良い経験を得るために1時間を費やしてください。
追加:
例の基本イメージは実際には最小のイメージです。 DEもなくxorgもありません。手動でインストールするか(RUN apt install ...
セクションにパッケージを追加する)、必要なソフトウェアがすでに含まれているイメージを使用できます。クイックGoogle検索でこの情報を入手しました(https://github.com/fcwu/docker-ubuntu-vnc-desktop)。私はそれを試したことがありませんが、効果があると思います。 VNCアクセスが必要な場合は、試してみて回答に情報を追加する必要があります。
ローカルネットワークに公開されている:
これはトリッキーかもしれません。あいまいなポート転送を使用して実行できると確信していますが、簡単な解決策は実行スクリプトを次のように変更することです。
#!/bin/bash
for i in $(seq 1 100); do
docker run -d --rm -p $((10000 + i)):22 --name my-ubuntu-$i my-ubuntu
done
その後、ホスト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)
答え2
仮想ネットワークの作成
または使用してドッカー、例えば
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サーバーなどのディストリビューション スラックスまたはアルパインLinux、事前にパッケージ化されたすべてのソフトウェアを使用してslaxとクラウドでシステムを構築すると、多くの
savechanges
オーバーヘッドが発生しますが、このようなツールを使用するとクラスタSSH次のコマンドを実行すると、同時にコマンドを実行できます。cssh [email protected].{04..254} -p 22
dropbear
dockerを使用している場合:docker-composeを介してまたは手動ですべてのコンテナを指定されたネットワークに接続します。 SSH アクセスが必要な場合は、CMD を変更して実行することもできます。
答え3
使用できる徒歩旅行者テスト環境を開始するために使用されます。実行するように定義した展開、ネットワーク構成などを作成したら、実行または起動してVagrantfile
マシンを起動できます。vagrant up <vmname>
vagrant up
それらすべて戻る。 Vagrantはさまざまな機能をサポートしています。仮想化プロバイダVirtual Box、VMware、KVM、AWS、Dockerなど...事前に構築された「ボックス」ファイル各システムを最初からインストールする代わりに。同時にVagrantを使用すると、カスタマイズされたタスクを実行できます。供給各仮想マシンの使用についてアンシプール、人形、シェフ、CFエンジンあるいは、短いシェルスクリプトかもしれません。同じVagrantfileでさまざまなディストリビューションを混合して一致させることができます。 SSH アクセスは自動的に設定されます。を実行してマシンにアクセスできますvagrant ssh <vmname>
。フォルダ同期ホストシステムからテスト環境にファイルを簡単にインポートできます。
詳細な手順は次のとおりです。
Vagrantと必要な仮想化プロバイダをダウンロードしてインストールします。
$ sudo apt install -y vagrant virtualbox
次の内容でVagrantfileを作成します。
Vagrant.configure("2") do |config| config.vm.box = "debian/buster64" (1..100).each do |i| config.vm.define "vm%03d" % i do |node| node.vm.hostname = "vm%03d" % i node.vm.network "public_network", ip: "192.168.1.%d" % (99 + i) end end config.vm.provision "shell" do |s| ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").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
仮想マシンを起動します。
$ parallel vagrant up ::: vm{001..100}
SSH経由で仮想マシンに接続する:Vagrant方式(Vagrant生成キーを使用):
$ vagrant ssh vm001
独自のキーを使用します(設定ステップで仮想マシンにインストールします)。
$ ssh vagrant@<IP>
またはrootアクセス権を取得します。
$ ssh root@<IP>
仮想マシンを実行して一時停止
vagrant suspend
し、数日後に起動してテストを続行できます(vagrant up
)。テスト環境はたくさんありますが、ディスク容量が限られている場合は、一部の仮想マシンを削除して後で再作成できます。仮想マシンを削除し、構成を削除します。
vagrant destroy -f rm -rf Vagrantfile .vagrant
答え4
独自のホスティングGitlabをお勧めします。 KubernetesとDockerをすぐに統合して実行する必要があるほとんどすべての作業を自動化できます。