Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodeFest 2019. Леонид Руденко (JetBrains) — Terraform на примере кластера Selenoid

CodeFest
April 06, 2019

CodeFest 2019. Леонид Руденко (JetBrains) — Terraform на примере кластера Selenoid

Тесты нескольких команд в JetBrains используют инфраструктуру на основе Selenoid. Поддерживать ее помогает Terraform.

Из доклада вы узнаете:
— что за инструмент Terraform;
— как Terraform может упростить развертывание и поддержку кластера Selenoid;
— в чем отличие от Ansible и стандартного configuration management Selenoid.

Terraform — достаточно универсальный инструмент. Найти ему применение можно не только в работе с Selenoid, но и в поддержке иной инфраструктуры.

CodeFest

April 06, 2019
Tweet

More Decks by CodeFest

Other Decks in Technology

Transcript

  1. 1. Motivation 2. Terraform 101 3. Tips & Tricks for

    Selenoid cluster 4. Alternatives: cm & ansible What’s going on here — 10
  2. 1. Motivation 2. Terraform 101 3. Tips & Tricks for

    Selenoid cluster 4. Alternatives: cm & ansible What’s going on here — 11
  3. docker pull selenoid/firefox:latest docker pull selenoid/chrome:latest docker pull aandryashin/selenoid:1.0.0 nano

    /etc/selenoid/browsers.json docker run -d -p 4444:4444 \ -v /etc/selenoid:/etc/selenoid:ro \ -v /var/run/docker.sock:/var/run/docker.sock \ aandryashin/selenoid:1.0.0 Selenoid Quick Start — 14
  4. Why Terraform? — Selenoid #1 Selenoid #2 GGR @Test Selenoid-UI

    #1 Selenoid-UI #2 68, 69, ... 47, 62, ... 68, 69, ... 47, 62, ... • 4 VMs • 9 containers • > 10 images 15
  5. 1. Motivation 2. Terraform 101 3. Tips & Tricks for

    Selenoid cluster 4. Alternatives: cm & ansible What’s going on here — 17
  6. • Configuration • Provider Terminology — provider "docker" { host

    = "tcp://virtual-machine.company.net:2375" } 19
  7. • Configuration • Provider Terminology — provider "vsphere" { user

    = "admin" password = "pa$$w0rd" vsphere_server = "vcenter-srv.company.net" allow_unverified_ssl = true } 20
  8. • Configuration • Provider • Resource Terminology — resource "docker_container"

    "selenoid" { image = "aerokube/selenoid:1.9.0" command = ["-limit", "8", "-timeout", "2m0s"] ... } 21
  9. • Configuration • Provider • Resource Terminology — resource "docker_container"

    "selenoid" { image = "aerokube/selenoid:1.9.0" command = ["-limit", "8", "-timeout", "2m0s"] ... } Resource name Resource type 22
  10. • Selenoid is running on http://localhost:4444 (Linux and Mac) •

    https://git.io/tf-task1 Task #1 — $ docker images | grep selenoid $ $ docker ps -a $ 25
  11. Resource: container — resource "docker_container" "selenoid" { name = "selenoid"

    image = "${docker_image.selenoid.latest}" command = ["-limit", "4", "-timeout", "2m0s"] ports { internal = 4444 external = 4444 } volumes { host_path = "/var/run/docker.sock" container_path = "/var/run/docker.sock" } upload { content = "{}" file = "/etc/selenoid/browsers.json" } } 28
  12. Resource: container — resource "docker_container" "selenoid" { name = "selenoid"

    image = "${docker_image.selenoid.latest}" command = ["-limit", "4", "-timeout", "2m0s"] ports { internal = 4444 external = 4444 } volumes { host_path = "/var/run/docker.sock" container_path = "/var/run/docker.sock" } upload { content = "{}" file = "/etc/selenoid/browsers.json" } } 29
  13. Resource: container — resource "docker_container" "selenoid" { name = "selenoid"

    image = "${docker_image.selenoid.latest}" command = ["-limit", "4", "-timeout", "2m0s"] ports { internal = 4444 external = 4444 } volumes { host_path = "/var/run/docker.sock" container_path = "/var/run/docker.sock" } upload { content = "{}" file = "/etc/selenoid/browsers.json" } } 30
  14. Resource: container — resource "docker_container" "selenoid" { name = "selenoid"

    image = "${docker_image.selenoid.latest}" command = ["-limit", "4", "-timeout", "2m0s"] ports { internal = 4444 external = 4444 } volumes { host_path = "/var/run/docker.sock" container_path = "/var/run/docker.sock" } upload { content = "{}" file = "/etc/selenoid/browsers.json" } } 31
  15. Resource: container — resource "docker_container" "selenoid" { name = "selenoid"

    image = "${docker_image.selenoid.latest}" command = ["-limit", "4", "-timeout", "2m0s"] ports { internal = 4444 external = 4444 } volumes { host_path = "/var/run/docker.sock" container_path = "/var/run/docker.sock" } upload { content = "{}" file = "/etc/selenoid/browsers.json" } } 32
  16. Terraform init — $ terraform init Initializing provider plugins... -

    Checking for available provider plugins on https://releases.hashicorp.com... - Downloading plugin for provider "docker" (1.0.1)... Terraform has been successfully initialized! $ 33
  17. Terraform init — $ terraform init Initializing provider plugins... -

    Checking for available provider plugins on https://releases.hashicorp.com... - Downloading plugin for provider "docker" (1.0.1)... Terraform has been successfully initialized! $ 34
  18. Terraform apply — $ terraform apply docker_image.selenoid: Creating... docker_image.selenoid: Creation

    complete after 4s docker_container.selenoid: Creating... docker_container.selenoid: Creation complete after 1s Apply complete! Resources: 2 added, 0 changed, 0 destroyed. $ 35
  19. Terraform apply — $ terraform apply ... Do you want

    to perform these actions? Terraform will perform the actions described above. Only ‘yes’ will be accepted to approve. Enter a value: 36
  20. Terraform apply — $ terraform apply docker_image.selenoid: Creating... docker_image.selenoid: Creation

    complete after 4s docker_container.selenoid: Creating... docker_container.selenoid: Creation complete after 1s Apply complete! Resources: 2 added, 0 changed, 0 destroyed. $ 37
  21. Terraform state file — $ ls selenoid.tf terraform.tfstate $ docker_image.selenoid:

    Creation complete after 4s docker_container.selenoid: Creating... docker_container.selenoid: Creation complete after 1s Apply complete! Resources: 2 added, 0 changed, 0 destroyed. $ 39
  22. Terraform destroy — $ terraform destroy docker_container.selenoid: Destroying... docker_container.selenoid: Destruction

    complete after 1s docker_image.selenoid: Destroying... docker_image.selenoid: Destruction complete after 0s Destroy complete! Resources: 2 destroyed. $ 40
  23. Terraform destroy — $ terraform destroy docker_container.selenoid: Destroying... docker_container.selenoid: Destruction

    complete after 1s docker_image.selenoid: Destroying... docker_image.selenoid: Destruction complete after 0s Destroy complete! Resources: 2 destroyed. $ 41
  24. Variable — variable "browsers" { type = "list" default =

    [ "selenoid/chrome:69.0", "selenoid/firefox:62.0" ] } 44
  25. Terraform apply — $ terraform apply docker_image.selenoid: Creating... docker_image.selenoid: Creation

    complete after 4s docker_container.selenoid: Creating... docker_container.selenoid: Creation complete after 1s Apply complete! Resources: 2 added, 0 changed, 0 destroyed. $ 50
  26. Terraform apply — $ terraform apply Terraform will perform the

    following actions: -/+ docker_container.selenoid (new resource required) Plan: 1 to add, 0 to change, 1 to destroy. $ 53
  27. Mount config directory — upload { content = "{}" file

    = "/etc/selenoid/browsers.json" } volumes { host_path = "/Users/leonid.rudenko/selenoid/" container_path = "/etc/selenoid/" } 55
  28. Mount config directory — upload { content = "{}" file

    = "/etc/selenoid/browsers.json" } volumes { host_path = "/Users/leonid.rudenko/selenoid/" container_path = "/etc/selenoid/" } 56
  29. Mount config directory — upload { content = "{}" file

    = "/etc/selenoid/browsers.json" } volumes { host_path = "/Users/leonid.rudenko/selenoid/" container_path = "/etc/selenoid/" } 57
  30. Local file resource and provisioner — resource "local_file" "browsers_json" {

    content = "${file("browsers.json")}" filename = "/Users/leonid.rudenko/selenoid/" provisioner "local_exec" { command = "docker kill –s HUP ${docker_container.selenoid.id}" } } 58
  31. Local file resource and provisioner — resource "local_file" "browsers_json" {

    content = "${file("browsers.json")}" filename = "/Users/leonid.rudenko/selenoid/" provisioner "local_exec" { command = "docker kill –s HUP ${docker_container.selenoid.id}" } } 59
  32. Local file resource and provisioner — resource "local_file" "browsers_json" {

    content = "${file("browsers.json")}" filename = "/Users/leonid.rudenko/selenoid/" provisioner "local_exec" { command = "docker kill –s HUP ${docker_container.selenoid.id}" } } 60
  33. Local file resource and provisioner — resource "local_file" "browsers_json" {

    content = "${file("browsers.json")}" filename = "/Users/leonid.rudenko/selenoid/" provisioner "local_exec" { command = "docker kill –s HUP ${docker_container.selenoid.id}" } } 61
  34. Terraform apply — $ terraform apply Terraform will perform the

    following actions: + docker_image.browser_images[2] -/+ local_file.browsers_json (new resource required) Plan: 2 to add, 0 to change, 1 to destroy. $ 63
  35. 1. Motivation 2. Terraform 101 3. Tips & Tricks for

    Selenoid cluster 4. Alternatives: cm & ansible What’s going on here — 65
  36. 1. Multiple Selenoids: create a module — • variables.tf •

    main.tf • browsers.json "${file("${path.module}/browsers.json")}" 70
  37. 1. Multiple Selenoids: module usage — module "selenoid" { source

    = "../modules/selenoid" hostname = "sel-1.***.net" selenoid_container_name = "sel1" } 71
  38. 1. Multiple Selenoids: module usage — module "selenoid" { source

    = "../modules/selenoid" hostname = "sel-1.***.net" selenoid_container_name = "sel1" } $ terraform init - module.selenoid Getting source "../modules/selenoid" 72
  39. resource "null_resource" "passwords" { triggers { passwords = "${sha1(file("./users.htpasswd"))}" }

    connection { host = "${var.hostname}" type = "ssh" user = "***" password = "***" } provisioner "file" { source = "./users.htpasswd" destination = "/home/jetbrains/users.htpasswd" } } 2. Grid Router — 75
  40. resource "null_resource" "passwords" { triggers { passwords = "${sha1(file("./users.htpasswd"))}" }

    connection { host = "${var.hostname}" type = "ssh" user = "***" password = "***" } provisioner "file" { source = "./users.htpasswd" destination = "/home/jetbrains/users.htpasswd" } } 2. Grid Router — 76
  41. resource "null_resource" "passwords" { triggers { passwords = "${sha1(file("./users.htpasswd"))}" }

    connection { host = "${var.hostname}" type = "ssh" user = "***" password = "***" } provisioner "file" { source = "./users.htpasswd" destination = "/home/jetbrains/users.htpasswd" } } 2. Grid Router — 77
  42. resource "null_resource" "passwords" { triggers { passwords = "${sha1(file("./users.htpasswd"))}" }

    connection { host = "${var.hostname}" type = "ssh" user = "***" password = "***" } provisioner "file" { source = "./users.htpasswd" destination = "/home/jetbrains/users.htpasswd" } } 2. Grid Router — 78
  43. resource "null_resource" "quota" { triggers { teamcity = "${sha1(file("./quota/teamcity.xml"))}" youtrack

    = "${sha1(file("./quota/youtrack.xml"))}" ... } connection { ... } provisioner "file" { source = "./quota" destination = "/home/jetbrains/" } provisioner "remote-exec" { inline = ["docker kill -s HUP ${docker_container.ggr.id}"] } } 2. Grid Router — 79
  44. variable "vsphere_user" {} variable "vsphere_password" {} provider "vmware" { vcenter_server

    = "vcenter-srv.***.net" user = "${var.vsphere_user}" password = "${var.vsphere_password}" insecure_connection = true } 3. VMs in vSphere: non-official provider — 81
  45. 3. Virtual machine parameters — • 10 containers, 4 CPU,

    8GB RAM • 8 containers, 4 CPU, 8GB RAM 85
  46. 3. Virtual machine parameters — • 10 containers, 4 CPU,

    8GB RAM • 8 containers, 4 CPU, 8GB RAM • 8 containers, 4 CPU, 6GB RAM 86
  47. 1. Motivation 2. Terraform 101 3. Tips & Tricks for

    Selenoid cluster 4. Alternatives: cm & ansible What’s going on here — 87
  48. 1. Selenoid cm: upgrade — 89 ./cm selenoid configure \

    --browsers "chrome:X.0;firefox:Y.0" \ --version 1.9.0 --force ./cm selenoid start && ./cm selenoid stop
  49. 1. Selenoid cm: drawbacks — • cm works with localhost

    • bash script • old browser images are not removed 92
  50. 1. Selenoid cm: drawbacks — • cm works with localhost

    • bash script • old browser images are not removed • can’t configure/upgrade ggr 93
  51. 1. Selenoid cm: drawbacks — • cm works with localhost

    • bash script • old browser images are not removed • can’t configure/upgrade ggr • can’t help with monitoring 94
  52. 1. Selenoid cm: drawbacks — • cm works with localhost

    • bash script • old browser images are not removed • can’t configure/upgrade ggr • can’t help with monitoring • no VM orchestration 95
  53. 2. Ansible — 97 • configuration management tool, procedural &

    declarative • ok, you can do everything with ansible :)
  54. 2. Ansible — 98 • configuration management tool, procedural rather

    than declarative • ok, you can do everything with ansible :) • even VM orchestration
  55. 2. Ansible — 99 • configuration management tool, procedural rather

    than declarative • ok, you can do everything with ansible :) • even VM orchestration • https://galaxy.ansible.com/iqoption/selenoid-docker
  56. 2. Ansible — 100 • configuration management tool, procedural rather

    than declarative • ok, you can do everything with ansible :) • even VM orchestration • https://galaxy.ansible.com/iqoption/selenoid-docker • think of task idempotence (state=present or state=absent)
  57. • Terraform basics • Real-life Selenoid cluster example • Take

    a look at your infrastructure "You see, I learned something today..." — 101