Pengantar arsitektur aplikasi fraktal

Pengantar arsitektur aplikasi fraktal

Bagian ini memperkenalkan arsitektur aplikasi dan menjelaskan bagaimana hal itu dirancang untuk memanfaatkan fitur awan secara umum dan OpenStack pada khususnya. Ini juga menjelaskan beberapa perintah di bagian sebelumnya.

Prinsip arsitektur aplikasi cloud

Aplikasi awan biasanya berbagi beberapa prinsip desain. Prinsip-prinsip ini mempengaruhi disain aplikasi Fractals.

Modularitas dan micro-services

Micro-services adalah pola desain penting yang membantu mencapai modularitas aplikasi. Memisahkan fungsi aplikasi logis menjadi layanan independen menyederhanakan perawatan dan penggunaan ulang. Komponen Decoupling juga mempermudah komponen skala individu secara selektif, sesuai kebutuhan. Selanjutnya, modularitas aplikasi adalah fitur aplikasi yang dibutuhkan yang dapat diukur dengan baik dan fault tolerant.

Skalabilitas

Aplikasi awan sering menggunakan banyak instance kecil daripada beberapa instance besar. Asalkan aplikasi cukup modular, Anda dapat dengan mudah mendistribusikan micro-service sebanyak mungkin sesuai kebutuhan. Arsitektur ini memungkinkan aplikasi tumbuh melewati batas yang diberlakukan oleh ukuran maksimum sebuah instance. Ini seperti mencoba memindahkan sejumlah besar orang dari satu tempat ke tempat lain; Hanya ada begitu banyak orang yang bisa Anda pakai di bus terbesar, tapi Anda bisa menggunakan jumlah bus atau mobil kecil yang tidak terbatas, yang hanya menyediakan kapasitas yang Anda butuhkan - dan tidak lebih.

Toleransi kesalahan

Dalam pemrograman awan, ada analogi terkenal yang dikenal sebagai "cattle vs pets". Jika Anda belum pernah mendengarnya, itu seperti ini:

Bila Anda berurusan dengan hewan peliharaan, Anda menamai dan merawat mereka. Jika mereka sakit, Anda merawat mereka kembali ke kesehatan, yang bisa menyulitkan dan sangat menyita waktu. Saat Anda berurusan dengan ternak, Anda memasang label bernomor di telinga mereka. Jika mereka sakit, Anda menurunkannya dan melanjutkan perjalanan.

Itu, seperti yang terjadi, adalah realitas baru pemrograman. Aplikasi dan sistem yang digunakan untuk dibuat di server besar dan mahal, dirawat oleh staf operasi yang berdedikasi untuk menjaga kesehatan mereka. Jika ada yang tidak beres dengan salah satu server tersebut, tugas staf adalah melakukan apa pun untuk memperbaikinya lagi dan menyimpan server dan aplikasinya.

Dalam pemrograman awan, sangat berbeda. Daripada server besar dan mahal, Anda memiliki mesin virtual yang bisa dipakai; Jika ada yang tidak beres, Anda mematikan server dan memutar yang baru. Masih ada staf operasi, tapi bukannya mengelola server individual kembali ke kesehatan, tugas mereka adalah memantau kesehatan keseluruhan sistem.

Ada keuntungan pasti arsitektur ini. Sangat mudah untuk mendapatkan server "new", tanpa masalah yang pasti muncul saat server telah berjalan dan berjalan selama berbulan-bulan, atau bahkan bertahun-tahun.

Seperti halnya infrastruktur klasik, kegagalan infrastruktur awan (hardware, jaringan, dan perangkat lunak) yang tidak dapat dihindari tidak dapat dihindari. Saat merancang awan, sangat penting aplikasi Anda dirancang untuk lingkungan tempat terjadi kegagalan setiap saat. Ini mungkin terdengar seperti pertanggungjawaban, tapi tidak demikian; Dengan merancang aplikasi Anda dengan tingkat toleransi kesalahan yang tinggi, Anda juga membuatnya tahan lama, dan lebih mudah beradaptasi, dalam menghadapi perubahan.

Toleransi kesalahan sangat penting untuk aplikasi berbasis cloud.

Otomatisasi

Jika sebuah aplikasi dimaksudkan untuk secara otomatis naik turun untuk memenuhi permintaan, maka tidak mungkin ada langkah manual dalam proses penggelaran komponen aplikasi apapun. Otomasi juga mengurangi waktu untuk pemulihan aplikasi Anda jika terjadi kegagalan komponen, meningkatkan toleransi dan ketahanan kesalahan.

