рдбреЙрдХрд░ рдЖрдгрд┐ рд╕рд░реНрд╡, рд╕рд░реНрд╡, рд╕рд░реНрд╡

TL;DR: рдПрдХ рд╡рд┐рд╣рдВрдЧрд╛рд╡рд▓реЛрдХрди рд▓реЗрдЦ - рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд╛рддрд╛рд╡рд░рдгрд╛рдЪреА рддреБрд▓рдирд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдорд╛рд░реНрдЧрджрд░реНрд╢рдХ. рдбреЙрдХрд░ рдЖрдгрд┐ рдЗрддрд░ рддрддреНрд╕рдо рдкреНрд░рдгрд╛рд▓реАрдВрдЪреНрдпрд╛ рд╢рдХреНрдпрддрд╛рдВрдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХреЗрд▓рд╛ рдЬрд╛рдИрд▓.

рдбреЙрдХрд░ рдЖрдгрд┐ рд╕рд░реНрд╡, рд╕рд░реНрд╡, рд╕рд░реНрд╡

рд╣реЗ рд╕рд░реНрд╡ рдХреБрдареВрди рдЖрд▓реЗ рдпрд╛рдЪрд╛ рдереЛрдбрд╛рд╕рд╛ рдЗрддрд┐рд╣рд╛рд╕

рдХрдерд╛

рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╡реЗрдЧрд│реЗ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдкрд╣рд┐рд▓рд╛ рд╕реБрдкреНрд░рд╕рд┐рджреНрдз рдорд╛рд░реНрдЧ рдореНрд╣рдгрдЬреЗ chroot. рддреНрдпрд╛рдЪ рдирд╛рд╡рд╛рдЪрд╛ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рд░реВрдЯ рдбрд┐рд░реЗрдХреНрдЯреНрд░реАрдордзреНрдпреЗ рдмрджрд▓ рдкреНрд░рджрд╛рди рдХрд░рддреЛ - рдЕрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ рдпрд╛рд▓рд╛ рдХреЙрд▓ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдордордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдкреНрд░рджрд╛рди рдХрд░рддреЛ, рдлрдХреНрдд рдпрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХреЗрддреАрд▓ рдлрд╛рдпрд▓реАрдВрдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдкреНрд░рджрд╛рди рдХрд░рддреЛ. рдкрд░рдВрддреБ рдЬрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд▓рд╛ рд╕реБрдкрд░рдпреВрдЬрд░ рдЕрдзрд┐рдХрд╛рд░ рджрд┐рд▓реЗ рдЧреЗрд▓реЗ рддрд░ рддреЗ рд╕рдВрднрд╛рд╡реНрдпрддрдГ chroot рдордзреВрди "рдкрд│реВрди" рдЬрд╛рдК рд╢рдХрддреЗ рдЖрдгрд┐ рдореБрдЦреНрдп рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдордордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдорд┐рд│рд╡реВ рд╢рдХрддреЛ. рддрд╕реЗрдЪ, рд░реВрдЯ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрджрд▓рдгреНрдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рдЗрддрд░ рд╕рдВрд╕рд╛рдзрдиреЗ (RAM, рдкреНрд░реЛрд╕реЗрд╕рд░), рддрд╕реЗрдЪ рдиреЗрдЯрд╡рд░реНрдХрдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдорд░реНрдпрд╛рджрд┐рдд рдирд╛рд╣реАрдд.

рдкреБрдвреАрд▓ рдорд╛рд░реНрдЧ рдореНрд╣рдгрдЬреЗ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХрд░реНрдирд▓рдЪреА рдпрдВрддреНрд░рдгрд╛ рд╡рд╛рдкрд░реВрди рдХрдВрдЯреЗрдирд░рдЪреНрдпрд╛ рдЖрдд рдПрдХ рдкреВрд░реНрдг-рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдгрд╛рд▓реА рд▓реЙрдиреНрдЪ рдХрд░рдгреЗ. рдпрд╛ рдкрджреНрдзрддреАрд▓рд╛ рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдордордзреНрдпреЗ рд╡реЗрдЧрд│реНрдпрд╛ рдкрджреНрдзрддреАрдиреЗ рдореНрд╣рдЯрд▓реЗ рдЬрд╛рддреЗ, рдкрд░рдВрддреБ рд╕рд╛рд░ рдПрдХрдЪ рдЖрд╣реЗ - рдЕрдиреЗрдХ рд╕реНрд╡рддрдВрддреНрд░ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдЪрд╛рд▓рд╡рдгреЗ, рдЬреНрдпрд╛рдкреИрдХреА рдкреНрд░рддреНрдпреЗрдХ рдореБрдЦреНрдп рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдЪрд╛рд▓рд╡рдгрд╛рд▒реНрдпрд╛ рддреНрдпрд╛рдЪ рдХрд░реНрдирд▓рд╡рд░ рдЪрд╛рд▓рддреЗ. рдпрд╛рдордзреНрдпреЗ Linux рд╕рд╛рдареА FreeBSD рдЬреЗрд▓, рд╕реЛрд▓рд╛рд░рд┐рд╕ рдЭреЛрди, OpenVZ рдЖрдгрд┐ LXC рдпрд╛рдВрдЪрд╛ рд╕рдорд╛рд╡реЗрд╢ рдЖрд╣реЗ. рдЕрд▓рдЧрд╛рд╡ рдХреЗрд╡рд│ рдбрд┐рд╕реНрдХ рд╕реНрдкреЗрд╕рд╕рд╛рдареАрдЪ рдирд╡реНрд╣реЗ рддрд░ рдЗрддрд░ рд╕рдВрд╕рд╛рдзрдирд╛рдВрд╕рд╛рдареА рджреЗрдЦреАрд▓ рдкреНрд░рджрд╛рди рдХреЗрд▓рд╛ рдЬрд╛рддреЛ, рд╡рд┐рд╢реЗрд╖рддрдГ, рдкреНрд░рддреНрдпреЗрдХ рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╡реЗрд│, рд░реЕрдо, рдиреЗрдЯрд╡рд░реНрдХ рдмрдБрдбрд╡рд┐рдбреНрдерд╡рд░ рдирд┐рд░реНрдмрдВрдз рдЕрд╕реВ рд╢рдХрддрд╛рдд. рдХреНрд░реЛрдЯрдЪреНрдпрд╛ рддреБрд▓рдиреЗрдд, рдХрдВрдЯреЗрдирд░ рд╕реЛрдбрдгреЗ рдЕрдзрд┐рдХ рдХрдареАрдг рдЖрд╣реЗ, рдХрд╛рд░рдг рдХрдВрдЯреЗрдирд░рдордзреАрд▓ рд╕реБрдкрд░рдпреБрдЬрд░рд▓рд╛ рдлрдХреНрдд рдХрдВрдЯреЗрдирд░рдЪреНрдпрд╛ рдЖрдд рдкреНрд░рд╡реЗрд╢ рдЕрд╕рддреЛ, рддрдерд╛рдкрд┐, рдХрдВрдЯреЗрдирд░рдЪреНрдпрд╛ рдЖрдд рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдЕрджреНрдпрдпрд╛рд╡рдд рдареЗрд╡рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрдгрд┐ рдЬреБрдиреНрдпрд╛ рдХрд░реНрдирд▓рдЪреНрдпрд╛ рд╡рд╛рдкрд░рд╛рдореБрд│реЗ рдЖрд╡реГрддреНрддреНрдпрд╛ (Linux рд╕рд╛рдареА рд╕рдВрдмрдВрдзрд┐рдд, рдереЛрдбреНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рдд FreeBSD), рдХрд░реНрдирд▓ рдЖрдпрд╕реЛрд▓реЗрд╢рди рд╕рд┐рд╕реНрдЯреАрдо рддреЛрдбрдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рдореБрдЦреНрдп рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдордордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдорд┐рд│рдгреНрдпрд╛рдЪреА рд╢рдХреНрдпрддрд╛ рд╢реВрдиреНрдп рдирд╕рд▓реЗрд▓реА рдЖрд╣реЗ.

рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ рдкреВрд░реНрдг рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рд▓рд╛рдБрдЪ рдХрд░рдгреНрдпрд╛рдРрд╡рдЬреА (рдЗрдирд┐рд╢рд┐рдПрд▓рд╛рдпрдЭреЗрд╢рди рд╕рд┐рд╕реНрдЯрдо, рдкреЕрдХреЗрдЬ рдореЕрдиреЗрдЬрд░ рдЗ.) рдЕрдиреБрдкреНрд░рдпреЛрдЧ рддреНрд╡рд░рд┐рдд рд▓реЙрдиреНрдЪ рдХреЗрд▓реЗ рдЬрд╛рдК рд╢рдХрддрд╛рдд, рдореБрдЦреНрдп рдЧреЛрд╖реНрдЯ рдореНрд╣рдгрдЬреЗ рдпрд╛ рд╕рдВрдзреАрд╕рд╣ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкреНрд░рджрд╛рди рдХрд░рдгреЗ (рдЖрд╡рд╢реНрдпрдХ рд▓рд╛рдпрдмреНрд░рд░реАрдЪреА рдЙрдкрд╕реНрдерд┐рддреА рдЖрдгрд┐ рдЗрддрд░ рдлрд╛рдпрд▓реА). рд╣реА рдХрд▓реНрдкрдирд╛ рдХрдВрдЯреЗрдирд░реАрдХреГрдд рдНрдкреНрд▓рд┐рдХреЗрд╢рди рд╡реНрд╣рд░реНрдЪреНрдпреБрдЕрд▓рд╛рдпрдЭреЗрд╢рдирд╕рд╛рдареА рдЖрдзрд╛рд░ рдореНрд╣рдгреВрди рдХрд╛рдо рдХрд░рддреЗ, рдЬреНрдпрд╛рдЪрд╛ рд╕рд░реНрд╡рд╛рдд рдкреНрд░рдореБрдЦ рдЖрдгрд┐ рд╕реБрдкреНрд░рд╕рд┐рджреНрдз рдкреНрд░рддрд┐рдирд┐рдзреА рдбреЙрдХрд░ рдЖрд╣реЗ. рдорд╛рдЧреАрд▓ рд╕рд┐рд╕реНрдЯреАрдордЪреНрдпрд╛ рддреБрд▓рдиреЗрдд, рдХрдВрдЯреЗрдирд░рдордзреАрд▓ рдЖрднрд╛рд╕реА рдиреЗрдЯрд╡рд░реНрдХрд╕рд╛рдареА рдЕрдВрдЧрднреВрдд рд╕рдорд░реНрдерди рдЖрдгрд┐ рдХрдВрдЯреЗрдирд░рдордзреАрд▓ рдЕреЕрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯреЗрдЯрдлреБрд▓рдиреЗрд╕рд╕рд╣ рдЕрдзрд┐рдХ рд▓рд╡рдЪрд┐рдХ рдкреГрдердХреНрдХрд░рдг рдпрдВрддреНрд░рдгрд╛, рдкрд░рд┐рдгрд╛рдореА рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдореЛрдареНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдиреЗ рднреМрддрд┐рдХ рд╕рд░реНрд╡реНрд╣рд░рдордзреВрди рдПрдХрдЪ рд╕рдордЧреНрд░ рд╡рд╛рддрд╛рд╡рд░рдг рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреА рдХреНрд╖рдорддрд╛ рдирд┐рд░реНрдорд╛рдг рдЭрд╛рд▓реА - рд╢рд┐рд╡рд╛рдп рдореЕрдиреНрдпреБрдЕрд▓ рд╕рдВрд╕рд╛рдзрди рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдирд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛.

