{"id":341242,"date":"2022-11-15T03:00:36","date_gmt":"2022-11-15T03:00:36","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=341242"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=341242","title":{"rendered":"<span>\u041f\u0438\u0448\u0435\u043c CD Pipeline \u0441 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0435\u0439 Docker, Kubernetes \u0438 Jenkins \u0432 Google Cloud (GCE\/GKE)<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b68\/0e5\/eb1\/b680e5eb14b5ef1bade9ef6f4bb18f59.png\" alt=\"\" title=\"\" width=\"780\" height=\"439\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b68\/0e5\/eb1\/b680e5eb14b5ef1bade9ef6f4bb18f59.png\"\/><figcaption><\/figcaption><\/figure>\n<div class=\"persona\" persona=\"true\"><img decoding=\"async\" persona=\"true\" class=\"image persona__image\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/a6d\/2ee\/642\/a6d2ee6420445760e000d8bbf2d0470d.jpg\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a6d\/2ee\/642\/a6d2ee6420445760e000d8bbf2d0470d.jpg\" data-blurred=\"true\"\/><\/p>\n<h5 class=\"persona__heading\" persona=\"true\">\u0410\u0432\u0442\u043e\u0440 \u0441\u0442\u0430\u0442\u044c\u0438: \u0420\u0443\u0441\u0442\u0435\u043c \u0413\u0430\u043b\u0438\u0435\u0432<\/h5>\n<p>Senior DevOps Engineer &amp; Integration Architect at IBM<\/p>\n<\/div>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0425\u0430\u0431\u0440! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u0420\u0443\u0441\u0442\u0435\u043c.<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u0431\u044b\u043b \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c \u0432\u043e\u0440\u043a\u0448\u043e\u043f\u0435 \u043e\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 iTechArt \u0438 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0442\u0430\u043c \u0434\u0435\u043b\u0430\u043b\u0438, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435 \u043f\u0438\u0441\u0430\u043b\u0438 CD Pipeline \u0441 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0435\u0439 Docker, Kubernetes \u0438 Jenkins \u0432 Google Cloud (GCE\/GKE).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/890\/f69\/fe4\/890f69fe43e828ec632c354f562e39ea.png\" alt=\"\" title=\"\" width=\"1327\" height=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/890\/f69\/fe4\/890f69fe43e828ec632c354f562e39ea.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0443\u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 GKE (Google Kubernetes Engine) \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Jenkins.<br \/>\u0422\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c.<\/p>\n<p>\u041d\u0430\u0448\u0438 \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u044b: Jenkins, Kubernetes(GKE), \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Github \u0438 \u0440\u0435\u0435\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 Dockerhub.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435:<\/p>\n<ul>\n<li>\n<p>GCP: Google Cloud Platform \u2014 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a \u043e\u0431\u0449\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u043e\u0431\u043b\u0430\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u0443\u0433\u0438 \u0447\u0435\u0440\u0435\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>Docker: Docker \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c, \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0442 \u043d\u0430\u0448\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435.<\/p>\n<\/li>\n<li>\n<p>Jenkins: \u044d\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u043d\u0430\u0434\u0435\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435. \u041e\u043d \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u0442 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 (\u0441\u0431\u043e\u0440\u043a\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435) \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>Kubernetes: Kubernetes \u0438\u043b\u0438 K8s \u2014 \u044d\u0442\u043e \u043f\u043e\u0440\u0442\u0430\u0442\u0438\u0432\u043d\u0430\u044f, \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438, \u0442.\u0435. \u0420\u0435\u0448\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 1: \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043c\u0430\u0448\u0438\u043d\u044b<\/h4>\n<p><strong>1. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043c\u0430\u0448\u0438\u043d\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430:<\/strong><\/p>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c Google Cloud Platform > Compute Engine > Create New Instance<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0a4\/876\/ba2\/0a4876ba2d7eaeed2da58b1818aa6597.png\" alt=\"\" title=\"\" width=\"704\" height=\"818\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0a4\/876\/ba2\/0a4876ba2d7eaeed2da58b1818aa6597.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e86\/a48\/567\/e86a48567cc153623b93089306ff1174.png\" alt=\"\" title=\"\" width=\"1191\" height=\"581\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e86\/a48\/567\/e86a48567cc153623b93089306ff1174.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>2. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 Jenkins \u0438 Docker Engine:<\/strong><\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Docker:<\/p>\n<pre><code class=\"bash\">sudo apt-get update sudo apt install docker.io<\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Jenkins:<\/p>\n<p> 1) \u0421\u043f\u0435\u0440\u0432\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c JDK:<\/p>\n<pre><code class=\"bash\">sudo apt-get update sudo apt install openjdk-11-jre-headless<\/code><\/pre>\n<p> 2) \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043b\u044e\u0447<\/p>\n<pre><code class=\"bash\">wget -q -O - https:\/\/pkg.jenkins.io\/debian-stable\/jenkins.io.key | sudo apt-key add -<\/code><\/pre>\n<p>\u00a03) Apt repo<\/p>\n<pre><code class=\"bash\">sudo sh -c 'echo deb https:\/\/pkg.jenkins.io\/debian-stable binary\/ > \/etc\/apt\/sources.list.d\/jenkins.list'<\/code><\/pre>\n<p>4) \u041e\u0431\u043d\u043e\u0432\u0438\u043c \u043f\u0430\u043a\u0435\u0442\u044b \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Jenkins<\/p>\n<pre><code class=\"bash\">sudo apt-get update sudo apt-get install jenkins<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u0430\u0442\u044c Jenkins\u2019\u0443 \u043f\u0440\u0438\u0432\u0435\u043b\u0435\u0433\u0438\u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430<\/p>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u0444\u0430\u0439\u043b <code>\/etc\/sudoers<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443:<\/p>\n<pre><code class=\"bash\">jenkins ALL=(ALL) NOPASSWD: ALL<\/code><\/pre>\n<p><strong>3. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440 Kubernetes \u0432 GKE<\/strong><\/p>\n<p><em>Open GCP console > GKE (Kubernetes engine) > Create<\/em><\/p>\n<h4>\u0428\u0430\u0433 2. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c Jenkins<\/h4>\n<p><strong>1. \u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0434\u044d\u0448\u0431\u043e\u0440\u0434 Jenkins \u0447\u0435\u0440\u0435\u0437 public IP \u0432\u0430\u0448\u0435\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043f\u043e \u043f\u043e\u0440\u0442\u0443 8080<\/strong><\/p>\n<pre><code>http:\/\/&lt;server_publicIP>:8080<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e76\/c59\/dfb\/e76c59dfb6a731ee44464327de796665.png\" alt=\"\" title=\"\" width=\"680\" height=\"450\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e76\/c59\/dfb\/e76c59dfb6a731ee44464327de796665.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u043d\u0430\u0439\u0434\u0435\u043c \u043f\u0430\u0440\u043e\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u043c<\/p>\n<pre><code>sudo cat \/var\/lib\/jenkins\/secrets\/initialAdminPassword<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0431\u0435\u0440\u0435\u043c <code>Install suggested plugins<\/code><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e52\/15a\/95b\/e5215a95bed8501113995881ed2e7bcf.png\" alt=\"\" title=\"\" width=\"680\" height=\"450\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e52\/15a\/95b\/e5215a95bed8501113995881ed2e7bcf.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Jenkins \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0434\u043b\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043c\u044b \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3f8\/e38\/de3\/3f8e38de359b5d1fcd1187e09b24ff16.png\" alt=\"\" title=\"\" width=\"680\" height=\"446\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3f8\/e38\/de3\/3f8e38de359b5d1fcd1187e09b24ff16.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>2. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b: Git, github, Docker pipeline, Google Kubernetes Engine<\/strong><\/p>\n<p>Jenkins Dashboard -> Plugin Manager -> Available -> Search bar<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ccd\/eb6\/070\/ccdeb6070dcc578f8033600010b5d47c.png\" alt=\"\" title=\"\" width=\"1600\" height=\"666\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ccd\/eb6\/070\/ccdeb6070dcc578f8033600010b5d47c.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>3. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u044b \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 GKE \u0438 Dockerhub<\/strong><\/p>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 Google:<\/p>\n<p><em>Open GCP console > IAM and Admin > service account > open default one or create new one > add key > create new key (json format) and save it<\/em><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fe0\/9f5\/707\/fe09f57073b8bf7f6980452e17dacc4b.png\" alt=\"\" title=\"\" width=\"687\" height=\"833\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fe0\/9f5\/707\/fe09f57073b8bf7f6980452e17dacc4b.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8d0\/366\/8e9\/8d03668e949c92ee7461b09b72220060.png\" alt=\"\" title=\"\" width=\"1197\" height=\"612\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8d0\/366\/8e9\/8d03668e949c92ee7461b09b72220060.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a91\/2ac\/c38\/a912acc38440402055cbfa10c9eee0d5.png\" alt=\"\" title=\"\" width=\"830\" height=\"553\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a91\/2ac\/c38\/a912acc38440402055cbfa10c9eee0d5.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043a\u043b\u044e\u0447 \u0432 Jenkins<\/p>\n<p><em>Jenkins Dashboard > manage Jenkins > manage credentials > Jenkins > global credentials > add credentials<\/em><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/151\/f51\/101\/151f5110142dc4bfe70d3dccac1263ed.png\" alt=\"\" title=\"\" width=\"1107\" height=\"308\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/151\/f51\/101\/151f5110142dc4bfe70d3dccac1263ed.png\"\/><figcaption><\/figcaption><\/figure>\n<p><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fab\/049\/b0c\/fab049b0cee4ef662f94ab2f593d47d0.png\" alt=\"\" title=\"\" width=\"954\" height=\"760\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fab\/049\/b0c\/fab049b0cee4ef662f94ab2f593d47d0.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f Docker \u0442\u043e\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c (\u0433\u0434\u0435 Secret &#8212; \u044d\u0442\u043e \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430)<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1dd\/f02\/6b3\/1ddf026b3b14ba3b9032490319f46550.png\" alt=\"\" title=\"\" width=\"817\" height=\"538\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1dd\/f02\/6b3\/1ddf026b3b14ba3b9032490319f46550.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>3. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Pipeline \u0432 Jenkins:<\/strong><\/p>\n<p>Dashboard -> New item<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/835\/de5\/80c\/835de580c17e2fb22dc7800e2dbc3b54.png\" alt=\"\" title=\"\" width=\"525\" height=\"245\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/835\/de5\/80c\/835de580c17e2fb22dc7800e2dbc3b54.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0434\u0438\u043c \u043b\u044e\u0431\u043e\u0435 \u0438\u043c\u044f, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c pipeline<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d86\/099\/77b\/d8609977be03ccb2f0b7a4963a8bb742.png\" alt=\"\" title=\"\" width=\"1600\" height=\"648\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d86\/099\/77b\/d8609977be03ccb2f0b7a4963a8bb742.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Definition = Pipeline script from SCM<\/p>\n<p>SCM = git<\/p>\n<p>Repository Url: url \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<br \/>Script Path: Jenkinsfile <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/770\/2d2\/2be\/7702d22bece6d3f6fbc646a79cea9797.png\" alt=\"\" title=\"\" width=\"1064\" height=\"522\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/770\/2d2\/2be\/7702d22bece6d3f6fbc646a79cea9797.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/da0\/996\/e92\/da0996e927cbc07afa18408ea297f61e.png\" alt=\"\" title=\"\" width=\"1109\" height=\"300\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/da0\/996\/e92\/da0996e927cbc07afa18408ea297f61e.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0428\u0430\u0433 3. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0444\u043e\u0440\u043a\u043d\u0435\u043c \u0438\u043b\u0438 \u0441\u043a\u043b\u043e\u043d\u0438\u043c \u0435\u0433\u043e: <a href=\"https:\/\/github.com\/komarserjio\/notejam\"><u>https:\/\/github.com\/komarserjio\/notejam<\/u><\/a><\/p>\n<p><strong>1. \u041d\u0430\u043f\u0438\u0448\u0435\u043c Dockerfile:<\/strong><\/p>\n<pre><code class=\"python\">FROM python:2.7 RUN mkdir app COPY django\/notejam app\/ COPY django\/requirements.txt .\/ RUN pip install -r requirements.txt RUN pip install psycopg2 WORKDIR app\/ EXPOSE 5000<\/code><\/pre>\n<p><strong>2. \u041d\u0430\u043f\u0438\u0448\u0435\u043c deployment.yaml \u0434\u043b\u044f Kubernetes<\/strong><br \/>\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0435\u0433\u043e \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0435\u0433\u043e \u0441\u043b\u0443\u0436\u0431\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0434\u043b\u044f persistent volume claim, secret, configMap, database deployment \u0438 service.<\/p>\n<pre><code class=\"python\">#data-db-persistentvolumeclaim.yam apiVersion: v1 kind: PersistentVolumeClaim metadata: \u00a0\u00a0labels: service: data-db \u00a0\u00a0name: data-db spec: \u00a0\u00a0accessModes: - ReadWriteOnce \u00a0\u00a0resources: requests: \u00a0\u00a0storage: 2Gi \u00a0\u00a0 --- #db-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: \u00a0\u00a0labels: service: db \u00a0\u00a0name: db-config data: \u00a0\u00a0db-name: \"nj\"  #db-secret apiVersion: v1 kind: Secret metadata: \u00a0\u00a0name: notejam-credentials type: Opaque data: \u00a0\u00a0user: YWRtaW4= \u00a0\u00a0password: YWRtaW5AMTIz  #db-deployment apiVersion: apps\/v1 kind: Deployment metadata: \u00a0\u00a0labels: service: db \u00a0\u00a0name: db spec: \u00a0\u00a0replicas: 1 \u00a0\u00a0selector: matchLabels: \u00a0\u00a0service: db \u00a0\u00a0template: metadata: \u00a0\u00a0labels: \u00a0\u00a0\u00a0\u00a0service: db \u00a0\u00a0\u00a0\u00a0tier: backend spec: \u00a0\u00a0containers: \u00a0\u00a0\u00a0\u00a0- image: postgres \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: database \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0env: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: POSTGRES_USER \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0valueFrom: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0secretKeyRef: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: notejam-credentials \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: user \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: POSTGRES_PASSWORD \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0valueFrom: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0secretKeyRef: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: notejam-credentials \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: password \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: POSTGRES_DB \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0valueFrom: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0configMapKeyRef: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: db-config \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: db-name \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ports: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- containerPort: 5432 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resources: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0requests: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 100m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 128Mi \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0limits: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 250m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 256Mi \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0volumeMounts: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- mountPath: \/var\/lib\/mysql\/data \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: data-db \u00a0\u00a0restartPolicy: Always \u00a0\u00a0volumes: \u00a0\u00a0\u00a0\u00a0- name: data-db \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0persistentVolumeClaim: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0claimName: data-db  #db-service.yaml apiVersion: v1 kind: Service metadata: \u00a0\u00a0labels: service: db \u00a0\u00a0name: db spec: \u00a0\u00a0ports: - name: \"5432\" \u00a0\u00a0protocol: TCP \u00a0\u00a0port: 5432 \u00a0\u00a0targetPort: 5432 \u00a0\u00a0selector: service: db  apiVersion: apps\/v1 kind: Deployment metadata: \u00a0\u00a0labels: service: web \u00a0\u00a0name: web spec: \u00a0\u00a0replicas: 1 \u00a0\u00a0selector: matchLabels: \u00a0\u00a0service: web \u00a0\u00a0template: metadata: \u00a0\u00a0labels: \u00a0\u00a0\u00a0\u00a0service: web spec: \u00a0\u00a0containers: \u00a0\u00a0\u00a0\u00a0- args: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- bash \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- -c \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- python manage.py syncdb --noinput &amp;&amp; python manage.py migrate &amp;&amp; python manage.py runserver 0.0.0.0:5000 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0image: arshad1914\/pipeline:latest \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: notejam \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ports: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- containerPort: 5000 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resources: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0requests: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 100m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 128Mi \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0limits: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 250m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 250Mi \u00a0\u00a0restartPolicy: Always  apiVersion: v1 kind: Service metadata: \u00a0\u00a0labels: service: web \u00a0\u00a0name: web spec: \u00a0\u00a0type: LoadBalancer \u00a0\u00a0ports: - name: \"5000\" \u00a0\u00a0port: 5000 \u00a0\u00a0targetPort: 5000 \u00a0\u00a0selector: service: web<\/code><\/pre>\n<p>3. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Jenkinsfile, \u0433\u0434\u0435 \u043e\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438<\/p>\n<pre><code class=\"python\">pipeline { agent any \u00a0\u00a0\u00a0\u00a0environment { \u00a0\u00a0\u00a0 PROJECT_ID = 'docker' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CLUSTER_NAME = 'jenkins' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LOCATION = 'us-central-1a' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CREDENTIALS_ID = 'kubernetes' \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0 stages { \u00a0\u00a0\u00a0\u00a0stage('Checkout') { \u00a0\u00a0\u00a0 steps { \u00a0\u00a0\u00a0 checkout scm \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0stage('Build image') { \u00a0\u00a0\u00a0 steps { \u00a0\u00a0\u00a0 script { \u00a0\u00a0\u00a0 app = docker.build(\"zetzo\/pipeline:{env.BUILD_ID}\") \u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 \u00a0 \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0stage('Deploy to K8s') { \u00a0\u00a0\u00a0 steps{ \u00a0\u00a0\u00a0 echo \"Deployment started ...\" \u00a0\u00a0\u00a0 sh 'ls -ltr' \u00a0\u00a0\u00a0 sh 'pwd' \u00a0\u00a0\u00a0 sh \"sed -i 's\/pipeline:latest\/pipeline:class: 'KubernetesEngineBuilder',  \u00a0\u00a0\u00a0 \u00a0 projectId: env.PROJECT_ID,  \u00a0\u00a0\u00a0 \u00a0 clusterName: env.CLUSTER_NAME,  \u00a0\u00a0\u00a0 \u00a0 location: env.LOCATION,  \u00a0\u00a0\u00a0 \u00a0 manifestPattern: 'deployment.yaml',  \u00a0\u00a0\u00a0 \u00a0 credentialsId: env.CREDENTIALS_ID,  \u00a0\u00a0\u00a0 \u00a0 verifyDeployments: true]) \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 }\u00a0\u00a0\u00a0\u00a0 }<\/code><\/pre>\n<p><strong>\u0428\u0430\u0433 4. \u041f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d (\u0441\u043f\u043e\u0439\u043b\u0435\u0440: \u0443\u0441\u043f\u0435\u0448\u043d\u043e)<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/96c\/e1f\/41b\/96ce1f41b343f638b3b6fcc08837897e.png\" alt=\"\" title=\"\" width=\"1600\" height=\"542\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/96c\/e1f\/41b\/96ce1f41b343f638b3b6fcc08837897e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u043b\u0438, \u0412\u044b \u0432\u043e\u0441\u0445\u0438\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b!<\/p>\n<p>P.s.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0447\u0442\u043e\u0431\u044b \u0434\u0435\u043f\u043b\u043e\u0439 \u0431\u044b\u043b \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\u044b\u043c (\u0442.\u0435. \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043e\u0442 Continuous Delivery \u043a Continuous Deployment), \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0435\u0431\u0445\u0443\u043a \u0432 \u0432\u0430\u0448\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 <\/p>\n<p><em>settings > webhooks > add webhooks > url \u0412\u0430\u0448\u0435\u0433\u043e Jenkins instance<\/em><\/p>\n<p>\u0412 \u0412\u0430\u0448\u0435\u043c Jenkins pipeline, \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u0442\u0430\u0432\u0438\u043c \u0433\u0430\u043b\u043e\u0447\u043a\u0443 \u0432 \u043f\u043e\u043b\u0435 \u0437\u0434\u0435\u0441\u044c<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/323\/64a\/da2\/32364ada2d759b47bb5c319372ad6c7e.png\" alt=\"\" title=\"\" width=\"422\" height=\"244\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/323\/64a\/da2\/32364ada2d759b47bb5c319372ad6c7e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0447\u0443 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435\u043c <a href=\"https:\/\/otus.pw\/QtnP\/\">\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u043a<\/a> \u043e\u0442 OTUS \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u044b\u043b\u043a\u0438 \u043a \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e &#171;\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0442\u043e\u0440\u0430&#187; &#8212; docker.<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/otus.pw\/QtnP\/\">\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u043a<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/699300\/\"> https:\/\/habr.com\/ru\/company\/otus\/blog\/699300\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<div class=\"persona\" persona=\"true\">\n<h5 class=\"persona__heading\" persona=\"true\">\u0410\u0432\u0442\u043e\u0440 \u0441\u0442\u0430\u0442\u044c\u0438: \u0420\u0443\u0441\u0442\u0435\u043c \u0413\u0430\u043b\u0438\u0435\u0432<\/h5>\n<p>Senior DevOps Engineer &amp; Integration Architect at IBM<\/p>\n<\/div>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0425\u0430\u0431\u0440! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u0420\u0443\u0441\u0442\u0435\u043c.<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u0431\u044b\u043b \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c \u0432\u043e\u0440\u043a\u0448\u043e\u043f\u0435 \u043e\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 iTechArt \u0438 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0442\u0430\u043c \u0434\u0435\u043b\u0430\u043b\u0438, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435 \u043f\u0438\u0441\u0430\u043b\u0438 CD Pipeline \u0441 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0435\u0439 Docker, Kubernetes \u0438 Jenkins \u0432 Google Cloud (GCE\/GKE).<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0443\u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 GKE (Google Kubernetes Engine) \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Jenkins.<br \/>\u0422\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c.<\/p>\n<p>\u041d\u0430\u0448\u0438 \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u044b: Jenkins, Kubernetes(GKE), \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Github \u0438 \u0440\u0435\u0435\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 Dockerhub.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435:<\/p>\n<ul>\n<li>\n<p>GCP: Google Cloud Platform \u2014 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a \u043e\u0431\u0449\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u043e\u0431\u043b\u0430\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u0443\u0433\u0438 \u0447\u0435\u0440\u0435\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>Docker: Docker \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c, \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0442 \u043d\u0430\u0448\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435.<\/p>\n<\/li>\n<li>\n<p>Jenkins: \u044d\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u043d\u0430\u0434\u0435\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435. \u041e\u043d \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u0442 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 (\u0441\u0431\u043e\u0440\u043a\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435) \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>Kubernetes: Kubernetes \u0438\u043b\u0438 K8s \u2014 \u044d\u0442\u043e \u043f\u043e\u0440\u0442\u0430\u0442\u0438\u0432\u043d\u0430\u044f, \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438, \u0442.\u0435. \u0420\u0435\u0448\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 1: \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043c\u0430\u0448\u0438\u043d\u044b<\/h4>\n<p><strong>1. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043c\u0430\u0448\u0438\u043d\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430:<\/strong><\/p>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c Google Cloud Platform > Compute Engine > Create New Instance<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>2. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 Jenkins \u0438 Docker Engine:<\/strong><\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Docker:<\/p>\n<pre><code class=\"bash\">sudo apt-get update sudo apt install docker.io<\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Jenkins:<\/p>\n<p> 1) \u0421\u043f\u0435\u0440\u0432\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c JDK:<\/p>\n<pre><code class=\"bash\">sudo apt-get update sudo apt install openjdk-11-jre-headless<\/code><\/pre>\n<p> 2) \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043b\u044e\u0447<\/p>\n<pre><code class=\"bash\">wget -q -O - https:\/\/pkg.jenkins.io\/debian-stable\/jenkins.io.key | sudo apt-key add -<\/code><\/pre>\n<p>\u00a03) Apt repo<\/p>\n<pre><code class=\"bash\">sudo sh -c 'echo deb https:\/\/pkg.jenkins.io\/debian-stable binary\/ > \/etc\/apt\/sources.list.d\/jenkins.list'<\/code><\/pre>\n<p>4) \u041e\u0431\u043d\u043e\u0432\u0438\u043c \u043f\u0430\u043a\u0435\u0442\u044b \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Jenkins<\/p>\n<pre><code class=\"bash\">sudo apt-get update sudo apt-get install jenkins<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u0430\u0442\u044c Jenkins\u2019\u0443 \u043f\u0440\u0438\u0432\u0435\u043b\u0435\u0433\u0438\u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430<\/p>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u0444\u0430\u0439\u043b <code>\/etc\/sudoers<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443:<\/p>\n<pre><code class=\"bash\">jenkins ALL=(ALL) NOPASSWD: ALL<\/code><\/pre>\n<p><strong>3. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440 Kubernetes \u0432 GKE<\/strong><\/p>\n<p><em>Open GCP console > GKE (Kubernetes engine) > Create<\/em><\/p>\n<h4>\u0428\u0430\u0433 2. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c Jenkins<\/h4>\n<p><strong>1. \u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0434\u044d\u0448\u0431\u043e\u0440\u0434 Jenkins \u0447\u0435\u0440\u0435\u0437 public IP \u0432\u0430\u0448\u0435\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043f\u043e \u043f\u043e\u0440\u0442\u0443 8080<\/strong><\/p>\n<pre><code>http:\/\/&lt;server_publicIP>:8080<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u043d\u0430\u0439\u0434\u0435\u043c \u043f\u0430\u0440\u043e\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u043c<\/p>\n<pre><code>sudo cat \/var\/lib\/jenkins\/secrets\/initialAdminPassword<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0431\u0435\u0440\u0435\u043c <code>Install suggested plugins<\/code><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Jenkins \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0434\u043b\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043c\u044b \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>2. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b: Git, github, Docker pipeline, Google Kubernetes Engine<\/strong><\/p>\n<p>Jenkins Dashboard -> Plugin Manager -> Available -> Search bar<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>3. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u044b \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 GKE \u0438 Dockerhub<\/strong><\/p>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 Google:<\/p>\n<p><em>Open GCP console > IAM and Admin > service account > open default one or create new one > add key > create new key (json format) and save it<\/em><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043a\u043b\u044e\u0447 \u0432 Jenkins<\/p>\n<p><em>Jenkins Dashboard > manage Jenkins > manage credentials > Jenkins > global credentials > add credentials<\/em><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f Docker \u0442\u043e\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c (\u0433\u0434\u0435 Secret &#8212; \u044d\u0442\u043e \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430)<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>3. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Pipeline \u0432 Jenkins:<\/strong><\/p>\n<p>Dashboard -> New item<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0434\u0438\u043c \u043b\u044e\u0431\u043e\u0435 \u0438\u043c\u044f, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c pipeline<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Definition = Pipeline script from SCM<\/p>\n<p>SCM = git<\/p>\n<p>Repository Url: url \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<br \/>Script Path: Jenkinsfile <\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0428\u0430\u0433 3. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0444\u043e\u0440\u043a\u043d\u0435\u043c \u0438\u043b\u0438 \u0441\u043a\u043b\u043e\u043d\u0438\u043c \u0435\u0433\u043e: <a href=\"https:\/\/github.com\/komarserjio\/notejam\"><u>https:\/\/github.com\/komarserjio\/notejam<\/u><\/a><\/p>\n<p><strong>1. \u041d\u0430\u043f\u0438\u0448\u0435\u043c Dockerfile:<\/strong><\/p>\n<pre><code class=\"python\">FROM python:2.7 RUN mkdir app COPY django\/notejam app\/ COPY django\/requirements.txt .\/ RUN pip install -r requirements.txt RUN pip install psycopg2 WORKDIR app\/ EXPOSE 5000<\/code><\/pre>\n<p><strong>2. \u041d\u0430\u043f\u0438\u0448\u0435\u043c deployment.yaml \u0434\u043b\u044f Kubernetes<\/strong><br \/>\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0435\u0433\u043e \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0435\u0433\u043e \u0441\u043b\u0443\u0436\u0431\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0434\u043b\u044f persistent volume claim, secret, configMap, database deployment \u0438 service.<\/p>\n<pre><code class=\"python\">#data-db-persistentvolumeclaim.yam apiVersion: v1 kind: PersistentVolumeClaim metadata: \u00a0\u00a0labels: service: data-db \u00a0\u00a0name: data-db spec: \u00a0\u00a0accessModes: - ReadWriteOnce \u00a0\u00a0resources: requests: \u00a0\u00a0storage: 2Gi \u00a0\u00a0 --- #db-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: \u00a0\u00a0labels: service: db \u00a0\u00a0name: db-config data: \u00a0\u00a0db-name: \"nj\"  #db-secret apiVersion: v1 kind: Secret metadata: \u00a0\u00a0name: notejam-credentials type: Opaque data: \u00a0\u00a0user: YWRtaW4= \u00a0\u00a0password: YWRtaW5AMTIz  #db-deployment apiVersion: apps\/v1 kind: Deployment metadata: \u00a0\u00a0labels: service: db \u00a0\u00a0name: db spec: \u00a0\u00a0replicas: 1 \u00a0\u00a0selector: matchLabels: \u00a0\u00a0service: db \u00a0\u00a0template: metadata: \u00a0\u00a0labels: \u00a0\u00a0\u00a0\u00a0service: db \u00a0\u00a0\u00a0\u00a0tier: backend spec: \u00a0\u00a0containers: \u00a0\u00a0\u00a0\u00a0- image: postgres \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: database \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0env: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: POSTGRES_USER \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0valueFrom: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0secretKeyRef: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: notejam-credentials \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: user \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: POSTGRES_PASSWORD \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0valueFrom: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0secretKeyRef: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: notejam-credentials \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: password \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: POSTGRES_DB \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0valueFrom: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0configMapKeyRef: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: db-config \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: db-name \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ports: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- containerPort: 5432 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resources: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0requests: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 100m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 128Mi \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0limits: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 250m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 256Mi \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0volumeMounts: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- mountPath: \/var\/lib\/mysql\/data \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: data-db \u00a0\u00a0restartPolicy: Always \u00a0\u00a0volumes: \u00a0\u00a0\u00a0\u00a0- name: data-db \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0persistentVolumeClaim: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0claimName: data-db  #db-service.yaml apiVersion: v1 kind: Service metadata: \u00a0\u00a0labels: service: db \u00a0\u00a0name: db spec: \u00a0\u00a0ports: - name: \"5432\" \u00a0\u00a0protocol: TCP \u00a0\u00a0port: 5432 \u00a0\u00a0targetPort: 5432 \u00a0\u00a0selector: service: db  apiVersion: apps\/v1 kind: Deployment metadata: \u00a0\u00a0labels: service: web \u00a0\u00a0name: web spec: \u00a0\u00a0replicas: 1 \u00a0\u00a0selector: matchLabels: \u00a0\u00a0service: web \u00a0\u00a0template: metadata: \u00a0\u00a0labels: \u00a0\u00a0\u00a0\u00a0service: web spec: \u00a0\u00a0containers: \u00a0\u00a0\u00a0\u00a0- args: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- bash \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- -c \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- python manage.py syncdb --noinput &amp;&amp; python manage.py migrate &amp;&amp; python manage.py runserver 0.0.0.0:5000 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0image: arshad1914\/pipeline:latest \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: notejam \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ports: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- containerPort: 5000 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resources: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0requests: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 100m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 128Mi \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0limits: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cpu: 250m \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory: 250Mi \u00a0\u00a0restartPolicy: Always  apiVersion: v1 kind: Service metadata: \u00a0\u00a0labels: service: web \u00a0\u00a0name: web spec: \u00a0\u00a0type: LoadBalancer \u00a0\u00a0ports: - name: \"5000\" \u00a0\u00a0port: 5000 \u00a0\u00a0targetPort: 5000 \u00a0\u00a0selector: service: web<\/code><\/pre>\n<p>3. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Jenkinsfile, \u0433\u0434\u0435 \u043e\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438<\/p>\n<pre><code class=\"python\">pipeline { agent any \u00a0\u00a0\u00a0\u00a0environment { \u00a0\u00a0\u00a0 PROJECT_ID = 'docker' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CLUSTER_NAME = 'jenkins' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LOCATION = 'us-central-1a' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CREDENTIALS_ID = 'kubernetes' \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0 stages { \u00a0\u00a0\u00a0\u00a0stage('Checkout') { \u00a0\u00a0\u00a0 steps { \u00a0\u00a0\u00a0 checkout scm \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0stage('Build image') { \u00a0\u00a0\u00a0 steps { \u00a0\u00a0\u00a0 script { \u00a0\u00a0\u00a0 app = docker.build(\"zetzo\/pipeline:{env.BUILD_ID}\") \u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 \u00a0 \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0stage('Deploy to K8s') { \u00a0\u00a0\u00a0 steps{ \u00a0\u00a0\u00a0 echo \"Deployment started ...\" \u00a0\u00a0\u00a0 sh 'ls -ltr' \u00a0\u00a0\u00a0 sh 'pwd' \u00a0\u00a0\u00a0 sh \"sed -i 's\/pipeline:latest\/pipeline:class: 'KubernetesEngineBuilder',  \u00a0\u00a0\u00a0 \u00a0 projectId: env.PROJECT_ID,  \u00a0\u00a0\u00a0 \u00a0 clusterName: env.CLUSTER_NAME,  \u00a0\u00a0\u00a0 \u00a0 location: env.LOCATION,  \u00a0\u00a0\u00a0 \u00a0 manifestPattern: 'deployment.yaml',  \u00a0\u00a0\u00a0 \u00a0 credentialsId: env.CREDENTIALS_ID,  \u00a0\u00a0\u00a0 \u00a0 verifyDeployments: true]) \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 }\u00a0\u00a0\u00a0\u00a0 }<\/code><\/pre>\n<p><strong>\u0428\u0430\u0433 4. \u041f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d (\u0441\u043f\u043e\u0439\u043b\u0435\u0440: \u0443\u0441\u043f\u0435\u0448\u043d\u043e)<\/strong><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u043b\u0438, \u0412\u044b \u0432\u043e\u0441\u0445\u0438\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b!<\/p>\n<p>P.s.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0447\u0442\u043e\u0431\u044b \u0434\u0435\u043f\u043b\u043e\u0439 \u0431\u044b\u043b \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\u044b\u043c (\u0442.\u0435. \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043e\u0442 Continuous Delivery \u043a Continuous Deployment), \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0435\u0431\u0445\u0443\u043a \u0432 \u0432\u0430\u0448\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 <\/p>\n<p><em>settings > webhooks > add webhooks > url \u0412\u0430\u0448\u0435\u0433\u043e Jenkins instance<\/em><\/p>\n<p>\u0412 \u0412\u0430\u0448\u0435\u043c Jenkins pipeline, \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u0442\u0430\u0432\u0438\u043c \u0433\u0430\u043b\u043e\u0447\u043a\u0443 \u0432 \u043f\u043e\u043b\u0435 \u0437\u0434\u0435\u0441\u044c<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0447\u0443 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435\u043c <a href=\"https:\/\/otus.pw\/QtnP\/\">\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u043a<\/a> \u043e\u0442 OTUS \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u044b\u043b\u043a\u0438 \u043a \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e &#171;\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0442\u043e\u0440\u0430&#187; &#8212; docker.<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/otus.pw\/QtnP\/\">\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u043a<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/699300\/\"> https:\/\/habr.com\/ru\/company\/otus\/blog\/699300\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-341242","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/341242","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=341242"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/341242\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=341242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=341242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=341242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}