เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจเซ‹เชจเชพ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚ เชœเชตเชพเชฌเซ€ + เช“เชŸเซ‹ เช—เชฟเชŸ เชชเซเชฒ

เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจเซ‹เชจเชพ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚ เชœเชตเชพเชฌเซ€ + เช“เชŸเซ‹ เช—เชฟเชŸ เชชเซเชฒ

เชถเซเชญ เชฆเชฟเชตเชธ

เช…เชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เช˜เชฃเชพ เช•เซเชฒเชพเช‰เชก เช•เซเชฒเชธเซเชŸเชฐ เช›เซ‡ เชœเซ‡เชฎเชพเช‚ เชฆเชฐเซ‡เช•เชฎเชพเช‚ เชฎเซ‹เชŸเซ€ เชธเช‚เช–เซเชฏเชพเชฎเชพเช‚ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจเซ‹ เช›เซ‡. เช…เชฎเซ‡ เช† เชธเชฎเช—เซเชฐ เชตเซเชฏเชตเชธเชพเชฏเชจเซ‡ เชนเซ‡เชŸเซเชเชจเชฐ เช–เชพเชคเซ‡ เชนเซ‹เชธเซเชŸ เช•เชฐเซ€เช เช›เซ€เช. เชฆเชฐเซ‡เช• เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚ เช…เชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชเช• เชฎเชพเชธเซเชŸเชฐ เชฎเชถเซ€เชจ เช›เซ‡, เชคเซ‡เชฎเชพเช‚เชฅเซ€ เชธเซเชจเซ‡เชชเชถเซ‹เชŸ เชฒเซ‡เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เช…เชจเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชจเซ€ เช…เช‚เชฆเชฐเชจเชพ เชคเชฎเชพเชฎ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจเซ‹เชฎเชพเช‚ เช†เชชเชฎเซ‡เชณเซ‡ เชตเชฟเชคเชฐเชฟเชค เชฅเชพเชฏ เช›เซ‡.

เช† เชธเซเช•เซ€เชฎ เช…เชฎเชจเซ‡ เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เช—เชฟเชŸเชฒเซ‡เชฌ-เชฐเชจเชฐเซเชธเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเชคเซ€ เชจเชฅเซ€, เช•เชพเชฐเชฃ เช•เซ‡ เชœเซเชฏเชพเชฐเซ‡ เช˜เชฃเชพ เชธเชฎเชพเชจ เชจเซ‹เช‚เชงเชพเชฏเซ‡เชฒเชพ เชฆเซ‹เชกเชตเซ€เชฐเซ‹ เชฆเซ‡เช–เชพเชฏ เช›เซ‡ เชคเซเชฏเชพเชฐเซ‡ เช˜เชฃเซ€ เชธเชฎเชธเซเชฏเชพเช“ เชŠเชญเซ€ เชฅเชพเชฏ เช›เซ‡, เชœเซ‡เชฃเซ‡ เช…เชฎเชจเซ‡ เช† เชฒเซ‡เช–/เชฎเชพเชฐเซเช—เชฆเชฐเซเชถเชฟเช•เชพ เชฒเช–เชตเชพ เชฎเชพเชŸเซ‡เชจเซ‹ เช‰เช•เซ‡เชฒ เชถเซ‹เชงเชตเชพ เชฎเชพเชŸเซ‡ เชชเซเชฐเซ‹เชคเซเชธเชพเชนเชฟเชค เช•เชฐเซเชฏเชพ เชนเชคเชพ.

เช† เช•เชฆเชพเชš เชถเซเชฐเซ‡เชทเซเช  เชชเซเชฐเชฅเชพ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เช† เช‰เช•เซ‡เชฒ เชถเช•เซเชฏ เชคเซ‡เชŸเชฒเซ‹ เช…เชจเซเช•เซ‚เชณ เช…เชจเซ‡ เชธเชฐเชณ เชฒเชพเช—เชคเซ‹ เชนเชคเซ‹.

เชŸเซเชฏเซเชŸเซ‹เชฐเซ€เชฏเชฒ เชฎเชพเชŸเซ‡, เช•เซƒเชชเชพ เช•เชฐเซ€เชจเซ‡ เชฌเชฟเชฒเชพเชกเซ€ เชœเซเช“.

