Answers: <p>I have <a href="https://github.com/simbo1905/microservices-demo-ansible" rel="nofollow noreferrer">created a demo with a role</a> that can install many springboot microservices on a fleet of VMs where you name a subset of the VMs where you want to place each service. The playbook can then run on all hosts, compute whether each service should be on each host, and will either run the install.yaml or uninstall.yml tasks. </p>
  
  <p>To install two of the same microservices with different runtime args you play something like:</p>
  
  <pre>
  roles:
      - {
        role: "ansible-role-springboot",
        sb_app_name: "microservices-registration",
        sb_app_group_id: "org.springframework.samples.service.service",
        sb_app_artifact_id: "microservices-demo",
        sb_app_version: "2.0.0.RELEASE",
        sb_app_run_args: '"registration 8082"',
        sb_app_healthcheck_urls: [
          "http://localhost:8082/actuator/health"
        ],
        <b>sb_hosts: [
          "my-test-vm"
        ]</b>
      }
      - {
        role: "ansible-role-springboot",
        sb_app_name: "microservices-web",
        sb_app_group_id: "org.springframework.samples.service.service",
        sb_app_artifact_id: "microservices-demo",
        sb_app_version: "2.0.1.RELEASE",
        sb_app_run_args: '"web 8083"',
        sb_app_healthcheck_urls: [
          "http://localhost:8083/actuator/health"
        ],
        <b>sb_hosts: [
          "my-test-vm"
        ]</b>
      }
  </pre>
  
  <p>The role is based upon <a href="https://github.com/orachide/ansible-role-springboot" rel="nofollow noreferrer">orachide/ansible-role-springboot</a> which seems very comprehensive. The new bit is in bold which is simply a list of host that should run the microservice. </p>
  
  <p>Normally we would expect to use different artefact ids and versions each time we apply the role. In the example above, it is running an official <a href="https://github.com/simbo1905/microservices-demo" rel="nofollow noreferrer">springboot microservices mega jar</a> that takes different <code>RUN_AS</code> args to run as different services. That seems a bit odd and not something I would recommend yet the role is agnostic to such details. </p>
  
  <p>What thing that the original role requires is that you use an executable jar file: </p>
  
  <pre><code>        &lt;plugin&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
              &lt;configuration&gt;
                  &lt;executable&gt;true&lt;/executable&gt;
              &lt;/configuration&gt;
          &lt;/plugin&gt;
  </code></pre>
  
  <p>It role will create a symlink to that executable and create an environment files to run it and all that good stuff. </p>
  
  <p>The modifications that I made were quite simple as the original role has logic to install or uninstall based on <code>sb_app_state</code>:</p>
  
  <pre><code>- import_tasks: install.yml
    when: &gt;
          sb_app_state == 'present'
  
  - import_tasks: uninstall.yml
    when: &gt;
          sb_app_state == 'absent'
  </code></pre>
  
  <p>So it was simply a matter of adding some logic to check whether the current hostname is in the <code>sb_hosts</code> list then update the value of <code>sb_app_state</code> as appropriate. That is done <a href="https://github.com/simbo1905/microservices-demo-ansible/blob/cfca2542694633356bab9abb8f01bf818fcc8e99/roles/ansible-role-springboot/tasks/main.yml#L9" rel="nofollow noreferrer">with a single line change</a>. </p>
  
  <p>The demo codebase uses test kitchen ansible with testinfra to unit test that the playbook works. Getting that working was well worth the effort to do automated acceptance tests of the playbook logic. </p>
  
Answers: CC BY-SA 4.0
Answers: 2019-02-19T16:45:58.420Z
Answers: 2019-02-20T06:42:07.087Z
Answers: 2019-02-20T06:42:07.087Z
Answers: simbo1905
Body: <p>I am working with a microservices application that is using Ansible to deploy to a fleet of VMs. We have different numbers of replicas of each microservice type running across the VM fleet. Deployments are working fine using a single deploy playbook, passing it extra variables to say which service to install, and giving naming it a group of hosts in the inventory to run against.</p>
  
  <p>Occasionally we need to move microservices between hosts to rebalance load. This isn't clean with how we have set up Ansible. Moving one microservice instance means adding one new host entry, and removing one old host entry, from the inventory group. The new instance is installed but no logic will run against the removed host. We have to run another playbook to uninstall the service from the removed host. </p>
  
  <p>I am looking for a way to reorganize ansible so that it will quickly move a microservice. I am thinking that we should use a single inventory group of all hosts and use a list variable to say which hosts a microservice runs on. A custom fact can be set when a service is installed. The install task can check the fact and that the current host is in the list. The uninstall task can also check the fact and that the current host isn't in the list. Is this the right way to organise the logic or is there a better way?</p>
  
