{"id":53611,"date":"2019-12-06T00:00:00","date_gmt":"2019-12-05T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1"},"modified":"2020-02-18T14:01:32","modified_gmt":"2020-02-18T11:01:32","slug":"legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1","title":{"rendered":"Easily and effortlessly deploy applications on Tarantool Cartridge (part 1)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Easily and effortlessly deploy applications on Tarantool Cartridge (part 1)\" src=\"\/wp-content\/uploads\/2019\/12\/0493b6c8d60253352bc971b216e9b63e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>We have already talked about <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/465503\/\">Tarantool Cartridge<\/a><\/noindex>, which allows you to develop distributed applications and package them. There's just one more step: learning how to deploy these applications and manage them. Don't worry, we've got everything covered! We have gathered all the best practices for working with Tarantool Cartridge and written the <noindex><a rel=\"nofollow\" href=\"https:\/\/galaxy.ansible.com\/tarantool\/cartridge\">ansible role<\/a><\/noindex>, which will unpack the package on the servers, start instances, cluster them, configure authorization, bootstrap vshard, enable automatic failover, and patch the cluster config.<\/p>\n<p><\/p>\n<p>Interested? Then come on in, we will tell and show you everything.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"nachnem-s-primera\">Let's start with an example<\/h1>\n<p><\/p>\n<p>We will only consider a part of the functionality of our role. You can always find a complete description of all its capabilities and input parameters in the <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tarantool\/ansible-cartridge#ansible-role-tarantool-cartridge\">the documentation<\/a><\/noindex>. But it's better to try once than to see a hundred times, so let's deploy a small application.<\/p>\n<p><\/p>\n<p>Tarantool Cartridge has a <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tarantool\/cartridge-cli\/tree\/master\/examples\/getting-started-app#application-example-based-on-tarantool-cartridge\">tutorial<\/a><\/noindex> for creating a small Cartridge application that stores information about bank customers and their accounts, as well as providing an API for managing data via HTTP. For this, the application describes two possible roles: <code>api<\/code> and <code>storage<\/code>, which can be assigned to instances.<\/p>\n<p><\/p>\n<p>The Cartridge itself does not dictate how to run processes; it only provides the means to configure already running instances. The rest, the user must do on their own: unpack configuration files, start services, and set up the topology. But we won't be doing all that, Ansible will handle it for us.<\/p>\n<p><\/p>\n<h3 id=\"ot-slov-k-delu\">From words to action<\/h3>\n<p><\/p>\n<p>So, let's deploy our application on two virtual machines and set up a simple topology:<\/p>\n<p><\/p>\n<ul>\n<li>Replica set <code>app-1<\/code> will implement the role <code>api<\/code>, which includes the role <code>vshard-router<\/code>. There will only be one instance here.<\/li>\n<li>Replica set <code>storage-1<\/code> implements the role <code>storage<\/code> (and at the same time <code>vshard-storage<\/code>), we will add two instances from different machines here.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Easily and effortlessly deploy applications on Tarantool Cartridge (part 1)\" src=\"\/wp-content\/uploads\/2019\/12\/62d20050e2d7a6358002ecd758222f1f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To run the example, we will need <noindex><a rel=\"nofollow\" href=\"https:\/\/www.vagrantup.com\/\">Vagrant<\/a><\/noindex> and <noindex><a rel=\"nofollow\" href=\"https:\/\/www.ansible.com\">Ansible<\/a><\/noindex> (version 2.8 or later).<\/p>\n<p><\/p>\n<p>The role itself is located in <noindex><a rel=\"nofollow\" href=\"https:\/\/galaxy.ansible.com\/docs\/\">Ansible Galaxy<\/a><\/noindex>. It is a repository that allows you to share your work and use ready-made roles.<\/p>\n<p><\/p>\n<p>Clone the repository with the example:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ git clone https:\/\/github.com\/dokshina\/deploy-tarantool-cartridge-app.git\n$ cd deploy-tarantool-cartridge-app &amp;&amp; git checkout 1.0.0<\/code><\/pre>\n<p><\/p>\n<p>Bring up the virtual machines:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ vagrant up<\/code><\/pre>\n<p><\/p>\n<p>Install the Tarantool Cartridge ansible role:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ ansible-galaxy install tarantool.cartridge,1.0.1<\/code><\/pre>\n<p><\/p>\n<p>Run the installed role:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ ansible-playbook -i hosts.yml playbook.yml<\/code><\/pre>\n<p><\/p>\n<p>We wait for the playbook to finish executing, and move on to <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8181\/admin\/cluster\/dashboard\">http:\/\/localhost:8181\/admin\/cluster\/dashboard<\/a><\/noindex> and enjoy the result:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Easily and effortlessly deploy applications on Tarantool Cartridge (part 1)\" src=\"\/wp-content\/uploads\/2019\/12\/6563ddf2f2bfc85714f327c8d6b2d1c4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>We can start loading data. Cool, right?<\/p>\n<p><\/p>\n<p>Now let's figure out how to work with this and also add another replicaset to the topology.<\/p>\n<p><\/p>\n<h3 id=\"nachinaem-razbiratsya\">Let's start figuring it out<\/h3>\n<p><\/p>\n<p>So, what happened?<\/p>\n<p><\/p>\n<p>We launched two virtual machines and ran an ansible playbook that set up our cluster. Let's take a look at the contents of the file <code>playbook.yml<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n- name: Deploy my Tarantool Cartridge app\n  hosts: all\n  become: true\n  become_user: root\n  tasks:\n  - name: Import Tarantool Cartridge role\n    import_role:\n      name: tarantool.cartridge<\/code><\/pre>\n<p><\/p>\n<p>Nothing interesting happens here, we are launching the ansible role called <code>tarantool.cartridge<\/code>.<\/p>\n<p><\/p>\n<p>All the important stuff (namely, the cluster configuration) is located in the <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/intro_inventory.html\">inventory<\/a><\/noindex>-file <code>hosts.yml<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\nall:\n  vars:\n    # common cluster variables\n    cartridge_app_name: getting-started-app\n    cartridge_package_path: .\\\/getting-started-app-1.0.0-0.rpm  # path to package\n\n    cartridge_cluster_cookie: app-default-cookie  # cluster cookie\n\n    # common ssh options\n    ansible_ssh_private_key_file: ~\\\/\\.vagrant.d\\\/insecure_private_key\n    ansible_ssh_common_args: '-o IdentitiesOnly=yes -o UserKnownHostsFile=\\\/dev\\\/null -o StrictHostKeyChecking=no'\n\n  # INSTANCES\n  hosts:\n    storage-1:\n      config:\n        advertise_uri: '172.19.0.2:3301'\n        http_port: 8181\n\n    app-1:\n      config:\n        advertise_uri: '172.19.0.3:3301'\n        http_port: 8182\n\n    storage-1-replica:\n      config:\n        advertise_uri: '172.19.0.3:3302'\n        http_port: 8183\n\n  children:\n    # GROUP INSTANCES BY MACHINES\n    host1:\n      vars:\n        # first machine connection options\n        ansible_host: 172.19.0.2\n        ansible_user: vagrant\n\n      hosts:  # instances to be started on the first machine\n        storage-1:\n\n    host2:\n      vars:\n        # second machine connection options\n        ansible_host: 172.19.0.3\n        ansible_user: vagrant\n\n      hosts:  # instances to be started on the second machine\n        app-1:\n        storage-1-replica:\n\n    # GROUP INSTANCES BY REPLICA SETS\n    replicaset_app_1:\n      vars:  # replica set configuration\n        replicaset_alias: app-1\n        failover_priority:\n          - app-1  # leader\n        roles:\n          - 'api'\n\n      hosts:  # replica set instances\n        app-1:\n\n    replicaset_storage_1:\n      vars:  # replica set configuration\n        replicaset_alias: storage-1\n        weight: 3\n        failover_priority:\n          - storage-1  # leader\n          - storage-1-replica\n        roles:\n          - 'storage'\n\n      hosts:   # replica set instances\n        storage-1:\n        storage-1-replica:<\/code><\/pre>\n<p><\/p>\n<p>All we need to do is learn how to manage instances and replicsets by changing the contents of this file. Later, we will add new sections to it. To avoid confusion about where to add them, you can refer to the final version of this file, <code>hosts.updated.yml<\/code>, which is located in the repository with the example.<\/p>\n<p><\/p>\n<h3 id=\"upravlenie-instansami\">Managing Instances<\/h3>\n<p><\/p>\n<p>In Ansible terms, each instance is a host (not to be confused with a physical server), i.e., a node in the infrastructure that Ansible will manage. For each host, we can specify connection parameters (such as <code>ansible_host<\/code> and <code>ansible_user<\/code>), as well as the instance configuration. The instance descriptions are located in the section <code>hosts<\/code>.<\/p>\n<p><\/p>\n<p>Let's consider the instance configuration <code>storage-1<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">all:\n  vars:\n    ...\n\n  # INSTANCES\n  hosts:\n    storage-1:\n      config:\n        advertise_uri: '172.19.0.2:3301'\n        http_port: 8181\n\n  ...<\/code><\/pre>\n<p><\/p>\n<p>In the variable <code>config<\/code> we specified the instance parameters \u2014 <code>advertise URI<\/code> and <code>HTTP port<\/code>.<br \/>\nBelow are the parameters of the instances <code>app-1<\/code> and <code>storage-1-replica<\/code>.<\/p>\n<p><\/p>\n<p>We need to inform Ansible about the connection parameters for each instance. It makes sense to group the instances by virtual machines. For this purpose, the instances are grouped into categories <code>host1<\/code> and <code>host2<\/code>, and in each group in the section <code>vars<\/code> the values are specified <code>ansible_host<\/code> and <code>ansible_user<\/code> for one virtual machine. And in the section <code>hosts<\/code> \u2014 hosts (which are also instances) that are included in this group:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">all:\n  vars:\n    ...\n  hosts:\n    ...\n  children:\n    # GROUP INSTANCES BY MACHINES\n    host1:\n      vars:\n        # first machine connection options\n        ansible_host: 172.19.0.2\n        ansible_user: vagrant\n       hosts:  # instances to be started on the first machine\n        storage-1:\n\n     host2:\n      vars:\n        # second machine connection options\n        ansible_host: 172.19.0.3\n        ansible_user: vagrant\n       hosts:  # instances to be started on the second machine\n        app-1:\n        storage-1-replica:<\/code><\/pre>\n<p><\/p>\n<p>Let's start making changes <code>hosts.yml<\/code>. We will add two more instances, <code>storage-2-replica<\/code> on the first virtual machine and <code>storage-2<\/code> on the second:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">all:\n  vars:\n    ...\n\n  # INSTANCES\n  hosts:\n    ...\n    storage-2:  # &lt;==\n      config:\n        advertise_uri: &#039;172.19.0.3:3303&#039;\n        http_port: 8184\n\n    storage-2-replica:  # &lt;==\n      config:\n        advertise_uri: &#039;172.19.0.2:3302&#039;\n        http_port: 8185\n\n  children:\n    # GROUP INSTANCES BY MACHINES\n    host1:\n      vars:\n        ...\n      hosts:  # instances to be started on the first machine\n        storage-1:\n        storage-2-replica:  # &lt;==\n\n    host2:\n      vars:\n        ...\n      hosts:  # instances to be started on the second machine\n        app-1:\n        storage-1-replica:\n        storage-2:  # &lt;==\n  ...<\/code><\/pre>\n<p><\/p>\n<p>Let's run the ansible playbook:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ ansible-playbook -i hosts.yml \n                   --limit storage-2,storage-2-replica \n                   playbook.yml<\/code><\/pre>\n<p><\/p>\n<p>Note the option <code>--limit<\/code>. Since each cluster instance is a host in Ansible terms, we can explicitly specify which instances should be configured when executing the playbook.<\/p>\n<p><\/p>\n<p>Once again, we enter the Web UI <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8181\/admin\/cluster\/dashboard\">http:\/\/localhost:8181\/admin\/cluster\/dashboard<\/a><\/noindex> and observe our new instances:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Easily and effortlessly deploy applications on Tarantool Cartridge (part 1)\" src=\"\/wp-content\/uploads\/2019\/12\/6181c359e4e5ec4adaee8737600a27e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Let\u2019s not stop there and learn to manage the topology.<\/p>\n<p><\/p>\n<h3 id=\"upravlenie-topologiey\">Topology Management<\/h3>\n<p><\/p>\n<p>We will group our new instances into a replica set <code>storage-2<\/code>. Let's add a new group <code>replicaset_storage_2<\/code> and describe its variables for the replica set similarly to <code>replicaset_storage_1<\/code>. In the section <code>hosts<\/code> let's specify which instances will be included in this group (that is, our replica set):<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\nall:\n  vars:\n    ...\n  hosts:\n    ...\n  children:\n    ...\n    # GROUP INSTANCES BY REPLICA SETS\n    ...\n    replicaset_storage_2:  # &lt;==\n      vars:  # replicaset configuration\n        replicaset_alias: storage-2\n        weight: 2\n        failover_priority:\n          - storage-2\n          - storage-2-replica\n        roles:\n          - &#039;storage&#039;\n\n      hosts:   # replicaset instances\n        storage-2:\n        storage-2-replica:<\/code><\/pre>\n<p><\/p>\n<p>Let's run the playbook again:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ ansible-playbook -i hosts.yml \n                   --limit replicaset_storage_2 \n                   --tags cartridge-replicasets \n                   playbook.yml<\/code><\/pre>\n<p><\/p>\n<p>In the parameter <code>--limit<\/code> this time we provided the name of the group corresponding to our replica set.<\/p>\n<p><\/p>\n<p>Let's consider the option <code>tags<\/code>.<\/p>\n<p><\/p>\n<p>Our role sequentially performs various tasks marked with the following tags:<\/p>\n<p><\/p>\n<ul>\n<li><code>cartridge-instances<\/code>: managing instances (configuration, connecting to membership);<\/li>\n<li><code>cartridge-replicasets<\/code>: managing topology (managing replica sets and permanently removing (expelling) instances from the cluster);<\/li>\n<li><code>cartridge-config<\/code>: managing other cluster parameters (vshard bootstrapping, automatic failover mode, authorization parameters, and application configuration).<\/li>\n<\/ul>\n<p><\/p>\n<p>We can explicitly specify which part of the work we want to do, then the role will skip the execution of the remaining tasks. In our case, we want to work only with the topology, so we specified <code>cartridge-replicasets<\/code>.<\/p>\n<p><\/p>\n<p>Let\u2019s evaluate the results of our efforts. We find the new replica set at <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8181\/admin\/cluster\/dashboard\">http:\/\/localhost:8181\/admin\/cluster\/dashboard<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Easily and effortlessly deploy applications on Tarantool Cartridge (part 1)\" src=\"\/wp-content\/uploads\/2019\/12\/20da99480df519b1ee239cd81f67b786.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hooray!<\/p>\n<p><\/p>\n<p>Experiment with changing the configurations of instances and replica sets and see how the cluster topology changes. You can try different operational scenarios, such as <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_delegation.html#rolling-update-batch-size\">rolling update<\/a><\/noindex> or increasing <code>memtx_memory<\/code>. The role will attempt to do this without restarting the instance, to minimize potential downtime of your application.<\/p>\n<p><\/p>\n<p>Don\u2019t forget to run <code>vagrant halt<\/code>, to stop the virtual machines when you're done working with them.<\/p>\n<p><\/p>\n<h1 id=\"a-chto-pod-kapotom\">What\u2019s under the hood?<\/h1>\n<p><\/p>\n<p>Here, I will explain in more detail what was happening under the hood of the ansible role during our experiments.<\/p>\n<p><\/p>\n<p>Let\u2019s go through the steps of deploying a Cartridge application.<\/p>\n<p><\/p>\n<h3 id=\"ustanovka-paketa-i-start-instansov\">Installing the package and starting instances<\/h3>\n<p><\/p>\n<p>First, we need to deliver the package to the server and install it. The role can currently work with RPM and DEB packages.<\/p>\n<p><\/p>\n<p>Next, we start the instances. It\u2019s very simple: each instance is a separate <code>systemd<\/code>-service. I\u2019ll explain with an example:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ systemctl start myapp@storage-1<\/code><\/pre>\n<p><\/p>\n<p>This command will start the instance <code>storage-1<\/code> of the application <code>myapp.<\/code>The started instance will look for its <noindex><a rel=\"nofollow\" href=\"https:\/\/www.tarantool.io\/ru\/doc\/2.2\/book\/cartridge\/cartridge_dev\/#configuring-instances\">configuration.<\/a><\/noindex> downward API support (simultaneously with this in <code>\/etc\/tarantool\/conf.d\/<\/code>You can view the instance logs using <code>journald<\/code>.<\/p>\n<p><\/p>\n<p>The unit file <code>\/etc\/systemd\/system\/myapp@.sevice<\/code> for the systemd service will be delivered along with the package.<\/p>\n<p><\/p>\n<p>Ansible has built-in modules for package installation and managing systemd services, so we haven't reinvented anything here.<\/p>\n<p><\/p>\n<h3 id=\"nastroyka-topologii-klastera\">Cluster topology configuration<\/h3>\n<p><\/p>\n<p>And this is where it gets interesting. Agree, it would be strange to bother with a special Ansible role for package installation and launching <code>systemd<\/code>-services.<\/p>\n<p><\/p>\n<p>You can configure the cluster manually:<\/p>\n<p><\/p>\n<ul>\n<li>First option: open the Web UI and click the buttons. This will be quite suitable for a one-time launch of multiple instances.<\/li>\n<li>Second option: you can use the GraphQL API. Here you can automate something, for example, write a script in Python.<\/li>\n<li>Third option (for the strong-spirited): enter the server, connect to one of the instances using <code>tarantoolctl connect<\/code> and perform all necessary actions with the Lua module <code>cartridge<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>The main task of our invention is to handle this most complex part of the work for you.<\/p>\n<p><\/p>\n<p>Ansible allows you to write your own module and use it in a role. Our role uses such modules to manage various cluster components.<\/p>\n<p><\/p>\n<p>How does it work? You describe the desired state of the cluster in a declarative config, and the role provides each module with its configuration section. The module compares the current state of the cluster with what was provided. Then, through the socket of one of the instances, code is executed that brings the cluster to the desired state.<\/p>\n<p><\/p>\n<h1 id=\"itogi\">Summary<\/h1>\n<p><\/p>\n<p>Today we explained and demonstrated how to deploy your application on Tarantool Cartridge and set up a simple topology. For this, we used Ansible\u2014a powerful tool that stands out for its ease of use and allows simultaneous configuration of many infrastructure nodes (in our case, these are the cluster instances).<\/p>\n<p><\/p>\n<p>Above, we covered one of the many ways to describe the cluster configuration using Ansible. Once you understand that you are ready to move forward, explore <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_best_practices.html\">best practices<\/a><\/noindex> for writing playbooks. You may find it more convenient to manage the topology using <code>group_vars<\/code> and <code>host_vars<\/code>.<\/p>\n<p><\/p>\n<p>Very soon we will explain how to permanently remove instances from the topology, bootstrap vshard, manage automatic failover mode, configure authorization, and patch the cluster config. Meanwhile, you can study and experiment with cluster parameter changes on your own. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tarantool\/ansible-cartridge#ansible-role-tarantool-cartridge\">documentation<\/a><\/noindex> and experiment with changing cluster parameters.<\/p>\n<p><\/p>\n<p>If something isn't working, be sure to <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tarantool\/ansible-cartridge\/issues\/new\">let us know<\/a><\/noindex> about the issue. We will resolve everything promptly!<\/p>\n<p>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/478710\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u044b \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438 \u043f\u0440\u043e Tarantool Cartridge, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0438\u0445. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432\u0441\u0435\u0433\u043e \u043d\u0438\u0447\u0435\u0433\u043e: \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u044d\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043c\u0438. \u041d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0439\u0442\u0435\u0441\u044c, \u043c\u044b \u0432\u0441\u0451 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438! \u041c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0432\u043c\u0435\u0441\u0442\u0435 \u0432\u0441\u0435 best practices \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Tarantool Cartridge \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 ansible-\u0440\u043e\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0437\u043b\u043e\u0436\u0438\u0442 \u043f\u0430\u043a\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u044b, \u0441\u0442\u0430\u0440\u0442\u0430\u043d\u0435\u0442 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442 \u0438\u0445 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-53611","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u044b \u0443\u0436\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041b\u0435\u0433\u043a\u043e \u0438 \u043d\u0435\u043f\u0440\u0438\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Tarantool Cartridge (\u0447\u0430\u0441\u0442\u044c 1) | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u044b \u0443\u0436\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-12-05T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:01:32+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Easily and effortlessly deploying applications on Tarantool Cartridge (part 1) | ProHoster","description":"We already are.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041b\u0435\u0433\u043a\u043e \u0438 \u043d\u0435\u043f\u0440\u0438\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Tarantool Cartridge (\u0447\u0430\u0441\u0442\u044c 1) | ProHoster","og:description":"\u041c\u044b \u0443\u0436\u0435.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/legko-i-neprinuzhdenno-deploim-prilozheniya-na-tarantool-cartridge-chast-1","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-12-05T21:00:00+00:00","article:modified_time":"2020-02-18T11:01:32+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"53611","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 08:06:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:22:49","updated":"2026-01-24 08:06:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/53611","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=53611"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/53611\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=53611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=53611"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=53611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}