เชฎเชพเชธเซเชŸเชฐ เชฎเชถเซ€เชจ เชชเชฐ เชœเชฐเซ‚เชฐเซ€ เชชเซ‡เช•เซ‡เชœเซ‹:

  • เช…เชœเช—เชฐ
  • เช—เชฟเชŸ
  • ssh เช•เซ€ เชธเชพเชฅเซ‡ เชซเชพเช‡เชฒ

เชคเชฎเชพเชฎ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจเซ‹ เชชเชฐ เช“เชŸเซ‹เชฎเซ‡เชŸเชฟเช• เช—เชŸ เชชเซเชฒ เชฒเชพเช—เซ เช•เชฐเชตเชพเชจเซ‹ เชธเชพเชฎเชพเชจเซเชฏ เชธเชฟเชฆเซเชงเชพเช‚เชค เช เช›เซ‡ เช•เซ‡ เชคเชฎเชพเชฐเซ‡ เชเช• เชฎเชถเซ€เชจเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เชœเซ‡เชจเชพ เชชเชฐ Ansible เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡. เช† เชฎเชถเซ€เชจเชฎเชพเช‚เชฅเซ€, เชœเชตเชพเชฌเซ€เชฌเชฒ เช—เชฟเชŸ เชชเซเชฒ เช•เชฎเชพเชจเซเชกเซเชธ เชฎเซ‹เช•เชฒเชถเซ‡ เช…เชจเซ‡ เช…เชชเชกเซ‡เชŸ เช•เชฐเซ‡เชฒเซ€ เชธเซ‡เชตเชพเชจเซ‡ เชชเซเชจเชƒเชถเชฐเซ‚ เช•เชฐเชถเซ‡. เช† เชนเซ‡เชคเซเช“ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เช•เซเชฒเชธเซเชŸเชฐเซ‹เชจเซ€ เชฌเชนเชพเชฐ เชเช• เช…เชฒเช— เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจ เชฌเชจเชพเชตเซเชฏเซเช‚ เช…เชจเซ‡ เชคเซ‡เชจเชพ เชชเชฐ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซเชฏเซเช‚:

  • เช…เชœเช—เชฐ
  • เชœเชตเชพเชฌเชฆเชพเชฐ
  • gitlab-เชฐเชจเชฐ

เชธเช‚เชธเซเชฅเชพเช•เซ€เชฏ เชฎเซเชฆเซเชฆเชพเช“เชฎเชพเช‚เชฅเซ€ - เชคเชฎเชพเชฐเซ‡ gitlab-runner เชจเซ€ เชจเซ‹เช‚เชงเชฃเซ€ เช•เชฐเชตเชพเชจเซ€, ssh-keygen เชฌเชจเชพเชตเชตเชพเชจเซ€, เช† เชฎเชถเซ€เชจเชจเซ€ เชธเชพเชฐเซเชตเชœเชจเชฟเช• ssh เช•เซ€ เช…เชชเชฒเซ‹เชก เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ .ssh/authorized_keys เชฎเชพเชธเซเชŸเชฐ เชฎเชถเซ€เชจ เชชเชฐ, เชฎเชพเชธเซเชŸเชฐ เชฎเชถเซ€เชจ เชชเชฐ เชœเชตเชพเชฌ เช†เชชเชตเชพ เชฎเชพเชŸเซ‡ เชชเซ‹เชฐเซเชŸ 22 เช–เซ‹เชฒเซ‹.

เชนเชตเซ‡ เช†เชชเชฃเซ‡ เชœเชตเชพเชฌเซ€เชฌเชฒ เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชฟเชค เช•เชฐเซ€เช

