ルーストアバウト

ルーストアバウト

100台の仮想サーバーを作成したいと思います。テストに使用されるため、作成と削除が簡単になります。

  • 他の物理システムからSSHを介してアクセスできる必要があります(公開SSHキーを提供)。
  • 独自のIPアドレスが必要で、他の物理ホストからアクセスできる必要がありますssh I.P.n.o(たとえば、ssh 10.0.0.99IPv4または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-1grepします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)

おすすめ記事