ossh: eksekusi perintah paralel di banyak server

Kadang-kadang perlu untuk menjalankan beberapa perintah patch Barmin di banyak server dan disarankan untuk tidak menunggu terlalu lama untuk hasil eksekusi. Untuk ini, saya menulis ossh (Satu SSH untuk mengatur semuanya). Berikut contoh cara kerjanya:



$ wc -l /tmp/ossh.ips
21418 /tmp/ossh.ips
$ time ossh -n -h /tmp/ossh.ips -c uptime -p 1000 >/tmp/ossh.out

real    3m10.310s
user    0m30.970s
sys     0m19.282s
$ grep 'load average' /tmp/ossh.out | sort -n -k5 | tail -n1
10.23.91.97   [1]  13:37:55 up 828 days,  2:34,  0 users,  load average: 8.29, 4.45, 3.90
$

      
      





Dalam contoh ini, file /tmp/ossh.ips berisi 21418 alamat ip mesin. -n berarti Anda tidak perlu melakukan kueri terbalik untuk menentukan nama berdasarkan alamat. -c uptime menyetel perintah yang ingin saya jalankan. -p 1000 memungkinkan hingga 1000 koneksi pada waktu yang sama. Seperti yang Anda lihat dari keluarannya, perintah bekerja cukup cepat.



Apa lagi yang bisa dilakukan ossh?



$ ossh -?
Usage: ossh [-?AinPv] [-c COMMAND] [-C COMMAND_FILE] [-H HOST_STRING] [-h HOST_FILE] [-I FILTER] [-k PRIVATE_KEY] [-l USER] [-o PORT] [-p PARALLELISM] [-T TIMEOUT] [-t TIMEOUT] [parameters ...]
 -?, --help        Show help
 -A, --askpass     Prompt for a password for ssh connects
 -c, --command=COMMAND
                   Command to run
 -C, --command-file=COMMAND_FILE
                   file with commands to run
 -H, --host=HOST_STRING
                   Add the given HOST_STRING to the list of hosts
 -h, --hosts=HOST_FILE
                   Read hosts from file
 -i, --ignore-failures
                   Ignore connection failures in the preconnect mode
 -I, --inventory=FILTER
                   Use FILTER expression to select hosts from inventory
 -k, --key=PRIVATE_KEY
                   Use this private key
 -l, --user=USER   Username for connections [$LOGNAME]
 -n, --showip      In the output show ips instead of names
 -o, --port=PORT   Port to connect to [22]
 -p, --par=PARALLELISM
                   How many hosts to run simultaneously [512]
 -P, --preconnect  Connect to all hosts before running command
 -T, --connect-timeout=TIMEOUT
                   Connect timeout in seconds [60]
 -t, --timeout=TIMEOUT
                   Run timeout in seconds
 -v, --verbose     Verbose output
$

      
      





Daftar host dapat ditentukan langsung pada baris perintah menggunakan opsi -H (dalam kasus beberapa host, mereka harus dipisahkan oleh spasi, dan seluruh daftar harus diapit tanda kutip seperti pada contoh di bawah) atau dimuat dari file menggunakan opsi -h. Baris yang dimulai dengan # dalam file akan diabaikan. Alamatnya bisa berisi port: my.host:2222. Anda dapat menggunakan perluasan tanda kurung: "host {1,3..5} .com" akan menjadi "host1.com host3.com host4.com host5.com". Baik -H dan -h dapat digunakan beberapa kali.



Untuk otorisasi akan digunakan

  • kata sandi yang akan diminta ossh saat menggunakan opsi -A
  • Sakelar ssh ditentukan oleh opsi -k
  • ssh-agent (dalam hal ini, Anda harus menentukan variabel lingkungan SSH_AUTH_SOCK)


Dalam urutan itu.



Terkadang Anda perlu memastikan Anda dapat masuk ke semua mesin sebelum menjalankan perintah. Ada opsi -P untuk ini. Secara default, jika setidaknya satu mesin tidak tersedia, ossh akan gagal. Jika Anda ingin mengabaikan koneksi yang gagal, gunakan opsi -i.



Ossh dapat menggunakan sistem inventaris Anda. Untuk melakukan ini, path harus berisi perintah ossh-inventory, dimana parameter dari opsi -I akan diteruskan. Opsi ini dapat digunakan berkali-kali. Perintah ossh-inventory harus mencetak baris ke keluaran standar dalam format:

_ _
      
      





Di mana alamat_mesin dapat berupa nama dns atau alamat ip.



Perintah yang akan dieksekusi ditentukan oleh opsi -C (baca dari file) atau -c (diambil dari baris perintah). Opsi ini dapat digunakan berkali-kali. Jika -C dan -c ada, perintah dari file akan dieksekusi terlebih dahulu, kemudian dari baris perintah.



Selain menjalankan perintah menggunakan ossh, Anda dapat melakukan streaming log secara real time:



$ ossh -H "web05 web06" -c "tail -f -c 0 /var/log/nginx/access.log|grep --line-buffered Wget"
web05 192.168.1.23 - - [22/Jun/2016:12:24:02 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
web05 192.168.1.49 - - [22/Jun/2016:12:24:07 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
web06 192.168.1.117 - - [22/Jun/2016:12:24:23 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
web05 192.168.1.29 - - [22/Jun/2016:12:24:30 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
...
      
      







Berikut adalah simulasi penerapan bergulir:



$ ossh -p 1 -H "test0{1..3}" -c "sleep 10 && date"
test01 Wed Jun 22 12:38:24 PDT 2016
test02 Wed Jun 22 12:38:34 PDT 2016
test03 Wed Jun 22 12:38:44 PDT 2016
$
      
      







Dapat dilihat bahwa perintah dijalankan secara berurutan di mesin. Hanya satu mesin yang terlibat dalam satu waktu. Untuk penerapan yang sebenarnya, "sleep 10 && date" harus diganti dengan, misalnya, "apt-get install -y your_package".



Untuk penerapan itulah versi pertama ossh ditulis. Seseorang akan bertanya mengapa saya tidak menggunakan beberapa sistem manajemen konfigurasi yang diterima secara umum? Faktanya adalah itu kembali pada tahun 2013 dan kami menggunakan koki. Jelas bahwa chef tidak cocok dengan kami khususnya dengan ketidakpastian kapan tepatnya perubahan akan diterapkan (chef-klien dilakukan setiap 30 menit). Untuk secara konsisten meluncurkan perubahan pada banyak mesin, beberapa pengembang menggunakan peretasan kotor: chef-klien tidak bekerja sepanjang waktu, tetapi diluncurkan sekali (melalui ssh) hanya pada saat diperlukan untuk melakukan penerapan. Pada saat itu, pekerjaan sedang dilakukan untuk mengganti chef dengan garam, tetapi peralihannya tidak mudah dan penyelesaiannya membutuhkan waktu tambahan. Kami sedang mengembangkan layanan baru,yang membutuhkan penerapan yang sering dan diluncurkan oleh satu-satunya paket Debian. Pertama, kami menggunakan utilitas pisau dari chef. Utilitas ini memungkinkan Anda untuk terhubung melalui ssh ke server yang diinginkan dan menjalankan perintah padanya. Pada titik tertentu, saya menyadari bahwa chef dalam hal ini adalah tautan tambahan dan menulis ossh.



Penting untuk dicatat bahwa ossh adalah alat untuk memecahkan masalah berskala besar dan non-standar. Jika kebutuhan untuk menggunakan ossh sering muncul, ini adalah alasan untuk memikirkan apakah Anda bekerja dengan baik dengan infrastruktur dan manajemen server. Berikut beberapa situasi di mana ossh membantu saya secara pribadi:

  • Setelah saya merapikan /root/.ssh/authorized_keys pada sejumlah besar server (ada sekitar 7000 pada saat itu). Pengembang mendaftarkan kunci mereka di sana, khususnya untuk proses memperbarui layanan mereka. Penting untuk mendapatkan daftar semua kunci yang digunakan pada semua mesin, dan memastikan bahwa menghapus kunci tersebut tidak akan menimbulkan bencana.
  • Untuk lompatan kedua tanpa rasa sakit
  • Ketika kami berjuang dengan TCP SACK PANIC , aturan iptables diluncurkan oleh sistem manajemen konfigurasi. Untuk memastikan semuanya baik-baik saja, saya memeriksa aturan yang benar dengan ossh. Dan itu tidak sia-sia sama sekali, ada mobil yang aturannya tidak berlaku.
  • Terkadang saya harus membuat lingkungan pengujian dengan ratusan (dan terkadang ribuan) mesin. Seringkali mesin ini diisolasi dari jaringan produksi dan tidak tersedia untuk sistem manajemen konfigurasi standar. Dalam situasi seperti ini, konfigurasi mesin dapat dilakukan dengan menggunakan ossh.


Saya meramalkan pertanyaan mengapa saya tidak menggunakan solusi yang sudah jadi. Seperti yang saya sebutkan di atas, kebutuhan untuk menjalankan perintah pada ribuan mesin pertama kali terpikir oleh saya pada tahun 2013. Pada saat itu, saya hanya dapat menemukan ssh paralel, yang tidak cocok untuk saya dengan berikut ini:

  • Saya tidak dapat menaikkan paralelisme di atas 150, kesalahan mulai terjadi saat menyambung ke server jarak jauh
  • parallel ssh mengumpulkan semua output dan membuangnya saat perintah selesai. Log streaming, misalnya, tidak mungkin dilakukan dengan bantuannya
  • Output ssh paralel (bagi saya pribadi) canggung untuk diurai


Awalnya ossh ditulis dalam ruby, untuk meningkatkan performa, saya menggunakan mesin acara, dan kemudian fiber. Saya baru-baru ini menulis ulang ossh untuk pergi. Saya akan berterima kasih jika go-ahli (saya tidak saat ini) melihat kode saya dan menunjukkan cara yang mungkin untuk memperbaikinya.



All Articles