diff --git a/examples/inventory-rolling-update/README.md b/examples/inventory-rolling-update/README.md new file mode 100644 index 0000000..6586d53 --- /dev/null +++ b/examples/inventory-rolling-update/README.md @@ -0,0 +1,40 @@ +# Rolling update to targets from inventory plugin + +This example runs a rolling update to set of servers. The servers are defined in a Terraform configuration in [resources](./resources) directory and used as target nodes via `server_group` option of the inventory plugin. + +To run this example, you will need: + +- Terraform +- Ansible +- upcloud-ansible-collection and UpCloud python SDK (`upcloud-api>=2.5.0`) + +First configure your credentials to UpCloud Terraform provider and Ansible inventory plugin by setting `UPCLOUD_USERNAME` and `UPCLOUD_PASSWORD` environment variables. + +Create the servers defined in the Terraform configuration with `terraform apply` command. + +```sh +terraform -chdir=resources apply +# Answer yes, when propted by Terraform +``` + +Configure a NGINX server with static web page by running the [configure-webserver.yml](./configure-webserver.yml) playbook. + +```sh +# For initial configuration, configure all targets in parallel +ansible-playbook configure-webserver.yml --extra-vars "serial_override=0" + +# When updating the targets, specify which tag (cow, dog, hello, tiger) to use +ansible-playbook configure-webserver.yml --extra-vars "animal=tiger" +``` + +To monitor how the rolling update proceeds, open another terminal window and curl the load-balancer URL. The URL is visible at the output of prevous `terraform apply` command and can be printed by running `terraform output`. + +```sh +watch -n 0.75 curl -s $(terraform -chdir=resources output lb_url) +``` + +Finally, to cleanup the created cloud resources, run `terraform destroy` in the [resources](./resources) directory. + +```sh +terraform -chdir=resources destroy +``` diff --git a/examples/inventory-rolling-update/ansible.cfg b/examples/inventory-rolling-update/ansible.cfg new file mode 100644 index 0000000..89136ac --- /dev/null +++ b/examples/inventory-rolling-update/ansible.cfg @@ -0,0 +1,6 @@ +[defaults] +host_key_checking = False +inventory = ./inventory.upcloud.yml + +[inventory] +enable_plugins = community.upcloud.upcloud diff --git a/examples/inventory-rolling-update/configure-webserver.yml b/examples/inventory-rolling-update/configure-webserver.yml new file mode 100644 index 0000000..dc485d7 --- /dev/null +++ b/examples/inventory-rolling-update/configure-webserver.yml @@ -0,0 +1,41 @@ +- name: Configure webserver + hosts: all + remote_user: admin + become: yes + serial: "{{ serial_override | default(1) }}" + vars: + animal: cow + tasks: + - name: Install nginx + apt: + package: nginx + state: latest + update_cache: yes + - name: Get latest static content release + uri: + url: https://api.github.com/repos/UpCloudLtd/hello-container/releases/latest + register: release + - name: Remote default from enabled sites + file: + path: /etc/nginx/sites-enabled/default + state: absent + notify: + - Restart nginx + - name: Download and unarchive static content ({{ animal }}) + unarchive: + remote_src: yes + src: https://github.com/UpCloudLtd/hello-container/releases/download/{{ release.json.tag_name }}/hello-{{ animal }}.tar.gz + dest: /usr/share/nginx/html/ + notify: + - Restart nginx + - name: Configure nginx + get_url: + url: https://github.com/UpCloudLtd/hello-container/releases/download/{{ release.json.tag_name }}/index.conf + dest: /etc/nginx/conf.d/ + notify: + - Restart nginx + handlers: + - name: Restart nginx + service: + name: nginx + state: restarted diff --git a/examples/inventory-rolling-update/inventory.upcloud.yml b/examples/inventory-rolling-update/inventory.upcloud.yml new file mode 100644 index 0000000..924f560 --- /dev/null +++ b/examples/inventory-rolling-update/inventory.upcloud.yml @@ -0,0 +1,2 @@ +plugin: community.upcloud.upcloud +server_group: ansible-inventory-example-servergroup diff --git a/examples/inventory-rolling-update/resources/.gitignore b/examples/inventory-rolling-update/resources/.gitignore new file mode 100644 index 0000000..5c842c3 --- /dev/null +++ b/examples/inventory-rolling-update/resources/.gitignore @@ -0,0 +1,3 @@ +.terraform/ +.terraform* +*.tfstate* diff --git a/examples/inventory-rolling-update/resources/main.tf b/examples/inventory-rolling-update/resources/main.tf new file mode 100644 index 0000000..94c9e72 --- /dev/null +++ b/examples/inventory-rolling-update/resources/main.tf @@ -0,0 +1,94 @@ +terraform { + required_providers { + upcloud = { + source = "UpCloudLtd/upcloud" + version = "~> 2.4" + } + } +} + +variable "prefix" { + type = string + default = "ansible-inventory-example-" +} + +variable "zone" { + type = string + default = "pl-waw1" +} + +locals { + publickey_filename = one(fileset(pathexpand("~/.ssh/"), "*.pub")) + publickey = file("~/.ssh/${local.publickey_filename}") +} + +resource "upcloud_network" "network" { + name = "${var.prefix}net" + zone = var.zone + + ip_network { + family = "IPv4" + address = "10.100.1.0/24" + dhcp = true + } +} + +resource "upcloud_server" "webservers" { + count = 3 + hostname = "${var.prefix}server-${count.index}" + title = "${var.prefix}server-${count.index}" + zone = var.zone + plan = "1xCPU-1GB" + + metadata = true + + login { + user = "admin" + keys = [ + local.publickey, + ] + } + template { + storage = "Ubuntu Server 22.04 LTS (Jammy Jellyfish)" + size = 25 + title = "${var.prefix}storage-${count.index}" + } + + # In production, the public interface should be (in most cases) omitted: + # - Use a jump-host in the same network to control the application nodes. + # - Use a NAT gateway to provide internet access for the application nodes. + network_interface { + type = "public" + } + + network_interface { + type = "utility" + } + + network_interface { + type = "private" + network = upcloud_network.network.id + } +} + +resource "upcloud_server_group" "webservers" { + title = "${var.prefix}servergroup" + anti_affinity_policy = "yes" + members = upcloud_server.webservers[*].id +} + +module "load_balancer" { + source = "UpCloudLtd/basic-loadbalancer/upcloud" + + name = "${var.prefix}lb" + zone = var.zone + network = upcloud_network.network.id + backend_servers = [for v in upcloud_server.webservers : v.network_interface.2.ip_address] + backend_server_port = 80 + + frontend_port = 80 +} + +output "lb_url" { + value = module.load_balancer.dns_name +}