рдЧреЛрджреА рдХрд╛рдордЧрд╛рд░

рдбреЙрдХрд░ рд╣реЗ рд╕рд░реНрд╡рд╛рдд рдкреНрд░рд╕рд┐рджреНрдз рдЕреЕрдкреНрд▓рд┐рдХреЗрд╢рди рдХрдВрдЯреЗрдирд░рд╛рдпрдЭреЗрд╢рди рд╕реЙрдлреНрдЯрд╡реЗрдЕрд░ рдЖрд╣реЗ. рдЧреЛ рднрд╛рд╖реЗрдд рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ, рддреЗ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдирд▓рдЪреНрдпрд╛ рдирд┐рдпрдорд┐рдд рдХреНрд╖рдорддрд╛рдВрдЪрд╛ рд╡рд╛рдкрд░ рдХрд░рддреЗ - cgroups, рдиреЗрдорд╕реНрдкреЗрд╕реЗрд╕, рдХреНрд╖рдорддрд╛ рдЗ. рддрд╕реЗрдЪ Aufs рдлрд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдЖрдгрд┐ рдбрд┐рд╕реНрдХ рд╕реНрдкреЗрд╕ рд╡рд╛рдЪрд╡рдгреНрдпрд╛рд╕рд╛рдареА рддрддреНрд╕рдо рдЗрддрд░.

рдбреЙрдХрд░ рдЖрдгрд┐ рд╕рд░реНрд╡, рд╕рд░реНрд╡, рд╕рд░реНрд╡
рд╕реНрд░реЛрдд: рд╡рд┐рдХрд┐рдореАрдбрд┐рдпрд╛

рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░

рдЖрд╡реГрддреНрддреА 1.11 рдкреВрд░реНрд╡реА, рдбреЙрдХрд░рдиреЗ рдХрдВрдЯреЗрдирд░рд╕рд╣ рд╕рд░реНрд╡ рдСрдкрд░реЗрд╢рдиреНрд╕ рдХрд░рдгрд╛рд░реА рдПрдХрд▓ рд╕реЗрд╡рд╛ рдореНрд╣рдгреВрди рдХрд╛рдо рдХреЗрд▓реЗ: рдХрдВрдЯреЗрдирд░рд╕рд╛рдареА рдкреНрд░рддрд┐рдорд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдгреЗ, рдХрдВрдЯреЗрдирд░ рд▓реЙрдиреНрдЪ рдХрд░рдгреЗ, API рд╡рд┐рдирдВрддреАрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреЗ. рдЖрд╡реГрддреНрддреА 1.11 рдкрд╛рд╕реВрди, рдбреЙрдХрд░ рдПрдХрдореЗрдХрд╛рдВрд╢реА рд╕рдВрд╡рд╛рдж рд╕рд╛рдзрдгрд╛рд░реЗ рдЕрдиреЗрдХ рднрд╛рдЧрд╛рдВрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЧрд▓реЗ рдЧреЗрд▓реЗ рдЖрд╣реЗрдд: рдХрдВрдЯреЗрдирд░, рдХрдВрдЯреЗрдирд░рдЪреЗ рд╕рдВрдкреВрд░реНрдг рдЬреАрд╡рди рдЪрдХреНрд░ рд╣рд╛рддрд╛рд│рдгреНрдпрд╛рд╕рд╛рдареА (рдбрд┐рд╕реНрдХ рд╕реНрдкреЗрд╕рдЪреЗ рд╡рд╛рдЯрдк, рдкреНрд░рддрд┐рдорд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдгреЗ, рдиреЗрдЯрд╡рд░реНрдХрд┐рдВрдЧ, рд▓реЙрдиреНрдЪ рдХрд░рдгреЗ, рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреЗ рдЖрдгрд┐ рдХрдВрдЯреЗрдирд░рдЪреНрдпрд╛ рд╕реНрдерд┐рддреАрдЪреЗ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░рдгреЗ) рдЖрдгрд┐ runC , рдХрдВрдЯреЗрдирд░ рд░рдирдЯрд╛рдЗрдореНрд╕, cgroups рдЪреНрдпрд╛ рд╡рд╛рдкрд░рд╛рд╡рд░ рдЖрдгрд┐ Linux рдХрд░реНрдирд▓рдЪреНрдпрд╛ рдЗрддрд░ рд╡реИрд╢рд┐рд╖реНрдЯреНрдпрд╛рдВрд╡рд░ рдЖрдзрд╛рд░рд┐рдд. рдбреЙрдХрд░ рд╕реЗрд╡рд╛ рд╕реНрд╡рддрдГрдЪ рд░рд╛рд╣рддреЗ, рдкрд░рдВрддреБ рдЖрддрд╛ рддреА рдлрдХреНрдд рдХрдВрдЯреЗрдирд░рд╡рд░ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХреЗрд▓реЗрд▓реНрдпрд╛ API рд╡рд┐рдирдВрддреАрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ.

рдбреЙрдХрд░ рдЖрдгрд┐ рд╕рд░реНрд╡, рд╕рд░реНрд╡, рд╕рд░реНрд╡

рд╕реНрдерд╛рдкрдирд╛ рдЖрдгрд┐ рд╕рдВрд░рдЪрдирд╛

рдбреЙрдХрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рдЪрд╛ рдорд╛рдЭрд╛ рдЖрд╡рдбрддрд╛ рдорд╛рд░реНрдЧ рдореНрд╣рдгрдЬреЗ рдбреЙрдХрд░-рдорд╢реАрди, рдЬреЗ рд░рд┐рдореЛрдЯ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ (рд╡рд┐рд╡рд┐рдз рдХреНрд▓рд╛рдЙрдбрд╕рд╣) рдбреЙрдХрд░ рдереЗрдЯ рд╕реНрдерд╛рдкрд┐рдд рдЖрдгрд┐ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рддреБрдореНрд╣рд╛рд▓рд╛ рд░рд┐рдореЛрдЯ рд╕рд░реНрд╡реНрд╣рд░рдЪреНрдпрд╛ рдлрд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдорд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕ рдЕрдиреБрдорддреА рджреЗрддреЗ рдЖрдгрд┐ рд╡рд┐рд╡рд┐рдз рдХрдорд╛рдВрдб рджреЗрдЦреАрд▓ рдЪрд╛рд▓рд╡реВ рд╢рдХрддреЗ.

рддрдерд╛рдкрд┐, 2018 рдкрд╛рд╕реВрди, рдкреНрд░рдХрд▓реНрдк рдлрд╛рд░рдЪ рдХрдореА рд╡рд┐рдХрд╕рд┐рдд рдЭрд╛рд▓рд╛ рдЖрд╣реЗ, рдореНрд╣рдгреВрди рдЖрдореНрд╣реА рдмрд╣реБрддреЗрдХ рд▓рд┐рдирдХреНрд╕ рд╡рд┐рддрд░рдгрд╛рдВрд╕рд╛рдареА рддреЗ рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдкрджреНрдзрддреАрдиреЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реВ - рдПрдХ рд░реЗрдкреЙрдЬрд┐рдЯрд░реА рдЬреЛрдбреВрди рдЖрдгрд┐ рдЖрд╡рд╢реНрдпрдХ рдкреЕрдХреЗрдЬреЗрд╕ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реВрди.

рд╣реА рдкрджреНрдзрдд рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд рд╕реНрдерд╛рдкрдиреЗрд╕рд╛рдареА рджреЗрдЦреАрд▓ рд╡рд╛рдкрд░рд▓реА рдЬрд╛рддреЗ, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдЙрддреНрддрд░рджрд╛рдпреА рдХрд┐рдВрд╡рд╛ рдЗрддрд░ рддрддреНрд╕рдо рдкреНрд░рдгрд╛рд▓реА рд╡рд╛рдкрд░рдгреЗ, рдкрд░рдВрддреБ рдореА рдпрд╛ рд▓реЗрдЦрд╛рдд рдпрд╛рдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░рдгрд╛рд░ рдирд╛рд╣реА.

рд╕реЗрдВрдЯреЛрд╕ 7 рд╡рд░ рд╕реНрдерд╛рдкрдирд╛ рдХреЗрд▓реА рдЬрд╛рдИрд▓, рдореА рд╡реНрд╣рд░реНрдЪреНрдпреБрдЕрд▓ рдорд╢реАрди рд╕рд░реНрд╡реНрд╣рд░ рдореНрд╣рдгреВрди рд╡рд╛рдкрд░реЗрди, рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдлрдХреНрдд рдЦрд╛рд▓реАрд▓ рдЖрджреЗрд╢ рдЪрд╛рд▓рд╡рд╛:

# yum install -y yum-utils
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install docker-ce docker-ce-cli containerd.io

рд╕реНрдерд╛рдкрдиреЗрдирдВрддрд░, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рд╕реЗрд╡рд╛ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ, рддреНрдпрд╛рд╕ рдСрдЯреЛрд▓реЛрдбрдордзреНрдпреЗ рдареЗрд╡рд╛:

# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent

рдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рддреБрдореНрд╣реА рдбреЙрдХрд░ рдЧрдЯ рддрдпрд╛рд░ рдХрд░реВ рд╢рдХрддрд╛, рдЬреНрдпрд╛рдЪреЗ рд╡рд╛рдкрд░рдХрд░реНрддреЗ sudo рд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░рд╕реЛрдмрдд рдХрд╛рдо рдХрд░реВ рд╢рдХрддреАрд▓, рд▓реЙрдЧрд┐рдВрдЧ рд╕реЗрдЯ рдХрд░реВ рд╢рдХрддреАрд▓, рдмрд╛рд╣реЗрд░реВрди API рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рд╕рдХреНрд╖рдо рдХрд░реВ рд╢рдХрддреАрд▓, рдлрд╛рдпрд░рд╡реЙрд▓ рдлрд╛рдЗрди-рдЯреНрдпреВрди рдХрд░рдгреНрдпрд╛рд╕ рд╡рд┐рд╕рд░реВ рдирдХрд╛ (рдЕрдиреБрдорддреА рдирд╕рд▓реЗрд▓реА рдкреНрд░рддреНрдпреЗрдХ рдЧреЛрд╖реНрдЯ рдЖрд╣реЗ. рд╡рд░реАрд▓ рдЖрдгрд┐ рдЦрд╛рд▓реА рдЙрджрд╛рд╣рд░рдгрд╛рдВрдордзреНрдпреЗ рдирд┐рд╖рд┐рджреНрдз - рдореА рд╣реЗ рд╕рд╛рдзреЗрдкрдгрд╛ рдЖрдгрд┐ рджреГрд╢реНрдпрд╛рд╕рд╛рдареА рд╡рдЧрд│рд▓реЗ рдЖрд╣реЗ), рдкрд░рдВрддреБ рдореА рдпреЗрдереЗ рдЕрдзрд┐рдХ рддрдкрд╢реАрд▓рд╛рдд рдЬрд╛рдгрд╛рд░ рдирд╛рд╣реА.

рдЗрддрд░ рд╡реИрд╢рд┐рд╖реНрдЯреНрдпреЗ

рд╡рд░реАрд▓ рдбреЙрдХрд░ рдорд╢реАрди рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рдПрдХ рдбреЙрдХрд░ рд░реЗрдЬрд┐рд╕реНрдЯреНрд░реА рджреЗрдЦреАрд▓ рдЖрд╣реЗ, рдХрдВрдЯреЗрдирд░рд╕рд╛рдареА рдкреНрд░рддрд┐рдорд╛ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдПрдХ рд╕рд╛рдзрди, рддрд╕реЗрдЪ рдбреЙрдХрд░ рдХрдВрдкреЛрдЭ - рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдВрдЪреНрдпрд╛ рддреИрдирд╛рддреА рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдПрдХ рд╕рд╛рдзрди, YAML рдлрд╛рдЗрд▓реНрд╕ рдХрдВрдЯреЗрдирд░ рддрдпрд╛рд░ рдЖрдгрд┐ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд рдЖрдгрд┐ рдЗрддрд░ рд╕рдВрдмрдВрдзрд┐рдд рдЧреЛрд╖реНрдЯреА (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдиреЗрдЯрд╡рд░реНрдХ, рдбреЗрдЯрд╛ рд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдкрд░реНрд╕рд┐рд╕реНрдЯрдВрдЯ рдлрд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо).

рд╣реЗ CICD рд╕рд╛рдареА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдЖрдпреЛрдЬрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рджреЗрдЦреАрд▓ рд╡рд╛рдкрд░рд▓реЗ рдЬрд╛рдК рд╢рдХрддреЗ. рдЖрдгрдЦреА рдПрдХ рдордиреЛрд░рдВрдЬрдХ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рдХреНрд▓рд╕реНрдЯрд░ рдореЛрдбрдордзреНрдпреЗ рдХрд╛рд░реНрдп рдХрд░рдд рдЖрд╣реЗ, рддрдерд╛рдХрдерд┐рдд рд╕реНрд╡реЙрд░реНрдо рдореЛрдб (рдЖрд╡реГрддреНрддреА 1.12 рдкреВрд░реНрд╡реА рддреЗ рдбреЙрдХрд░ рд╕реНрд╡реЙрд░реНрдо рдореНрд╣рдгреВрди рдУрд│рдЦрд▓реЗ рдЬрд╛рдд рд╣реЛрддреЗ), рдЬреЗ рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдЕрдиреЗрдХ рд╕рд░реНрд╡реНрд╣рд░рдордзреВрди рдПрдХрдЪ рдкрд╛рдпрд╛рднреВрдд рд╕реБрд╡рд┐рдзрд╛ рдПрдХрддреНрд░ рдХрд░рдгреНрдпрд╛рд╕ рдЕрдиреБрдорддреА рджреЗрддреЗ. рд╕рд░реНрд╡ рд╕рд░реНрд╡реНрд╣рд░рдЪреНрдпрд╛ рд╢реАрд░реНрд╖рд╕реНрдерд╛рдиреА рд╡реНрд╣рд░реНрдЪреНрдпреБрдЕрд▓ рдиреЗрдЯрд╡рд░реНрдХрд╕рд╛рдареА рд╕рдорд░реНрдерди рдЖрд╣реЗ, рдЕрдВрдЧрднреВрдд рд▓реЛрдб рдмреЕрд▓рдиреНрд╕рд░ рдЖрд╣реЗ, рддрд╕реЗрдЪ рдХрдВрдЯреЗрдирд░рд╕рд╛рдареА рд░рд╣рд╕реНрдпрд╛рдВрд╕рд╛рдареА рд╕рдорд░реНрдерди рдЖрд╣реЗ.

рдбреЙрдХрд░ рдХрдВрдкреЛрдЬрдордзреАрд▓ YAML рдлрд╛рдпрд▓реА рдЕрд╢рд╛ рдХреНрд▓рд╕реНрдЯрд░рд╕рд╛рдареА рдХрд┐рд░рдХреЛрд│ рдмрджрд▓рд╛рдВрд╕рд╣ рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рдК рд╢рдХрддрд╛рдд, рд╡рд┐рд╡рд┐рдз рдХрд╛рд░рдгрд╛рдВрд╕рд╛рдареА рд▓рд╣рд╛рди рдЖрдгрд┐ рдордзреНрдпрдо рдХреНрд▓рд╕реНрдЯрд░реНрд╕рдЪреА рджреЗрдЦрднрд╛рд▓ рдкреВрд░реНрдгрдкрдгреЗ рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд рдХрд░рддрд╛рдд. рдореЛрдареНрдпрд╛ рдХреНрд▓рд╕реНрдЯрд░рд╕рд╛рдареА, рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рд╢реНрд░реЗрдпрд╕реНрдХрд░ рдЖрд╣реЗ рдХрд╛рд░рдг рдЭреБрдВрдб рдореЛрдб рджреЗрдЦрднрд╛рд▓ рдЦрд░реНрдЪ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдЪреНрдпрд╛ рддреБрд▓рдиреЗрдд рдЬрд╛рд╕реНрдд рдЕрд╕реВ рд╢рдХрддреЛ. RunC рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рдХрдВрдЯреЗрдирд░рд╕рд╛рдареА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рд╡рд╛рддрд╛рд╡рд░рдг рдореНрд╣рдгреВрди, рдЖрдкрдг рд╕реНрдерд╛рдкрд┐рдд рдХрд░реВ рд╢рдХрддрд╛, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде рдХрд╛рдЯрд╛ рдХрдВрдЯреЗрдирд░реНрд╕

рдбреЙрдХрд░рд╕реЛрдмрдд рдХрд╛рдо рдХрд░рдд рдЖрд╣реЗ

рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рдЖрдгрд┐ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рдирдирдВрддрд░, рдЖрдореНрд╣реА рдПрдХ рдХреНрд▓рд╕реНрдЯрд░ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░реВ рдЬреНрдпрд╛рдордзреНрдпреЗ рдЖрдореНрд╣реА рд╡рд┐рдХрд╛рд╕ рдХрд╛рд░реНрдпрд╕рдВрдШрд╛рд╕рд╛рдареА GitLab рдЖрдгрд┐ Docker Registry рддреИрдирд╛рдд рдХрд░реВ. рд╕рд░реНрд╡реНрд╣рд░ рдореНрд╣рдгреВрди, рдореА рддреАрди рд╡реНрд╣рд░реНрдЪреНрдпреБрдЕрд▓ рдорд╢реАрдиреНрд╕ рд╡рд╛рдкрд░реЗрди, рдЬреНрдпрд╛рд╡рд░ рдореА рдЕрддрд┐рд░рд┐рдХреНрддрдкрдгреЗ GlusterFS рд╡рд┐рддрд░рд┐рдд FS рддреИрдирд╛рдд рдХрд░реАрди, рдореА рддреЗ рдбреЙрдХрд░ рд╡реНрд╣реЙрд▓реНрдпреВрдо рд╕реНрдЯреЛрд░реЗрдЬ рдореНрд╣рдгреВрди рд╡рд╛рдкрд░реЗрди, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдбреЙрдХрд░ рд░реЗрдЬрд┐рд╕реНрдЯреНрд░реАрдЪреА рдЕрдпрд╢рд╕реНрд╡реА-рд╕реБрд░рдХреНрд╖рд┐рдд рдЖрд╡реГрддреНрддреА рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╕рд╛рдареА. рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╕рд╛рдареА рдкреНрд░рдореБрдЦ рдШрдЯрдХ: рдбреЙрдХрд░ рд░рдЬрд┐рд╕реНрдЯреНрд░реА, рдкреЛрд╕реНрдЯрдЧреНрд░реЗрд╕рдХреНрдпреВрдПрд▓, рд░реЗрдбрд┐рд╕, рдЧрд┐рдЯрд▓реЕрдм рд░рдирд░рдЪреНрдпрд╛ рд╕рдорд░реНрдердирд╛рд╕рд╣ рд╕реНрд╡реЙрд░реНрдордЪреНрдпрд╛ рд╡рд░. Postgresql рдХреНрд▓рд╕реНрдЯрд░рд┐рдВрдЧрд╕рд╣ рд▓рд╛рдБрдЪ рдХреЗрд▓реЗ рдЬрд╛рдИрд▓ рд╕реНрдЯреЛрд▓реЙрди, рддреНрдпрд╛рдореБрд│реЗ рддреБрдореНрд╣рд╛рд▓рд╛ Postgresql рдбреЗрдЯрд╛ рд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА GlusterFS рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╛рд╣реА. рдЙрд░реНрд╡рд░рд┐рдд рдЧрдВрднреАрд░ рдбреЗрдЯрд╛ GlusterFS рд╡рд░ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХреЗрд▓рд╛ рдЬрд╛рдИрд▓.

