αžšαž”αŸ€αž”αž”αž„αŸ’αž€αžΎαž autoscaler αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž…αž„αŸ’αž€αŸ„αž˜

αžŸαž½αžŸαŸ’αžαžΈ! αž™αžΎαž„αž”αžŽαŸ’αžαž»αŸ‡αž”αžŽαŸ’αžαžΆαž›αž˜αž“αž»αžŸαŸ’αžŸαž±αŸ’αž™αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž‘αž·αž“αŸ’αž“αž“αŸαž™αž’αŸ†αŸ” αžœαžΆαž˜αž·αž“αž’αžΆαž…αž‘αŸ…αžšαž½αž…αž‘αŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαžŸαŸ’αžšαž˜αŸƒαž˜αžΎαž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž’αž”αŸ‹αžšαŸ†αž›αžΎαž‘αž·αž“αŸ’αž“αž“αŸαž™αž’αŸ†αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž…αž„αŸ’αž€αŸ„αž˜αžšαž”αžŸαŸ‹αžœαžΆ αžŠαŸ‚αž›αž’αŸ’αž“αž€αž…αžΌαž›αžšαž½αž˜αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž‚αŸ’αž“αžΆαŸ” αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž αŸαžαž»αž•αž›αž“αŸαŸ‡ αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αžαŸ‚αž„αžαŸ‚αž˜αžΆαž“αžœαžΆ :) αž™αžΎαž„αž”αžΆαž“αž…αžΌαž›αžšαž½αž˜αž€αŸ’αž“αž»αž„αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ αž€αžΆαžšαž›αŸƒαžαž˜αŸ’αžšαžΌαžœ αž“αž·αž„αž€αžΆαžšαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžšαž”αžŸαŸ‹αžœαžΆ αž αžΎαž™αž”αž»αžšαžŸαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž€αžΆαžšαž„αžΆαžš MapReduce αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž“αŸ…αž‘αžΈαž“αŸ„αŸ‡ αž αžΎαž™αž”αŸ’αžšαžΎ Spark αŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αŸ’αžšαž€αžΆαžŸαž“αŸαŸ‡ αž™αžΎαž„αž“αžΉαž„αž”αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αž™αžΎαž„αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸƒαž€αžΆαžšαž•αŸ’αž‘αž»αž€αž…αž„αŸ’αž€αŸ„αž˜αž˜αž·αž“αžŸαŸ’αž˜αžΎαž‚αŸ’αž“αžΆαžŠαŸ„αž™αž€αžΆαžšαžŸαžšαžŸαŸαžš autoscaler αžšαž”αžŸαŸ‹αž™αžΎαž„αž•αŸ’αž‘αžΆαž›αŸ‹αžŠαŸ„αž™αž”αŸ’αžšαžΎ cloud αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž–αž–αž€ Mail.ru.

αž”αž‰αŸ’αž αžΆ

αž…αž„αŸ’αž€αŸ„αž˜αžšαž”αžŸαŸ‹αž™αžΎαž„αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž€αŸ’αž“αž»αž„αž‘αž˜αŸ’αžšαž„αŸ‹αž’αž˜αŸ’αž˜αžαžΆαž‘αŸαŸ” αž€αžΆαžšαž”αŸ„αŸ‡αž…αŸ„αž›αž‚αžΊαž˜αž·αž“αžŸαŸ’αž˜αžΎαž‚αŸ’αž“αžΆαžαŸ’αž›αžΆαŸ†αž„αŸ” αž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸ αž˜αžΆαž“αžαŸ’αž“αžΆαž€αŸ‹αž’αž“αž»αžœαžαŸ’αž αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž˜αž“αž»αžŸαŸ’αžŸαž‘αžΆαŸ†αž„ 30 αž“αžΆαž€αŸ‹ αž“αž·αž„αž‚αŸ’αžšαžΌαž˜αŸ’αž“αžΆαž€αŸ‹αž‘αŸ…αž…αž„αŸ’αž€αŸ„αž˜ αž αžΎαž™αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž”αŸ’αžšαžΎαžœαžΆαŸ” αž¬αž˜αŸ’αžαž„αž‘αŸ€αž αž˜αžΆαž“αžαŸ’αž„αŸƒαž˜αž»αž“αžαŸ’αž„αŸƒαž•αž»αžαž€αŸ†αžŽαžαŸ‹ αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž”αž“αŸ’αž‘αž»αž€αž€αžΎαž“αž‘αžΎαž„αž™αŸ‰αžΆαž„αžαŸ’αž›αžΆαŸ†αž„αŸ” αž“αŸ…αžŸαž›αŸ‹αž“αŸƒαž–αŸαž›αžœαŸαž›αžΆαžŠαŸ‚αž›αž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αŸ’αž“αž»αž„αžšαž”αŸ€αž”αž˜αž·αž“αž•αŸ’αž‘αž»αž€αŸ”

αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž‘αžΈ 1 αž‚αžΊαžšαž€αŸ’αžŸαžΆαž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ‚αž›αž“αžΉαž„αž‘αž”αŸ‹αž‘αž›αŸ‹αž“αžΉαž„αž”αž“αŸ’αž‘αž»αž€αžαŸ’αž–αžŸαŸ‹αž”αŸ†αž•αž»αž αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αžΉαž„αž“αŸ…αž‘αŸ†αž“αŸαžšαž’αžŸαŸ‹αž–αŸαž›αžŠαŸ‚αž›αž“αŸ…αžŸαž›αŸ‹αŸ”

αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ #2 αž‚αžΊαžαŸ’αžšαžΌαžœαžšαž€αŸ’αžŸαžΆαž…αž„αŸ’αž€αŸ„αž˜αžαžΌαž…αž˜αž½αž™ αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αž“αŸ’αžαŸ‚αž˜αžαŸ’αž“αžΆαŸ†αž„αžŠαŸ„αž™αžŠαŸƒαž˜αž»αž“αžαŸ’αž“αžΆαž€αŸ‹ αž“αž·αž„αž€αŸ†αž‘αž»αž„αž–αŸαž›αž•αŸ’αž‘αž»αž€αžαŸ’αž–αžŸαŸ‹αž”αŸ†αž•αž»αžαŸ”

αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ #3 αž‚αžΊαžšαž€αŸ’αžŸαžΆαž…αž„αŸ’αž€αŸ„αž˜αžαžΌαž…αž˜αž½αž™ αž αžΎαž™αžŸαžšαžŸαŸαžš autoscaler αžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž”αž“αŸ’αž‘αž»αž€αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž“αŸƒ cluster αž αžΎαž™αžŠαŸ„αž™αž”αŸ’αžšαžΎ APIs αž•αŸ’αžŸαŸαž„αŸ— αž”αž“αŸ’αžαŸ‚αž˜ αž“αž·αž„αž›αž»αž”αžαŸ’αž“αžΆαŸ†αž„αž…αŸαž‰αž–αžΈ cluster αŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αŸ’αžšαž€αžΆαžŸαž“αŸαŸ‡ αž™αžΎαž„αž“αžΉαž„αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž›αŸαž 3 αŸ” αž§αž”αž€αžšαžŽαŸαžœαžΆαžŸαŸ‹αžŸαŸ’αž‘αž„αŸ‹αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž“αŸαŸ‡αž–αžΉαž„αž•αŸ’αž’αŸ‚αž€αžαŸ’αž›αžΆαŸ†αž„αž›αžΎαž€αžαŸ’αžαžΆαžαžΆαž„αž€αŸ’αžšαŸ…αž‡αžΆαž‡αžΆαž„αž€αžαŸ’αžαžΆαžαžΆαž„αž€αŸ’αž“αž»αž„ αž αžΎαž™αž’αŸ’αž“αž€αž•αŸ’αžαž›αŸ‹αžŸαŸαžœαžΆαž‡αžΆαžšαžΏαž™αŸ—αž˜αž·αž“αž•αŸ’αžαž›αŸ‹αžœαžΆαž‘αŸαŸ” αž™αžΎαž„αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž–αž–αž€ Mail.ru Cloud Solutions αž αžΎαž™αžŸαžšαžŸαŸαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž’αŸ’αžœαžΎαž˜αžΆαžαŸ’αžšαžŠαŸ’αž‹αžΆαž“αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αžŠαŸ„αž™αž”αŸ’αžšαžΎ MCS API αŸ” αž αžΎαž™αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž™αžΎαž„αž”αž„αŸ’αžšαŸ€αž“αž–αžΈαžšαž”αŸ€αž”αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž‘αž·αž“αŸ’αž“αž“αŸαž™ αž™αžΎαž„αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαž”αž„αŸ’αž αžΆαž‰αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžŸαžšαžŸαŸαžš autoscaler αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸ„αž›αž”αŸ†αžŽαž„αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ αž αžΎαž™αž”αŸ’αžšαžΎαžœαžΆαž‡αžΆαž˜αž½αž™ cloud αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€

αžαž˜αŸ’αžšαžΌαžœαž€αžΆαžšαž‡αžΆαž˜αž»αž“

αžŠαŸ†αž”αžΌαž„αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžαŸ‚αž˜αžΆαž“αž…αž„αŸ’αž€αŸ„αž˜ Hadoop αŸ” αž§αž‘αžΆαž αžšαžŽαŸ αž™αžΎαž„αž”αŸ’αžšαžΎαž€αžΆαžšαž…αŸ‚αž€αž…αžΆαž™ HDP αŸ”