เช•เชพเชฐเชฃ เช•เซ‡ เช…เชฎเชพเชฐเซ‹ เชงเซเชฏเซ‡เชฏ เชถเช•เซเชฏ เช›เซ‡ เชคเซ‡ เชฌเชงเซเช‚ เชธเซเชตเชšเชพเชฒเชฟเชค เช•เชฐเชตเชพเชจเซ‹ เช›เซ‡. เชซเชพเชˆเชฒเชฎเชพเช‚ /etc/ansible/ansible.cfg เช…เชฎเซ‡ เชฒเชพเช‡เชจเชจเซ‡ เช…เชจเช•เซ‹เชฎเซ‡เชจเซเชŸ เช•เชฐเซ€เชถเซเช‚ host_key_checking = Falseเชœเซ‡เชฅเซ€ เชœเชตเชพเชฌเชฆเชพเชฐ เชจเชตเชพ เชฎเชถเซ€เชจเซ‹เชจเซ€ เชชเซเชทเซเชŸเชฟ เชฎเชพเชŸเซ‡ เชชเซ‚เช›เซ‡ เชจเชนเซ€เช‚.

เช†เช—เชณ, เชคเชฎเชพเชฐเซ‡ เชœเชตเชพเชฌ เช†เชชเชตเชพ เชฎเชพเชŸเซ‡ เช†เชชเชฎเซ‡เชณเซ‡ เช‡เชจเซเชตเซ‡เชจเซเชŸเชฐเซ€ เชซเชพเช‡เชฒ เชœเชจเชฐเซ‡เชŸ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡, เชœเซเชฏเชพเช‚เชฅเซ€ เชคเซ‡ เชฎเชถเซ€เชจเซ‹เชจเซ€ เช†เช‡เชชเซ€ เชฒเซ‡เชถเซ‡ เชœเซ‡เชจเชพ เชชเชฐ เชคเชฎเชพเชฐเซ‡ เช—เชฟเชŸ เชชเซเชฒ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡.

เช…เชฎเซ‡ Hetzner's API เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช† เชซเชพเช‡เชฒ เชœเชจเชฐเซ‡เชŸ เช•เชฐเซ€เช เช›เซ€เช, เชคเชฎเซ‡ เชคเชฎเชพเชฐเชพ AWS, Asure, เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚เชฅเซ€ เชนเซ‹เชธเซเชŸเชจเซ€ เชฏเชพเชฆเซ€ เชฒเชˆ เชถเช•เซ‹ เช›เซ‹ (เชคเชฎเชพเชฐเซ€ เชšเชพเชฒเซ€ เชฐเชนเซ‡เชฒ เชฎเชถเซ€เชจเซ‹ เชชเซเชฐเชฆเชฐเซเชถเชฟเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชคเชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เช•เซเชฏเชพเช‚เช• API เช›เซ‡, เช–เชฐเซเช‚ เชจเซ‡?).

เช‡เชจเซเชตเซ‡เชจเซเชŸเชฐเซ€ เชซเชพเช‡เชฒเชจเซเช‚ เชฎเชพเชณเช–เซเช‚ เชœเชตเชพเชฌเซ€ เชฎเชพเชŸเซ‡ เช–เซ‚เชฌ เชœ เชฎเชนเชคเซเชตเชชเซ‚เชฐเซเชฃ เช›เซ‡; เชคเซ‡ เช†เชจเชพ เชœเซ‡เชตเซเช‚ เชฆเซ‡เช–เชพเชตเซเช‚ เชœเซ‹เชˆเช:

[ะณั€ัƒะฟะฟะฐ]
ip-ะฐะดั€ะตั
ip-ะฐะดั€ะตั

[ะณั€ัƒะฟะฟะฐ2]
ip-ะฐะดั€ะตั
ip-ะฐะดั€ะตั

เช†เชตเซ€ เชซเชพเช‡เชฒ เชœเชจเชฐเซ‡เชŸ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เชเช• เชธเชฐเชณ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชฌเชจเชพเชตเซ€เชถเซเช‚ (เชšเชพเชฒเซ‹ เชคเซ‡เชจเซ‡ เช•เซ‰เชฒ เช•เชฐเซ€เช vm_list):

#!/bin/bash
echo [group] > /etc/ansible/cloud_ip &&
"ะฒะฐัˆ CLI ะทะฐะฟั€ะพั ะฝะฐ ะฟะพะปัƒั‡ะตะฝะธะต IP ะทะฐะฟัƒั‰ะตะฝะฝั‹ั… ะผะฐัˆะธะฝ ะฒ ะบะปะฐัั‚ะตั€ะต"  >> /etc/ansible/cloud_ip
echo " " >> /etc/ansible/cloud_ip
echo [group2] > /etc/ansible/cloud_ip &&
"ะฒะฐัˆ CLI ะทะฐะฟั€ะพั ะฝะฐ ะฟะพะปัƒั‡ะตะฝะธะต IP ะทะฐะฟัƒั‰ะตะฝะฝั‹ั… ะผะฐัˆะธะฝ ะฒ ะดั€ัƒะณะพะผ ะบะปะฐัั‚ะตั€ะต"  >> /etc/ansible/cloud_ip