рд╕рд░реНрд╡ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ GlusterFS рдЙрдкрдпреЛрдЬрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА (рддреНрдпрд╛рдВрдирд╛ node1, node2, node3 рдореНрд╣рдгрддрд╛рдд), рддреБрдореНрд╣рд╛рд▓рд╛ рдкреЕрдХреЗрдЬреЗрд╕ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреЗ, рдлрд╛рдпрд░рд╡реЙрд▓ рд╕рдХреНрд╖рдо рдХрд░рдгреЗ, рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рддрдпрд╛рд░ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

# yum -y install centos-release-gluster7
# yum -y install glusterfs-server
# systemctl enable glusterd
# systemctl start glusterd
# firewall-cmd --add-service=glusterfs --permanent
# firewall-cmd --reload
# mkdir -p /srv/gluster
# mkdir -p /srv/docker
# echo "$(hostname):/docker /srv/docker glusterfs defaults,_netdev 0 0" >> /etc/fstab

рд╕реНрдерд╛рдкрдиреЗрдирдВрддрд░, GlusterFS рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рдЪреЗ рдХрд╛рдо рдПрдХрд╛ рдиреЛрдбрд╡рд░реВрди рд╕реБрд░реВ рдареЗрд╡рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде node1:

# gluster peer probe node2
# gluster peer probe node3
# gluster volume create docker replica 3 node1:/srv/gluster node2:/srv/gluster node3:/srv/gluster force
# gluster volume start docker

рдордЧ рддреБрдореНрд╣рд╛рд▓рд╛ рдкрд░рд┐рдгрд╛рдореА рд╡реНрд╣реЙрд▓реНрдпреВрдо рдорд╛рдЙрдВрдЯ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ (рдЖрджреЗрд╢ рд╕рд░реНрд╡ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдЪрд╛рд▓рд╡рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ):

# mount /srv/docker

рд╕реНрд╡реЙрд░реНрдо рдореЛрдб рдПрдХрд╛ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЗрд▓рд╛ рдЖрд╣реЗ, рдЬреЛ рд▓реАрдбрд░ рдЕрд╕реЗрд▓, рдмрд╛рдХреАрдЪреНрдпрд╛рдВрдирд╛ рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рд╕рд╛рдореАрд▓ рд╡реНрд╣рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓, рдореНрд╣рдгреВрди рдкрд╣рд┐рд▓реНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдХрдорд╛рдВрдб рдЪрд╛рд▓рд╡рд▓реНрдпрд╛рдЪрд╛ рдкрд░рд┐рдгрд╛рдо рдмрд╛рдХреАрдЪреНрдпрд╛рд╡рд░ рдХреЙрдкреА рдЖрдгрд┐ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдХреНрд▓рд╕реНрдЯрд░ рд╕реЗрдЯрдЕрдк, рдореА node1 рд╡рд░ рдХрдорд╛рдВрдб рдЪрд╛рд▓рд╡рддреЛ:

# docker swarm init
Swarm initialized: current node (a5jpfrh5uvo7svzz1ajduokyq) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0c5mf7mvzc7o7vjk0wngno2dy70xs95tovfxbv4tqt9280toku-863hyosdlzvd76trfptd4xnzd xx.xx.xx.xx:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# docker swarm join-token manager

рджреБрд╕рд▒реНрдпрд╛ рдХрдорд╛рдВрдбрдЪрд╛ рдирд┐рдХрд╛рд▓ рдХреЙрдкреА рдХрд░рд╛, node2 рдЖрдгрд┐ node3 рд╡рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░рд╛:

# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.

рд╣реЗ рд╕рд░реНрд╡реНрд╣рд░рдЪреЗ рдкреНрд░рд╛рдердорд┐рдХ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдкреВрд░реНрдг рдХрд░рддреЗ, рдЪрд▓рд╛ рд╕реЗрд╡рд╛ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреЗ рд╕реБрд░реВ рдХрд░реВрдпрд╛, рдЕрдиреНрдпрдерд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреЗрд▓реНрдпрд╛рд╢рд┐рд╡рд╛рдп, рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреЗрд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд░реНтАНрдпрд╛ рдХрдорд╛рдВрдбреНрд╕ node1 рд╡рд░реВрди рд▓рд╛рдБрдЪ рдХреЗрд▓реНрдпрд╛ рдЬрд╛рддреАрд▓.

рд╕рд░реНрд╡ рдкреНрд░рдердо, рдХрдВрдЯреЗрдирд░рд╕рд╛рдареА рдиреЗрдЯрд╡рд░реНрдХ рддрдпрд╛рд░ рдХрд░реВрдпрд╛:

# docker network create --driver=overlay etcd
# docker network create --driver=overlay pgsql
# docker network create --driver=overlay redis
# docker network create --driver=overlay traefik
# docker network create --driver=overlay gitlab

рдордЧ рдЖрдореНрд╣реА рд╕рд░реНрд╡реНрд╣рд░ рдЪрд┐рдиреНрд╣рд╛рдВрдХрд┐рдд рдХрд░рддреЛ, рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдХрд╛рд╣реА рд╕реЗрд╡рд╛ рдмрдВрдзрдирдХрд╛рд░рдХ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╣реЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3

рдкреБрдвреЗ, рдЖрдореНрд╣реА etcd рдбреЗрдЯрд╛ рд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рддрдпрд╛рд░ рдХрд░рддреЛ, рдЯреНрд░реЕрдлрд┐рдХ рдЖрдгрд┐ рд╕реНрдЯреЛрд▓реЙрдирд▓рд╛ рдЖрд╡рд╢реНрдпрдХ рдЕрд╕рд▓реЗрд▓реЗ KV рд╕реНрдЯреЛрд░реЗрдЬ. Postgresql рдкреНрд░рдорд╛рдгреЗрдЪ, рд╣реЗ рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рдмрд╛рдВрдзрд▓реЗрд▓реЗ рдХрдВрдЯреЗрдирд░ рдЕрд╕рддреАрд▓, рдореНрд╣рдгреВрди рдЖрдореНрд╣реА рд╕рд░реНрд╡ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рд╣реА рдЖрдЬреНрдЮрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░рддреЛ:

# mkdir -p /srv/etcd

рдкреБрдвреЗ, etcd рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдлрд╛рдЗрд▓ рддрдпрд╛рд░ рдХрд░рд╛ рдЖрдгрд┐ рддреА рд▓рд╛рдЧреВ рдХрд░рд╛:

00etcd.yml

version: '3.7'

services:
  etcd1:
    image: quay.io/coreos/etcd:latest
    hostname: etcd1
    command:
      - etcd
      - --name=etcd1
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd1:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd1:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd1vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node1]
  etcd2:
    image: quay.io/coreos/etcd:latest
    hostname: etcd2
    command:
      - etcd
      - --name=etcd2
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd2:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd2:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd2vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node2]
  etcd3:
    image: quay.io/coreos/etcd:latest
    hostname: etcd3
    command:
      - etcd
      - --name=etcd3
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd3:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd3:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd3vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node3]

volumes:
  etcd1vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"
  etcd2vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"
  etcd3vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"

networks:
  etcd:
    external: true

# docker stack deploy --compose-file 00etcd.yml etcd

рдереЛрдбреНрдпрд╛ рд╡реЗрд│рд╛рдиреЗ, рдЖрдореНрд╣реА рддрдкрд╛рд╕рддреЛ рдХреА etcd рдХреНрд▓рд╕реНрдЯрд░ рд╡рд╛рдврд▓рд╛ рдЖрд╣реЗ:

# docker exec $(docker ps | awk '/etcd/ {print $1}')  etcdctl member list
ade526d28b1f92f7: name=etcd1 peerURLs=http://etcd1:2380 clientURLs=http://etcd1:2379 isLeader=false
bd388e7810915853: name=etcd3 peerURLs=http://etcd3:2380 clientURLs=http://etcd3:2379 isLeader=false
d282ac2ce600c1ce: name=etcd2 peerURLs=http://etcd2:2380 clientURLs=http://etcd2:2379 isLeader=true
# docker exec $(docker ps | awk '/etcd/ {print $1}')  etcdctl cluster-health
member ade526d28b1f92f7 is healthy: got healthy result from http://etcd1:2379
member bd388e7810915853 is healthy: got healthy result from http://etcd3:2379
member d282ac2ce600c1ce is healthy: got healthy result from http://etcd2:2379
cluster is healthy

Postgresql рд╕рд╛рдареА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рддрдпрд╛рд░ рдХрд░рд╛, рд╕рд░реНрд╡ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдХрдорд╛рдВрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░рд╛:

# mkdir -p /srv/pgsql

рдкреБрдвреЗ, Postgresql рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдлрд╛рдЗрд▓ рддрдпрд╛рд░ рдХрд░рд╛:

01pgsql.yml

version: '3.7'

services:
  pgsentinel:
    image: sorintlab/stolon:master-pg10
    command:
      - gosu
      - stolon
      - stolon-sentinel
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
      - --log-level=debug
    networks:
      - etcd
      - pgsql
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 30s
        order: stop-first
        failure_action: pause
  pgkeeper1:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper1
    command:
      - gosu
      - stolon
      - stolon-keeper
      - --pg-listen-address=pgkeeper1
      - --pg-repl-username=replica
      - --uid=pgkeeper1
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper1:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node1]
  pgkeeper2:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper2
    command:
      - gosu
      - stolon 
      - stolon-keeper
      - --pg-listen-address=pgkeeper2
      - --pg-repl-username=replica
      - --uid=pgkeeper2
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper2:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node2]
  pgkeeper3:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper3
    command:
      - gosu
      - stolon 
      - stolon-keeper
      - --pg-listen-address=pgkeeper3
      - --pg-repl-username=replica
      - --uid=pgkeeper3
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper3:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node3]
  postgresql:
    image: sorintlab/stolon:master-pg10
    command: gosu stolon stolon-proxy --listen-address 0.0.0.0 --cluster-name stolon-cluster --store-backend=etcdv3 --store-endpoints http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 30s
        order: stop-first
        failure_action: rollback