αžŠαžΎαž˜αŸ’αž”αžΈαž±αŸ’αž™αžαŸ’αž“αžΆαŸ†αž„αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜ αž“αž·αž„αžŠαž€αž…αŸαž‰αž™αŸ‰αžΆαž„αž†αžΆαž”αŸ‹αžšαž αŸαžŸ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžαŸ‚αž˜αžΆαž“αž€αžΆαžšαž…αŸ‚αž€αž…αžΆαž™αžαž½αž“αžΆαž‘αžΈαž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αžαŸ’αž“αžΆαŸ†αž„αŸ”

  1. αžαŸ’αž“αžΆαŸ†αž„αž˜αŸαŸ” αž‡αžΆαž€αžΆαžšαž”αŸ’αžšαžŸαžΎαžšαžŽαžΆαžŸαŸ‹ αž‚αŸ’αž˜αžΆαž“αž’αŸ’αžœαžΈαž…αžΆαŸ†αž”αžΆαž…αŸ‹αžŠαžΎαž˜αŸ’αž”αžΈαž–αž“αŸ’αž™αž›αŸ‹αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž‘αŸαŸ– αžαŸ’αž“αžΆαŸ†αž„αžŸαŸ†αžαžΆαž“αŸ‹αž“αŸƒαž…αž„αŸ’αž€αŸ„αž˜ αžŠαŸ‚αž›αž§αž‘αžΆαž αžšαžŽαŸ αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆ Spark αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαžšαž”αŸ€αž”αž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜αŸ”
  2. αžαŸ’αž“αžΆαŸ†αž„αž€αžΆαž›αž”αžšαž·αž…αŸ’αž†αŸαž‘αŸ” αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžαŸ’αž“αžΆαŸ†αž„αžŠαŸ‚αž›αž’αŸ’αž“αž€αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸ…αž›αžΎ HDFS αž“αž·αž„αž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž€αžΆαžšαž‚αžŽαž“αžΆαž€αžΎαžαž‘αžΎαž„αŸ”
  3. αžαŸ’αž“αžΆαŸ†αž„αž€αž»αŸ†αž–αŸ’αž™αžΌαž‘αŸαžšαŸ” αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžαŸ’αž“αžΆαŸ†αž„αžŠαŸ‚αž›αž’αŸ’αž“αž€αž˜αž·αž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž’αŸ’αžœαžΈαž“αŸ…αž›αžΎ HDFS αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž€αžΆαžšαž‚αžŽαž“αžΆαž€αžΎαžαž‘αžΎαž„αŸ”

αž…αŸ†αžŽαž»αž…αžŸαŸ†αžαžΆαž“αŸ‹αŸ” αž€αžΆαžšαž’αŸ’αžœαžΎαž˜αžΆαžαŸ’αžšαžŠαŸ’αž‹αžΆαž“αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž“αžΉαž„αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αžŸαžΆαžšαžαŸ’αž“αžΆαŸ†αž„αž“αŸƒαž”αŸ’αžšαž—αŸαž‘αž‘αžΈαž”αžΈαŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‘αž‘αž½αž›αž™αž€ αž“αž·αž„αž”αž“αŸ’αžαŸ‚αž˜αžαŸ’αž“αžΆαŸ†αž„αž“αŸƒαž”αŸ’αžšαž—αŸαž‘αž‘αžΈαž–αžΈαžš αž›αŸ’αž”αžΏαž“αž†αŸ’αž›αžΎαž™αžαž”αž“αžΉαž„αž‘αžΆαž”αžŽαžΆαžŸαŸ‹ - αž€αžΆαžšαž”αž‰αŸ’αžˆαž”αŸ‹ αž“αž·αž„αž”αž‰αŸ’αž…αžΌαž›αž‘αžΎαž„αžœαž·αž‰αž“αžΉαž„αž…αŸ†αžŽαžΆαž™αž–αŸαž›αž…αŸ’αžšαžΎαž“αž˜αŸ‰αŸ„αž„αž“αŸ…αž›αžΎαž…αž„αŸ’αž€αŸ„αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ” αž‡αžΆαž€αžΆαžšαž–αž·αžαžŽαžΆαžŸαŸ‹ αž“αŸαŸ‡αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž’αŸ’αž“αž€αžšαŸ†αž–αžΉαž„αž–αžΈαž€αžΆαžšαž’αŸ’αžœαžΎαž˜αžΆαžαŸ’αžšαžŠαŸ’αž‹αžΆαž“αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž“αŸ„αŸ‡αž‘αŸαŸ” αž“αŸ„αŸ‡αž‚αžΊαž™αžΎαž„αž˜αž·αž“αž”αŸ‰αŸ‡αžαŸ’αž“αžΆαŸ†αž„αž“αŸƒαž”αŸ’αžšαž—αŸαž‘αž‘αžΈαž˜αž½αž™αž“αž·αž„αž‘αžΈαž–αžΈαžšαž‘αŸαŸ” αž–αž½αž€αžœαžΆαž“αžΉαž„αžαŸ†αžŽαžΆαž„αž±αŸ’αž™αž€αŸ’αžšαž»αž˜αžŠαŸ‚αž›αž’αžΆαž…αžŸαž˜αŸ’αžšαŸαž…αž”αžΆαž“αž’αž”αŸ’αž”αž”αžšαž˜αžΆαžŠαŸ‚αž›αž“αžΉαž„αž˜αžΆαž“αž–αŸαž‰αž˜αž½αž™αžšαž™αŸˆαž–αŸαž›αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ”

αžŠαžΌαž…αŸ’αž“αŸαŸ‡ autoscaler αžšαž”αžŸαŸ‹αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžšαžŸαŸαžšαž“αŸ…αž€αŸ’αž“αž»αž„ Python 3 αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Ambari API αžŠαžΎαž˜αŸ’αž”αžΈαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜ cluster αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ API αž–αžΈ Mail.ru Cloud Solutions (MCS) αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ αž“αž·αž„αž”αž‰αŸ’αžˆαž”αŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αŸ”

αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™

  1. αž˜αŸ‰αžΌαžŒαž»αž› autoscaler.py. αžœαžΆαž˜αžΆαž“αž”αžΈαžαŸ’αž“αžΆαž€αŸ‹αŸ– 1) αž˜αž»αžαž„αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™ Ambari, 2) αž˜αž»αžαž„αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™ MCS, 3) αž˜αž»αžαž„αžΆαžšαžŠαŸ‚αž›αž‘αžΆαž€αŸ‹αž‘αž„αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž‘αŸ…αž“αžΉαž„αžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαžšαž”αžŸαŸ‹ autoscaler αŸ”
  2. αžŸαŸ’αž‚αŸ’αžšαžΈαž” observer.py. αžŸαŸ†αžαžΆαž“αŸ‹αžœαžΆαž˜αžΆαž“αž…αŸ’αž”αžΆαž”αŸ‹αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆαŸ– αž–αŸαž›αžŽαžΆ αž“αž·αž„αž–αŸαž›αžŽαžΆαž˜αž½αž™αžŠαžΎαž˜αŸ’αž”αžΈαž αŸ…αž˜αž»αžαž„αžΆαžš autoscaler αŸ”
  3. αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ config.py. αž§αž‘αžΆαž αžšαžŽαŸ αžœαžΆαž˜αžΆαž“αž”αž‰αŸ’αž‡αžΈαžαŸ’αž“αžΆαŸ†αž„αžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž‘αŸ†αž αŸ†αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž· αž“αž·αž„αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαžŠαŸ‚αž›αž‡αŸ‡αž₯αž‘αŸ’αž’αž·αž–αž› αž§αž‘αžΆαž αžšαžŽαŸ αžšαž™αŸˆαž–αŸαž›αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαžšαž„αŸ‹αž…αžΆαŸ†αž…αžΆαž”αŸ‹αž–αžΈαž–αŸαž›αžŠαŸ‚αž›αžαŸ’αž“αžΆαŸ†αž„αžαŸ’αž˜αžΈαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αŸ” αžœαžΆαž€αŸαž˜αžΆαž“αžαŸ’αžšαžΆαž–αŸαž›αžœαŸαž›αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžαŸ’αž“αžΆαž€αŸ‹αž•αž„αžŠαŸ‚αžš αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž˜αž»αž“αž–αŸαž›αžαŸ’αž“αžΆαž€αŸ‹ αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž’αžαž·αž”αžšαž˜αžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αŸ”

αž₯αž‘αžΌαžœαž“αŸαŸ‡ αžŸαžΌαž˜αž€αŸ’αžšαž‘αŸαž€αž˜αžΎαž›αž”αŸ†αžŽαŸ‚αž€αž“αŸƒαž€αžΌαžŠαž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžšαž–αžΈαžšαžŠαŸ†αž”αžΌαž„αŸ”

1. αž˜αŸ‰αžΌαžŒαž»αž› Autoscaler.py

αžαŸ’αž“αžΆαž€αŸ‹ Ambari

αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž”αŸ†αžŽαŸ‚αž€αž“αŸƒαž€αžΌαžŠαžŠαŸ‚αž›αž˜αžΆαž“αžαŸ’αž“αžΆαž€αŸ‹αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž… Ambari:

class Ambari:
    def __init__(self, ambari_url, cluster_name, headers, auth):
        self.ambari_url = ambari_url
        self.cluster_name = cluster_name
        self.headers = headers
        self.auth = auth

    def stop_all_services(self, hostname):
        url = self.ambari_url + self.cluster_name + '/hosts/' + hostname + '/host_components/'
        url2 = self.ambari_url + self.cluster_name + '/hosts/' + hostname
        req0 = requests.get(url2, headers=self.headers, auth=self.auth)
        services = req0.json()['host_components']
        services_list = list(map(lambda x: x['HostRoles']['component_name'], services))
        data = {
            "RequestInfo": {
                "context":"Stop All Host Components",
                "operation_level": {
                    "level":"HOST",
                    "cluster_name": self.cluster_name,
                    "host_names": hostname
                },
                "query":"HostRoles/component_name.in({0})".format(",".join(services_list))
            },
            "Body": {
                "HostRoles": {
                    "state":"INSTALLED"
                }
            }
        }
        req = requests.put(url, data=json.dumps(data), headers=self.headers, auth=self.auth)
        if req.status_code in [200, 201, 202]:
            message = 'Request accepted'
        else:
            message = req.status_code
        return message

αžαžΆαž„αž›αžΎαž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸαž’αŸ’αž“αž€αž’αžΆαž…αž˜αžΎαž›αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž˜αž»αžαž„αžΆαžš stop_all_servicesαžŠαŸ‚αž›αž”αž‰αŸ’αžˆαž”αŸ‹αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž›αžΎαžαŸ’αž“αžΆαŸ†αž„αž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ‚αž›αž…αž„αŸ‹αž”αžΆαž“αŸ”

αž“αŸ…αž…αŸ’αžšαž€αž…αžΌαž›αžαŸ’αž“αžΆαž€αŸ‹αžšαŸ€αž“ Ambari αž’αŸ’αž“αž€αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αŸ–

  • ambari_urlαž§αž‘αžΆαž αžšαžŽαŸαžŠαžΌαž…αž‡αžΆ 'http://localhost:8080/api/v1/clusters/',
  • cluster_name - αžˆαŸ’αž˜αŸ„αŸ‡αž€αŸ’αžšαž»αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž“αŸ… Ambari,
  • headers = {'X-Requested-By': 'ambari'}
  • αž“αž·αž„αžαžΆαž„αž€αŸ’αž“αž»αž„ auth αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžˆαŸ’αž˜αŸ„αŸ‡αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ αž“αž·αž„αž–αžΆαž€αŸ’αž™αžŸαž˜αŸ’αž„αžΆαžαŸ‹αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ AmbariαŸ– auth = ('login', 'password').