เชœเชตเชพเชฌ เช†เชชเชตเชพเชจเซเช‚ เช•เชพเชฎ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ IP เชเชกเซเชฐเซ‡เชธ เชชเซเชฐเชพเชชเซเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชฎเซˆเชคเซเชฐเซ€เชชเซ‚เชฐเซเชฃ เช›เซ‡ เช•เซ‡ เชจเชนเซ€เช‚ เชคเซ‡ เชคเชชเชพเชธเชตเชพเชจเซ‹ เช† เชธเชฎเชฏ เช›เซ‡:

/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'hostname' group

เช†เช‰เชŸเชชเซเชŸเชฎเชพเช‚ เชฎเชถเซ€เชจเซ‹เชจเชพ เชนเซ‹เชธเซเชŸเชจเชพเชฎ เชนเซ‹เชตเชพ เชœเซ‹เชˆเช เช•เซ‡ เชœเซ‡เชจเชพ เชชเชฐ เช†เชฆเซ‡เชถ เชšเชฒเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹.
เชตเชพเช•เซเชฏเชฐเชšเชจเชพ เชตเชฟเชถเซ‡ เชฅเซ‹เชกเชพเช• เชถเชฌเซเชฆเซ‹:

  • /etc/ansible/./vm_list - เชฎเชถเซ€เชจเซ‹เชจเซ€ เชฏเชพเชฆเซ€ เชฌเชจเชพเชตเซ‹
  • -i - เช‡เชจเซเชตเซ‡เชจเซเชŸเชฐเซ€ เชซเชพเช‡เชฒเชจเซ‹ เชธเช‚เชชเซ‚เชฐเซเชฃ เชฎเชพเชฐเซเช—
  • -m - เชถเซ‡เชฒ เชฎเซ‹เชกเซเชฏเซเชฒเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชœเชตเชพเชฌเชฆเชพเชฐเชจเซ‡ เช•เชนเซ‹
  • - เช เชฆเชฒเซ€เชฒ เช›เซ‡. เช•เซ‹เชˆเชชเชฃ เช†เชฆเซ‡เชถ เช…เชนเซ€เช‚ เชฆเชพเช–เชฒ เช•เชฐเซ€ เชถเช•เชพเชฏ เช›เซ‡
  • เชœเซ‚เชฅ - เชคเชฎเชพเชฐเชพ เช•เซเชฒเชธเซเชŸเชฐเชจเซเช‚ เชจเชพเชฎ. เชœเซ‹ เชคเชฎเชพเชฐเซ‡ เชฌเชงเชพ เช•เซเชฒเชธเซเชŸเชฐเซ‹ เชชเชฐ เช† เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชนเซ‹เชฏ, เชคเซ‹ เชฌเชงเชพเชฎเชพเช‚ เชœเซ‚เชฅ เชฌเชฆเชฒเซ‹

เชšเชพเชฒเซ‹ เช†เช—เชณ เชœเชˆเช - เชšเชพเชฒเซ‹ เช†เชชเชฃเชพ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจเซ‹ เชชเชฐ เช—เชฟเชŸ เชชเซเชฒ เช•เชฐเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเซ€เช:

/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'cd /path/to/project && git pull' group 

เชœเซ‹ เช†เช‰เชŸเชชเซเชŸเชฎเชพเช‚ เช†เชชเชฃเซ‡ เชชเชนเซ‡เชฒเชพเชฅเซ€ เชœ เช…เชฆเซเชฏเชคเชจ เช…เชฅเชตเชพ เชฐเซ€เชชเซ‹เชเซ€เชŸเชฐเซ€เชฎเชพเช‚เชฅเซ€ เช…เชจเชฒเซ‹เชกเชฟเช‚เช— เชœเซ‹เชฏเซ‡ เช›เซ‡, เชคเซ‹ เชฌเชงเซเช‚ เช•เชพเชฎ เช•เชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡.