volumes:
  pgkeeper1:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"
  pgkeeper2:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"
  pgkeeper3:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"

secrets:
  pgsql:
    file: "/srv/docker/postgres"
  pgsql_repl:
    file: "/srv/docker/replica"

networks:
  etcd:
    external: true
  pgsql:
    external: true

рдЖрдореНрд╣реА рд░рд╣рд╕реНрдпреЗ рд╡реНрдпреБрддреНрдкрдиреНрди рдХрд░рддреЛ, рдлрд╛рдЗрд▓ рд▓рд╛рдЧреВ рдХрд░рддреЛ:

# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/replica
# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/postgres
# docker stack deploy --compose-file 01pgsql.yml pgsql

рдХрд╛рд╣реА рд╡реЗрд│рд╛рдиреЗ (рдЖрджреЗрд╢рд╛рдЪреЗ рдЖрдЙрдЯрдкреБрдЯ рдкрд╣рд╛ рдбреЙрдХрд░ рд╕реЗрд╡рд╛ lsрдХреА рд╕рд░реНрд╡ рд╕реЗрд╡рд╛ рд╡рд╛рдврд▓реНрдпрд╛ рдЖрд╣реЗрдд) Postgresql рдХреНрд▓рд╕реНрдЯрд░ рд╕реБрд░реВ рдХрд░рд╛:

# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 init

Postgresql рдХреНрд▓рд╕реНрдЯрд░рдЪреА рддрдпрд╛рд░реА рддрдкрд╛рд╕рдд рдЖрд╣реЗ:

# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 status
=== Active sentinels ===

ID      LEADER
26baa11d    false
74e98768    false
a8cb002b    true

=== Active proxies ===

ID
4d233826
9f562f3b
b0c79ff1

=== Keepers ===

UID     HEALTHY PG LISTENADDRESS    PG HEALTHY  PG WANTEDGENERATION PG CURRENTGENERATION
pgkeeper1   true    pgkeeper1:5432         true     2           2
pgkeeper2   true    pgkeeper2:5432          true            2                   2
pgkeeper3   true    pgkeeper3:5432          true            3                   3

=== Cluster Info ===

Master Keeper: pgkeeper3

===== Keepers/DB tree =====

pgkeeper3 (master)
тФЬтФАpgkeeper2
тФФтФАpgkeeper1

рдЖрдореНрд╣реА рдмрд╛рд╣реЗрд░реВрди рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдЙрдШрдбрдгреНрдпрд╛рд╕рд╛рдареА рдЯреНрд░реЕрдлрд┐рдХ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рддреЛ:

03traefik.yml

version: '3.7'

services:
  traefik:
    image: traefik:latest
    command: >
      --log.level=INFO
      --providers.docker=true
      --entryPoints.web.address=:80
      --providers.providersThrottleDuration=2
      --providers.docker.watch=true
      --providers.docker.swarmMode=true
      --providers.docker.swarmModeRefreshSeconds=15s
      --providers.docker.exposedbydefault=false
      --accessLog.bufferingSize=0
      --api=true
      --api.dashboard=true
      --api.insecure=true
    networks:
      - traefik
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.role == manager
        preferences:
          - spread: node.id
      labels:
        - traefik.enable=true
        - traefik.http.routers.traefik.rule=Host(`traefik.example.com`)
        - traefik.http.services.traefik.loadbalancer.server.port=8080
        - traefik.docker.network=traefik

networks:
  traefik:
    external: true

# docker stack deploy --compose-file 03traefik.yml traefik

рдЖрдореНрд╣реА рд░реЗрдбрд┐рд╕ рдХреНрд▓рд╕реНрдЯрд░ рд╕реБрд░реВ рдХрд░рддреЛ, рдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА рд╕рд░реНрд╡ рдиреЛрдбреНрд╕рд╡рд░ рд╕реНрдЯреЛрд░реЗрдЬ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рддрдпрд╛рд░ рдХрд░рддреЛ:

# mkdir -p /srv/redis

05redis.yml

version: '3.7'

services:
  redis-master:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '6379:6379'
    environment:
      - REDIS_REPLICATION_MODE=master
      - REDIS_PASSWORD=xxxxxxxxxxx
    deploy:
      mode: global
      restart_policy:
        condition: any
    volumes:
      - 'redis:/opt/bitnami/redis/etc/'

  redis-replica:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '6379'
    depends_on:
      - redis-master
    environment:
      - REDIS_REPLICATION_MODE=slave
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=xxxxxxxxxxx
      - REDIS_PASSWORD=xxxxxxxxxxx
    deploy:
      mode: replicated
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: any

  redis-sentinel:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '16379'
    depends_on:
      - redis-master
      - redis-replica
    entrypoint: |
      bash -c 'bash -s <<EOF
      "/bin/bash" -c "cat <<EOF > /opt/bitnami/redis/etc/sentinel.conf
      port 16379
      dir /tmp
      sentinel monitor master-node redis-master 6379 2
      sentinel down-after-milliseconds master-node 5000
      sentinel parallel-syncs master-node 1
      sentinel failover-timeout master-node 5000
      sentinel auth-pass master-node xxxxxxxxxxx
      sentinel announce-ip redis-sentinel
      sentinel announce-port 16379
      EOF"
      "/bin/bash" -c "redis-sentinel /opt/bitnami/redis/etc/sentinel.conf"
      EOF'
    deploy:
      mode: global
      restart_policy:
        condition: any

volumes:
  redis:
    driver: local
    driver_opts:
      type: 'none'
      o: 'bind'
      device: "/srv/redis"

networks:
  redis:
    external: true

# docker stack deploy --compose-file 05redis.yml redis

рдбреЙрдХрд░ рд░реЗрдЬрд┐рд╕реНрдЯреНрд░реА рдЬреЛрдбрд╛:

06registry.yml

version: '3.7'

services:
  registry:
    image: registry:2.6
    networks:
      - traefik
    volumes:
      - registry_data:/var/lib/registry
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
      labels:
        - traefik.enable=true
        - traefik.http.routers.registry.rule=Host(`registry.example.com`)
        - traefik.http.services.registry.loadbalancer.server.port=5000
        - traefik.docker.network=traefik

volumes:
  registry_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/registry"

networks:
  traefik:
    external: true

# mkdir /srv/docker/registry
# docker stack deploy --compose-file 06registry.yml registry

рдЖрдгрд┐ рд╢реЗрд╡рдЯреА - GitLab:

08gitlab-runner.yml

version: '3.7'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    networks:
      - pgsql
      - redis
      - traefik
      - gitlab
    ports:
      - 22222:22
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        postgresql['enable'] = false
        redis['enable'] = false
        gitlab_rails['registry_enabled'] = false
        gitlab_rails['db_username'] = "gitlab"
        gitlab_rails['db_password'] = "XXXXXXXXXXX"
        gitlab_rails['db_host'] = "postgresql"
        gitlab_rails['db_port'] = "5432"
        gitlab_rails['db_database'] = "gitlab"
        gitlab_rails['db_adapter'] = 'postgresql'
        gitlab_rails['db_encoding'] = 'utf8'
        gitlab_rails['redis_host'] = 'redis-master'
        gitlab_rails['redis_port'] = '6379'
        gitlab_rails['redis_password'] = 'xxxxxxxxxxx'
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.yandex.ru"
        gitlab_rails['smtp_port'] = 465
        gitlab_rails['smtp_user_name'] = "[email protected]"
        gitlab_rails['smtp_password'] = "xxxxxxxxx"
        gitlab_rails['smtp_domain'] = "example.com"
        gitlab_rails['gitlab_email_from'] = '[email protected]'
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_tls'] = true
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
        external_url 'http://gitlab.example.com/'
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    volumes:
      - gitlab_conf:/etc/gitlab
      - gitlab_logs:/var/log/gitlab
      - gitlab_data:/var/opt/gitlab
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
        - node.role == manager
      labels:
        - traefik.enable=true
        - traefik.http.routers.gitlab.rule=Host(`gitlab.example.com`)
        - traefik.http.services.gitlab.loadbalancer.server.port=80
        - traefik.docker.network=traefik
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    networks:
      - gitlab
    volumes:
      - gitlab_runner_conf:/etc/gitlab
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
        - node.role == manager

volumes:
  gitlab_conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/conf"
  gitlab_logs:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/logs"
  gitlab_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/data"
  gitlab_runner_conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/runner"

networks:
  pgsql:
    external: true
  redis:
    external: true
  traefik:
    external: true
  gitlab:
    external: true

# mkdir -p /srv/docker/gitlab/conf
# mkdir -p /srv/docker/gitlab/logs
# mkdir -p /srv/docker/gitlab/data
# mkdir -p /srv/docker/gitlab/runner
# docker stack deploy --compose-file 08gitlab-runner.yml gitlab

рдХреНрд▓рд╕реНрдЯрд░ рдЖрдгрд┐ рд╕реЗрд╡рд╛рдВрдЪреА рдЕрдВрддрд┐рдо рд╕реНрдерд┐рддреА:

# docker service ls
ID                  NAME                   MODE                REPLICAS            IMAGE                          PORTS
lef9n3m92buq        etcd_etcd1             replicated          1/1                 quay.io/coreos/etcd:latest
ij6uyyo792x5        etcd_etcd2             replicated          1/1                 quay.io/coreos/etcd:latest
fqttqpjgp6pp        etcd_etcd3             replicated          1/1                 quay.io/coreos/etcd:latest
hq5iyga28w33        gitlab_gitlab          replicated          1/1                 gitlab/gitlab-ce:latest        *:22222->22/tcp
dt7s6vs0q4qc        gitlab_gitlab-runner   replicated          1/1                 gitlab/gitlab-runner:latest
k7uoezno0h9n        pgsql_pgkeeper1        replicated          1/1                 sorintlab/stolon:master-pg10
cnrwul4r4nse        pgsql_pgkeeper2        replicated          1/1                 sorintlab/stolon:master-pg10
frflfnpty7tr        pgsql_pgkeeper3        replicated          1/1                 sorintlab/stolon:master-pg10
x7pqqchi52kq        pgsql_pgsentinel       replicated          3/3                 sorintlab/stolon:master-pg10
mwu2wl8fti4r        pgsql_postgresql       replicated          3/3                 sorintlab/stolon:master-pg10
9hkbe2vksbzb        redis_redis-master     global              3/3                 bitnami/redis:latest           *:6379->6379/tcp
l88zn8cla7dc        redis_redis-replica    replicated          3/3                 bitnami/redis:latest           *:30003->6379/tcp
1utp309xfmsy        redis_redis-sentinel   global              3/3                 bitnami/redis:latest           *:30002->16379/tcp
oteb824ylhyp        registry_registry      replicated          1/1                 registry:2.6
qovrah8nzzu8        traefik_traefik        replicated          3/3                 traefik:latest                 *:80->80/tcp, *:443->443/tcp

