Sebelum ni saya menulis tentang menggunakan Git untuk menyuruh server mengemaskini aplikasi atau kod. Dengan hanya membuat push ke repo di server Git, server aplikasi juga akan mengemaskini dirinya dengan kod yang terkini.
AWS, Autoscaling dan ELB
Saya banyak menggunakan server di Amazon Web Service (AWS). Antara ciri yang hebat di AWS adalah autoscaling. Dengan autoscaling, kita boleh membina sebuah load balancer dan meletakkan server-server di bawahnya. Maka, trafik yang diterima oleh website akan diagih-agihkan kepada server-server yang terdapat di bawah ELastic Load Balancer (ELB) ini. Biasanya server-server ini adalah serupa, mempunyai kod yang sama, setting yang sama dan lain-lain. Dengan autoscaling, kita boleh tetapkan beberapa peraturan bila dan keadaannya untuk AWS menambah atau mengurangkan server di bawah ELB ini.
Sebagai contoh, saya boleh tetapkan peraturan sebegini:
- peraturan ini untuk ELB “API SERVER”
- apabila server terakhir menggunakan CPU melebihi 80%, tambah server baru
- apabila server terakhir menggunakan CPU kurang daripada 20%, tutup server terakhir
- jumlah server maksima adalah 10 dan jumlah server minima ada 1
Dengan sebegini, Autoscaling akan memulakan kerja.
Git dan Hook
Seperti yang pernah terangkan dalam artikel yang dulu, sesebuah server Git biasanya mempunyai setting Hook. Dengan Hook, apabila kita melakukan push, kita boleh memberitahu server Git kita (Gitlab, Github, BitBucket dan lain-lain) agar memanggil sesebuah URL luar dan menghantar maklumat tentang push itu. Antara maklumat yang dihantar adalah programmer yang membuat push, branch yang terlibat dan lain-lain.
Untuk membuat kemaskini di server aplikasi, URL luar adalah satu skrip PHP (atau lain-lain bahasa) di server aplikasi yang akan membuat arahan “git pull” dari server aplikasi ke server Git.
Apabila semuanya dipasang baik, ini adalah rentetan aktiviti yang berlaku apabila seorang programmer membuat “push” ke server Git.
- Programmer membuat “git push” ke Gitlab
- Dengan Hook, Gitlab memanggil skrip PHP (mungkin pull.php) di server aplikasi
- pull.php akan membuat “git pull” dari server aplikasi
- Server aplikasi menerima kod-kod terkini melalui arahan “git pull” tadi
Isu Yang Timbul Dengan AWS AutoScaling
Apabila kita menetapkan hook di Gitlab, kita perlu tahu alamat server aplikasi atau URL untuk skrip pull.php tadi. Dengan AutoScaling, kita tak tahu apa alamat server-server yang dibina oleh AWS. Setiap server diberikan alamat IP secara rawak. Jadi, inilah masalahnya apabila kita mahu melaksanakan kemaskini dengan git push, tetapi dengan tetapan AutoScaling.
Penyelesaiannya
Kita perlukan cara untuk mengetahui apakah alamat IP untuk server-server di bawah ELB tanpa perlu login ke dalam konsol AWS. Terdapat dua cara sebenarnya:
Cara pertama – Apabila kita membina ELB dengan Autoscaling, kita boleh menetapkan untuk menerima makluman (notification via SNS) apabila server ditambah atau dibuang. Makluman ini boleh ditetapkan agar diterima oleh sesuatu skrip. Skrip ini boleh menyimpan dan mengemaskini senarai server di bawah ELB. Tetapi melihat kepada data yang diberi, ianya masih tidak memberikan alamat IP server. Ia hanya memberikan ID untuk server itu sahaja. Kita masih boleh tahu apakah alamat IP untuk server baru tu, tapi kita perlu menggunakan AWS SDK.
AWS SDK adalah sistem API boleh AWS untuk segala operasi di dalam akaun AWS kita. Terdapat beberapa library untuk .NET, Ruby, Python dan juga PHP. Saya gunakan PHP AWS SDK.
Cara kedua – Selain daripada menunggu makluman autoscaling, dengan AWS SDK, boleh juga kita terus bertanyakan sahaja apakah server-server di bawah sesuatu ELB. Kemudian, AWS SDK akan memulangkan ID server-server. Kita perlu bertanyakan kepada AWS SDK sekali lagi untuk IP server-server ini.
Bila kita mengetahui alamat IP server yang terlibat, bolehlah kita memanggil skrip yang akan membuat arahan “git pull”.
Saya mengguna kaedah kedua. Maka saya tuliskan sebuah kod ringkas untuk membuat semua operasi ini. Ini apa yang berlaku apabila seseorang membuat push ke repo Gitlab (atau Github, BitBucket, dll).
- Programmer push kerja ke repo di Gitlab
- Gitlab, melalui hook menghantar data ke skrip (trigger.php) di server yang khusus (bukan di bawah ELB)
- trigger.php menggunakan library PHP AWS SDK bertanyakan info berkenaan server-server di bawah ELB yang dimahukan
- Apabila mendapat senarai alamat IP untuk server-server di bawah ELB yang dikehendaki, trigger.php mengakses skrip (pull.php) di server-server di bawah ELB
- pull.php yang berada di setiap server di bawah ELB akan melaksanakan arahan “git pull” di server masing-masing
- Dengan arahan “git pull”, setiap server akan dikemaskini dengan kod aplikasi terkini
Sekiranya dirasakan berguna, boleh dapatkan kod PHP saya untuk operasi ini
Nota
Server-server di bawah ELB mestilah mempunyai alamat IP public agar boleh diakses oleh trigger.php tadi.
Sememangnya ini contoh yang ringkas. Jika dilihat pada kod saya di Github, untuk keselamatan, kita boleh menghadkan yang pull.php hanya boleh diakses daripada IP-IP tertentu. Kalau kita boleh begitu, pastikan IP untuk server di mana trigger.php berada dimasukkan. Begitu juga untuk trigger.php, kita boleh hanya membenarkan hanya IP Github yang boleh mengaksesnya.
Artikel ini juga mengandaikan yang anda telah menyediakan server aplikasi dengan SSH key atau deploy key untuk operasi Git oleh sistem dalam server.
Membina AutoScaling dalam AWS, kita akan menggunakan AMI (image) daripada satu server yang kita telah bina dahulu. Pastikan AMI itu dibina daripada server yang cukup untuk arahan apabila server baru dihidupkan ataupun direboot. Saya menggunakan OS Ubuntu untuk server-server, dan operasi ini boleh dibuat dengan skrip /etc/rc.local ataupun dengan arahan masa @reboot di dalam crontab. Ini biasa digunakan untuk membuat git pull pertama apabila server baru dihidupkan. Ini memastikan kod aplikasi sentiasa yang terkini.
Kalau menggunakan Elastic Beanstalk, ciri ini memang sudah ada. Kita boleh gunakan Elastic Beanstalk command line tool untuk menghantar kod secara Git ke server-server yang terlibat. Tapi ini saya belum pernah cuba dan saya tiada setup yang menggunakan Elastic Beanstalk. Maklumat lanjut tentang Git and Elastic Beanstalk.
Saya kira itu saja daripada saya. Sekiranya ada soalan, boleh bertanya di komen.