{"id":363462,"date":"2024-05-21T01:56:26","date_gmt":"2024-05-21T01:56:26","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=363462"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T01:56:26","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=363462","title":{"rendered":"<span>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0438\u0433\u0440 MS-DOS \u0432 Kubernetes<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><a href=\"https:\/\/habr.com\/ru\/companies\/ruvds\/articles\/781902\/\"><\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/sd\/se\/vk\/sdsevkb_5_uq0f7lizck_qtyhye.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/sd\/se\/vk\/sdsevkb_5_uq0f7lizck_qtyhye.jpeg\" data-blurred=\"true\"\/><\/div>\n<p><\/a><br \/>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/caiiiycuk\/js-dos\">JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 js-dos<\/a> \u0432 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 Kubernetes, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0438\u0433\u0440\u0430\u043c MS-DOS \u0432 \u0432\u0438\u0434\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 Kubernetes \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0445 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u043e \u0445\u043e\u0434\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u0434\u0430\u043c \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e, \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0433\u043e \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 Kubernetes \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/go.dev\/\">Golang<\/a> \u0438 <a href=\"https:\/\/github.com\/kubernetes-sigs\/kubebuilder\">Kubebuilder<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/sdk.operatorframework.io\/\">Operator SDK<\/a>.<a name=\"habracut\"><\/a><\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/font><\/h2>\n<p>  <strong><font color=\"#3AC1EF\">js-dos<\/font><\/strong> \u2014 \u044d\u0442\u043e JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u043f\u043e\u043b\u043d\u043e\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 DOS-\u043f\u043b\u0435\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c MS-DOS \u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0445 \u0432 \u0432\u0435\u0431-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435; \u043f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u043f\u043e\u0440\u0442 \u0437\u043d\u0430\u043c\u0435\u043d\u0438\u0442\u043e\u0433\u043e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 <a href=\"https:\/\/www.dosbox.com\/\">DOSBOX<\/a> \u043d\u0430 JavaScript. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 js-dos \u043f\u0440\u043e\u0441\u0442\u0430, \u043d\u043e \u043e\u0447\u0435\u043d\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0430, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432: \u0432 iframe, \u0432 nodeJS, \u0432 React \u0438\u043b\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430 \u00ab\u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0439\u00bb HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c\u043e\u0439 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u0412 \u043d\u0430\u0448\u0435\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c.<\/p>\n<p>  <strong><font color=\"#3AC1EF\">js-dos<\/font><\/strong> \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u043e\u0432 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <strong><font color=\"#3AC1EF\">bundle<\/font><\/strong>. Bundle \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e zip-\u0444\u0430\u0439\u043b\u044b, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u043a\u0443\u0447\u0443 \u0444\u0430\u0439\u043b\u043e\u0432, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0438 \u0441\u0430\u043c\u043e\u0439 \u0438\u0433\u0440\u044b; \u0432\u0441\u0451 \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043e \u0432 \u0444\u0430\u0439\u043b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c <code>.jsdos<\/code>. \u0414\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0433\u0440\u044b \u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u043d\u0435\u043c\u0443 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 (\u0441 \u043e\u0447\u0435\u043d\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 js-dos, \u0435\u0451 \u0444\u0430\u0439\u043b CSS, \u0444\u0430\u0439\u043b \u0438\u0433\u0440\u044b \u0434\u043b\u044f js-dos, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0434\u043b\u044f \u0438\u0433\u0440\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e DOSBOX \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u0430\u043c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 DOSBOX \u0432 \u0432\u0438\u0434\u0435 WASM.<\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/font><\/h2>\n<p>  <\/p>\n<blockquote><p><strong><font color=\"#3AC1EF\">\u0412\u0430\u0436\u043d\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/font><\/strong>: \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u043c \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e\u043c \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 Kubernetes \u0438\u043b\u0438 \u043f\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043d\u0430 Golang. \u041e\u043d\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 Go \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 Kubernetes; \u043f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 Kubebuilder \u0438\u043b\u0438 Operator SDK.<\/p><\/blockquote>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c: <em>\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u0435\u0434\u0438\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0431\u0430\u043d\u0434\u043b (bundle) \u0438\u0433\u0440\u044b \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 Kubernetes \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0432\u0441\u0435\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/em><\/p>\n<p>  \u0421\u0430\u043c\u043e\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/api-extension\/custom-resources\/#:~:text=A%20custom%20resource%20is%20an,resources%2C%20making%20Kubernetes%20more%20modular.\">Custom Resource<\/a> (CR) \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u044f\u0442 \u044d\u0442\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b Kubernetes, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u043e\u0432\u0451\u043c \u044d\u0442\u043e\u0442 CR <code>Game<\/code>; \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432 \u0441\u0430\u043c\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0444\u043e\u0440\u043c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"cpp\">type GameSpec struct {   \/\/ +kubebuilder:validation:Required  \/\/ +kubebuilder:validation:Type=string  GameName string `json:\"gameName\"`   \/\/ +kubebuilder:validation:Required  \/\/ +kubebuilder:validation:Pattern:=`^https?:\\\/\\\/(?:www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&amp;\\\/=]*)$`  Url string `json:\"url\"`   \/\/ +kubebuilder:default:=false  \/\/ +kubebuilder:validation:Required  \/\/ +kubebuilder:validation:Type=boolean  Deploy bool `json:\"deploy\"`   \/\/ +optional  \/\/ +kubebuilder:default=80  \/\/ +kubebuilder:validation:Type=integer  \/\/ +kubebuilder:validation:Minimum=1  \/\/ +kubebuilder:validation:Maximum=65535  \/\/ +kubebuilder:validation:ExclusiveMinimum=false  \/\/ +kubebuilder:validation:ExclusiveMaximum=false  Port int `json:\"port,omitempty\"` }<\/code><\/pre>\n<p>  <code>Game<\/code> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0451\u0445 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f: <code>GameName<\/code> \u2014 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u044d\u0442\u043e \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438\u0433\u0440\u044b, <code>Url<\/code> \u2014 \u044d\u0442\u043e \u0430\u0434\u0440\u0435\u0441, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0430\u043d\u0434\u043b \u0438\u0433\u0440\u044b, <code>Deploy<\/code> \u2014 \u044d\u0442\u043e \u0431\u0443\u043b\u0435\u0432 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0438\u0433\u0440\u044b; \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 <code>Port<\/code> \u2014 \u044d\u0442\u043e \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 Kubernetes.<\/p>\n<blockquote><p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u043a\u0435\u0440\u044b (\u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438) <code>\/\/ +kubebuilder:validation<\/code> \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0438\u043b\u0438 \u0442\u0438\u043f\u043e\u0432, \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u043b\u0438 \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 regex \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e API. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/book.kubebuilder.io\/reference\/markers\/crd-validation\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u0422\u0430\u043a\u0438\u0435 \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438; \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438, \u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f \u043e \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 <a href=\"https:\/\/book.kubebuilder.io\/reference\/admission-webhook.html?highlight=admission#admission-webhooks\">Admissions Webhooks<\/a>.<\/p><\/blockquote>\n<p>  \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044e. \u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0445\u0440\u0430\u043d\u044f\u0449\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0438\u0433\u0440\u0435. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u0430 \u0438\u0433\u0440\u0430 \u0431\u044b\u043b\u0430 \u0438\u0433\u0440\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0435\u0449\u0451 \u043f\u0430\u0440\u0443 \u0432\u0435\u0449\u0435\u0439. \u041d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c <strong><font color=\"#3AC1EF\">\u0430)<\/font><\/strong> \u0431\u0430\u043d\u0434\u043b <strong><font color=\"#3AC1EF\">\u0431)<\/font><\/strong> \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <strong><font color=\"#3AC1EF\">\u0432)<\/font><\/strong> \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 DOSBOX \u0438 \u0432\u0441\u0451, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0451\u043c \u0441\u043d\u0438\u0437\u0443. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c; \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 <strong><font color=\"#3AC1EF\">nginx<\/font><\/strong>, \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0441\u0442\u0443\u044e HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u044e\u0449\u0438\u0439 \u0435\u0451 \u0432 \u043f\u043e\u0440\u0442 80. \u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0441\u043e\u0437\u0434\u0430\u0432 <strong><font color=\"#3AC1EF\">Pod<\/font><\/strong> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u044d\u0442\u043e\u043c Pod \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 <strong><font color=\"#3AC1EF\">nginx<\/font><\/strong>, \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0449\u0438\u0439 \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<p>  <em>\u041d\u043e \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u0443 HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 (\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u0443\u044e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0433\u0440\u044b) Kubernetes \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0443 nginx \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0435\u0451?<\/em> \u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u043e\u0441\u0442: \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <strong><font color=\"#3AC1EF\">ConfigMap<\/font><\/strong>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043f\u043e\u0437\u0436\u0435 \u0441\u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 nginx \u043a\u0430\u043a <strong><font color=\"#3AC1EF\">Volume<\/font><\/strong>:<\/p>\n<pre><code class=\"nginx\">apiVersion: v1 kind: ConfigMap metadata:   name: {{.Name}}-index-configmap   namespace: {{.Namespace}} data:   index.html: |     &lt;!doctype html>     &lt;html>     &lt;head>         &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"\/>         &lt;style>             html, body, #jsdos {                 width: 100%;                 height: 100%;                 margin: 0;                 padding: 0;             }         &lt;\/style>         &lt;script src=\"js-dos.js\">&lt;\/script>         &lt;link href=\"js-dos.css\" rel=\"stylesheet\">     &lt;\/head>     &lt;body>     &lt;div id=\"jsdos\"\/>     &lt;script>         emulators.pathPrefix = \"\/\";         Dos(document.getElementById(\"jsdos\"))             .run(\"{{.Bundle}}\");     &lt;\/script>     &lt;\/body>     &lt;\/html><\/code><\/pre>\n<p>  \u0412 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <code>data<\/code> ConfigMap \u043c\u044b \u0443\u043a\u0430\u0436\u0435\u043c \u043a\u043b\u044e\u0447 <code>index.html<\/code>, \u0430 \u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043d\u043e <strong><font color=\"#3AC1EF\">template<\/font><\/strong>-\u0432\u0435\u0440\u0441\u0438\u0438 HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0435\u0439 \u0437\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0433\u0440\u044b.<\/p>\n<blockquote><p>\u041d\u0438\u0436\u0435 \u044f \u043e\u0431\u044a\u044f\u0441\u043d\u044e, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e\u0442 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u0438\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p><\/blockquote>\n<p>  \u041d\u043e \u0437\u0434\u0435\u0441\u044c \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430! \u041a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0432\u044b\u0448\u0435, <em>HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0433\u0440\u044b<\/em> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong><font color=\"#3AC1EF\">js-dos.js<\/font><\/strong>, <strong><font color=\"#3AC1EF\">jsdos.css<\/font><\/strong> \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 url \u0431\u0430\u043d\u0434\u043b\u0430 <strong><font color=\"#3AC1EF\">{{.Bundle}}<\/font><\/strong>).<\/p>\n<p>  <em>\u0413\u0434\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b?<\/em> \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0438\u0445 \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 Volume, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0443 nginx \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e-\u0442\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443. \u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u044d\u0442\u043e\u0433\u043e, \u043c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0432 \u043d\u0430\u0448\u0435\u043c Pod <strong><font color=\"#3AC1EF\">\u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440<\/font><\/strong>, \u043d\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e: \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<blockquote><p>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 (Init Container) \u2014 \u044d\u0442\u043e \u043e\u0441\u043e\u0431\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0435 <strong><font color=\"#3AC1EF\">\u0434\u043e<\/font><\/strong> \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432 Pod. \u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435, \u0438 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u043c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/p><\/blockquote>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0431\u0440\u0430\u0437\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"https:\/\/busybox.net\/\">busybox<\/a>, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432 \u0435\u0433\u043e \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b <code>wget<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043a\u0430\u0447\u0430\u0435\u0442 \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u0445 \u0432 \u0442\u0443 \u0436\u0435 \u043f\u0430\u043f\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0430 HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430. \u041f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 volume, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 nginx.<\/p>\n<pre><code class=\"nginx\">wget -P \"\/mnt\/game\" --no-check-certificate \\  {{.BundleUrl}} \\ https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/js-dos.css \\ https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/js-dos.js \\ https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/wdosbox.js \\ https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/wdosbox.wasm<\/code><\/pre>\n<p>  \u041d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u0432\u043f\u043e\u043b\u043d\u0435 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c: <em>\u043f\u043e\u0441\u0442\u043e\u0439\u0442\u0435-\u043a\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0451\u0442 Volume, \u043a\u0442\u043e \u0438 \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c?<\/em> \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 HTML-\u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 nginx \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u043e\u0441\u0442: <strong><font color=\"#3AC1EF\">ConfigMap<\/font><\/strong> \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a volume \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u043d\u043e \u0434\u043b\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u0441\u043a\u0430\u0447\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c nginx \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/\"><strong><font color=\"#3AC1EF\">PersistentVolumeClaim<\/font><\/strong><\/a> (PVC):<\/p>\n<pre><code class=\"nginx\">apiVersion: v1 kind: PersistentVolumeClaim metadata:   name: {{.Name}}-pvc   namespace: {{.Namespace}} spec:   accessModes:     - ReadWriteOnce   resources:     requests:       storage: {{.Storage}}Mi<\/code><\/pre>\n<p>  <em>PersistentVolumeClaim<\/em> (PVC) \u2014 \u044d\u0442\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041e\u043d \u0441\u0445\u043e\u0436 \u0441 Pod. Pod \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0443\u0437\u043b\u043e\u0432, \u0430 PVC \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b Persistent Volume (PV). Pod \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0443\u0440\u043e\u0432\u043d\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (CPU \u0438\u043b\u0438 \u043f\u0430\u043c\u044f\u0442\u044c). Claim \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0438 \u0440\u0435\u0436\u0438\u043c\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a ReadWriteOnce, ReadOnlyMany \u0438\u043b\u0438 ReadWriteMany).<\/p>\n<p>  PVC \u2014 \u044d\u0442\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430; \u043a\u043e\u0433\u0434\u0430 Pod \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a PVC (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438) \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 PersistentVolume, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0451\u043d \u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b.<\/p>\n<p>  \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c: <em>\u0432\u0441\u0451 \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u044b\u043c, \u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u043d\u0430\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a?<\/em> \u0414\u0430, \u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <strong><font color=\"#3AC1EF\">Deployment<\/font><\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u0430\u0434\u0435\u0442\u044c \u0432\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0438:<\/p>\n<pre><code class=\"nginx\">apiVersion: apps\/v1 kind: Deployment metadata:   name: {{.Name}}   namespace: {{.Namespace}}   labels:     app: {{.Name}} spec:   replicas: 1   selector:     matchLabels:       app: {{.Name}}   template:     metadata:       name: {{.Name}}       labels:         app: {{.Name}}     spec:       volumes:         - name: {{.Name}}-storage           persistentVolumeClaim:             claimName: {{.Name}}-pvc         - name: {{.Name}}-index           configMap:             name: {{.Name}}-index-configmap       containers:         - name: {{.Name}}-engine           image: nginx           imagePullPolicy: IfNotPresent           ports:             - containerPort: 80           volumeMounts:             - mountPath: \/usr\/share\/nginx\/html               name: {{.Name}}-storage             - mountPath: \/usr\/share\/nginx\/html\/index.html               subPath: index.html               name: {{.Name}}-index       initContainers:         - name: {{.Name}}-init           image: busybox:1.28           imagePullPolicy: IfNotPresent           command: [ \"sh\" ]           args:             - -c             - >-                 wget -P \"\/mnt\/game\" --no-check-certificate {{.BundleUrl}} https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/js-dos.css https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/js-dos.js https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/wdosbox.js https:\/\/js-dos.com\/v7\/build\/releases\/latest\/js-dos\/wdosbox.wasm;           volumeMounts:             - mountPath: \/mnt\/game               name: {{.Name}}-storage       restartPolicy: Always<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/cr\/4w\/lk\/cr4wlkxub5ifpyfptpmayktocvm.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/cr\/4w\/lk\/cr4wlkxub5ifpyfptpmayktocvm.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  \u0417\u0430\u0433\u043b\u044f\u043d\u0443\u0432 \u0432 <code>spec.volumes<\/code>, \u043c\u043e\u0436\u043d\u043e \u0447\u0451\u0442\u043a\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u0432\u0430 volume, \u043e\u0434\u0438\u043d \u0438\u0437 ConfigMap, \u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u0437 PVC. \u0421\u0434\u0435\u043b\u0430\u043d\u043d\u044b\u0439 \u0438\u0437 PVC \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 (\u0441\u043c. <code>volumeMounts<\/code> \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <code>containers<\/code> \u0438 <code>initContainers<\/code>). \u0412 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 nginx \u0435\u0441\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u044c, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0441\u0451 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442: <em>\u043e\u0431\u0430<\/em> volume \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 nginx, \u043e\u0442\u043a\u0443\u0434\u0430 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0431\u0440\u0430\u0442\u044c HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <code>index.html<\/code>.<\/p>\n<pre><code class=\"nginx\">volumeMounts:             - mountPath: \/usr\/share\/nginx\/html               name: {{.Name}}-storage             - mountPath: \/usr\/share\/nginx\/html\/index.html               subPath: index.html               name: {{.Name}}-index<\/code><\/pre>\n<p>  \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0443 nginx \u0432\u043d\u0435 \u0433\u0440\u0430\u043d\u0438\u0446 Kubernetes, \u0442\u0430\u043a \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u0441\u044b\u0433\u0440\u0430\u0442\u044c \u0432 \u0438\u0433\u0440\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043c <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/\"><strong><font color=\"#3AC1EF\">Service<\/font><\/strong><\/a>:<\/p>\n<pre><code class=\"nginx\">apiVersion: v1 kind: Service metadata:   name: {{.Name}}   namespace: {{.Namespace}} spec:   selector:     app: {{.Name}}   ports:     - protocol: TCP       port: {{.Port}}       targetPort: 80   type: ClusterIP<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430<\/font><\/h2>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0433\u043e \u00ab\u0448\u0443\u043c\u0430\u00bb, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c <strong><font color=\"#3AC1EF\">\u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e<\/font><\/strong> <code>Game<\/code> \u2014 \u0441\u0435\u0439\u0447\u0430\u0441 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 js-dos <a href=\"https:\/\/dos.zone\/\">dos.zone<\/a> \u0435\u0441\u0442\u044c \u043f\u043e\u0447\u0442\u0438 <strong><font color=\"#3AC1EF\">2000 \u0438\u0433\u0440<\/font><\/strong>.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 (reconciliation), \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0433\u0440\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0445 <em>Event Filters<\/em>, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043d\u0430 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f\/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\/\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u0449\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u0435\u0434\u0438\u043a\u0430\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a watch-\u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u0443\u0435\u0442, \u0434\u043e\u043b\u0436\u0435\u043d \u043b\u0438 \u043e\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"go\">var (  gameEventFilters = builder.WithPredicates(predicate.Funcs{   UpdateFunc: func(e event.UpdateEvent) bool {    return e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration()   },   DeleteFunc: func(e event.DeleteEvent) bool {    return !e.DeleteStateUnknown   },   CreateFunc: func(e event.CreateEvent) bool {    switch object := e.Object.(type) {    case *operatorv1alpha1.Game:     return object.Spec.Deploy    default:     return false    }   },  }) )  func (r *GameReconciler) SetupWithManager(mgr ctrl.Manager) error {  return ctrl.NewControllerManagedBy(mgr).   For(&amp;operatorv1alpha1.Game{}, gameEventFilters).  Complete(r) }<\/code><\/pre>\n<p>  \u041c\u044b \u0438\u043c\u0435\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0447\u0435\u0440\u0435\u0437 \u0447\u0435\u0442\u044b\u0440\u0435 \u043f\u0440\u0435\u0434\u0438\u043a\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438: <code>GenericFunc<\/code> (\u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f), <code>CreateFunc<\/code>, <code>UpdateFunc<\/code> \u0438 <code>DeleteFunc<\/code>. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f <em>Update<\/em> \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 <code>specs<\/code> <code>Game<\/code>, \u0430 \u043d\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 <code>status<\/code> \u043f\u0440\u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u043d\u0430 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 <code>ObjectOld<\/code> \u0438 <code>ObjectNew<\/code>:<\/p>\n<pre><code class=\"go\">UpdateFunc: func(e event.UpdateEvent) bool {    return e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration()   }<\/code><\/pre>\n<p>  \u041c\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u0433\u043b\u0443\u0448\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f <em>Delete<\/em>. \u041f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f <code>Game<\/code> \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435. <code>DeleteStateUnknown<\/code> \u0440\u0430\u0432\u043d\u043e <code>false<\/code>, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d API-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439:<\/p>\n<pre><code class=\"go\">DeleteFunc: func(e event.DeleteEvent) bool {    return !e.DeleteStateUnknown   }<\/code><\/pre>\n<p>  \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <em>Create<\/em> \u043c\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0432\u044b\u0437\u0432\u0430\u0432\u0448\u0438\u0439 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 CR \u2014 \u044d\u0442\u043e <code>Game<\/code> \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0435\u0433\u043e \u043f\u043e\u043b\u044f <code>Spec.deploy<\/code> \u0440\u0430\u0432\u043d\u043e <code>true<\/code>.<\/p>\n<pre><code class=\"go\">CreateFunc: func(e event.CreateEvent) bool {    switch object := e.Object.(type) {    case *operatorv1alpha1.Game:     return object.Spec.Deploy    default:     return false    }   }<\/code><\/pre>\n<p>  \u041d\u0430 \u0442\u043e \u0435\u0441\u0442\u044c \u0434\u0432\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b: \u0430) <code>Game<\/code> <strong><font color=\"#3AC1EF\">\u0432\u043b\u0430\u0434\u0435\u0435\u0442<\/font><\/strong> \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444\u0435 (<code>Deployment<\/code>; \u0430 Deployment, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0432\u043b\u0430\u0434\u0435\u0435\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 <code>Pod<\/code>, <code>ConfigMap<\/code>, <code>PVC<\/code>, <code>PV<\/code> \u0438 <code>Service<\/code>. \u0415\u0441\u043b\u0438 \u043c\u044b \u0443\u0434\u0430\u043b\u0438\u043c <code>Game<\/code>, \u0442\u043e \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u044d\u0442\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0443\u0434\u0430\u043b\u044f\u043b\u0438\u0441\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438). \u0415\u0441\u043b\u0438 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0437\u0430 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0442\u0430\u043a\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u0442\u043e \u0443 \u043d\u0430\u0441 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u0431) \u043a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0440\u0430\u043d\u0435\u0435, \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e <code>Game<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430\u0445. \u0415\u0441\u043b\u0438 \u043e\u043d\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0432\u044b\u0437\u043e\u0432\u0443\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u043c\u044b \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u043d\u0435\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 Game, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 <code>Spec.Deploy<\/code> \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 true, \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f <em>Create<\/em>.<\/p>\n<p>  \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0446\u0438\u043a\u043b\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"go\">func (r *GameReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {  logger = log.FromContext(ctx).WithName(\"controller\")   game := &amp;operatorv1alpha1.Game{}  if err := r.Get(ctx, req.NamespacedName, game); err != nil {   if apierrors.IsNotFound(err) {    return ctrl.Result{}, nil   }    logger.V(5).Error(err, \"unable to fetch game\")   return ctrl.Result{}, err  }   if !game.Spec.Deploy {   err := r.DeleteDeployment(ctx, req, game)   if err != nil {    return ctrl.Result{}, err   }    _ = r.SetStatus(ctx, req, game, false)   return ctrl.Result{}, nil  }   deployment, err := r.CreateOrUpdateDeployment(ctx, req, game)  if err != nil {   return ctrl.Result{}, err  }   _, err = r.CreateOrUpdateConfigMap(ctx, req, game, deployment)  if err != nil {   return ctrl.Result{}, err  }   _, err = r.CreateOrUpdatePersistentVolumeClaim(ctx, req, game, deployment)  if err != nil {   return ctrl.Result{}, err  }   _, err = r.CreateOrUpdateService(ctx, req, game, deployment)  if err != nil {   return ctrl.Result{}, err  }   return r.RefreshStatus(ctx, req, game, deployment.Labels[\"app\"]) }<\/code><\/pre>\n<p>  \u0417\u0430\u0434\u0430\u0447\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>Reconcile<\/code> \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u043c <code>Game<\/code>. \u0415\u0441\u043b\u0438 <code>Spec.Deploy<\/code> \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>false<\/code>, \u0442\u043e \u0432\u0441\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0438\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u044b (\u0435\u0441\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0431\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b), \u0430 \u0437\u0430\u0442\u0435\u043c <code>Spec.Deploy<\/code> \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>true<\/code>, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0431\u044b\u043b\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<p>  \u041a\u0430\u0436\u0434\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>CreateOrUpdateXXX<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0434\u0432\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<p>  <b><font color=\"#3AC1EF\">\u0430)<\/font><\/b> \u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430:<\/p>\n<p>  \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b Kubernetes \u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u0434\u043d\u043e\u0433\u043e Golang, \u0431\u0435\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u0432, \u043d\u043e \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044c; \u043a \u0442\u043e\u043c\u0443 \u0436\u0435 \u0432 \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435 \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>  \u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u0432 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0432 \u0438\u0434\u0438\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0434\u043b\u044f Golang \u0441\u0442\u0438\u043b\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 <code>text\/template<\/code>. \u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b \u0432\u0441\u0435 \u044d\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u044b YAML \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430\u0437\u0432\u0430\u043b <code>manifests<\/code>. \u042f \u0441\u043e\u0437\u0434\u0430\u043b \u043f\u0430\u043a\u0435\u0442 <code>assets<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u043f\u0430\u043a\u0435\u0442 <code>embed<\/code> \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u0432.<\/p>\n<pre><code class=\"go\">\/\/go:embed manifests\/*  manifests embed.FS<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/sh\/-x\/zj\/sh-xzj9tbmppci8lp9dorxj-j7c.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/sh\/-x\/zj\/sh-xzj9tbmppci8lp9dorxj-j7c.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>getTemplate<\/code> \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>manifests.ReadFile<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0437 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u043d\u0443\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0448\u0430\u0431\u043b\u043e\u043d:<\/p>\n<pre><code class=\"go\">func getTemplate(name string) (*template.Template, error) {  manifestBytes, err := manifests.ReadFile(fmt.Sprintf(\"manifests\/%s.yaml\", name))  if err != nil {   return nil, err  }   tmp := template.New(name)  parse, err := tmp.Parse(string(manifestBytes))  if err != nil {   return nil, err  }   return parse, nil }<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0443\u044e <code>struct<\/code> <code>metadata<\/code> \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f PVC):<\/p>\n<pre><code class=\"go\">metadata := struct {   Namespace string   Name      string   Storage   uint64  }{   Namespace: namespace,   Name:      name,   Storage:   storage,  }<\/code><\/pre>\n<p>  \u0412\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>getObject<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0439 <code>struct<\/code>, \u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u0443 Golang, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0437\u043d\u0430\u0435\u0442 API-\u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<pre><code class=\"go\">func getObject(name string, gv schema.GroupVersion, metadata any) (runtime.Object, error) {  parse, err := getTemplate(name)  if err != nil {   return nil, err  }   var buffer bytes.Buffer  err = parse.Execute(&amp;buffer, metadata)  if err != nil {   return nil, err  }   object, err := runtime.Decode(   appsCodecs.UniversalDecoder(gv),   buffer.Bytes(),  )   return object, nil }<\/code><\/pre>\n<p>  <b><font color=\"#3AC1EF\">\u0431)<\/font><\/b> \u0420\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0440\u0435\u0441\u0443\u0440\u0441:<\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u043a\u0430\u0436\u0434\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>CreateOrUpdateXXX<\/code> \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441 \u0432 Kubernetes (\u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>SetControllerReference<\/code>):<\/p>\n<pre><code class=\"go\">deployment, err = assets.GetDeployment(game.Namespace, game.Name, game.Spec.Port, game.Spec.Url)   if err != nil {    logger.Error(err, \"unable to parse deployment template\")    return nil, err   }    err = ctrl.SetControllerReference(game, deployment, r.Scheme)   if err != nil {    logger.Error(err, \"unable to set controller reference\")    return nil, err   }    err = r.Create(ctx, deployment)   if err != nil {    logger.Error(err, \"unable to create deployment\")    return nil, err   }<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/qx\/ti\/5q\/qxti5qil6zljlfy4byakp6ndxf8.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/qx\/ti\/5q\/qxti5qil6zljlfy4byakp6ndxf8.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  \u041e\u0436\u0438\u0434\u0430\u044f \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0435\u0433\u043e \u0441\u0442\u0430\u0442\u0443\u0441 (\u043a\u0430\u0436\u0434\u044b\u0435 15 \u0441\u0435\u043a\u0443\u043d\u0434). \u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u0442\u0443\u0441 Pod \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f ready, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u044b\u0445\u043e\u0434 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0436\u0438\u0434\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f (Create, Update \u0438\u043b\u0438 Delete), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.<\/p>\n<pre><code class=\"go\">func (r *GameReconciler) RefreshStatus(  ctx context.Context,  req ctrl.Request,  game *operatorv1alpha1.Game,  appLabel string, ) (ctrl.Result, error) {  ready, err := r.GetStatus(ctx, req, appLabel)  if err != nil {   logger.V(5).Error(err, \"unable to fetch pod status\")    _ = r.SetStatus(ctx, req, game, false)    return ctrl.Result{    Requeue:      true,    RequeueAfter: 15 * time.Second,   }, err  }   if !ready {   logger.Info(\"pod not ready, requeue in 15sec\")    _ = r.SetStatus(ctx, req, game, ready)    return ctrl.Result{    Requeue:      true,    RequeueAfter: 15 * time.Second,   }, nil  }   err = r.SetStatus(ctx, req, game, ready)  if err != nil {   return ctrl.Result{    Requeue:      true,    RequeueAfter: 15 * time.Second,   }, nil  }   return ctrl.Result{}, nil }<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/sv\/q-\/bo\/svq-boeguaa6ledlgsu1z9weave.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/sv\/q-\/bo\/svq-boeguaa6ledlgsu1z9weave.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 Deployment \u0438 Pod \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0438\u0445 \u0432 PV.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0451\u043c \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442 \u0432 \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Prince_of_Persia\">Prince of Persia<\/a>:<\/p>\n<pre><code class=\"nginx\">apiVersion: operator.contrib.dosbox.com\/v1alpha1 kind: Game metadata:   name: prince-of-persia spec:   gameName: \"Prince of Persia\"   url: \"https:\/\/cdn.dos.zone\/original\/2X\/1\/1179a7c9e05b1679333ed6db08e7884f6e86c155.jsdos\"   deploy: true<\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u043f\u043e\u0440\u0442\u0430 Service \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 (\u044f \u0432\u044b\u0431\u0440\u0430\u043b \u043f\u043e\u0440\u0442 8080; \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u043d\u0435 \u0432\u0430\u0436\u043d\u043e, \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 \u043f\u043e\u0440\u0442 \u0432\u044b \u0440\u0435\u0448\u0438\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044e):<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/ww\/td\/fy\/wwtdfyfhsng2ejx3gye2skcvwom.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/ww\/td\/fy\/wwtdfyfhsng2ejx3gye2skcvwom.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u0420\u0430\u0431\u043e\u0442\u0430 \u043d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435<\/font><\/h2>\n<p>  \u042d\u0442\u043e\u0442 \u043c\u0438\u043d\u0438-\u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u0430\u043b\u0451\u043a \u043e\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f. \u0412 \u043d\u0451\u043c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u0430\u0436\u0435 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 \u0432 PV, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043c\u0435\u0442\u0440\u0438\u043a \u0432 Prometheus, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 Kubernetes, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 Conditions \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0434\u043b\u044f CR, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043b\u0438\u043c\u0438\u0442\u043e\u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0435\u0433\u043e \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u044f \u043e\u0442 \u044d\u0442\u0438\u0445 \u0440\u0435\u0442\u0440\u043e\u0438\u0433\u0440; \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0444\u043e\u0440\u043a\u043d\u0443\u0442\u044c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438: <a href=\"https:\/\/github.com\/akyriako\/kube-dosbox\">GitHub \u2014 akyriako\/kube-dosbox<\/a>.<\/p>\n<blockquote><p><b><font color=\"#3AC1EF\"><a href=\"https:\/\/t.me\/ruvds_community\">\u0421\u043a\u0438\u0434\u043a\u0438, \u0438\u0442\u043e\u0433\u0438 \u0440\u043e\u0437\u044b\u0433\u0440\u044b\u0448\u0435\u0439 \u0438 \u043d\u043e\u0432\u043e\u0441\u0442\u0438 \u043e \u0441\u043f\u0443\u0442\u043d\u0438\u043a\u0435 RUVDS \u2014 \u0432 \u043d\u0430\u0448\u0435\u043c Telegram-\u043a\u0430\u043d\u0430\u043b\u0435 ?<\/a><\/font><\/b><\/p><\/blockquote>\n<p><a href=\"http:\/\/ruvds.com\/ru-rub?utm_source=habr&amp;utm_medium=article&amp;utm_campaign=perevod&amp;utm_content=sozdanie_emulyatora_igr_msdos_v_kubernetes\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/4g\/dr\/oa\/4gdroaajo7o0zzvwwx5__rlzhwi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/4g\/dr\/oa\/4gdroaajo7o0zzvwwx5__rlzhwi.png\"\/><\/a><\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/781902\/\"> https:\/\/habr.com\/ru\/articles\/781902\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><a href=\"https:\/\/habr.com\/ru\/companies\/ruvds\/articles\/781902\/\"><\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/sd\/se\/vk\/sdsevkb_5_uq0f7lizck_qtyhye.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/sd\/se\/vk\/sdsevkb_5_uq0f7lizck_qtyhye.jpeg\" data-blurred=\"true\"\/><\/div>\n<p><\/a><br \/>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/caiiiycuk\/js-dos\">JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 js-dos<\/a> \u0432 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 Kubernetes, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0438\u0433\u0440\u0430\u043c MS-DOS \u0432 \u0432\u0438\u0434\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 Kubernetes \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0445 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u043e \u0445\u043e\u0434\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u0434\u0430\u043c \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e, \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0433\u043e \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 Kubernetes \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/go.dev\/\">Golang<\/a> \u0438 <a href=\"https:\/\/github.com\/kubernetes-sigs\/kubebuilder\">Kubebuilder<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/sdk.operatorframework.io\/\">Operator SDK<\/a>.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-363462","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/363462","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=363462"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/363462\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=363462"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=363462"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=363462"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}