рдЖрдгрдЦреА рдХрд╛рдп рд╕реБрдзрд╛рд░рддрд╛ рдпреЗрдИрд▓? https рдХрдВрдЯреЗрдирд░рд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА Traefik рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЗрд▓реНрдпрд╛рдЪреА рдЦрд╛рддреНрд░реА рдХрд░рд╛, Postgresql рдЖрдгрд┐ Redis рд╕рд╛рдареА tls рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдЬреЛрдбрд╛. рдкрд░рдВрддреБ рд╕рд░реНрд╡рд╕рд╛рдзрд╛рд░рдгрдкрдгреЗ, рддреБрдореНрд╣реА рддреЗ рдЖрдзреАрдЪ рд╡рд┐рдХрд╕рдХрд╛рдВрдирд╛ PoC рдореНрд╣рдгреВрди рджреЗрдК рд╢рдХрддрд╛. рдЖрддрд╛ рдбреЙрдХрд░рдЪреЗ рдкрд░реНрдпрд╛рдп рдкрд╛рд╣реВ.

рдкреЛрдбрдореЕрди

рдкреЙрдбреНрд╕рджреНрд╡рд╛рд░реЗ рдЧрдЯрдмрджреНрдз рдХреЗрд▓реЗрд▓реЗ рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрдЦреА рдПрдХ рд╕реБрдкреНрд░рд╕рд┐рджреНрдз рдЗрдВрдЬрд┐рди (рд╢реЗрдВрдЧрд╛, рдХрдВрдЯреЗрдирд░рдЪреЗ рдЧрдЯ рдПрдХрддреНрд░ рддреИрдирд╛рдд). рдбреЙрдХрд░рдЪреНрдпрд╛ рд╡рд┐рдкрд░реАрдд, рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдХреЛрдгрддреНрдпрд╛рд╣реА рд╕реЗрд╡реЗрдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╛рд╣реА, рд╕рд░реНрд╡ рдХрд╛рдо рд▓рд┐рдмрдкреЙрдб рд▓рд╛рдпрдмреНрд░рд░реАрджреНрд╡рд╛рд░реЗ рдХреЗрд▓реЗ рдЬрд╛рддреЗ. Go рдордзреНрдпреЗ рджреЗрдЦреАрд▓ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдЖрд╣реЗ, runC рд╕рд╛рд░рдЦреЗ рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА OCI рдЕрдиреБрд░реВрдк рд░рдирдЯрд╛рдЗрдо рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

рдбреЙрдХрд░ рдЖрдгрд┐ рд╕рд░реНрд╡, рд╕рд░реНрд╡, рд╕рд░реНрд╡

рдкреЙрдбрдореЕрдирд╕реЛрдмрдд рдХрд╛рдо рдХрд░рдгреЗ рд╕рд░реНрд╡рд╕рд╛рдзрд╛рд░рдгрдкрдгреЗ рдбреЙрдХрд░рд╕рд╛рд░рдЦреЗрдЪ рдЖрд╣реЗ, рдЬреНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рдд рддреБрдореНрд╣реА рд╣реЗ рдЕрд╕реЗ рдХрд░реВ рд╢рдХрддрд╛ (рдпрд╛ рд▓реЗрдЦрд╛рдЪреНрдпрд╛ рд▓реЗрдЦрдХрд╛рд╕рд╣ рдЕрдиреЗрдХрд╛рдВрдиреА рдкреНрд░рдпрддреНрди рдХреЗрд▓рд╛ рдЖрд╣реЗ рдЕрд╕рд╛ рджрд╛рд╡рд╛ рдХреЗрд▓рд╛ рдЖрд╣реЗ):

$ alias docker=podman

рдЖрдгрд┐ рддреБрдореНрд╣реА рдХрд╛рдо рдХрд░рдд рд░рд╛рд╣реВ рд╢рдХрддрд╛. рд╕рд░реНрд╡рд╕рд╛рдзрд╛рд░рдгрдкрдгреЗ, рдкреЙрдбрдореЕрдирдЪреА рдкрд░рд┐рд╕реНрдерд┐рддреА рдЦреВрдк рдордиреЛрд░рдВрдЬрдХ рдЖрд╣реЗ, рдХрд╛рд░рдг рдЬрд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдЪреНрдпрд╛ рд╕реБрд░реБрд╡рд╛рддреАрдЪреНрдпрд╛ рдЖрд╡реГрддреНрддреНрдпрд╛рдВрдиреА рдбреЙрдХрд░рд╕реЛрдмрдд рдХрд╛рдо рдХреЗрд▓реЗ рдЕрд╕реЗрд▓, рддрд░ рд╕реБрдорд╛рд░реЗ 2015 рдкрд╛рд╕реВрди, рдХрдВрдЯреЗрдирд░ рд╡рд░реНрд▓реНрдб (рдУрд╕реАрдЖрдп - рдУрдкрди рдХрдВрдЯреЗрдирд░ рдЗрдирд┐рд╢рд┐рдПрдЯрд┐рд╡реНрд╣) рдкреНрд░рдорд╛рдгрд┐рдд рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ рдЖрдгрд┐ рдбреЙрдХрд░рд▓рд╛ рдХрдВрдЯреЗрдирд░ рдЖрдгрд┐ рд░рдирд╕реАрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рдкрд░реНрдпрд╛рдпреА рдбреЙрдХрд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдордзреНрдпреЗ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд┐рдХрд╕рд┐рдд рдХреЗрд▓реЗ рдЬрд╛рдд рдЖрд╣реЗ: CRI-O. рдпрд╛ рд╕рдВрджрд░реНрднрд╛рдд рдкреЙрдбрдореЕрди рд╣рд╛ рдХрдВрдЯреЗрдирд░ рдЧреНрд░реБрдкрд┐рдВрдЧрд╕рд╣ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдЪреНрдпрд╛ рддрддреНрддреНрд╡рд╛рдВрд╡рд░ рддрдпрд╛рд░ рдХреЗрд▓реЗрд▓рд╛ рдбреЙрдХрд░рдЪрд╛ рдкрд░реНрдпрд╛рдп рдЖрд╣реЗ, рдкрд░рдВрддреБ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реЗрд╡рд╛рдВрд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░-рд╢реИрд▓реАрддреАрд▓ рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рдгреЗ рд╣реЗ рдкреНрд░рдХрд▓реНрдкрд╛рдЪреЗ рдореБрдЦреНрдп рдзреНрдпреЗрдп рдЖрд╣реЗ. рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдгрд╛рд╕реНрддрд╡, рдХреЛрдгрддрд╛рд╣реА рдЭреБрдВрдб рдореЛрдб рдирд╛рд╣реА, рдХрд╛рд░рдг рд╡рд┐рдХрд╕рдХ рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рдореНрд╣рдгрддрд╛рдд рдХреА рдЬрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдХреНрд▓рд╕реНрдЯрд░рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЕрд╕реЗрд▓ рддрд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдШреНрдпрд╛.

рд╕реЗрдЯрд┐рдВрдЧ

рд╕реЗрдВрдЯреЛрд╕ 7 рд╡рд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдлрдХреНрдд рдПрдХреНрд╕реНрдЯреНрд░рд╛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕рдХреНрд░рд┐рдп рдХрд░рд╛ рдЖрдгрд┐ рдирдВрддрд░ рдХрдорд╛рдВрдбрд╕рд╣ рд╕рд░реНрд╡рдХрд╛рд╣реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛:

# yum -y install podman

рдЗрддрд░ рд╡реИрд╢рд┐рд╖реНрдЯреНрдпреЗ

рдкреЙрдбрдореЕрди рд╕рд┐рд╕реНрдЯрдордбрд╕рд╛рдареА рдпреБрдирд┐рдЯреНрд╕ рд╡реНрдпреБрддреНрдкрдиреНрди рдХрд░реВ рд╢рдХрддреЛ, рдЕрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ рд╕рд░реНрд╡реНрд╣рд░ рд░реАрдмреВрдЯ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ рдХрдВрдЯреЗрдирд░ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдЪреА рд╕рдорд╕реНрдпрд╛ рд╕реЛрдбрд╡рддреЗ. рдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ pid 1 рдореНрд╣рдгреВрди рдпреЛрдЧреНрдпрд░рд┐рддреНрдпрд╛ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА systemd рдШреЛрд╖рд┐рдд рдХреЗрд▓реЗ рдЬрд╛рддреЗ. рдХрдВрдЯреЗрдирд░ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдПрдХ рд╡реЗрдЧрд│реЗ рдмрд┐рд▓реНрдбрд╣ рдЯреВрд▓ рдЖрд╣реЗ, рддреЗрдереЗ рддреГрддреАрдп-рдкрдХреНрд╖ рд╕рд╛рдзрдиреЗ рджреЗрдЦреАрд▓ рдЖрд╣реЗрдд - рдбреЙрдХрд░-рдХрдВрдкреЛрдЬрдЪреЗ рдЕреЕрдирд╛рд▓реЙрдЧреНрд╕, рдЬреЗ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕-рд╕реБрд╕рдВрдЧрдд рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдлрд╛рдЗрд▓реНрд╕ рджреЗрдЦреАрд▓ рд╡реНрдпреБрддреНрдкрдиреНрди рдХрд░рддрд╛рдд, рддреНрдпрд╛рдореБрд│реЗ рдкреЙрдбрдореЕрдирдкрд╛рд╕реВрди рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдордзреНрдпреЗ рд╕рдВрдХреНрд░рдордг рд╢рдХреНрдп рддрд┐рддрдХреЗ рд╕реЛрдкреЗ рдЖрд╣реЗ.

рдкреЙрдбрдореЕрдирд╕реЛрдмрдд рдХрд╛рдо рдХрд░рдд рдЖрд╣реЗ