αž˜αž»αžαž„αžΆαžšαžαŸ’αž›αž½αž“αžœαžΆαž‚αžΊαž‚αŸ’αž˜αžΆαž“αž’αŸ’αžœαžΈαž€αŸ’αžšαŸ…αž–αžΈαž€αžΆαžšαž αŸ…αž–αžΈαžšαž”αžΈαžŠαž„αžαžΆαž˜αžšαž™αŸˆ REST API αž‘αŸ…αž€αžΆαž“αŸ‹ Ambari αž“αŸ„αŸ‡αž‘αŸαŸ” αžαžΆαž˜αž‘αžŸαŸ’αžŸαž“αŸˆαž‘αžΌαž‡αžΈαžαž› αžŠαŸ†αž”αžΌαž„αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΈαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžŠαŸ‚αž›αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ…αž›αžΎαžαŸ’αž“αžΆαŸ†αž„αž˜αž½αž™ αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŸαž½αžšαž“αŸ…αž›αžΎαž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αžαž›αŸ‹αž±αŸ’αž™ αž“αŸ…αž›αžΎαžαŸ’αž“αžΆαŸ†αž„αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αžαž›αŸ‹αž±αŸ’αž™ αžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž‘αŸαžšαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž–αžΈαž”αž‰αŸ’αž‡αžΈαž‘αŸ…αžšαžŠαŸ’αž‹αŸ” INSTALLED. αž˜αž»αžαž„αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž‘αžΆαŸ†αž„αž’αžŸαŸ‹ αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αž‘αŸαžšαžαŸ’αž“αžΆαŸ†αž„αž‘αŸ…αž‡αžΆαžšαžŠαŸ’αž‹ Maintenance αž›αŸ” αž˜αžΎαž›αž‘αŸ…αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆ - αž–αž½αž€αž‚αŸαž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž‡αžΆαžŸαŸ†αžŽαžΎαž˜αž½αž™αž…αŸ†αž“αž½αž“αžαžΆαž˜αžšαž™αŸˆ API αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ”

αžαŸ’αž“αžΆαž€αŸ‹ Mcs

αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž”αŸ†αžŽαŸ‚αž€αž“αŸƒαž€αžΌαžŠαžŠαŸ‚αž›αž˜αžΆαž“αžαŸ’αž“αžΆαž€αŸ‹αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž… Mcs:

class Mcs:
    def __init__(self, id1, id2, password):
        self.id1 = id1
        self.id2 = id2
        self.password = password
        self.mcs_host = 'https://infra.mail.ru:8774/v2.1'

    def vm_turn_on(self, hostname):
        self.token = self.get_mcs_token()
        host = self.hostname_to_vmname(hostname)
        vm_id = self.get_vm_id(host)
        mcs_url1 = self.mcs_host + '/servers/' + self.vm_id + '/action'
        headers = {
            'X-Auth-Token': '{0}'.format(self.token),
            'Content-Type': 'application/json'
        }
        data = {'os-start' : 'null'}
        mcs = requests.post(mcs_url1, data=json.dumps(data), headers=headers)
        return mcs.status_code

αž“αŸ…αž…αŸ’αžšαž€αž…αžΌαž›αžαŸ’αž“αžΆαž€αŸ‹αžšαŸ€αž“ Mcs αž™αžΎαž„αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž‚αž˜αŸ’αžšαŸ„αž„αž“αŸ…αžαžΆαž„αž€αŸ’αž“αž»αž„αž–αž–αž€ αž“αž·αž„αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ αž€αŸαžŠαžΌαž…αž‡αžΆαž–αžΆαž€αŸ’αž™αžŸαž˜αŸ’αž„αžΆαžαŸ‹αžšαž”αžŸαŸ‹αž‚αžΆαžαŸ‹αŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αž»αžαž„αžΆαžš vm_turn_on αž™αžΎαž„β€‹αž…αž„αŸ‹β€‹αž”αžΎαž€β€‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“β€‹αž˜αž½αž™β€‹αŸ” αžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαž“αŸ…αž‘αžΈαž“αŸαŸ‡αž‚αžΊαžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰αž”αž“αŸ’αžαž·αž…αŸ” αž“αŸ…αžŠαžΎαž˜αž€αžΌαžŠ αž˜αž»αžαž„αžΆαžšαž”αžΈαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαž αŸ…αžαžΆ: 1) αž™αžΎαž„αžαŸ’αžšαžΌαžœαž‘αž‘αž½αž›αž”αžΆαž“αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹ 2) αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αŸ†αž”αŸ’αž›αŸ‚αž„ hostname αž‘αŸ…αž‡αžΆαžˆαŸ’αž˜αŸ„αŸ‡αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž€αŸ’αž“αž»αž„ MCS 3) αž‘αž‘αž½αž›αž”αžΆαž“ id αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αŸαŸ‡αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž™αžΎαž„αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž’αŸ’αžœαžΎαž€αžΆαžšαžŸαŸ’αž“αžΎαžŸαž»αŸ†αž”αŸ’αžšαž€αžΆαžŸ αž αžΎαž™αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αŸαŸ‡αŸ”

αž“αŸαŸ‡αž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž˜αž»αžαž„αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž‘αž‘αž½αž›αž”αžΆαž“αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αŸ–