Programmatic interfaces (APIs)

Seperti banyak aplikasi cloud, aplikasi Fractals memiliki RESTful API. Anda dapat menghubungkannya secara langsung dan menghasilkan fraktal, atau Anda dapat mengintegrasikannya sebagai komponen aplikasi yang lebih besar. Setiap saat antarmuka standar seperti API tersedia, pengujian otomatis menjadi jauh lebih layak, meningkatkan kualitas perangkat lunak.

Arsitektur aplikasi fraktal

Aplikasi Fractals dirancang dengan prinsip-prinsip dari subbagian sebelumnya. Anda akan mencatat itu di Mulai, kami menerapkan aplikasi dengan gaya all-in-one, pada satu mesin virtual. Ini bukan praktik yang baik, tapi karena aplikasinya menggunakan layanan mikro untuk memisahkan fungsi aplikasi logis, kita bisa mengubahnya dengan mudah.

digraph {
  API -> Database [color=green];
  API -> Database [color=orange];
  Database -> API [color=red];
  API -> Webinterface [color=red];
  API -> "Queue Service" [color=orange];
  "Queue Service" -> Worker [color=orange];
  Worker -> API [color=green];
}

Pesan antrian digunakan untuk memudahkan komunikasi antara layanan aplikasi Fraktal. Aplikasi Fraktal menggunakan work queue (atau task queue) untuk mendistribusikan task (tugas) ke layanan pekerja.

Pesan antrian bekerja dengan cara yang mirip dengan antrean (atau berbaris, bagi kita di sisi lain lautan) di bank yang dilayani oleh beberapa pegawai. Antrian pesan dalam aplikasi kami memberikan umpan permintaan kerja yang dapat dilakukan satu per satu oleh pekerja, apakah ada satu layanan pekerja ataupun ratusan di antaranya.

Ini adalah sebuah useful pattern untuk banyak aplikasi awan yang memiliki daftar panjang permintaan masuk dan kumpulan sumber daya untuk melayani mereka. Ini juga berarti bahwa seorang pekerja mungkin mogok dan tugas akan diproses oleh pekerja lain.

Catatan

The RabbitMQ getting started tutorial memberikan pengenalan yang bagus untuk pesan antrian.

digraph {
  rankdir=LR;
  Queue [shape="doublecircle"];
  API -> Queue;
  Queue -> "Worker 1";
  Queue -> "Worker 2";
}

Layanan pekerja mengkonsumsi pesan dari antrian kerja dan kemudian memprosesnya untuk membuat file image fraktal yang sesuai.

Tentu saja ada juga antarmuka web yang menawarkan cara yang lebih ramah untuk mengakses API untuk melihat image fraktal yang dibuat, dan antarmuka command line yang sederhana.

screenshot of the webinterface

Ada juga beberapa storage back end (untuk menyimpan image fraktal yang dihasilkan) dan komponen basis data (untuk menyimpan keadaan tugas), namun kami akan membicarakan hal-hal tersebut di Make it durable dan Block Storage masing-masing.

Bagaimana aplikasi Fractals berinteraksi dengan OpenStack

Magic revisited

Jadi apa sebenarnya permintaan itu di akhir bagian sebelumnya? Mari kita lihat lagi. Dalam subbagian ini, kami hanya menjelaskan apa yang telah Anda lakukan di bagian sebelumnya; Anda tidak perlu menjalankan perintah ini lagi.

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -i messaging -r api -r worker -r demo
'''

instance_name = 'all-in-one'
testing_instance = conn.create_node(name=instance_name,
                                   image=image,
                                   size=flavor,
                                   ex_keyname=keypair_name,
                                   ex_userdata=userdata,
                                   ex_security_groups=[all_in_one_security_group])

Kami menjelaskan image and flavor di :doc: getting_started, jadi pada bagian berikut, kami akan menjelaskan parameter lainnya secara rinci, termasuk ex_userdata (cloud-init) dan ex_keyname (key pairs).

Perkenalan pada cloud-init

cloud-init adalah alat yang melakukan tugas konfigurasi instance saat boot instance awan, dan dipasang pada sebagian besar image awan. ex_userdata, yang dilewatkan ke create_node, adalah data konfigurasi yang dilewatkan ke cloud-init.

Dalam hal ini, kami menyajikan sebuah skrip shell sebagai userdata. Ketika create_node Menciptakan instance, cloud-init Mengeksekusi skrip shell di variable userdata.

Bila kunci publik SSH diberikan selama pembuatan instance, awan init memasang kunci ini di akun pengguna. (Nama pengguna bervariasi di antara image awan.) Lihat Obtaining Images bagian dari panduan image untuk pedoman tentang nama pengguna yang harus Anda gunakan saat SSHing. Jika Anda masih mengalami masalah saat log in, mintalah provider awan untuk mengkonfirmasi nama pengguna.

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api -r worker -r demo
'''