Comments: CC BY-SA 4.0
Comments: 2019-02-17T12:25:58.003Z
Comments: Allow me one question: why don't you use an orchestrator or Kubernetes / Docker swarm
Comments: Marged
Comments: CC BY-SA 4.0
Comments: 2019-02-17T12:32:37.840Z
Comments: At my own enterprises we use do use k8s on aws and I have open sourced my automation with helmfile as ”ocd” At a particular global client they haven't yet approved containers for production. They do have on-prem GitHub and on-prem ansible tower.
Comments: simbo1905
Tags: <ansible><microservices>
Title: How to have Ansible move a microservice?
UserDisplayName: simbo1905
ThreadText: # How to have Ansible move a microservice?
  
  (Asked by: username_0 on 2019-02-16)
  
  I am working with a microservices application that is using Ansible to deploy to a fleet of VMs. We have different numbers of replicas of each microservice type running across the VM fleet. Deployments are working fine using a single deploy playbook, passing it extra variables to say which service to install, and giving naming it a group of hosts in the inventory to run against.
  
  Occasionally we need to move microservices between hosts to rebalance load. This isn't clean with how we have set up Ansible. Moving one microservice instance means adding one new host entry, and removing one old host entry, from the inventory group. The new instance is installed but no logic will run against the removed host. We have to run another playbook to uninstall the service from the removed host.
  
  I am looking for a way to reorganize ansible so that it will quickly move a microservice. I am thinking that we should use a single inventory group of all hosts and use a list variable to say which hosts a microservice runs on. A custom fact can be set when a service is installed. The install task can check the fact and that the current host is in the list. The uninstall task can also check the fact and that the current host isn't in the list. Is this the right way to organise the logic or is there a better way?
  
  **Tags:** ansible, microservices
  
  > **Comments:**
  > **username_1**: Allow me one question: why don't you use an orchestrator or Kubernetes / Docker swarm  
  > **username_0**: At my own enterprises we use do use k8s on aws and I have open sourced my automation with helmfile as ”ocd” At a particular global client they haven't yet approved containers for production. They do have on-prem GitHub and on-prem ansible tower.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2019-02-19. Score: 0 | Accepted answer
  
  I have [created a demo with a role](https://github.com/username_0/microservices-demo-ansible) that can install many springboot microservices on a fleet of VMs where you name a subset of the VMs where you want to place each service. The playbook can then run on all hosts, compute whether each service should be on each host, and will either run the install.yaml or uninstall.yml tasks.
  
  To install two of the same microservices with different runtime args you play something like:
  
  ```
  
  roles:
      - {
        role: "ansible-role-springboot",
        sb_app_name: "microservices-registration",
        sb_app_group_id: "org.springframework.samples.service.service",
        sb_app_artifact_id: "microservices-demo",
        sb_app_version: "2.0.0.RELEASE",
        sb_app_run_args: '"registration 8082"',
        sb_app_healthcheck_urls: [
          "http://localhost:8082/actuator/health"
        ],
        sb_hosts: [
          "my-test-vm"
        ]
      }
      - {
        role: "ansible-role-springboot",
        sb_app_name: "microservices-web",
        sb_app_group_id: "org.springframework.samples.service.service",
        sb_app_artifact_id: "microservices-demo",
        sb_app_version: "2.0.1.RELEASE",
        sb_app_run_args: '"web 8083"',
        sb_app_healthcheck_urls: [
          "http://localhost:8083/actuator/health"
        ],
        sb_hosts: [
          "my-test-vm"
        ]
      }
  
  ```
  
  The role is based upon [orachide/ansible-role-springboot](https://github.com/orachide/ansible-role-springboot) which seems very comprehensive. The new bit is in bold which is simply a list of host that should run the microservice.
  
  Normally we would expect to use different artefact ids and versions each time we apply the role. In the example above, it is running an official [springboot microservices mega jar](https://github.com/username_0/microservices-demo) that takes different `RUN_AS` args to run as different services. That seems a bit odd and not something I would recommend yet the role is agnostic to such details.
  
  What thing that the original role requires is that you use an executable jar file:
  
  ```
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
              <configuration>
                  <executable>true</executable>
              </configuration>
          </plugin>
  
  ```
  
  It role will create a symlink to that executable and create an environment files to run it and all that good stuff.
  
  The modifications that I made were quite simple as the original role has logic to install or uninstall based on `sb_app_state`:
  
  ```
  - import_tasks: install.yml
    when: >
          sb_app_state == 'present'
  
  - import_tasks: uninstall.yml
    when: >
          sb_app_state == 'absent'
  
  ```
  
  So it was simply a matter of adding some logic to check whether the current hostname is in the `sb_hosts` list then update the value of `sb_app_state` as appropriate. That is done [with a single line change](https://github.com/username_0/microservices-demo-ansible/blob/cfca2542694633356bab9abb8f01bf818fcc8e99/roles/ansible-role-springboot/tasks/main.yml#L9).
  
  The demo codebase uses test kitchen ansible with testinfra to unit test that the playbook works. Getting that working was well worth the effort to do automated acceptance tests of the playbook logic.
  
  
  ---
  
  