{"id":490598,"date":"2026-08-11T16:30:55","date_gmt":"2026-08-11T16:30:55","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=490598"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2026-08-11T16:30:55","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=490598","title":{"rendered":"MLOps \u0434\u043b\u044f DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430: \u043a\u0430\u043a \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u042d\u0442\u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u043e\u0442 \u0433\u043e\u043b\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0438 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043d\u0451\u043c \u0442\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443.<\/p>\n<h3>\u0417\u0430\u0447\u0435\u043c DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443 MLOps?<\/h3>\n<p>\u041f\u043e \u0434\u0430\u043d\u043d\u044b\u043c \u043e\u0442\u0440\u0430\u0441\u043b\u0435\u0432\u044b\u0445 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439, \u0434\u043e 80% ML-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0442\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u00ab\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u00bb. \u041c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u0443\u0447\u0430\u044e\u0442 \u0432 Jupyter-\u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430\u0445, \u043d\u043e \u0434\u043e \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430 \u043e\u043d\u0438 \u0434\u043e\u0445\u043e\u0434\u044f\u0442 \u0440\u0435\u0434\u043a\u043e \u2014 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435\u0442 \u0432\u043d\u044f\u0442\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432, \u043a\u0430\u043a \u0438\u0445 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u044b\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c.<\/p>\n<p>\u041a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u2014 \u0440\u0430\u0437\u0440\u044b\u0432 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u043a\u0443\u043b\u044c\u0442\u0443\u0440\u0430\u043c\u0438. \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442 \u043c\u044b\u0441\u043b\u0438\u0442 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u043c: \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043f\u043e\u0433\u043e\u043d\u044f\u043b \u0442\u0435\u0441\u0442\u044b, \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0440\u0438\u0435\u043c\u043b\u0438\u043c\u044b\u0435 \u043d\u0430 \u0435\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u2014 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430. DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043c\u044b\u0441\u043b\u0438\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c: \u043a\u043e\u0434 \u0432 Git, \u0442\u0435\u0441\u0442\u044b \u0432 CI, \u0441\u0431\u043e\u0440\u043a\u0430, \u0434\u0435\u043f\u043b\u043e\u0439, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433, \u0430\u043b\u0435\u0440\u0442\u044b. <br \/>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u044e\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u0435\u0439\u043a-\u0445\u043e\u043b\u0434\u0435\u0440\u043e\u0432 \u0438\u0437 \u0431\u0438\u0437\u043d\u0435\u0441-\u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0439, \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c?<br \/>\u041f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043a devops-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443 \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442: \u0432\u043e\u0442 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f ML-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 &#8212; \u0441\u0434\u0435\u043b\u0430\u0439 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043c\u043e\u0433 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c!<br \/>\u0414\u0430 \u043f\u0440\u043e\u0441\u0442\u044f\u0442 \u043c\u0435\u043d\u044f \u043a\u043e\u043b\u043b\u0435\u0433\u0438, \u043d\u043e \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u044b &#8212; \u043b\u044e\u0434\u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u0438\u0435 (\u0445\u043e\u0442\u044c \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c) &#8212; \u0438\u043c \u0441\u043b\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u0438\u043d\u043e\u0433\u0434\u0430 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 git, \u043a\u0430\u043a \u0432\u0441\u0435 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 docker \u0438 \u043f\u0440\u0438\u0447\u0435\u043c \u0437\u0434\u0435\u0441\u044c devsecops (\u044d\u0442\u043e \u0432\u0441\u0435 \u0438\u0437 \u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430, \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 &#8212; \u043d\u0430 \u0432\u0441\u0435\u0445 \u043d\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f!)? <br \/>\u0418\u0437 \u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0434\u0430\u0442\u044c \u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 GPU \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0443\u0434\u0430 Jupyter &#8212; \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043b\u044e\u0447\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u0438. \u0418 \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442 \u0442\u043e\u0436\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c devops \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443 \u0447\u0442\u043e \u0435\u043c\u0443 \u043d\u0430\u0434\u043e.<\/p>\n<p>\u041a\u0430\u043a \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u0430? \u041a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d \u0447\u0435\u043c-\u0442\u043e \u0437\u0430\u043d\u044f\u0442? &#8212; \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443 &#8212; \u043d\u0430\u0431\u043e\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0442.\u0434.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044d\u0442\u0438 \u0434\u0432\u043e\u0435 \u043f\u044b\u0442\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c ML-\u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0435\u0437 \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u2014 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c.<\/p>\n<p><strong><em>MLOps<\/em><\/strong> \u2014 \u044d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u043e\u0442 \u043a\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u043c\u0438\u0440\u0430. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u2014 \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, CI\/CD, \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433, \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u2014 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0435\u0449\u0451 \u0438 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043c\u043e\u0434\u0435\u043b\u0438. \u0410 \u044d\u0442\u043e \u0447\u0443\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0447\u0435\u043c \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434.<\/p>\n<h2>\u0427\u0435\u043c ML-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e CI\/CD<\/h2>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u2014 \u044d\u0442\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0434\u0451\u0442 \u0441\u0435\u0431\u044f \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e. \u0412 ML \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u0440\u0451\u0445 \u0432\u0435\u0449\u0435\u0439: \u043a\u043e\u0434\u0430, \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0433\u0438\u043f\u0435\u0440\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443:<\/p>\n<p><strong>\u0414\u0430\u043d\u043d\u044b\u0435 \u2014 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/strong> \u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442\u044c \u043a\u043e\u0434 \u0432 Git. \u041d\u0443\u0436\u043d\u043e \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u044b, \u043f\u0440\u0438\u0447\u0451\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u043e \u0445\u0435\u0448\u0443 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043b\u044e\u0431\u043e\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442. Git \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u2014 \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u044b \u0432\u0435\u0441\u044f\u0442 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u044b. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 DVC (Data Version Control), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 Git \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0451\u0433\u043a\u0438\u0435 <code>.dvc<\/code>-\u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438, \u0430 \u0441\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u044b \u2014 \u0432 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 MinIO.<\/p>\n<p><strong>\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a.<\/strong> \u0412 CI\/CD \u0441\u0431\u043e\u0440\u043a\u0430 \u043b\u0438\u0431\u043e \u0437\u0435\u043b\u0451\u043d\u0430\u044f, \u043b\u0438\u0431\u043e \u043a\u0440\u0430\u0441\u043d\u0430\u044f. \u0412 ML \u043d\u0443\u0436\u043d\u043e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c\u0438 \u0438 \u0433\u0438\u043f\u0435\u0440\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0438\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u0435\u043d \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u2014 \u043c\u044b \u0432\u0437\u044f\u043b\u0438 MLflow \u0441 PostgreSQL \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u044d\u043a\u0435\u043d\u0434\u0430.<\/p>\n<p><strong>\u0414\u0440\u0435\u0439\u0444 \u043c\u043e\u0434\u0435\u043b\u0438.<\/strong> \u0421\u0430\u043c\u0430\u044f \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c ML \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435: \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0433\u0440\u0430\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434\u0435. \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f (concept drift). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b ML-\u043c\u043e\u0434\u0435\u043b\u0438 \u2014 \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0439, \u0430 \u043d\u0435 \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0439. \u041c\u043e\u0434\u0435\u043b\u044c \u043d\u0443\u0436\u043d\u043e \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u043e\u0431\u0443\u0447\u0430\u0442\u044c.<\/p>\n<p><strong>Model Registry \u2014 \u0430\u043d\u0430\u043b\u043e\u0433 Container Registry.<\/strong> \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u043a\u0430\u0442\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0432 prod, \u0435\u0451 \u043d\u0443\u0436\u043d\u043e \u0433\u0434\u0435-\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c, \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0443\u043c\u0435\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c. MLflow Model Registry \u0441 \u0430\u043b\u0438\u0430\u0441\u0430\u043c\u0438 (<code>@champion<\/code>, <code>@challenger<\/code>) \u0440\u0435\u0448\u0430\u0435\u0442 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443. \u0421\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0433\u0440\u0443\u0437\u0438\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e \u0430\u043b\u0438\u0430\u0441\u0443 <code>@champion<\/code> \u2014 \u0447\u0442\u043e\u0431\u044b \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0430\u043b\u0438\u0430\u0441, \u043d\u0435 \u043c\u0435\u043d\u044f\u044f \u043a\u043e\u0434 (\u0442\u0443\u0442 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0444\u043b\u043e\u0443).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043d\u0430 \u044f\u0437\u044b\u043a DevOps: CI\/CD \u0432 ML \u2014 \u044d\u0442\u043e \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e Docker-\u043e\u0431\u0440\u0430\u0437\u044b, \u043d\u043e \u0438 \u043e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u0441\u0442\u0430\u0434\u0438\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0434, \u043d\u043e \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043c\u043e\u0434\u0435\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 Model Registry.<\/p>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430: \u0447\u0442\u043e \u0438 \u0437\u0430\u0447\u0435\u043c \u043c\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b\u0438<\/h3>\n<p>\u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435: \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 GitLab, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 Docker Registry, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 Ingress, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0412\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u2014 open-source. \u041d\u0443 \u0438 \u043d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 (\u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f!) &#8212; \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 &#171;\u043e\u0431\u044a\u0435\u043c\u043e\u0432&#187; \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c.<\/p>\n<h4>\u0414\u0432\u0430 \u043a\u043e\u043d\u0442\u0443\u0440\u0430<\/h4>\n<p>\u041a\u043b\u0430\u0441\u0442\u0435\u0440 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d \u043d\u0430 \u0434\u0432\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u0442\u0443\u0440\u0430:<\/p>\n<p><strong>Kubernetes-\u043a\u043b\u0430\u0441\u0442\u0435\u0440 (serving &amp; platform).<\/strong> \u0417\u0434\u0435\u0441\u044c \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 GPU: \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0441\u0435\u043a\u0440\u0435\u0442\u044b, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433, \u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u043d\u0444\u0435\u0440\u0435\u043d\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. <\/p>\n<p><strong>GPU-\u0441\u0435\u0440\u0432\u0435\u0440 (training node, \u0432\u043d\u0435 K8s).<\/strong> \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430 \u0441 GPU NVIDIA, \u043d\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u2014 \u0447\u0435\u0440\u0435\u0437 Docker-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0441 nvidia-container-toolkit. \u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u043d\u0435 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430? GPU-\u0436\u0435\u043b\u0435\u0437\u043e \u0434\u043e\u0440\u043e\u0433\u043e\u0435, \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a K8s-\u043d\u043e\u0434\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0448\u0430\u0440\u0438\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438. \u0410 \u0442\u0430\u043a \u2014 \u043e\u0434\u0438\u043d GPU-\u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435, \u043f\u043e\u043a\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0437\u0430\u043d\u044f\u0442 \u0441\u0432\u043e\u0438\u043c \u0434\u0435\u043b\u043e\u043c. <\/p>\n<h4>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0442\u0435\u043a<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430\u0447\u0435\u043c<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044f<\/p>\n<\/td>\n<td>\n<p align=\"left\">Kubernetes <\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">GitOps \/ CD<\/p>\n<\/td>\n<td>\n<p align=\"left\">ArgoCD<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439 \u0438\u0437 Git<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI<\/p>\n<\/td>\n<td>\n<p align=\"left\">GitLab CI\/CD<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0435\u0441\u0442\u044b, \u0441\u0431\u043e\u0440\u043a\u0430, \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">MinIO (S3)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b MLflow<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0422\u0440\u0435\u043a\u0438\u043d\u0433 ML<\/p>\n<\/td>\n<td>\n<p align=\"left\">MLflow + PostgreSQL<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b + Model Registry<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">ML-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">FastAPI <\/p>\n<\/td>\n<td>\n<p align=\"left\">REST API \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u0439<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0412\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/td>\n<td>\n<p align=\"left\">DVC<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u0435\u0440\u0441\u0438\u0438 \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u043e\u0432<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0421\u0440\u0435\u0434\u0430 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">JupyterLab<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">Celery + Redis<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0447\u0435\u0440\u0435\u0434\u044c GPU-\u0437\u0430\u0434\u0430\u0447<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0421\u0435\u043a\u0440\u0435\u0442\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">OpenBao(Vault) + ESO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">SAST<\/p>\n<\/td>\n<td>\n<p align=\"left\">Bandit <\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0410\u043d\u0430\u043b\u0438\u0437 Python-\u043a\u043e\u0434\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0421\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">Trivy<\/p>\n<\/td>\n<td>\n<p align=\"left\">CVE \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u0445<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433<\/p>\n<\/td>\n<td>\n<p align=\"left\">Prometheus + Grafana<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041c\u0435\u0442\u0440\u0438\u043a\u0438 API<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0421\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043d\u0442\u0443\u0440\u0430\u043c\u0438 \u2014 \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0442\u044c: GPU-\u0441\u0435\u0440\u0432\u0435\u0440 \u0445\u043e\u0434\u0438\u0442 \u0432 MLflow, MinIO \u0438 Redis \u0447\u0435\u0440\u0435\u0437 Ingress\/LoadBalancer. \u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u043f\u043b\u044e\u0441: \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0435\u0442\u0430\u0446\u0438\u044f GPU-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435 \u0434\u0430\u0451\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c k8s.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b <strong>\u043d\u0435<\/strong> \u0432\u0437\u044f\u043b\u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p><strong>Kubeflow.<\/strong> \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u0435-\u0444\u0430\u043a\u0442\u043e \u0434\u043b\u044f MLOps \u043d\u0430 K8s, \u043d\u043e \u043e\u043d \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u043f\u043e\u0434 \u043e\u0431\u043b\u0430\u043a\u0430. \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c Kubeflow \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u2014 \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e \u0438\u0437-\u0437\u0430 \u043d\u0435\u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 <strong>\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/strong>. \u041f\u043b\u044e\u0441 \u043e\u043d \u0442\u0430\u0449\u0438\u0442 \u0437\u0430 \u0441\u043e\u0431\u043e\u0439 CRD, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u044e\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443. \u0414\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u2014 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e.<\/p>\n<p><strong>Airflow.<\/strong> \u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440, \u043d\u043e \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u00abDAG \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e\u00bb \u043f\u043b\u043e\u0445\u043e \u043b\u043e\u0436\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u0443\u044e \u043f\u0440\u0438\u0440\u043e\u0434\u0443 ML-\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432. \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442 \u0445\u043e\u0447\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u00ab\u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441\u00bb \u0438\u0437 \u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430, \u0430 \u043d\u0435 \u0436\u0434\u0430\u0442\u044c \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e scheduled run. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 Celery + Redis \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u0443\u044e \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443.<\/p>\n<p><strong>HashiCorp Vault.<\/strong> \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438: \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 HashiCorp \u043d\u0430 BSL (Business Source License) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Vault \u0432 production \u0441\u0442\u0430\u043b\u043e \u0440\u0438\u0441\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u043c. \u041c\u044b \u0432\u0437\u044f\u043b\u0438 OpenBao \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0444\u043e\u0440\u043a \u043f\u043e\u0434 MPL 2.0, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e API.<\/p>\n<h4>GitOps: Apps-of-Apps<\/h4>\n<p>GitOps-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 Apps-of-Apps. \u041a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 ArgoCD Application \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 Applications \u2014 \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0451\u0442\u0441\u044f sync-wave &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0445\u043e\u0447\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f, \u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438\u0437 \u0432\u043e\u043b\u0442\u0430 \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0442\u044f\u043d\u0443\u043b\u0438\u0441\u044c.<\/p>\n<p><strong>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f:<\/strong><\/p>\n<pre><code>gitops\/\u251c\u2500\u2500 apps\/                  # ArgoCD Applications (\u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442)\u251c\u2500\u2500 charts\/                # \u0417\u0430\u0432\u0435\u043d\u0434\u043e\u0440\u0435\u043d\u043d\u044b\u0435 Helm-\u0447\u0430\u0440\u0442\u044b (mlflow, postgresql, redis, ...)\u251c\u2500\u2500 helm-values\/           # Helm values \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u251c\u2500\u2500 manifests\/             # \u041d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 K8s-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b (inference, monitoring)\u251c\u2500\u2500 secrets\/               # ExternalSecret-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b (OpenBao \u2192 K8s)\u251c\u2500\u2500 namespaces\/            # Namespace \u0441 TLS-\u043b\u0435\u0439\u0431\u043b\u0430\u043c\u0438\u251c\u2500\u2500 bootstrap\/             # root-app.yaml (\u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0432\u0440\u0443\u0447\u043d\u0443\u044e)\u2514\u2500\u2500 docker\/sops-cmp\/       # Dockerfile \u0434\u043b\u044f ArgoCD CMP sidecar (SOPS)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 ArgoCD Application \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, MLflow:<\/p>\n<pre><code class=\"yaml\">apiVersion: argoproj.io\/v1alpha1kind: Applicationmetadata:  name: mlflow  namespace: argocd  annotations:    argocd.argoproj.io\/sync-wave: \"3\"spec:  project: default  sources:    - repoURL: https:\/\/code.appsec-team.ru\/mlops\/mlops-platform.git      path: charts\/mlflow      targetRevision: main      helm:        valueFiles:          - $values\/helm-values\/mlflow-values.yaml    - repoURL: https:\/\/code.appsec-team.ru\/mlops\/mlops-platform.git      targetRevision: main      ref: values  destination:    server: https:\/\/kubernetes.default.svc    namespace: mlflow  syncPolicy:    automated:      prune: true      selfHeal: true    syncOptions:      - CreateNamespace=true<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0430\u0440\u0442 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u044f\u043c\u043e \u0432 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (<code>gitops\/charts\/mlflow\/<\/code>) \u2014 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 Helm-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432. \u0412 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430\u0434\u0451\u0436\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442: \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0440\u0442\u044b, \u043d\u0435\u0442 \u0440\u0438\u0441\u043a\u0430, \u0447\u0442\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441\u0442\u0430\u043d\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0438 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0440\u0442\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 code review \u043d\u0430\u0440\u0430\u0432\u043d\u0435 \u0441 values. \u0414\u0432\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 (sources) \u0432 \u043e\u0434\u043d\u043e\u043c Application \u2014 \u0444\u0438\u0447\u0430 ArgoCD 2.6+ \u2014 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0432 \u043d\u0451\u043c.<\/p>\n<h3>\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440: \u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u0431\u043e\u043b\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0421\u0430\u043c\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u2014 \u043d\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u0430 \u043b\u043e\u0433\u0438\u0441\u0442\u0438\u043a\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432. \u0412\u0441\u0451, \u0447\u0442\u043e \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043f\u043e \u0449\u0435\u043b\u0447\u043a\u0443, \u0437\u0434\u0435\u0441\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u0442\u0430\u0449\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c \u043f\u0435\u0440\u0438\u043c\u0435\u0442\u0440\u0430.<\/p>\n<h4>\u041f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 Docker Registry<\/h4>\n<p>\u0412\u0441\u0435 \u043e\u0431\u0440\u0430\u0437\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 docker registry, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Harbor. Helm-\u0447\u0430\u0440\u0442\u044b \u0447\u0430\u0441\u0442\u043e \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u044b (<a href=\"http:\/\/docker.io\" rel=\"noopener noreferrer nofollow\">docker.io<\/a>, <a href=\"http:\/\/quay.io\" rel=\"noopener noreferrer nofollow\">quay.io<\/a>) \u2014 \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 registry \u0438 \u043f\u0440\u0430\u0432\u0438\u0442\u044c values.<\/p>\n<pre><code class=\"yaml\">image:  registry: registry.appsec-team.ru  repository: public\/bitnami\/postgresql<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>SOPS \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 KMS<\/h4>\n<p>\u0412 \u043e\u0431\u043b\u0430\u043a\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b GitOps-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0448\u0438\u0444\u0440\u0443\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 KMS. \u0412 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c SOPS \u0441 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 age. ArgoCD \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0447\u0435\u0440\u0435\u0437 CMP sidecar \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>sops --decrypt<\/code> \u043f\u0435\u0440\u0435\u0434 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430.<\/p>\n<pre><code class=\"yaml\"># argocd-values.yaml (\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442)controller:  extraContainers:    - name: sops-cmp      image: registry.appsec-team.ru\/public\/argocd-sops-cmp:3.12.2      command: [\/var\/run\/argocd\/argocd-cmp-server]      volumeMounts:        - name: sops-age-key          mountPath: \/root\/.config\/sops\/age\/keys.txt          subPath: keys.txt<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Age key \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a Secret \u0438 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 Git. \u041c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438 \u043a\u043e\u043c\u043c\u0438\u0442\u044f\u0442\u0441\u044f \u0432 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435 (<code>.enc.yaml<\/code>).<\/p>\n<h4>OpenBao \u0432\u043c\u0435\u0441\u0442\u043e Vault<\/h4>\n<p>OpenBao \u2014 \u0444\u043e\u0440\u043a Vault \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MPL 2.0, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e API. \u0420\u0430\u0437\u0432\u0451\u0440\u043d\u0443\u0442 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 HA \u0441 \u0442\u0440\u0435\u043c\u044f \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u043c\u0438 \u0432 K8s. \u0412\u0441\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 KV-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0441 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0435\u0439 \u043f\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c.<\/p>\n<p>External Secrets Operator (ESO) \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 OpenBao \u0432 K8s Secrets. \u041c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 ExternalSecret \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 mapping:<\/p>\n<pre><code class=\"yaml\">apiVersion: external-secrets.io\/v1kind: ExternalSecretmetadata:  name: mlflow-credentials  namespace: mlflowspec:  refreshInterval: 5m  secretStoreRef:    name: cluster-secret-store    kind: ClusterSecretStore  target:    name: mlflow-credentials  data:    - secretKey: MLFLOW_TRACKING_USERNAME      remoteRef:        key: secret\/mlflow        property: trackingUsername    - secretKey: MLFLOW_TRACKING_PASSWORD      remoteRef:        key: secret\/mlflow        property: trackingPassword<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>ExternalSecret \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u0449\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0443\u0442\u0435\u0439 KV \u0432 \u043e\u0434\u0438\u043d Kubernetes Secret. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u044d\u0442\u043e, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c <code>MLFLOW_TRACKING_USERNAME<\/code> \u0438 <code>MLFLOW_TRACKING_PASSWORD<\/code> \u0432 singleuser-\u043f\u043e\u0434\u044b JupyterLab \u0438\u0437 \u0442\u043e\u0433\u043e \u0436\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f MLflow \u0438 inference.<\/p>\n<h4>\u0421\u0435\u0442\u044c \u0438 TLS<\/h4>\n<p>\u0412\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 nginx Ingress Controller (\u043a\u043b\u0430\u0441\u0441 <code>nginx-internal<\/code>) \u0441 \u0435\u0434\u0438\u043d\u044b\u043c wildcard TLS-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u043c. \u0411\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u2014 MetalLB \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c IP (\u043d\u0430\u0440\u0443\u0436\u0443 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0442\u043e\u0440\u0447\u0438\u0442). \u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c namespace \u0447\u0435\u0440\u0435\u0437 ClusterExternalSecret:<\/p>\n<pre><code class=\"yaml\">apiVersion: external-secrets.io\/v1kind: ClusterExternalSecretmetadata:  name: tls-wildcardspec:  externalSecretName: tls-wildcard  namespaceSelectors:    - matchLabels:        mlops.platform\/tls: \"true\"  externalSecretSpec:    # ... \u0442\u044f\u043d\u0435\u0442 tls.crt + tls.key \u0438\u0437 OpenBao<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043b\u0435\u0439\u0431\u043b <code>mlops.platform\/tls: \"true\"<\/code> \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 namespace \u2014 \u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0442\u0430\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<h3>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b: \u0447\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c<\/h3>\n<h4>MLflow: \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 SQLite<\/h4>\n<p>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 MLflow \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 SQLite. \u042d\u0442\u043e\u0433\u043e \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u043e\u0432\u043d\u043e \u0434\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0432\u043e\u0440\u043a\u0435\u0440\u0430. Gunicorn \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 worker-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c\u0438 + SQLite <code>:memory:<\/code> = \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u043e\u0440\u043a\u0435\u0440 \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0411\u0414. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: <code>RESOURCE_DOES_NOT_EXIST<\/code> \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u2014 run \u0441\u043e\u0437\u0434\u0430\u043b\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u0435, \u0430 log_param \u043f\u0440\u0438\u0448\u0451\u043b \u0432 \u0434\u0440\u0443\u0433\u043e\u0439.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435: PostgreSQL \u043a\u0430\u043a backend store. \u0412 community-charts\/mlflow 1.8.1 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>existingDatabaseSecret<\/code>:<\/p>\n<pre><code class=\"yaml\">backendStore:  existingDatabaseSecret: mlflow-db-credentials  existingDatabaseSecretKey: DATABASE_URL  postgres:    enabled: true<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>MLflow \u0437\u0430\u0449\u0438\u0449\u0451\u043d \u0431\u0430\u0437\u043e\u0432\u043e\u0439 HTTP-\u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 Nginx Ingress \u2014 \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e MLflow (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043b\u0430\u0442\u043d\u0430\u044f), \u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Ingress:<\/p>\n<pre><code class=\"yaml\">ingress:  enabled: true  annotations:    nginx.ingress.kubernetes.io\/auth-type: basic    nginx.ingress.kubernetes.io\/auth-secret: mlflow-basic-auth<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>GPU-\u0441\u0435\u0440\u0432\u0435\u0440: \u043c\u0435\u0442\u0430-\u0432\u043e\u0440\u043a\u0435\u0440<\/h4>\n<p>\u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 GPU \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447. \u0418\u0434\u0435\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e GPU-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 ML-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u2014 \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0432\u0438\u0434\u0430 \u00ab\u0437\u0430\u043f\u0443\u0441\u0442\u0438 Docker-\u043e\u0431\u0440\u0430\u0437 X \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 Y \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f Z\u00bb.<\/p>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0442\u044b\u0440\u044c\u043c\u044f \u043f\u043e\u043b\u044f\u043c\u0438:<\/p>\n<pre><code class=\"python\"># dispatch.py \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0437 JupyterLab \u0438\u043b\u0438 GitLab CItask_data = {    \"project\": \"churn-model\",    \"image\": \"registry.appsec-team.ru\/mlops\/churn-worker:latest\",    \"command\": \"python src\/train.py --algorithm xgboost --n_estimators 200\",    \"env\": {        \"MLFLOW_TRACKING_URI\": \"https:\/\/mlflow.service.appsec-team.ru\",        \"AWS_ACCESS_KEY_ID\": \"...\",    },}result = celery_app.send_task(\"train_model\", args=[task_data], queue=\"train\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0435\u0442\u0430-\u0432\u043e\u0440\u043a\u0435\u0440 \u043d\u0430 GPU-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u0437 Redis, \u0434\u0435\u043b\u0430\u0435\u0442 <code>docker pull<\/code> \u043e\u0431\u0440\u0430\u0437\u0430 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440:<\/p>\n<pre><code class=\"python\"># meta-worker \u2014 Celery task handler@app.task(name=\"train_model\", bind=True)def train_model(self, task_data):    project = task_data[\"project\"]    image = task_data[\"image\"]    command = task_data[\"command\"]    env = task_data.get(\"env\", {})    client = docker.from_env()    container = client.containers.run(        image=image,        command=command,        environment=env,        runtime=\"nvidia\",        device_requests=[docker.types.DeviceRequest(count=-1, capabilities=[[\"gpu\"]])],        remove=True,        detach=False,    )    return {\"status\": \"completed\", \"exit_code\": container.wait()[\"StatusCode\"]}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Docker Socket Proxy \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e<\/h4>\n<p>\u041c\u0435\u0442\u0430-\u0432\u043e\u0440\u043a\u0435\u0440 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a Docker-\u0434\u0435\u043c\u043e\u043d\u0443 GPU-\u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0415\u0441\u043b\u0438 \u0434\u0430\u0442\u044c \u0435\u043c\u0443 \u043f\u0440\u044f\u043c\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a <code>\/var\/run\/docker.sock<\/code>, \u044d\u0442\u043e \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e root-\u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u043a \u0445\u043e\u0441\u0442\u0443: \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u043e\u0432\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0445\u043e\u0441\u0442\u0430 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u043f\u0440\u043e\u043a\u0441\u0438 <code>linuxserver\/socket-proxy<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0442\u0430\u0451\u0442 \u043c\u0435\u0436\u0434\u0443 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u043c \u0438 \u0441\u043e\u043a\u0435\u0442\u043e\u043c Docker \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"yaml\"># docker-compose.yml \u043d\u0430 GPU-\u0441\u0435\u0440\u0432\u0435\u0440\u0435services:  socket-proxy:    image: lscr.io\/linuxserver\/socket-proxy    environment:      - IMAGES=1        # docker pull      - CONTAINERS=1    # docker run, docker logs      - POST=1          # docker wait      # \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u2014 0 (\u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e)    volumes:      - \/var\/run\/docker.sock:\/var\/run\/docker.sock:ro  worker:    image: registry.appsec-team.ru\/mlops\/meta-worker:latest    environment:      - DOCKER_HOST=tcp:\/\/socket-proxy:2375  # \u043d\u0435 \/var\/run\/docker.sock!<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439: \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0435\u0442\u0430\u0446\u0438\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u0430\u0442\u0430\u043a\u0443\u044e\u0449\u0438\u0439 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0432\u0441\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0445\u043e\u0441\u0442\u0430, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u0442\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c Docker API, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u043f\u0440\u043e\u043a\u0441\u0438.<\/p>\n<h4>MinIO: \u0434\u0432\u0430 Ingress&#8217;\u0430 \u2014 \u043d\u0435 \u0431\u0430\u0433, \u0430 \u0444\u0438\u0447\u0430<\/h4>\n<p>MinIO \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0432\u0430 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0440\u0442\u0430\u0445: S3 API \u043d\u0430 9000 \u0438 \u0432\u0435\u0431-\u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043d\u0430 9001. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u0434\u0432\u0430 Ingress:<\/p>\n<ul>\n<li>\n<p><a href=\"http:\/\/minio.service.appsec-team.ru\" rel=\"noopener noreferrer nofollow\"><code>minio.service.appsec-team.ru<\/code><\/a> \u2192 \u043f\u043e\u0440\u0442 9000 (S3 API \u0434\u043b\u044f DVC, MLflow, boto3)<\/p>\n<\/li>\n<li>\n<p><code>s3.service.appsec-team.ru<\/code> \u2192 \u043f\u043e\u0440\u0442 9001 (\u0432\u0435\u0431-\u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430)<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435\u043b\u044c\u0437\u044f \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u043e\u0434\u043d\u0438\u043c? \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044c S3 API \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, MinIO \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0442 \u043d\u0430 \u043f\u043e\u0440\u0442 9001 (\u043a\u043e\u043d\u0441\u043e\u043b\u044c). \u041d\u043e Ingress \u043d\u0435 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u043f\u043e\u0440\u0442 \u043d\u0430 \u0442\u043e\u043c \u0436\u0435 \u0434\u043e\u043c\u0435\u043d\u0435 \u2014 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439. \u0420\u0430\u0437\u043d\u044b\u0435 \u0434\u043e\u043c\u0435\u043d\u044b \u0434\u043b\u044f API \u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u2014 \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.<\/p>\n<h4>JupyterLab: OAuth \u0438 \u043f\u0440\u043e\u0431\u0440\u043e\u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432<\/h4>\n<p>JupyterHub \u0440\u0430\u0437\u0432\u0451\u0440\u043d\u0443\u0442 \u0447\u0435\u0440\u0435\u0437 Helm-\u0447\u0430\u0440\u0442 <code>jupyterhub\/jupyterhub<\/code> (Zero to JupyterHub). \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u2014 \u0447\u0435\u0440\u0435\u0437 Keycloak SSO \u0441 GenericOAuthenticator:<\/p>\n<pre><code class=\"yaml\">hub:  config:    JupyterHub:      authenticator_class: generic-oauth    GenericOAuthenticator:      client_id: jupyterlab      client_secret: \"...\"  # \u0438\u0437 OpenBao \u0447\u0435\u0440\u0435\u0437 existingSecret      authorize_url: https:\/\/keycloak.service.appsec-team.ru\/realms\/mlops\/protocol\/openid-connect\/auth      token_url: https:\/\/keycloak.service.appsec-team.ru\/realms\/mlops\/protocol\/openid-connect\/token      userdata_url: https:\/\/keycloak.service.appsec-team.ru\/realms\/mlops\/protocol\/openid-connect\/userinfo      oauth_callback_url: https:\/\/jupyter.service.appsec-team.ru\/hub\/oauth_callback<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Env-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f singleuser-\u043f\u043e\u0434\u043e\u0432 (MLflow credentials, MinIO keys) \u043f\u0440\u043e\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 ExternalSecret. \u0412\u0430\u0436\u043d\u043e: <code>extraEnv<\/code> \u0432 z2jh-\u0447\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 dict-\u0444\u043e\u0440\u043c\u0430\u0442, \u0430 \u043d\u0435 K8s-\u0441\u043f\u0438\u0441\u043e\u043a:<\/p>\n<pre><code class=\"yaml\">singleuser:  extraEnv:    MLFLOW_TRACKING_URI: \"https:\/\/mlflow.service.appsec-team.ru\"    MLFLOW_TRACKING_USERNAME:      valueFrom:        secretKeyRef:          name: jupyterlab-credentials          key: MLFLOW_TRACKING_USERNAME    AWS_ACCESS_KEY_ID:      valueFrom:        secretKeyRef:          name: jupyterlab-credentials          key: AWS_ACCESS_KEY_ID<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>CI\/CD: \u043e\u0442 git push \u0434\u043e production<\/h3>\n<p>\u041a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d \u0432 <code>.gitlab-ci.yml<\/code> \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c push \u0432 main.<\/p>\n<h4>\u0421\u0431\u043e\u0440\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0441 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c<\/h4>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u0438\u0434\u0451\u0442 \u0447\u0435\u0440\u0435\u0437 <code>docker buildx<\/code> \u043d\u0430 DinD-\u0440\u0430\u043d\u043d\u0435\u0440\u0435. \u041a\u0435\u0448 \u0441\u043b\u043e\u0451\u0432 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u2014 \u044d\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0437\u0430 \u0441 PyTorch, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0435\u0437 \u043a\u0435\u0448\u0430 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f 15 \u043c\u0438\u043d\u0443\u0442:<\/p>\n<pre><code class=\"yaml\">build:api:  stage: build  image: docker:24-dind  script:    - docker buildx build      --cache-from type=registry,ref=$CI_REGISTRY_IMAGE\/cache:api      --cache-to type=registry,ref=$CI_REGISTRY_IMAGE\/cache:api,mode=max      -f Dockerfile.api      -t $CI_REGISTRY_IMAGE\/churn-api:$CI_COMMIT_SHORT_SHA      --push .<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u2014 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0432 Dockerfile. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u043e\u043f\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f <code>pip install<\/code>, \u043f\u043e\u0442\u043e\u043c \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"java\"># \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 (\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0440\u0435\u0434\u043a\u043e \u2192 \u0441\u043b\u043e\u0439 \u043a\u0435\u0448\u0438\u0440\u0443\u0435\u0442\u0441\u044f)COPY requirements.api.txt .RUN pip install --no-cache-dir -r requirements.api.txt# \u041f\u043e\u0442\u043e\u043c \u043a\u043e\u0434 (\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u043e \u2192 \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0441\u043b\u043e\u0439)COPY src\/ .\/src\/<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u0430\u0432\u043a\u0430 <code>.py<\/code>-\u0444\u0430\u0439\u043b\u0430 \u043d\u0435 \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0441\u043b\u043e\u0438 \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0430\u043a\u0435\u0442\u0430\u043c\u0438 \u2014 \u0438 \u0432\u0440\u0435\u043c\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 3 \u043c\u0438\u043d\u0443\u0442 \u0434\u043e 20\u201340 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<h4>\u0421\u0442\u0430\u0434\u0438\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/h4>\n<p>Bandit \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 Python-\u043a\u043e\u0434 \u043d\u0430 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 (\u043e\u043f\u0430\u0441\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438, \u0441\u043b\u0430\u0431\u0430\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f) \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 medium \u0438 \u0432\u044b\u0448\u0435:<\/p>\n<pre><code class=\"yaml\">sast:bandit:  stage: sast  script:    - pip install bandit    - bandit -r src\/ -ll -f txt -o bandit-report.txt  artifacts:    paths:      - bandit-report.txt<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Trivy \u0441\u043a\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 \u043d\u0430 CVE \u0432 \u043f\u0430\u043a\u0435\u0442\u0430\u0445 \u041e\u0421 \u0438 Python-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445:<\/p>\n<pre><code class=\"yaml\">scan:trivy:  stage: scan  image: aquasec\/trivy:latest  script:    - trivy image --severity HIGH,CRITICAL      --ignore-unfixed      $CI_REGISTRY_IMAGE\/churn-api:$CI_COMMIT_SHORT_SHA    - trivy image --severity HIGH,CRITICAL      --format template --template \"@contrib\/gitlab.tpl\"      -o trivy-report.json      $CI_REGISTRY_IMAGE\/churn-api:$CI_COMMIT_SHORT_SHA  artifacts:    paths:      - trivy-report.json<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>DevSecOps: \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c ML-\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430<\/h3>\n<p>\u0412 ML-\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u043e \u043e\u0442\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u043b\u0430\u043d \u2014 \u00ab\u043b\u0438\u0448\u044c \u0431\u044b \u043c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430\u00bb. \u041c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0435\u0440\u0435\u043a\u043e\u0441.<\/p>\n<h4>\u0414\u0432\u0430 \u0443\u0440\u043e\u0432\u043d\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432<\/h4>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u2014 SOPS + age \u0434\u043b\u044f GitOps-credentials. ArgoCD-\u0441\u0435\u043a\u0440\u0435\u0442\u044b (\u0442\u043e\u043a\u0435\u043d\u044b, \u043a\u043b\u044e\u0447\u0438) \u0448\u0438\u0444\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u043c \u0438 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u044b\u0432\u0430\u044e\u0442\u0441\u044f CMP-\u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u043c ArgoCD \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435. \u041e\u043d\u0438 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435 \u0432 Git.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u2014 OpenBao + External Secrets Operator \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432 (\u043f\u0430\u0440\u043e\u043b\u0438 \u0411\u0414, \u043a\u043b\u044e\u0447\u0438 MinIO, \u0442\u043e\u043a\u0435\u043d\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432). \u041c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b ExternalSecret \u043b\u0435\u0436\u0430\u0442 \u0432 Git \u043e\u0442\u043a\u0440\u044b\u0442\u043e (\u043e\u043d\u0438 \u043b\u0438\u0448\u044c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442, \u043e\u0442\u043a\u0443\u0434\u0430 \u0432\u0437\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435), \u0430 \u0441\u0430\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0436\u0438\u0432\u0443\u0442 \u0432 OpenBao.<\/p>\n<h4>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430<\/h4>\n<p>\u041e\u0431\u0440\u0430\u0437 API \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043d\u0435\u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"java\">RUN useradd --create-home --uid 1000 appuserUSER appuser<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 Kubernetes-\u0434\u0435\u043f\u043b\u043e\u0439\u043c\u0435\u043d\u0442\u0435 \u0437\u0430\u0434\u0430\u043d \u0441\u0442\u0440\u043e\u0433\u0438\u0439 SecurityContext:<\/p>\n<pre><code class=\"yaml\">securityContext:  runAsNonRoot: true  runAsUser: 1000  readOnlyRootFilesystem: true  allowPrivilegeEscalation: false  capabilities:    drop: [\"ALL\"]  seccompProfile:    type: RuntimeDefault<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 uvicorn \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f emptyDir volume \u043d\u0430 <code>\/tmp<\/code>.<\/p>\n<h4>\u0427\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0437\u0430 \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438<\/h4>\n<p><strong>Auto-Unseal OpenBao.<\/strong> \u0412 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0435 OpenBao \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u043e\u0439 unseal (\u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0430 \u0438\u0437 \u043f\u044f\u0442\u0438). \u0414\u043b\u044f production \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Auto-Unseal \u0447\u0435\u0440\u0435\u0437 Transit Seal \u0438\u043b\u0438 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 KMS \u2014 \u043d\u043e \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u0433\u043e KMS \u043d\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Transit-\u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0438\u043b\u0438 \u043c\u0438\u0440\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0443\u0447\u043d\u044b\u043c unseal.<\/p>\n<p><strong>\u0417\u0430\u0449\u0438\u0442\u0430 \u043c\u043e\u0434\u0435\u043b\u0438.<\/strong> \u041c\u043e\u0434\u0435\u043b\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 MinIO \u043a\u0430\u043a pickle-\u0444\u0430\u0439\u043b. Pickle \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u2014 \u044d\u0442\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 \u0430\u0442\u0430\u043a\u0438. \u0412 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0435 \u043c\u044b \u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0432 \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u043d\u043e \u0434\u043b\u044f production \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c safer-\u0444\u043e\u0440\u043c\u0430\u0442\u044b (ONNX, MLflow pyfunc \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u0438).<\/p>\n<h3>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433: \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e latency<\/h3>\n<p>FastAPI-\u0441\u0435\u0440\u0432\u0438\u0441 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 <code>prometheus-fastapi-instrumentator<\/code> \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0435 <code>\/metrics<\/code>. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p><code>http_requests_total<\/code> \u2014 \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u043e\u0439 \u043f\u043e handler, method, status_code<\/p>\n<\/li>\n<li>\n<p><code>http_request_duration_seconds<\/code> \u2014 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 (p50, p95, p99)<\/p>\n<\/li>\n<li>\n<p><code>http_requests_in_progress<\/code> \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>Prometheus \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 ServiceMonitor:<\/p>\n<pre><code class=\"yaml\">apiVersion: monitoring.coreos.com\/v1kind: ServiceMonitormetadata:  name: inference  namespace: monitoringspec:  selector:    matchLabels:      app: inference  endpoints:    - port: http      path: \/metrics      interval: 15s      timeout: 10s<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Grafana-\u0434\u0430\u0448\u0431\u043e\u0440\u0434 \u00abMLOps \u2014 Inference Service\u00bb \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u043e\u0441\u0435\u043c\u044c \u043f\u0430\u043d\u0435\u043b\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><strong>Stat-\u043f\u0430\u043d\u0435\u043b\u0438:<\/strong> RPS, Error Rate 5xx (\u043f\u043e\u0440\u043e\u0433\u0438 1%\/5%), Latency p99 (\u043f\u043e\u0440\u043e\u0433\u0438 100ms\/500ms), Total Requests (1h)<\/p>\n<\/li>\n<li>\n<p><strong>Timeseries-\u043f\u0430\u043d\u0435\u043b\u0438:<\/strong> Latency Percentiles (p50\/p95\/p99), Request Rate by Status Code (2xx\/4xx\/5xx), RPS \u043f\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c, Memory Usage<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u0448\u0431\u043e\u0440\u0434 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 GitOps-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043a\u0430\u043a ConfigMap \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f ArgoCD:<\/p>\n<pre><code class=\"yaml\">apiVersion: v1kind: ConfigMapmetadata:  name: inference-dashboard  labels:    grafana_dashboard: \"1\"data:  dashboard.json: |    # ... JSON \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430 ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>\u0427\u0442\u043e \u041d\u0415 \u0432\u043e\u0448\u043b\u043e \u0432 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f<\/h4>\n<p>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0434\u0440\u0435\u0439\u0444\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 (concept drift) \u0438 ML-\u043c\u0435\u0442\u0440\u0438\u043a (\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u0436\u0438\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445) \u2014 \u0441\u0430\u043c\u0430\u044f \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c MLOps-\u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u0437\u0430 \u0440\u0430\u043c\u043a\u0430\u043c\u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430. \u0414\u043b\u044f production \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432 \u0438 \u0431\u0438\u0442\u044c \u0442\u0440\u0435\u0432\u043e\u0433\u0443, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u043e\u0433\u043e.<\/p>\n<h3>\u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c: \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 MLOps<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c MLOps-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 \u0432 \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0432\u043e\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0447\u0430\u0442\u044c:<\/p>\n<p><strong>\u0428\u0430\u0433 1: GitOps-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 + ArgoCD.<\/strong> \u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0443\u0447\u043d\u044b\u043c \u0431\u0430\u0440\u0434\u0430\u043a\u043e\u043c. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 Apps-of-Apps, \u0440\u0430\u0437\u0431\u0435\u0439\u0442\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u043e sync-wave, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 SOPS \u0434\u043b\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432.<\/p>\n<p><strong>\u0428\u0430\u0433 2: MLflow + PostgreSQL + MinIO.<\/strong> \u042d\u0442\u043e \u044f\u0434\u0440\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, Model Registry. \u0412\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u2014 \u043b\u0438\u0431\u043e \u043e\u0431\u0432\u0435\u0441, \u043b\u0438\u0431\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f.<\/p>\n<p><strong>\u0428\u0430\u0433 3: JupyterLab.<\/strong> \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0433\u0434\u0435-\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 SSO, \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u044c\u0442\u0435 credentials \u0432 env, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 MLflow SDK \u0438 DVC \u0432 \u043e\u0431\u0440\u0430\u0437 singleuser.<\/p>\n<p><strong>\u0428\u0430\u0433 4: GitLab CI \u0441 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u0441\u0442\u0430\u0434\u0438\u044f\u043c\u0438.<\/strong> \u0422\u0435\u0441\u0442\u044b \u2192 Bandit \u2192 \u0441\u0431\u043e\u0440\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u0430 \u2192 Trivy \u2192 \u0434\u0435\u043f\u043b\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 ArgoCD. \u0421\u0442\u0430\u0434\u0438\u044e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p><strong>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043b\u043e\u0436\u0438\u0442\u044c:<\/strong><\/p>\n<ul>\n<li>\n<p>GPU-\u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043c\u0435\u0442\u0430-\u0432\u043e\u0440\u043a\u0435\u0440 \u2014 \u0435\u0441\u043b\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430 CPU, \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 \u043d\u0435 \u043d\u0443\u0436\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>OpenBao \u2014 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c sealed secrets \u0438\u043b\u0438 age-\u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0432 Git (\u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u043d\u0430 \u0448\u0430\u0433\u0435 1)<\/p>\n<\/li>\n<li>\n<p>Prometheus\/Grafana \u2014 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430\u0447\u043d\u0451\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0430\u0444\u0438\u043a<\/p>\n<\/li>\n<li>\n<p>Keycloak SSO \u2014 \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u0445\u0432\u0430\u0442\u0438\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 basic-auth JupyterHub<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u0442\u043e\u0433\u0438<\/h3>\n<p>\u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435:<\/p>\n<ul>\n<li>\n<p><strong>15 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 ArgoCD<\/strong> \u2014 \u0432\u0441\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e \u0438\u0437 Git<\/p>\n<\/li>\n<li>\n<p><strong>2 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u0432 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435<\/strong> \u2014 JupyterLab \u0438 GitLab CI, \u043e\u0431\u0435 \u0432\u0435\u0434\u0443\u0442 \u0432 \u043e\u0434\u043d\u0443 \u043e\u0447\u0435\u0440\u0435\u0434\u044c Redis<\/p>\n<\/li>\n<li>\n<p><strong>0 \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432 \u0432 \u043a\u043e\u0434\u0435<\/strong> \u2014 \u0432\u0441\u0451 \u0432 OpenBao \u0438\u043b\u0438 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043e SOPS<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u043b\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043e\u0442 git push \u0434\u043e production<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0444\u0435\u0440\u0435\u043d\u0441: <\/strong> \u043c\u043e\u0434\u0435\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u043e\u0434\u0430, \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u0430 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f, \u0438 \u044f \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0437\u0430 \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0434\u0440\u0435\u0439\u0444\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, Auto-Unseal OpenBao, A\/B-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0439. \u041d\u043e \u043e\u043d\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0433\u043b\u0430\u0432\u043d\u043e\u0435: MLOps \u2014 \u044d\u0442\u043e \u043d\u0435 \u043c\u0430\u0433\u0438\u044f \u0438 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u0441\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0437\u0430\u043a\u043e\u043d\u0430\u043c\u0438. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e DevOps-\u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438, \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u043d\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b ML-\u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440, \u0432\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u0442\u0435 80% \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f MLOps-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 20% \u2014 \u044d\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430 ML: Model Registry, \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0447\u0435\u0440\u0435\u0434\u044c GPU-\u0437\u0430\u0434\u0430\u0447. \u0421 \u044d\u0442\u0438\u043c \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043c\u0435\u0440\u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0443 \u0438 \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0434\u043e\u043b\u0438\u0441\u0442\u0430\u043b, \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043c\u043e\u0438 \u0438\u0437\u044b\u0441\u043a\u0430\u043d\u0438\u044f:<\/p>\n<p><a href=\"https:\/\/gitverse.ru\/vsb2007\/mlops-platform\" rel=\"noopener noreferrer nofollow\">https:\/\/gitverse.ru\/vsb2007\/mlops-platform<\/a><\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c \u0431\u044b\u043b \u043f\u043e\u043b\u0435\u0437\u0435\u043d \ud83d\ude42<\/p>\n<p><strong><em>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435!<\/em><\/strong><\/p>\n<\/div>\n<p>\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\/1069368\/\">https:\/\/habr.com\/ru\/articles\/1069368\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u042d\u0442\u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u043e\u0442 \u0433\u043e\u043b\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0438 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043d\u0451\u043c \u0442\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443.\u0417\u0430\u0447\u0435\u043c DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443 MLOps?\u041f\u043e \u0434\u0430\u043d\u043d\u044b\u043c \u043e\u0442\u0440\u0430\u0441\u043b\u0435\u0432\u044b\u0445 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439, \u0434\u043e 80% ML-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0442\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u00ab\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u00bb. \u041c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u0443\u0447\u0430\u044e\u0442 \u0432 Jupyter-\u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430\u0445, \u043d\u043e \u0434\u043e \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430 \u043e\u043d\u0438 \u0434\u043e\u0445\u043e\u0434\u044f\u0442 \u0440\u0435\u0434\u043a\u043e \u2014 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435\u0442 \u0432\u043d\u044f\u0442\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432, \u043a\u0430\u043a \u0438\u0445 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u044b\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c.\u041a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u2014 \u0440\u0430\u0437\u0440\u044b\u0432 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u043a\u0443\u043b\u044c\u0442\u0443\u0440\u0430\u043c\u0438. \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442 \u043c\u044b\u0441\u043b\u0438\u0442 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u043c: \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043f\u043e\u0433\u043e\u043d\u044f\u043b \u0442\u0435\u0441\u0442\u044b, \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0440\u0438\u0435\u043c\u043b\u0438\u043c\u044b\u0435 \u043d\u0430 \u0435\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u2014 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430. DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043c\u044b\u0441\u043b\u0438\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c: \u043a\u043e\u0434 \u0432 Git, \u0442\u0435\u0441\u0442\u044b \u0432 CI, \u0441\u0431\u043e\u0440\u043a\u0430, \u0434\u0435\u043f\u043b\u043e\u0439, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433, \u0430\u043b\u0435\u0440\u0442\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u044e\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u0435\u0439\u043a-\u0445\u043e\u043b\u0434\u0435\u0440\u043e\u0432 \u0438\u0437 \u0431\u0438\u0437\u043d\u0435\u0441-\u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0439, \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c?\u041f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043a devops-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443 \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442: \u0432\u043e\u0442 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f ML-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 &#8212; \u0441\u0434\u0435\u043b\u0430\u0439 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043c\u043e\u0433 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c!\u0414\u0430 \u043f\u0440\u043e\u0441\u0442\u044f\u0442 \u043c\u0435\u043d\u044f \u043a\u043e\u043b\u043b\u0435\u0433\u0438, \u043d\u043e \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u044b &#8212; \u043b\u044e\u0434\u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u0438\u0435 (\u0445\u043e\u0442\u044c \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c) &#8212; \u0438\u043c \u0441\u043b\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u0438\u043d\u043e\u0433\u0434\u0430 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 git, \u043a\u0430\u043a \u0432\u0441\u0435 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 docker \u0438 \u043f\u0440\u0438\u0447\u0435\u043c \u0437\u0434\u0435\u0441\u044c devsecops (\u044d\u0442\u043e \u0432\u0441\u0435 \u0438\u0437 \u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430, \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 &#8212; \u043d\u0430 \u0432\u0441\u0435\u0445 \u043d\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f!)? \u0418\u0437 \u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0434\u0430\u0442\u044c \u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 GPU \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0443\u0434\u0430 Jupyter &#8212; \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043b\u044e\u0447\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u0438. \u0418 \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442 \u0442\u043e\u0436\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c devops \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443 \u0447\u0442\u043e \u0435\u043c\u0443 \u043d\u0430\u0434\u043e.\u041a\u0430\u043a \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u0430? \u041a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d \u0447\u0435\u043c-\u0442\u043e \u0437\u0430\u043d\u044f\u0442? &#8212; \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443 &#8212; \u043d\u0430\u0431\u043e\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0442.\u0434.\u041a\u043e\u0433\u0434\u0430 \u044d\u0442\u0438 \u0434\u0432\u043e\u0435 \u043f\u044b\u0442\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c ML-\u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0435\u0437 \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u2014 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c.MLOps \u2014 \u044d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u043e\u0442 \u043a\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u043c\u0438\u0440\u0430. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u2014 \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, CI\/CD, \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433, \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u2014 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0435\u0449\u0451 \u0438 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043c\u043e\u0434\u0435\u043b\u0438. \u0410 \u044d\u0442\u043e \u0447\u0443\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0447\u0435\u043c \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434.\u0427\u0435\u043c ML-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e CI\/CD\u0412 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u2014 \u044d\u0442\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0434\u0451\u0442 \u0441\u0435\u0431\u044f \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e. \u0412 ML \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u0440\u0451\u0445 \u0432\u0435\u0449\u0435\u0439: \u043a\u043e\u0434\u0430, \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0433\u0438\u043f\u0435\u0440\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443:\u0414\u0430\u043d\u043d\u044b\u0435 \u2014 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442\u044c \u043a\u043e\u0434 \u0432 Git. \u041d\u0443\u0436\u043d\u043e \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u044b, \u043f\u0440\u0438\u0447\u0451\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u043e \u0445\u0435\u0448\u0443 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043b\u044e\u0431\u043e\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442. Git \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u2014 \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u044b \u0432\u0435\u0441\u044f\u0442 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u044b. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 DVC (Data Version Control), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 Git \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0451\u0433\u043a\u0438\u0435 .dvc-\u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438, \u0430 \u0441\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u044b \u2014 \u0432 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 MinIO.\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a. \u0412 CI\/CD \u0441\u0431\u043e\u0440\u043a\u0430 \u043b\u0438\u0431\u043e \u0437\u0435\u043b\u0451\u043d\u0430\u044f, \u043b\u0438\u0431\u043e \u043a\u0440\u0430\u0441\u043d\u0430\u044f. \u0412 ML \u043d\u0443\u0436\u043d\u043e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c\u0438 \u0438 \u0433\u0438\u043f\u0435\u0440\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0438\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u0435\u043d \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u2014 \u043c\u044b \u0432\u0437\u044f\u043b\u0438 MLflow \u0441 PostgreSQL \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u044d\u043a\u0435\u043d\u0434\u0430.\u0414\u0440\u0435\u0439\u0444 \u043c\u043e\u0434\u0435\u043b\u0438. \u0421\u0430\u043c\u0430\u044f \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c ML \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435: \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0433\u0440\u0430\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434\u0435. \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f (concept drift). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b ML-\u043c\u043e\u0434\u0435\u043b\u0438 \u2014 \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0439, \u0430 \u043d\u0435 \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0439. \u041c\u043e\u0434\u0435\u043b\u044c \u043d\u0443\u0436\u043d\u043e \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u043e\u0431\u0443\u0447\u0430\u0442\u044c.Model Registry \u2014 \u0430\u043d\u0430\u043b\u043e\u0433 Container Registry. \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u043a\u0430\u0442\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0432 prod, \u0435\u0451 \u043d\u0443\u0436\u043d\u043e \u0433\u0434\u0435-\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c, \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0443\u043c\u0435\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c. MLflow Model Registry \u0441 \u0430\u043b\u0438\u0430\u0441\u0430\u043c\u0438 (@champion, @challenger) \u0440\u0435\u0448\u0430\u0435\u0442 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443. \u0421\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0433\u0440\u0443\u0437\u0438\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e \u0430\u043b\u0438\u0430\u0441\u0443 @champion \u2014 \u0447\u0442\u043e\u0431\u044b \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0430\u043b\u0438\u0430\u0441, \u043d\u0435 \u043c\u0435\u043d\u044f\u044f \u043a\u043e\u0434 (\u0442\u0443\u0442 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0444\u043b\u043e\u0443).\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043d\u0430 \u044f\u0437\u044b\u043a DevOps: CI\/CD \u0432 ML \u2014 \u044d\u0442\u043e \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e Docker-\u043e\u0431\u0440\u0430\u0437\u044b, \u043d\u043e \u0438 \u043e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u0441\u0442\u0430\u0434\u0438\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0434, \u043d\u043e \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043c\u043e\u0434\u0435\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 Model Registry.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430: \u0447\u0442\u043e \u0438 \u0437\u0430\u0447\u0435\u043c \u043c\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b\u0438\u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435: \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 GitLab, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 Docker Registry, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 Ingress, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0412\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u2014 open-source. \u041d\u0443 \u0438 \u043d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 (\u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f!) &#8212; \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 &#171;\u043e\u0431\u044a\u0435\u043c\u043e\u0432&#187; \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c.\u0414\u0432\u0430 \u043a\u043e\u043d\u0442\u0443\u0440\u0430\u041a\u043b\u0430\u0441\u0442\u0435\u0440 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d \u043d\u0430 \u0434\u0432\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u0442\u0443\u0440\u0430:Kubernetes-\u043a\u043b\u0430\u0441\u0442\u0435\u0440 (serving &amp; platform). \u0417\u0434\u0435\u0441\u044c \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 GPU: \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0441\u0435\u043a\u0440\u0435\u0442\u044b, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433, \u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u043d\u0444\u0435\u0440\u0435\u043d\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. GPU-\u0441\u0435\u0440\u0432\u0435\u0440 (training node, \u0432\u043d\u0435 K8s). \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430 \u0441 GPU NVIDIA, \u043d\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u2014 \u0447\u0435\u0440\u0435\u0437 Docker-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0441 nvidia-container-toolkit. \u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u043d\u0435 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430? GPU-\u0436\u0435\u043b\u0435\u0437\u043e \u0434\u043e\u0440\u043e\u0433\u043e\u0435, \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a K8s-\u043d\u043e\u0434\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0448\u0430\u0440\u0438\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438. \u0410 \u0442\u0430\u043a \u2014 \u043e\u0434\u0438\u043d GPU-\u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435, \u043f\u043e\u043a\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0437\u0430\u043d\u044f\u0442 \u0441\u0432\u043e\u0438\u043c \u0434\u0435\u043b\u043e\u043c. \u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0442\u0435\u043a\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u0417\u0430\u0447\u0435\u043c\u041e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044fKubernetes \u0411\u0430\u0437\u043e\u0432\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430GitOps \/ CDArgoCD\u0414\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439 \u0438\u0437 GitCIGitLab CI\/CD\u0422\u0435\u0441\u0442\u044b, \u0441\u0431\u043e\u0440\u043a\u0430, \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435MinIO (S3)\u0414\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b MLflow\u0422\u0440\u0435\u043a\u0438\u043d\u0433 MLMLflow + PostgreSQL\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b + Model RegistryML-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435FastAPI REST API \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u0439\u0412\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445DVC\u0412\u0435\u0440\u0441\u0438\u0438 \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u043e\u0432\u0421\u0440\u0435\u0434\u0430 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432JupyterLab\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435Celery + Redis\u041e\u0447\u0435\u0440\u0435\u0434\u044c GPU-\u0437\u0430\u0434\u0430\u0447\u0421\u0435\u043a\u0440\u0435\u0442\u044bOpenBao(Vault) + ESO\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435SASTBandit \u0410\u043d\u0430\u043b\u0438\u0437 Python-\u043a\u043e\u0434\u0430\u0421\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432TrivyCVE \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u0445\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433Prometheus + Grafana\u041c\u0435\u0442\u0440\u0438\u043a\u0438 API\u0421\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043d\u0442\u0443\u0440\u0430\u043c\u0438 \u2014 \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0442\u044c: GPU-\u0441\u0435\u0440\u0432\u0435\u0440 \u0445\u043e\u0434\u0438\u0442 \u0432 MLflow, MinIO \u0438 Redis \u0447\u0435\u0440\u0435\u0437 Ingress\/LoadBalancer. \u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u043f\u043b\u044e\u0441: \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0435\u0442\u0430\u0446\u0438\u044f GPU-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435 \u0434\u0430\u0451\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c k8s.\u0422\u0435\u043f\u0435\u0440\u044c \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u043d\u0435 \u0432\u0437\u044f\u043b\u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.Kubeflow. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u0435-\u0444\u0430\u043a\u0442\u043e \u0434\u043b\u044f MLOps \u043d\u0430 K8s, \u043d\u043e \u043e\u043d \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u043f\u043e\u0434 \u043e\u0431\u043b\u0430\u043a\u0430. \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c Kubeflow \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u2014 \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e \u0438\u0437-\u0437\u0430 \u043d\u0435\u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u043b\u044e\u0441 \u043e\u043d \u0442\u0430\u0449\u0438\u0442 \u0437\u0430 \u0441\u043e\u0431\u043e\u0439 CRD, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u044e\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443. \u0414\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u2014 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e.Airflow. \u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440, \u043d\u043e \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u00abDAG \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e\u00bb \u043f\u043b\u043e\u0445\u043e \u043b\u043e\u0436\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u0443\u044e \u043f\u0440\u0438\u0440\u043e\u0434\u0443 ML-\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432. \u0414\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442 \u0445\u043e\u0447\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u00ab\u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441\u00bb \u0438\u0437 \u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430, \u0430 \u043d\u0435 \u0436\u0434\u0430\u0442\u044c \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e scheduled run. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 Celery + Redis \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u0443\u044e \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443.HashiCorp Vault. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438: \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 HashiCorp \u043d\u0430 BSL (Business Source License) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Vault \u0432 production \u0441\u0442\u0430\u043b\u043e \u0440\u0438\u0441\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u043c. \u041c\u044b \u0432\u0437\u044f\u043b\u0438 OpenBao \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0444\u043e\u0440\u043a \u043f\u043e\u0434 MPL 2.0, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e API.GitOps: Apps-of-AppsGitOps-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 Apps-of-Apps. \u041a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 ArgoCD Application \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 Applications \u2014 \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0451\u0442\u0441\u044f sync-wave &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0445\u043e\u0447\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f, \u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438\u0437 \u0432\u043e\u043b\u0442\u0430 \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0442\u044f\u043d\u0443\u043b\u0438\u0441\u044c.\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f:gitops\/\u251c\u2500\u2500 apps\/                  # ArgoCD Applications (\u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442)\u251c\u2500\u2500 charts\/                # \u0417\u0430\u0432\u0435\u043d\u0434\u043e\u0440\u0435\u043d\u043d\u044b\u0435 Helm-\u0447\u0430\u0440\u0442\u044b (mlflow, postgresql, redis, &#8230;)\u251c\u2500\u2500 helm-values\/           # Helm values \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u251c\u2500\u2500 manifests\/             # \u041d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 K8s-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b (inference, monitoring)\u251c\u2500\u2500 secrets\/               # ExternalSecret-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b (OpenBao \u2192 K8s)\u251c\u2500\u2500 namespaces\/            # Namespace \u0441 TLS-\u043b\u0435\u0439\u0431\u043b\u0430\u043c\u0438\u251c\u2500\u2500 bootstrap\/             # root-app.yaml (\u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0432\u0440\u0443\u0447\u043d\u0443\u044e)\u2514\u2500\u2500 docker\/sops-cmp\/       # Dockerfile \u0434\u043b\u044f ArgoCD CMP sidecar (SOPS)\u041a\u0430\u0436\u0434\u044b\u0439 ArgoCD Application \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, MLflow:apiVersion: argoproj.io\/v1alpha1kind: Applicationmetadata:  name: mlflow  namespace: argocd  annotations:    argocd.argoproj.io\/sync-wave: &#171;3&#187;spec:  project: default  sources:    &#8212; repoURL: https:\/\/code.appsec-team.ru\/mlops\/mlops-platform.git      path: charts\/mlflow      targetRevision: main      helm:        valueFiles:          &#8212; $values\/helm-values\/mlflow-values.yaml    &#8212; repoURL: https:\/\/code.appsec-team.ru\/mlops\/mlops-platform.git      targetRevision: main      ref: values  destination:    server: https:\/\/kubernetes.default.svc    namespace: mlflow  syncPolicy:    automated:      prune: true      selfHeal: true    syncOptions:      &#8212; CreateNamespace=true\u0427\u0430\u0440\u0442 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u044f\u043c\u043e \u0432 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (gitops\/charts\/mlflow\/) \u2014 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 Helm-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432. \u0412 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430\u0434\u0451\u0436\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442: \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0440\u0442\u044b, \u043d\u0435\u0442 \u0440\u0438\u0441\u043a\u0430, \u0447\u0442\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441\u0442\u0430\u043d\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0438 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0440\u0442\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 code review \u043d\u0430\u0440\u0430\u0432\u043d\u0435 \u0441 values. \u0414\u0432\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 (sources) \u0432 \u043e\u0434\u043d\u043e\u043c Application \u2014 \u0444\u0438\u0447\u0430 ArgoCD 2.6+ \u2014 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0432 \u043d\u0451\u043c.\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440: \u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u0431\u043e\u043b\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u0421\u0430\u043c\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u2014 \u043d\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u0430 \u043b\u043e\u0433\u0438\u0441\u0442\u0438\u043a\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432. \u0412\u0441\u0451, \u0447\u0442\u043e \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043f\u043e \u0449\u0435\u043b\u0447\u043a\u0443, \u0437\u0434\u0435\u0441\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u0442\u0430\u0449\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c \u043f\u0435\u0440\u0438\u043c\u0435\u0442\u0440\u0430.\u041f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 Docker Registry\u0412\u0441\u0435 \u043e\u0431\u0440\u0430\u0437\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 docker registry, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Harbor. Helm-\u0447\u0430\u0440\u0442\u044b \u0447\u0430\u0441\u0442\u043e \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u044b (docker.io, quay.io) \u2014 \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 registry \u0438 \u043f\u0440\u0430\u0432\u0438\u0442\u044c values.image:  registry: registry.appsec-team.ru  repository: public\/bitnami\/postgresqlSOPS \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 KMS\u0412 \u043e\u0431\u043b\u0430\u043a\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b GitOps-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0448\u0438\u0444\u0440\u0443\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 KMS. \u0412 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c SOPS \u0441 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 age. ArgoCD \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0447\u0435\u0440\u0435\u0437 CMP sidecar \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 sops &#8212;decrypt \u043f\u0435\u0440\u0435\u0434 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430.# argocd-values.yaml (\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442)controller:  extraContainers:    &#8212; name: sops-cmp      image: registry.appsec-team.ru\/public\/argocd-sops-cmp:3.12.2      command: [\/var\/run\/argocd\/argocd-cmp-server]      volumeMounts:        &#8212; name: sops-age-key          mountPath: \/root\/.config\/sops\/age\/keys.txt          subPath: keys.txtAge key \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a Secret \u0438 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 Git. \u041c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438 \u043a\u043e\u043c\u043c\u0438\u0442\u044f\u0442\u0441\u044f \u0432 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435 (.enc.yaml).OpenBao \u0432\u043c\u0435\u0441\u0442\u043e VaultOpenBao \u2014 \u0444\u043e\u0440\u043a Vault \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MPL 2.0, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e API. \u0420\u0430\u0437\u0432\u0451\u0440\u043d\u0443\u0442 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 HA \u0441 \u0442\u0440\u0435\u043c\u044f \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u043c\u0438 \u0432 K8s. \u0412\u0441\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 KV-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0441&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-490598","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/490598","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=490598"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/490598\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=490598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=490598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=490598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}