Setelah instance dibuat, unduhan cloud-init dan jalankan skrip yang disebut install.sh. Script ini menginstal aplikasi Fractals. Cloud-init bisa mengkonsumsi script bash dan sejumlah tipe data yang berbeda. Anda bahkan bisa menyediakan beberapa jenis data. Anda dapat menemukan lebih banyak informasi tentang cloud-init di official documentation.

Pengantar key pair (pasangan kunci)

Keamanan penting bila menyangkut instance Anda; Anda tidak bisa memiliki siapa pun yang mengaksesnya. Untuk mengaktifkan masuk ke sebuah instance, Anda harus menyediakan kunci publik dari pasangan kunci SSH selama pembuatan instance. Pada bagian pertama, Anda membuat dan mengunggah pasangan kunci ke OpenStack, dan cloud-init memasangnya untuk akun pengguna.

Bahkan dengan kunci di tempat, bagaimanapun, Anda harus memiliki peraturan kelompok keamanan yang sesuai untuk mengakses instance Anda.

Pengantar kelompok keamanan

Kelompok keamanan adalah kumpulan aturan akses jaringan yang diterapkan pada jaringan instance. Secara default, hanya lalu lintas jalan keluar (outbound) yang diperbolehkan. Anda harus secara eksplisit mengaktifkan akses jaringan masuk (inbound) dengan membuat aturan kelompok keamanan.

Peringatan

Menghapus aturan egress yang dibuat oleh OpenStack akan menyebabkan jaringan instance Anda terputus.

Mulailah dengan membuat grup keamanan untuk instance all-in-one dan menambahkan aturan yang sesuai, seperti HTTP (port TCP 80) dan SSH (port TCP 22):

all_in_one_security_group = conn.ex_create_security_group('all-in-one', 'network access for all-in-one application.')
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 22, 22)

Catatan

ex_create_security_group_rule() mengambil rentang port sebagai masukan. Inilah sebabnya mengapa port 80 dan 22 dilewati dua kali.

Anda dapat mencantumkan kelompok keamanan yang tersedia dengan:

conn.ex_list_security_groups()

Setelah membuat aturan atau grup, Anda juga dapat menghapusnya:

conn.ex_delete_security_group_rule(rule)
conn.ex_delete_security_group(security_group)

Untuk melihat grup keamanan mana yang berlaku untuk sebuah instance, Anda dapat:

conn.ex_get_node_security_groups(testing_instance)

Setelah Anda mengkonfigurasi izin, Anda harus tahu di mana mengakses aplikasi.

Pengantar Floating IP (IP Mengambang)

Seperti dalam TI tradisional, instance awan diakses melalui alamat IP yang diberikan OpenStack. Bagaimana ini sebenarnya dilakukan tergantung pada pengaturan jaringan untuk awan Anda. Dalam beberapa kasus, Anda hanya akan mendapatkan alamat IP rout-able internet yang diberikan langsung ke instance Anda.

Cara yang paling umum untuk awan OpenStack untuk mengalokasikan alamat IP Internet rout-able ke instance, bagaimanapun, adalah melalui penggunaan floating IP. Floating IP adalah alamat yang ada sebagai entitas tersendiri, dan dapat dikaitkan dengan antarmuka jaringan instance yang spesifik. Bila alamat floating IP dikaitkan dengan antarmuka jaringan instance, OpenStack re-directs traffic yang terikat alamat tersebut ke alamat alamat antarmuka jaringan internal instance. Provider awan Anda umumnya akan menawarkan kolam floating IP untuk Anda gunakan.

Untuk menggunakan floating IP, Anda harus mengalokasikan IP ke proyek Anda terlebih dulu, kemudian mengaitkannya ke antarmuka jaringan instance Anda.

Catatan