เชนเชตเซ‡ เช† เชคเซ‡ เช›เซ‡ เชœเซ‡ เชคเซ‡ เชฌเชงเชพ เชฎเชพเชŸเซ‡ เชนเชคเซเช‚

เชšเชพเชฒเซ‹ เช—เชฟเชŸเชฒเซ‡เชฌเชฎเชพเช‚ เชฎเชพเชธเซเชŸเชฐ เชฌเซเชฐเชพเชจเซเชšเชฎเชพเช‚ เช•เชฎเชฟเชŸ เช•เชฐเชคเซ€ เชตเช–เชคเซ‡ เช…เชฎเชพเชฐเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเซ‡ เช†เชชเชฎเซ‡เชณเซ‡ เชšเชพเชฒเชคเชพ เชถเซ€เช–เชตเซ€เช

เชชเซเชฐเชฅเชฎ, เชšเชพเชฒเซ‹ เช†เชชเชฃเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเซ‡ เชตเชงเซ เชธเซเช‚เชฆเชฐ เชฌเชจเชพเชตเซ€เช เช…เชจเซ‡ เชคเซ‡เชจเซ‡ เชเช•เซเชเชฟเช•เซเชฏเซเชŸเซ‡เชฌเชฒ เชซเชพเช‡เชฒเชฎเชพเช‚ เชฎเซ‚เช•เซ€เช (เชšเชพเชฒเซ‹ เชคเซ‡เชจเซ‡ exec_pull เช•เชนเซ€เช) -

#!/bin/bash

/etc/ansible/./get_vms && ansible -i /etc/ansible/cloud_ip -m shell -a "$@"

เชšเชพเชฒเซ‹ เช†เชชเชฃเชพ เช—เชฟเชŸเชฒเซ‡เชฌ เชชเชฐ เชœเชˆเช เช…เชจเซ‡ เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸเชฎเชพเช‚ เชเช• เชซเชพเช‡เชฒ เชฌเชจเชพเชตเซ€เช .gitlab-ci.yml
เช…เชฎเซ‡ เชจเซ€เชšเซ‡เชจเชพเชจเซ‡ เช…เช‚เชฆเชฐ เชฎเซ‚เช•เซ€เช เช›เซ€เช:

variables:
  GIT_STRATEGY: none
  VM_GROUP: group

stages:
  - pull
  - restart

run_exec_pull:
  stage: pull
  script:
  
   - /etc/ansible/exec_pull 'cd /path/to/project/'$CI_PROJECT_NAME' && git pull' $VM_GROUP
  
  only:
  - master

run_service_restart:
  stage: restart
  script:
 
   - /etc/ansible/exec_pull 'your_app_stop && your_app_start' $VM_GROUP
   
  only:
  - master 

เชฌเชงเซเช‚ เชคเซˆเชฏเชพเชฐ เช›เซ‡. เชนเชตเซ‡ -

  • เชชเซเชฐเชคเชฟเชฌเชฆเซเชงเชคเชพ เชฌเชจเชพเชตเซ‹
  • เชฎเชจเซ‡ เช–เซเชถเซ€ เช›เซ‡ เช•เซ‡ เชฌเชงเซเช‚ เช•เชพเชฎ เช•เชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡

.yml เชจเซ‡ เช…เชจเซเชฏ เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸเซเชธเชฎเชพเช‚ เชธเซเชฅเชพเชจเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชคเซ€ เชตเช–เชคเซ‡, เชคเชฎเชพเชฐเซ‡ เชซเช•เซเชค เชชเซเชจเชƒเชชเซเชฐเชพเชฐเช‚เชญ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชธเซ‡เชตเชพเชจเซเช‚ เชจเชพเชฎ เช…เชจเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชจเซเช‚ เชจเชพเชฎ เชฌเชฆเชฒเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เช•เซ‡ เชœเซ‡เชจเชพ เชชเชฐ เชœเชตเชพเชฌเชฆเชพเชฐ เช†เชฆเซ‡เชถเซ‹ เช…เชฎเชฒเชฎเชพเช‚ เช†เชตเชถเซ‡.

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