def get_mcs_token(self):
        url = 'https://infra.mail.ru:35357/v3/auth/tokens?nocatalog'
        headers = {'Content-Type': 'application/json'}
        data = {
            'auth': {
                'identity': {
                    'methods': ['password'],
                    'password': {
                        'user': {
                            'id': self.id1,
                            'password': self.password
                        }
                    }
                },
                'scope': {
                    'project': {
                        'id': self.id2
                    }
                }
            }
        }
        params = (('nocatalog', ''),)
        req = requests.post(url, data=json.dumps(data), headers=headers, params=params)
        self.token = req.headers['X-Subject-Token']
        return self.token

αžαŸ’αž“αžΆαž€αŸ‹β€‹αž’αŸ’αžœαžΎβ€‹αž˜αžΆαžαŸ’αžšαžŠαŸ’αž‹αžΆαž“β€‹αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·

αžαŸ’αž“αžΆαž€αŸ‹αž“αŸαŸ‡αž˜αžΆαž“αž˜αž»αžαž„αžΆαžšαžŠαŸ‚αž›αž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαžαŸ’αž›αž½αž“αž―αž„αŸ”

αž“αŸαŸ‡αž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž€αžΌαžŠαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαŸ’αž“αžΆαž€αŸ‹αž“αŸαŸ‡αž˜αžΎαž›αž‘αŸ…αŸ–

class Autoscaler:
    def __init__(self, ambari, mcs, scaling_hosts, yarn_ram_per_node, yarn_cpu_per_node):
        self.scaling_hosts = scaling_hosts
        self.ambari = ambari
        self.mcs = mcs
        self.q_ram = deque()
        self.q_cpu = deque()
        self.num = 0
        self.yarn_ram_per_node = yarn_ram_per_node
        self.yarn_cpu_per_node = yarn_cpu_per_node

    def scale_down(self, hostname):
        flag1 = flag2 = flag3 = flag4 = flag5 = False
        if hostname in self.scaling_hosts:
            while True:
                time.sleep(5)
                status1 = self.ambari.decommission_nodemanager(hostname)
                if status1 == 'Request accepted' or status1 == 500:
                    flag1 = True
                    logging.info('Decomission request accepted: {0}'.format(flag1))
                    break
            while True:
                time.sleep(5)
                status3 = self.ambari.check_service(hostname, 'NODEMANAGER')
                if status3 == 'INSTALLED':
                    flag3 = True
                    logging.info('Nodemaneger decommissioned: {0}'.format(flag3))
                    break
            while True:
                time.sleep(5)
                status2 = self.ambari.maintenance_on(hostname)
                if status2 == 'Request accepted' or status2 == 500:
                    flag2 = True
                    logging.info('Maintenance request accepted: {0}'.format(flag2))
                    break
            while True:
                time.sleep(5)
                status4 = self.ambari.check_maintenance(hostname, 'NODEMANAGER')
                if status4 == 'ON' or status4 == 'IMPLIED_FROM_HOST':
                    flag4 = True
                    self.ambari.stop_all_services(hostname)
                    logging.info('Maintenance is on: {0}'.format(flag4))
                    logging.info('Stopping services')
                    break
            time.sleep(90)
            status5 = self.mcs.vm_turn_off(hostname)
            while True:
                time.sleep(5)
                status5 = self.mcs.get_vm_info(hostname)['server']['status']
                if status5 == 'SHUTOFF':
                    flag5 = True
                    logging.info('VM is turned off: {0}'.format(flag5))
                    break
            if flag1 and flag2 and flag3 and flag4 and flag5:
                message = 'Success'
                logging.info('Scale-down finished')
                logging.info('Cooldown period has started. Wait for several minutes')
        return message

αž™αžΎαž„αž‘αž‘αž½αž›αž™αž€αžαŸ’αž“αžΆαž€αŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž…αžΌαž›αŸ” Ambari ΠΈ Mcsαž”αž‰αŸ’αž‡αžΈαžαŸ’αž“αžΆαŸ†αž„αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αž‰αŸ’αž‰αžΆαžαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αŸ’αžœαžΎαž˜αžΆαžαŸ’αžšαžŠαŸ’αž‹αžΆαž“ αž€αŸαžŠαžΌαž…αž‡αžΆαž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžαŸ’αž“αžΆαŸ†αž„αŸ– αž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ† αž“αž·αž„αžŸαŸŠαžΈαž—αžΈαž™αžΌαžŠαŸ‚αž›αž”αžΆαž“αž”αŸ‚αž„αž…αŸ‚αž€αž‘αŸ…αžαŸ’αž“αžΆαŸ†αž„αž€αŸ’αž“αž»αž„ YARN αŸ” αžœαžΆαž€αŸαž˜αžΆαž“αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαžαžΆαž„αž€αŸ’αž“αž»αž„ 2 q_ram, q_cpu αžŠαŸ‚αž›αž‡αžΆαž‡αž½αžšαŸ” αžŠαŸ„αž™αž”αŸ’αžšαžΎαž–αž½αž€αžœαžΆαž™αžΎαž„αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αžαž˜αŸ’αž›αŸƒαž“αŸƒαž”αž“αŸ’αž‘αž»αž€αž…αž„αŸ’αž€αŸ„αž˜αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž™αžΎαž„αžƒαžΎαž‰αžαžΆαž€αŸ’αž“αž»αž„αžšαž™αŸˆαž–αŸαž› 5 αž“αžΆαž‘αžΈαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸαŸ‡αž˜αžΆαž“αž€αžΆαžšαž€αžΎαž“αž‘αžΎαž„αž‡αžΆαž”αž“αŸ’αžαž”αž“αŸ’αž‘αžΆαž”αŸ‹ αž“αŸ„αŸ‡αž™αžΎαž„αžŸαž˜αŸ’αžšαŸαž…αžαžΆαž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αž“αŸ’αžαŸ‚αž˜αžαŸ’αž“αžΆαŸ†αž„ +1 αž‘αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜αŸ” αžŠαžΌαž…αž‚αŸ’αž“αžΆβ€‹αž“αŸαŸ‡β€‹αžŠαŸ‚αžšβ€‹αž…αŸ†αž–αŸ„αŸ‡β€‹αžŸαŸ’αžαžΆαž“αž—αžΆαž–β€‹αž˜αž·αž“β€‹αž”αžΆαž“β€‹αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹β€‹αž…αž„αŸ’αž€αŸ„αž˜αŸ”