Mengalokasikan sebuah floating IP ke sebuah instance tidak mengubah alamat IP dari instance, menyebabkan OpenStack untuk menetapkan aturan terjemahan jaringan untuk mengizinkan sebuah additional alamat IP.

unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        print("Found an unused Floating IP: %s" % floating_ip)
        break

Jika Anda tidak memiliki floating IP bebas yang telah dialokasikan sebelumnya untuk proyek Anda, pertama pilih kolam floating IP yang ditawarkan oleh provider Anda. Dalam contoh ini, kami telah memilih yang pertama dan menganggapnya memiliki alamat IP yang tersedia.

pool = conn.ex_list_floating_ip_pools()[0]

Sekarang minta agar alamat dari kolam ini dialokasikan untuk proyek Anda.

unused_floating_ip = pool.create_floating_ip()

Sekarang Anda memiliki alamat floating IP yang tidak terpakai yang dialokasikan untuk proyek Anda, kaitkan ke sebuah instance.

conn.ex_attach_floating_ip_to_node(instance, unused_floating_ip)

Itu membawa kita ke tempat kita berakhir di akhir Mulai. Tapi kemana kita pergi dari sini?

Memisahkan layanan di beberapa instance

Kami telah berbicara tentang memisahkan fungsi menjadi layanan mikro yang berbeda, dan bagaimana hal itu memungkinkan kami memanfaatkan arsitektur awan. Sekarang mari kita lihat itu beraksi.

Sisa tutorial ini tidak akan mereferensikan all-in-one instance yang Anda buat di bagian pertama. Luangkan waktu untuk menghapus instance ini.

Mudah untuk membagi layanan menjadi beberapa instance. Kita akan membuat instance controller yang disebut app-controller, yang menghosting layanan API, database, dan pesan. Kami juga akan membuat instance pekerja yang disebut app-worker-1, yang hanya menghasilkan fraktal.

Langkah pertama adalah memulai instance controller. Instance memiliki layanan API, database, dan layanan pesan, seperti yang dapat Anda lihat dari parameter yang dikirimkan ke skrip instalasi.

Parameter

Deskripsi

Values

-i

Instal layanan

messaging (install RabbitMQ) and faafo (install the Faafo app).

-r

Enable/start something

api (enable and start the API service), worker (enable and start the worker service), dan demo (run the demo mode to request random fractals).

worker_group = conn.ex_create_security_group('worker', 'for services that run on a worker node')
conn.ex_create_security_group_rule(worker_group, 'TCP', 22, 22)