рдХреЛрдгрддрд╛рд╣реА рдЭреБрдВрдб рдореЛрдб рдирд╕рд▓реНрдпрд╛рдореБрд│реЗ (рдХреНрд▓рд╕реНрдЯрд░рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЕрд╕рд▓реНрдпрд╛рд╕ рддреЗ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рд╡рд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдгреЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЖрд╣реЗ), рдЖрдореНрд╣реА рддреЗ рд╡реЗрдЧрд│реНрдпрд╛ рдХрдВрдЯреЗрдирд░рдордзреНрдпреЗ рдПрдХрддреНрд░ рдХрд░реВ.

рдкреЙрдбрдореЕрди-рдХрдВрдкреЛрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛:

# yum -y install python3-pip
# pip3 install podman-compose

рдкреЙрдбрдореЕрдирд╕рд╛рдареА рдкрд░рд┐рдгрд╛рдореА рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдлрд╛рдЗрд▓ рдереЛрдбреА рд╡реЗрдЧрд│реА рдЖрд╣реЗ, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде рдЖрдореНрд╣рд╛рд▓рд╛ рдПрдХ рд╡реЗрдЧрд│рд╛ рдЦрдВрдб рд╡рд┐рднрд╛рдЧ рдереЗрдЯ рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧрд╛рдд рд╣рд▓рд╡рд╛рд╡рд╛ рд▓рд╛рдЧрд▓рд╛.

gitlab-podman.yml

version: '3.7'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    hostname: gitlab.example.com
    restart: unless-stopped
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    ports:
      - "80:80"
      - "22222:22"
    volumes:
      - /srv/podman/gitlab/conf:/etc/gitlab
      - /srv/podman/gitlab/data:/var/opt/gitlab
      - /srv/podman/gitlab/logs:/var/log/gitlab
    networks:
      - gitlab

  gitlab-runner:
    image: gitlab/gitlab-runner:alpine
    restart: unless-stopped
    depends_on:
      - gitlab
    volumes:
      - /srv/podman/gitlab/runner:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - gitlab

networks:
  gitlab:

# podman-compose -f gitlab-runner.yml -d up

рдХрд╛рдорд╛рдЪрд╛ рдкрд░рд┐рдгрд╛рдо:

# podman ps
CONTAINER ID  IMAGE                                  COMMAND               CREATED             STATUS                 PORTS                                      NAMES
da53da946c01  docker.io/gitlab/gitlab-runner:alpine  run --user=gitlab...  About a minute ago  Up About a minute ago  0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp  root_gitlab-runner_1
781c0103c94a  docker.io/gitlab/gitlab-ce:latest      /assets/wrapper       About a minute ago  Up About a minute ago  0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp  root_gitlab_1

рддреЗ systemd рдЖрдгрд┐ kubernetes рд╕рд╛рдареА рдХрд╛рдп рд╡реНрдпреБрддреНрдкрдиреНрди рдХрд░реЗрд▓ рддреЗ рдкрд╛рд╣реВ рдпрд╛, рдпрд╛рд╕рд╛рдареА рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдкреЙрдбрдЪреЗ рдирд╛рд╡ рдХрд┐рдВрд╡рд╛ рдЖрдпрдбреА рд╢реЛрдзрдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

# podman pod ls
POD ID         NAME   STATUS    CREATED          # OF CONTAINERS   INFRA ID
71fc2b2a5c63   root   Running   11 minutes ago   3                 db40ab8bf84b

рдХреБрдмрд░реНрдиреЗрдЯреНрд╕:

# podman generate kube 71fc2b2a5c63
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.6.4
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-07-29T19:22:40Z"
  labels:
    app: root
  name: root
spec:
  containers:
  - command:
    - /assets/wrapper
    env:
    - name: PATH
      value: /opt/gitlab/embedded/bin:/opt/gitlab/bin:/assets:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
      value: gitlab.example.com
    - name: container
      value: podman
    - name: GITLAB_OMNIBUS_CONFIG
      value: |
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    - name: LANG
      value: C.UTF-8
    image: docker.io/gitlab/gitlab-ce:latest
    name: rootgitlab1
    ports:
    - containerPort: 22
      hostPort: 22222
      protocol: TCP
    - containerPort: 80
      hostPort: 80
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - mountPath: /var/opt/gitlab
      name: srv-podman-gitlab-data
    - mountPath: /var/log/gitlab
      name: srv-podman-gitlab-logs
    - mountPath: /etc/gitlab
      name: srv-podman-gitlab-conf
    workingDir: /
  - command:
    - run
    - --user=gitlab-runner
    - --working-directory=/home/gitlab-runner
    env:
    - name: PATH
      value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
    - name: container
      value: podman
    image: docker.io/gitlab/gitlab-runner:alpine
    name: rootgitlab-runner1
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - mountPath: /etc/gitlab-runner
      name: srv-podman-gitlab-runner
    - mountPath: /var/run/docker.sock
      name: var-run-docker.sock
    workingDir: /
  volumes:
  - hostPath:
      path: /srv/podman/gitlab/runner
      type: Directory
    name: srv-podman-gitlab-runner
  - hostPath:
      path: /var/run/docker.sock
      type: File
    name: var-run-docker.sock
  - hostPath:
      path: /srv/podman/gitlab/data
      type: Directory
    name: srv-podman-gitlab-data
  - hostPath:
      path: /srv/podman/gitlab/logs
      type: Directory
    name: srv-podman-gitlab-logs
  - hostPath:
      path: /srv/podman/gitlab/conf
      type: Directory
    name: srv-podman-gitlab-conf
status: {}

systemd:

# podman generate systemd 71fc2b2a5c63
# pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
Documentation=man:podman-generate-systemd(1)
Requires=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Before=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
ExecStop=/usr/bin/podman stop -t 10 db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa/userdata/conmon.pid

[Install]
WantedBy=multi-user.target
# container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
ExecStop=/usr/bin/podman stop -t 10 da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864/userdata/conmon.pid

[Install]
WantedBy=multi-user.target
# container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
ExecStop=/usr/bin/podman stop -t 10 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3/userdata/conmon.pid

[Install]
WantedBy=multi-user.target

рджреБрд░реНрджреИрд╡рд╛рдиреЗ, рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, systemd рд╕рд╛рдареА рд╡реНрдпреБрддреНрдкрдиреНрди рдХреЗрд▓реЗрд▓реЗ рдпреБрдирд┐рдЯ рджреБрд╕рд░реЗ рдХрд╛рд╣реАрд╣реА рдХрд░рдд рдирд╛рд╣реА (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдЕрд╢реА рд╕реЗрд╡рд╛ рд░реАрд╕реНрдЯрд╛рд░реНрдЯ рдЭрд╛рд▓реНрдпрд╛рд╡рд░ рдЬреБрдиреЗ рдХрдВрдЯреЗрдирд░ рд╕рд╛рдл рдХрд░рдгреЗ), рддреНрдпрд╛рдореБрд│реЗ рддреБрдореНрд╣рд╛рд▓рд╛ рдЕрд╢рд╛ рдЧреЛрд╖реНрдЯреА рд╕реНрд╡рдд: рдЬреЛрдбрд▓реНрдпрд╛ рдЬрд╛рддреАрд▓.

рддрддреНрд╡рддрдГ, рдкреЙрдбрдореЕрди рдХрдВрдЯреЗрдирд░ рдХрд╛рдп рдЖрд╣реЗрдд рдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдбреЙрдХрд░-рдХрдВрдкреЛрдЭрд╕рд╛рдареА рдЬреБрдиреА рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рдирдВрддрд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдЪреНрдпрд╛ рджрд┐рд╢реЗрдиреЗ, рдХреНрд▓рд╕реНрдЯрд░рд╡рд░ рдЬрд╛рдгреНрдпрд╛рд╕рд╛рдареА рдХрд┐рдВрд╡рд╛ рдбреЙрдХрд░рд╕рд╛рдареА рд╡рд╛рдкрд░рдгреНрдпрд╛рд╕-рд╕реЛрдкрд╛ рдкрд░реНрдпрд╛рдп рдорд┐рд│рд╡рдгреНрдпрд╛рд╕рд╛рдареА рдкреБрд░реЗрд╕реЗ рдЖрд╣реЗ.

рдЖрд░рдХреЗрдЯреА

рдкреНрд░рдХрд▓реНрдк рд╕рдВрдЧреНрд░рд╣рдгрд╛рдд рдЧреЗрд▓реЗ рд╕реБрдорд╛рд░реЗ рд╕рд╣рд╛ рдорд╣рд┐рдиреНрдпрд╛рдВрдкреВрд░реНрд╡реА рд░реЗрдбрд╣реЕрдЯрдиреЗ рддреЗ рд╡рд┐рдХрдд рдШреЗрддрд▓реНрдпрд╛рдореБрд│реЗ, рдореНрд╣рдгреВрди рдореА рддреНрдпрд╛рд╡рд░ рдЕрдзрд┐рдХ рддрдкрд╢реАрд▓рд╡рд╛рд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдгрд╛рд░ рдирд╛рд╣реА. рд╕рд░реНрд╡рд╕рд╛рдзрд╛рд░рдгрдкрдгреЗ, рдпрд╛рдиреЗ рдЦреВрдк рдЪрд╛рдВрдЧрд▓реА рдЫрд╛рдк рд╕реЛрдбрд▓реА, рдкрд░рдВрддреБ рдбреЙрдХрд░рдЪреНрдпрд╛ рддреБрд▓рдиреЗрдд, рдЖрдгрд┐ рддреНрдпрд╛рд╣реВрдирд╣реА рдЕрдзрд┐рдХ рдкреЙрдбрдореЕрдирдЪреНрдпрд╛ рддреБрд▓рдиреЗрдд, рддреЗ рдПрдХ рд╕рдВрдпреЛрдЬрдирд╛рд╕рд╛рд░рдЦреЗ рджрд┐рд╕рддреЗ. рдЖрд░рдХреЗрдЯреАрдЪреНрдпрд╛ рд╢реАрд░реНрд╖рд╕реНрдерд╛рдиреА рдХреЛрд░рдУрдПрд╕ рд╡рд┐рддрд░рдг рджреЗрдЦреАрд▓ рддрдпрд╛рд░ рдХреЗрд▓реЗ рдЧреЗрд▓реЗ рд╣реЛрддреЗ (рдЬрд░реА рддреНрдпрд╛рдВрдЪреНрдпрд╛рдХрдбреЗ рдореВрд│рддрдГ рдбреЙрдХрд░ рд╣реЛрддреЗ), рдкрд░рдВрддреБ рддреЗ рджреЗрдЦреАрд▓ рд░реЗрдбрд╣реЕрдЯрдЪреНрдпрд╛ рдЦрд░реЗрджреАрдирдВрддрд░ рд╕рдВрдкрд▓реЗ.