αž€αžΌαžŠαžαžΆαž„αž›αžΎαž‚αžΊαž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸαž“αŸƒαž˜αž»αžαž„αžΆαžšαžŠαŸ‚αž›αžŠαž€αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž…αŸαž‰αž–αžΈαž…αž„αŸ’αž€αŸ„αž˜ αž αžΎαž™αž”αž‰αŸ’αžˆαž”αŸ‹αžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž–αž–αž€αŸ” αž‘αžΈαž˜αž½αž™αž‚αžΊαž€αžΆαžšαž”αžŽαŸ’αžαŸαž‰αž…αŸαž‰ YARN Nodemanagerαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžšαž”αŸ€αž”αž”αžΎαž€ Maintenanceαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž™αžΎαž„αž”αž‰αŸ’αžˆαž”αŸ‹αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“ αž αžΎαž™αž”αž·αž‘αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αžαž“αŸ…αž€αŸ’αž“αž»αž„αž–αž–αž€αŸ”

2. αžŸαŸ’αž‚αŸ’αžšαžΈαž” observer.py

αž€αžΌαžŠαž‚αŸ†αžšαžΌαž–αžΈαž‘αžΈαž“αŸ„αŸ‡αŸ–

if scaler.assert_up(config.scale_up_thresholds) == True:
        hostname = cloud.get_vm_to_up(config.scaling_hosts)
        if hostname != None:
            status1 = scaler.scale_up(hostname)
            if status1 == 'Success':
                text = {"text": "{0} has been successfully scaled-up".format(hostname)}
                post = {"text": "{0}".format(text)}
                json_data = json.dumps(post)
                req = requests.post(webhook, data=json_data.encode('ascii'), headers={'Content-Type': 'application/json'})
                time.sleep(config.cooldown_period*60)

αž“αŸ…αž€αŸ’αž“αž»αž„αžœαžΆ αž™αžΎαž„αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžαžΎαž›αž€αŸ’αžαžαžŽαŸ’αžŒαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž‘αžΎαž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž”αž„αŸ’αž€αžΎαž“αžŸαž˜αžαŸ’αžαž—αžΆαž–αžšαž”αžŸαŸ‹αž…αž„αŸ’αž€αŸ„αž˜ αž“αž·αž„αžαžΆαžαžΎαž˜αžΆαž“αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžŽαžΆαž˜αž½αž™αž“αŸ…αž€αŸ’αž“αž»αž„αž‘αž»αž“αž”αŸ†αžšαž»αž„ αž‘αž‘αž½αž›αž”αžΆαž“αžˆαŸ’αž˜αŸ„αŸ‡αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αž½αž™αž€αŸ’αž“αž»αž„αž…αŸ†αž“αŸ„αž˜αž–αž½αž€αž‚αŸ αž”αž“αŸ’αžαŸ‚αž˜αžœαžΆαž‘αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜ αž“αž·αž„αž•αŸ’αžŸαž–αŸ’αžœαž•αŸ’αžŸαžΆαž™αžŸαžΆαžšαž’αŸ†αž–αžΈαžœαžΆαž“αŸ…αž›αžΎ Slack αžšαž”αžŸαŸ‹αž€αŸ’αžšαž»αž˜αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž“αŸ„αŸ‡αžœαžΆαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ cooldown_periodαž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž™αžΎαž„αž˜αž·αž“αž”αž“αŸ’αžαŸ‚αž˜ αž¬αžŠαž€αž’αŸ’αžœαžΈαž…αŸαž‰αž–αžΈαž…αž„αŸ’αž€αŸ„αž˜ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αžαžΆαž˜αžŠαžΆαž“αž”αž“αŸ’αž‘αž»αž€αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαžœαžΆαž˜αžΆαž“αžŸαŸ’αžαŸαžšαž—αžΆαž– αž“αž·αž„αžŸαŸ’αžαž·αžαž“αŸ…αž€αŸ’αž“αž»αž„αž…αŸ’αžšαž€αžšαž”αŸ€αž„αž“αŸƒαžαž˜αŸ’αž›αŸƒαž•αŸ’αž‘αž»αž€αžŠαŸαž›αŸ’αž’αž”αŸ’αžšαžŸαžΎαžš αž“αŸ„αŸ‡αž™αžΎαž„αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž”αž“αŸ’αžαž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαžαŸ’αž“αžΆαŸ†αž„αž˜αž½αž™αž˜αž·αž“αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹ αž“αŸ„αŸ‡αž™αžΎαž„αž”αž“αŸ’αžαŸ‚αž˜αž˜αž½αž™αž‘αŸ€αžαŸ”

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžšαžŽαžΈαž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž™αžΎαž„αž˜αžΆαž“αž˜αŸαžšαŸ€αž“αž“αŸ…αžαžΆαž„αž˜αž»αž αž™αžΎαž„αžŠαžΉαž„αž…αŸ’αž”αžΆαžŸαŸ‹αžαžΆαžαŸ’αž“αžΆαŸ†αž„αž˜αž½αž™αž“αžΉαž„αž˜αž·αž“αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž αžΎαž™αž™αžΎαž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžαŸ’αž“αžΆαŸ†αž„αž₯αžαž‚αž·αžαžαŸ’αž›αŸƒαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž—αŸ’αž›αžΆαž˜αŸ— αž αžΎαž™αžšαž€αŸ’αžŸαžΆαžœαžΆαž±αŸ’αž™αžŸαž€αž˜αŸ’αž˜αžšαž αžΌαžαžŠαž›αŸ‹αž…αž»αž„αž”αž‰αŸ’αž…αž”αŸ‹αž“αŸƒαž˜αŸαžšαŸ€αž“αŸ” αžœαžΆαž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αž”αŸ’αžšαžΎαž”αž‰αŸ’αž‡αžΈαž–αŸαž›αžœαŸαž›αžΆαž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“