controller_group = conn.ex_create_security_group('control', 'for services that run on a control node')
conn.ex_create_security_group_rule(controller_group, 'TCP', 22, 22)
conn.ex_create_security_group_rule(controller_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(controller_group, 'TCP', 5672, 5672, source_security_group=worker_group)

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api
'''

instance_controller_1 = conn.create_node(name='app-controller',
                                         image=image,
                                         size=flavor,
                                         ex_keyname='demokey',
                                         ex_userdata=userdata,
                                         ex_security_groups=[controller_group])

conn.wait_until_running([instance_controller_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_controller_1, unused_floating_ip)
print('Application will be deployed to http://%s' % unused_floating_ip.ip_address)

Perhatikan bahwa saat ini, saat Anda membuat grup keamanan, Anda menyertakan aturan yang hanya berlaku untuk instance yang merupakan bagian dari grup pekerja.

Selanjutnya, mulai instance kedua, yang akan menjadi instance pekerja:

instance_controller_1 = conn.ex_get_node_details(instance_controller_1.id)
if instance_controller_1.public_ips:
    ip_controller = instance_controller_1.private_ips[0]
else:
    ip_controller = instance_controller_1.public_ips[0]

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -r worker -e 'http://%(ip_controller)s' -m 'amqp://guest:guest@%(ip_controller)s:5672/'
''' % {'ip_controller': ip_controller}
instance_worker_1 = conn.create_node(name='app-worker-1',
                                        image=image,
                                        size=flavor,
                                        ex_keyname='demokey',
                                        ex_userdata=userdata,
                                        ex_security_groups=[worker_group])

conn.wait_until_running([instance_worker_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_worker_1, unused_floating_ip)
print('The worker will be available for SSH at %s' % unused_floating_ip.ip_address)


Perhatikan bahwa Anda telah menambahkan instance ini ke worker_group, sehingga bisa mengakses controller.

Seperti yang dapat Anda lihat dari parameter yang dilewatkan ke skrip instalasi, Anda mendefinisikan instance ini sebagai instance pekerja. Tapi, Anda juga menyampaikan alamat instance API dan antrean pesan sehingga pekerja dapat mengambil permintaan. Skrip instalasi aplikasi Fractals menerima beberapa parameter.

Parameter

Deskripsi

Contoh

-e

URL endpoint dari layanan API.

http://localhost/

-m

URL transport dari layanan pesan.

amqp://guest:guest@localhost:5672/

-d

URL koneksi untuk database (tidak digunakan disini).

sqlite:////tmp/sqlite.db

Sekarang jika Anda membuat permintaan untuk fraktal baru, Anda terhubung ke instance pengontrol, app-controller, tapi pekerjaan sebenarnya akan dilakukan oleh instance pekerja yang terpisah - app-worker-1.

Login dengan SSH dan gunakan aplikasi Fractal

Masuk ke instance pekerja, app-worker-1, dengan SSH, gunakan pasangan kunci SSH yang sebelumnya ditambahkan"demokey ". Mulailah dengan mendapatkan alamat IP pekerja:

ip_instance_worker_1 = instance_worker_1.private_ips[0]
print(ip_instance_worker_1)

Sekarang Anda bisa SSH ke instance:

$ ssh -i ~/.ssh/id_rsa USERNAME@IP_WORKER_1

Catatan

Menggantikan IP_WORKER_1 Dengan alamat IP dari instance pekerja dan USERNAME ke nama pengguna yang sesuai.

Setelah Anda masuk (logged in), periksa untuk melihat apakah proses layanan pekerja berjalan seperti yang diharapkan. Anda dapat menemukan log dari layanan pekerja di direktori /var/log/supervisor/.

worker # ps ax | grep faafo-worker
17210 ?        R      7:09 /usr/bin/python /usr/local/bin/faafo-worker

Buka top untuk memantau penggunaan CPU dari proses faafo-worker.

Sekarang masuk ke instance controller, app-controller, juga dengan SSH, gunakan pasangan kunci SSH yang sebelumnya ditambahkan"demokey ".

$ ssh -i ~/.ssh/id_rsa USERNAME@IP_CONTROLLER

Catatan

Ganti IP_CONTROLLER dengan alamat IP dari instance controller dan USERNAME ke nama pengguna yang sesuai.

Periksa untuk melihat apakah proses layanan API berjalan seperti yang diharapkan. Anda dapat menemukan log untuk layanan API di direktori /var/log/supervisor/.

controller # ps ax | grep faafo-api
17209 ?        Sl     0:19 /usr/bin/python /usr/local/bin/faafo-api

Sekarang panggil antarmuka command line aplikasi Fraktal (faafo) untuk meminta beberapa fraktal baru. Perintah berikut meminta beberapa fraktal dengan parameter acak:

controller # faafo --endpoint-url http://localhost --verbose create
2015-04-02 03:55:02.708 19029 INFO faafo.client [-] generating 6 task(s)

Perhatikan top pada instance pekerja. Tepat setelah menelepon faafo, proses faafo-worker harus mulai menghabiskan banyak siklus CPU.

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
17210 root      20   0  157216  39312   5716 R 98.8  3.9  12:02.15 faafo-worker

Untuk menunjukkan rincian fraktal spesifik gunakan subcommand show dari Faafo CLI.

controller # faafo show 154c7b41-108e-4696-a059-1bde9bf03d0a
+------------+------------------------------------------------------------------+
| Parameter  | Value                                                            |
+------------+------------------------------------------------------------------+
| uuid       | 154c7b41-108e-4696-a059-1bde9bf03d0a                             |
| duration   | 4.163147 seconds                                                 |
| dimensions | 649 x 869 pixels                                                 |
| iterations | 362                                                              |
| xa         | -1.77488588389                                                   |
| xb         | 3.08249829401                                                    |
| ya         | -1.31213919301                                                   |
| yb         | 1.95281690897                                                    |
| size       | 71585 bytes                                                      |
| checksum   | 103c056f709b86f5487a24dd977d3ab88fe093791f4f6b6d1c8924d122031902 |
+------------+------------------------------------------------------------------+

Ada lebih banyak perintah yang tersedia; cari tahu lebih banyak tentang mereka faafo get --help, faafo list --help, dan faafo delete --help.

Catatan

Aplikasi menyimpan image fraktal yang dihasilkan secara langsung di database yang digunakan oleh instance layanan API. Penyimpanan file image dalam database bukanlah praktik yang baik. Kami melakukannya di sini sebagai contoh hanya sebagai cara mudah untuk mengaktifkan beberapa instance agar memiliki akses ke data. Untuk praktik terbaik, kami merekomendasikan menyimpan objek di Object Storage, yang tercakup dalam Make it durable.

Langkah selanjutnya

Anda sekarang harus memiliki pemahaman dasar tentang arsitektur aplikasi berbasis cloud. Selain itu, Anda sudah berlatih memulai instance baru, secara otomatis mengonfigurasikannya saat boot, dan bahkan memodulasi sebuah aplikasi sehingga Anda dapat menggunakan beberapa instance untuk menjalankannya. Ini adalah langkah dasar untuk meminta dan menggunakan sumber daya untuk menjalankan aplikasi Anda di awan OpenStack.

Dari sini, buka Scaling out untuk mempelajari cara meningkatkan skala aplikasi Anda. Atau, cobalah salah satu langkah berikut dalam tutorialnya:

Sampel kode lengkap

File berikut berisi semua kode dari bagian tutorial ini. Sampel kode komprehensif ini memungkinkan Anda melihat dan menjalankan kode sebagai satu skrip.

Sebelum menjalankan skrip ini, konfirmasikan bahwa Anda telah menyetel informasi autentikasi, flavor ID, dan image ID.

# step-1
userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -i messaging -r api -r worker -r demo
'''

instance_name = 'all-in-one'
testing_instance = conn.create_node(name=instance_name,
                                   image=image,
                                   size=flavor,
                                   ex_keyname=keypair_name,
                                   ex_userdata=userdata,
                                   ex_security_groups=[all_in_one_security_group])

# step-2
userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api -r worker -r demo
'''

# step-3
all_in_one_security_group = conn.ex_create_security_group('all-in-one', 'network access for all-in-one application.')
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 22, 22)

# step-4
conn.ex_list_security_groups()

# step-5
conn.ex_delete_security_group_rule(rule)
conn.ex_delete_security_group(security_group)

# step-6
conn.ex_get_node_security_groups(testing_instance)

# step-7
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        print("Found an unused Floating IP: %s" % floating_ip)
        break

# step-8
pool = conn.ex_list_floating_ip_pools()[0]

# step-9
unused_floating_ip = pool.create_floating_ip()

# step-10
conn.ex_attach_floating_ip_to_node(instance, unused_floating_ip)

# step-11
worker_group = conn.ex_create_security_group('worker', 'for services that run on a worker node')
conn.ex_create_security_group_rule(worker_group, 'TCP', 22, 22)

controller_group = conn.ex_create_security_group('control', 'for services that run on a control node')
conn.ex_create_security_group_rule(controller_group, 'TCP', 22, 22)
conn.ex_create_security_group_rule(controller_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(controller_group, 'TCP', 5672, 5672, source_security_group=worker_group)

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api
'''

instance_controller_1 = conn.create_node(name='app-controller',
                                         image=image,
                                         size=flavor,
                                         ex_keyname='demokey',
                                         ex_userdata=userdata,
                                         ex_security_groups=[controller_group])

conn.wait_until_running([instance_controller_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_controller_1, unused_floating_ip)
print('Application will be deployed to http://%s' % unused_floating_ip.ip_address)

# step-12
instance_controller_1 = conn.ex_get_node_details(instance_controller_1.id)
if instance_controller_1.public_ips:
    ip_controller = instance_controller_1.private_ips[0]
else:
    ip_controller = instance_controller_1.public_ips[0]

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -r worker -e 'http://%(ip_controller)s' -m 'amqp://guest:guest@%(ip_controller)s:5672/'
''' % {'ip_controller': ip_controller}
instance_worker_1 = conn.create_node(name='app-worker-1',
                                        image=image,
                                        size=flavor,
                                        ex_keyname='demokey',
                                        ex_userdata=userdata,
                                        ex_security_groups=[worker_group])

conn.wait_until_running([instance_worker_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_worker_1, unused_floating_ip)
print('The worker will be available for SSH at %s' % unused_floating_ip.ip_address)


# step-13
ip_instance_worker_1 = instance_worker_1.private_ips[0]
print(ip_instance_worker_1)

# step-14
Creative Commons Attribution 3.0 License

Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.