рдкрд▓рд╢

рдЕрдзрд┐рдХ рдПрдХ рдкреНрд░рдХрд▓реНрдк, рдЬреНрдпрд╛рдЪреЗ рд▓реЗрдЦрдХ рдлрдХреНрдд рдХрдВрдЯреЗрдирд░ рддрдпрд╛рд░ рдЖрдгрд┐ рдЪрд╛рд▓рд╡реВ рдЗрдЪреНрдЫрд┐рдд рд╣реЛрддреЗ. рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг рдЖрдгрд┐ рд╕рдВрд╣рд┐рддреЗрдЪрд╛ рдЖрдзрд╛рд░ рдШреЗрдд, рд▓реЗрдЦрдХрд╛рдиреЗ рдорд╛рдирдХрд╛рдВрдЪреЗ рдкрд╛рд▓рди рдХреЗрд▓реЗ рдирд╛рд╣реА, рдкрд░рдВрддреБ рдХреЗрд╡рд│ рд╕реНрд╡рддрдГрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддрд▓рд╛, рдЬреЗ рддрддреНрддреНрд╡рддрдГ рддреНрдпрд╛рдиреЗ рдХреЗрд▓реЗ.

рдирд┐рд╖реНрдХрд░реНрд╖

рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдЪреА рдкрд░рд┐рд╕реНрдерд┐рддреА рдЦреВрдк рдордиреЛрд░рдВрдЬрдХ рдЖрд╣реЗ: рдПрдХреАрдХрдбреЗ, рдбреЙрдХрд░рд╕рд╣, рдЖрдкрдг рдХреНрд▓рд╕реНрдЯрд░ (рд╕реНрд╡рд╛рд░реНрдо рдореЛрдбрдордзреНрдпреЗ) рдПрдХрддреНрд░ рдХрд░реВ рд╢рдХрддрд╛, рдЬреНрдпрд╛рджреНрд╡рд╛рд░реЗ рдЖрдкрдг рдХреНрд▓рд╛рдпрдВрдЯрд╕рд╛рдареА рдЙрддреНрдкрд╛рджрди рд╡рд╛рддрд╛рд╡рд░рдг рджреЗрдЦреАрд▓ рдЪрд╛рд▓рд╡реВ рд╢рдХрддрд╛, рд╣реЗ рд╡рд┐рд╢реЗрд╖рддрдГ рд▓рд╣рд╛рди рд╕рдВрдШрд╛рдВрд╕рд╛рдареА рд╕рддреНрдп рдЖрд╣реЗ (3-5 рд▓реЛрдХ ), рдХрд┐рдВрд╡рд╛ рдПрдХ рд▓рд╣рд╛рди рдПрдХреВрдг рднрд╛рд░ , рдХрд┐рдВрд╡рд╛ рдЙрдЪреНрдЪ рднрд╛рд░рд╛рдВрд╕рд╣ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рд╕реЗрдЯ рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рдЧреБрдВрддрд╛рдЧреБрдВрдд рд╕рдордЬреВрди рдШреЗрдгреНрдпрд╛рдЪреА рдЗрдЪреНрдЫрд╛ рдирд╕рдгреЗ.

рдкреЙрдбрдореЕрди рдкреВрд░реНрдг рд╕реБрд╕рдВрдЧрддрддрд╛ рдкреНрд░рджрд╛рди рдХрд░рдд рдирд╛рд╣реА, рдкрд░рдВрддреБ рддреНрдпрд╛рдЪрд╛ рдПрдХ рдорд╣рддреНрддреНрд╡рд╛рдЪрд╛ рдлрд╛рдпрджрд╛ рдЖрд╣реЗ - рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рд╛рдзрдирд╛рдВрд╕рд╣ (рдмрд┐рд▓реНрдбрд╛рд╣ рдЖрдгрд┐ рдЗрддрд░) рдХреБрдмрд░рдиреЗрдЯрд╕рд╣ рд╕реБрд╕рдВрдЧрддрддрд╛. рдореНрд╣рдгреВрди, рдореА рдЦрд╛рд▓реАрд▓рдкреНрд░рдорд╛рдгреЗ рдХрд╛рдорд╛рд╕рд╛рдареА рд╕рд╛рдзрдирд╛рдЪреНрдпрд╛ рдирд┐рд╡рдбреАрдХрдбреЗ рдЬрд╛рдИрди: рд▓рд╣рд╛рди рд╕рдВрдШрд╛рдВрд╕рд╛рдареА рдХрд┐рдВрд╡рд╛ рдорд░реНрдпрд╛рджрд┐рдд рдмрдЬреЗрдЯрд╕рд╣ - рдбреЙрдХрд░ (рд╕рдВрднрд╛рд╡реНрдп рдЭреБрдВрдб рдореЛрдбрд╕рд╣), рд╡реИрдпрдХреНрддрд┐рдХ рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯрд╡рд░ рд╕реНрд╡рддрдГрд╕рд╛рдареА рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА - рдкреЙрдбрдореЕрди рдХреЙрдорд░реЗрдбреНрд╕ рдЖрдгрд┐ рдЗрддрд░ рдкреНрд░рддреНрдпреЗрдХрд╛рд╕рд╛рдареА - рдХреБрдмрд░реНрдиреЗрдЯреНрд╕.

рдорд▓рд╛ рдЦрд╛рддреНрд░реА рдирд╛рд╣реА рдХреА рдбреЙрдХрд░рдЪреА рдкрд░рд┐рд╕реНрдерд┐рддреА рднрд╡рд┐рд╖реНрдпрд╛рдд рдмрджрд▓рдгрд╛рд░ рдирд╛рд╣реА, рд╢реЗрд╡рдЯреА, рддреЗ рдкрд╛рдпрдирд┐рдпрд░ рдЖрд╣реЗрдд рдЖрдгрд┐ рд╣рд│реВрд╣рд│реВ рдорд╛рдирдХреАрдХрд░рдг рджреЗрдЦреАрд▓ рдХрд░рдд рдЖрд╣реЗрдд, рдкрд░рдВрддреБ рдкреЙрдбрдореЕрди, рддреНрдпрд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡ рдХрдорддрд░рддрд╛рдВрд╕рд╣ (рдлрдХреНрдд рд▓рд┐рдирдХреНрд╕рд╡рд░ рдХрд╛рд░реНрдп рдХрд░рддреЗ, рдХреНрд▓рд╕реНрдЯрд░рд┐рдВрдЧ рдирд╛рд╣реА, рдЕрд╕реЗрдВрдмреНрд▓реА рдЖрдгрд┐ рдЗрддрд░ рдХреНрд░рд┐рдпрд╛ рддреГрддреАрдп-рдкрдХреНрд╖рд╛рдЪреЗ рдирд┐рд░реНрдгрдп рдЖрд╣реЗрдд) рднрд╡рд┐рд╖реНрдп рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рдЖрд╣реЗ, рдореНрд╣рдгреВрди рдореА рдкреНрд░рддреНрдпреЗрдХрд╛рд▓рд╛ рдЯрд┐рдкреНрдкрдгреНрдпрд╛рдВрдордзреНрдпреЗ рдпрд╛ рдирд┐рд╖реНрдХрд░реНрд╖рд╛рдВрд╡рд░ рдЪрд░реНрдЪрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдордВрддреНрд░рд┐рдд рдХрд░рддреЛ.

PS 3 рдСрдЧрд╕реНрдЯ рд░реЛрдЬреА рдЖрдореНрд╣реА рд▓реЙрдиреНрдЪ рдХрд░рдд рдЖрд╣реЛрдд "рдбреЙрдХрд░ рд╡реНрд╣рд┐рдбрд┐рдУ рдХреЛрд░реНрд╕рдЬрд┐рдереЗ рддреБрдореНрд╣реА рддреНрдпрд╛рдЪреНрдпрд╛ рдХрд╛рдорд╛рдмрджреНрджрд▓ рдЕрдзрд┐рдХ рдЬрд╛рдгреВрди рдШреЗрдК рд╢рдХрддрд╛. рдЖрдореНрд╣реА рддреНрдпрд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡ рд╕рд╛рдзрдирд╛рдВрдЪреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реВ: рдореВрд▓рднреВрдд рдЕрдореВрд░реНрддрддреЗрдкрд╛рд╕реВрди рдиреЗрдЯрд╡рд░реНрдХ рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕рдкрд░реНрдпрдВрдд, рд╡рд┐рд╡рд┐рдз рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдЖрдгрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдВрд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рдмрд╛рд░рдХрд╛рд╡реЗ. рддреБрдореНрд╣реА рддрдВрддреНрд░рдЬреНрдЮрд╛рдирд╛рд╢реА рдкрд░рд┐рдЪрд┐рдд рд╡реНрд╣рд╛рд▓ рдЖрдгрд┐ рдбреЙрдХрд░ рдХреБрдареЗ рдЖрдгрд┐ рдХрд╕реЗ рд╡рд╛рдкрд░рд╛рд╡реЗ рд╣реЗ рд╕рдордЬреЗрд▓. рдЖрдореНрд╣реА рд╕рд░реНрд╡реЛрддреНрддрдо рд╕рд░рд╛рд╡ рдкреНрд░рдХрд░рдгреЗ рджреЗрдЦреАрд▓ рд╕рд╛рдорд╛рдпрд┐рдХ рдХрд░реВ.

рд░рд┐рд▓реАрдЭ рд╣реЛрдгреНрдпрд╛рдкреВрд░реНрд╡реА рдкреНрд░реА-рдСрд░реНрдбрд░рдЪреА рдХрд┐рдВрдордд: 5000 рд░реВрдмрд▓. рдХрд╛рд░реНрдпрдХреНрд░рдо "рдбреЙрдХрд░ рд╡реНрд╣рд┐рдбрд┐рдУ рдХреЛрд░реНрд╕" рдЖрдврд│реВ рд╢рдХрддреЛ рдЕрднреНрдпрд╛рд╕рдХреНрд░рдо рдкреГрд╖реНрдард╛рд╡рд░.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