Autoscaler αž‚αžΊαž‡αžΆαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŠαŸαž›αŸ’αž’ αž“αž·αž„αž„αžΆαž™αžŸαŸ’αžšαž½αž›αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžšαžŽαžΈαž‘αžΆαŸ†αž„αž“αŸ„αŸ‡ αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αž‡αž½αž”αž”αŸ’αžšαž‘αŸ‡αž€αžΆαžšαž•αŸ’αž‘αž»αž€αž…αž„αŸ’αž€αŸ„αž˜αž˜αž·αž“αžŸαŸ’αž˜αžΎαž‚αŸ’αž“αžΆαŸ” αž’αŸ’αž“αž€αžŸαž˜αŸ’αžšαŸαž…αž”αžΆαž“αž“αžΌαžœαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ‚αž›αž…αž„αŸ‹αž”αžΆαž“αž€αŸ’αž“αž»αž„αž–αŸαž›αžŠαŸ†αžŽαžΆαž›αž‚αŸ’αž“αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αž‘αž»αž€αžαŸ’αž–αžŸαŸ‹αž”αŸ†αž•αž»αž αž αžΎαž™αž€αŸ’αž“αž»αž„αž–αŸαž›αžαŸ‚αž˜αž½αž™αž˜αž·αž“αžαŸ’αžšαžΌαžœαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž…αž„αŸ’αž€αŸ„αž˜αž“αŸαŸ‡αž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž•αŸ’αž‘αž»αž€αž€αŸ’αžšαŸ„αž˜ αžŠαŸ„αž™αžŸαž“αŸ’αžŸαŸ†αž”αŸ’αžšαžΆαž€αŸ‹αŸ” αž‡αžΆαž€αžΆαžšαž”αŸ’αžšαžŸαžΎαžšαžŽαžΆαžŸαŸ‹, αž”αžΌαž€αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸαŸ‡αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž€αžΆαžšαž…αžΌαž›αžšαž½αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ” autoscaler αžαŸ’αž›αž½αž“αžœαžΆαž‚αŸ’αž˜αžΆαž“αž’αŸ’αžœαžΈαž€αŸ’αžšαŸ…αžαŸ‚αž–αžΈαžŸαŸ†αžŽαž»αŸ†αž“αŸƒαžŸαŸ†αžŽαžΎαž‘αŸ…αž€αžΆαž“αŸ‹ API αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž…αž„αŸ’αž€αŸ„αž˜ αž“αž·αž„ API αž’αŸ’αž“αž€αž•αŸ’αžαž›αŸ‹αžŸαŸαžœαžΆαž–αž–αž€ αžŠαŸ‚αž›αžŸαžšαžŸαŸαžšαžŠαŸ„αž™αž™αŸ„αž„αž‘αŸ…αžαžΆαž˜αžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž˜αž½αž™αŸ” αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž’αŸ’αž“αž€αž–αž·αžαž‡αžΆαžαŸ’αžšαžΌαžœαž…αž„αž…αžΆαŸ†αž‚αžΊαž€αžΆαžšαž”αŸ‚αž„αž…αŸ‚αž€αžαŸ’αž“αžΆαŸ†αž„αž‡αžΆ 3 αž”αŸ’αžšαž—αŸαž‘ αžŠαžΌαž…αžŠαŸ‚αž›αž™αžΎαž„αž”αžΆαž“αžŸαžšαžŸαŸαžšαž–αžΈαž˜αž»αž“αŸ” αž αžΎαž™αž’αŸ’αž“αž€αž“αžΉαž„αžŸαž”αŸ’αž”αžΆαž™αž…αž·αžαŸ’αžαŸ”

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