F5Networks / terraform-provider-bigip

Terraform resources that can configure F5 BIG-IP products
https://registry.terraform.io/providers/F5Networks/bigip/latest/docs
Mozilla Public License 2.0
103 stars 119 forks source link

Add F5 Cluster configuration (configsync, failoveraddresses, trust) #643

Open Otimun opened 2 years ago

Otimun commented 2 years ago

Unable to use current terraform configuration to build a cluster. Have been trying to use the documented resources:

bigip_cm_device bigip_cm_devicegroup

There seem to be a number of things missing for the cluster to be constructed:

Is your feature request related to a problem? Please describe.

I am trying to move the cluster building away from Declarative Onboarding since this is a little sketchy at times. Steps undertaken to see if current terraform provider is able to achieve building a cluster:

first trying to create resources with at least the configsync_ip

resource "bigip_cm_device" "cm_device" {
  count              = var.init_ha_group
  name              = "${var.hostname}.${var.domain}"
  configsync_ip = var.sync_ip_address
  depends_on   = [bigip_net_selfip.sync_selfIP]
}

failed because cannot create new device object with same name as already exists: ╷ │ Error: HTTP 409 :: {"code":409,"message":"01020066:3: The requested system device () already exists in partition Common.","errorStack":[],"apiError":3} │ │ with module.clustering_2.bigip_cm_device.cm_device, │ on ../../../modules/f5_clustering/clustering.tf line 17, in resource "bigip_cm_device" "cm_device": │ 17: resource "bigip_cm_device" "cm_device" { │

Importing the cm_device and then trying to make the adjustments:

terraform import module.clustering_1.bigip_cm_device.cm_device <name host1>
terraform import module.clustering_2.bigip_cm_device.cm_device <name host2>
terraform apply

failed because a modify was not possible on device: │ Error: HTTP 403 :: {"code":403,"message":"Operation is not supported on component /cm/device.","errorStack":[],"apiError":1} │ │ with module.clustering_1.bigip_cm_device.cm_device, │ on ../../../modules/f5_clustering/clustering.tf line 17, in resource "bigip_cm_device" "cm_device": │ 17: resource "bigip_cm_device" "cm_device" {

When adding the other device with the command and creating the HA_Group:

resource "bigip_cm_device" "cm_device" {
  count             = var.init_ha_group
  name          = "${var.hostname_peer}.${var.domain}"
  configsync_ip = var.sync_peer_ip_address
  depends_on    = [bigip_net_selfip.sync_selfIP]
}

resource "bigip_cm_devicegroup" "HA_Group" {
  count             = var.init_ha_group
  name              = "HA_Group"
  auto_sync         = "enabled"
  network_failover  = "enabled"
  full_load_on_sync = "false"
  save_on_auto_sync = "false"
  type              = "sync-failover"
  device {
    name = "${var.hostname}.${var.domain}"
  }
  device {
    name = "${var.hostname_peer}.${var.domain}"
  }
  depends_on = [
    bigip_cm_device.cm_device
  ]
}

The configuration was succesfull, but the new device did not actually represent the other f5.

From the above it is clear that the current terraform resources are not adequate to build a F5 cluster. Hence this is a feature request to be able to do so with aditional resources.

Describe the solution you'd like

Implementation and documentation of steps to create a cluster using Terraform. The solution most probably will need the following working parts:

Describe alternatives you've considered

This is currently working with Declarative Onboarding using the following code: "configsync": { "class": "ConfigSync", "configsyncIp": "/Common/${SYNC_SELF}/address" }, "failoverAddress": { "class": "FailoverUnicast", "addressPorts": [ { "address": "/Common/${SYNC_SELF}/address", "port": 1026 }, { "address": "${MGMT_IP}", "port": 1026 } ] }, "trust": { "class": "DeviceTrust", "localUsername": "admin", "localPassword": "${ADMIN_PASSWORD}", "remoteHost": "${MGMT_IP_OTHER}", "remoteUsername": "admin", "remotePassword": "${ADMIN_PASSWORD}" }, "HA_Group": { "class": "DeviceGroup", "type": "sync-failover", "members": [ "${MGMT_IP_OTHER}", "${MGMT_IP}" ], "owner": "${MGMT_IP_OTHER}", "autoSync": true, "saveOnAutoSync": false, "networkFailover": true, "fullLoadOnSync": false, "asmSync": "${ASM_SYNC}" }

trinaths commented 2 years ago

@Otimun Suggest use DO and share your feedback.

Otimun commented 2 years ago

Hi @trinaths, thanks for your response. This configuration does work in DO, but to keep Declarative Onboarding as a module working for all devices (both standalone and cluster devices) I've removed it from the funcionality there.

Instead I found another workaround using bigip_command resources:

resource "bigip_command" "ha_configuration" {
  commands = [
    "modify cm device ${var.hostname}.${var.domain} configsync-ip ${var.sync_ip_address}",
    "modify cm device ${var.hostname}.${var.domain} unicast-address { { ip ${var.sync_ip_address} port 1026 } { ip management-ip port 1026 } }",
  ]
  depends_on = [bigip_net_selfip.sync_selfIP]
}

resource "bigip_command" "delete_ha" {
  commands = [
    "modify cm device  ${var.hostname}.${var.domain} configsync-ip none",
    "modify cm device ${var.hostname}.${var.domain} unicast-address none"
  ]
  when       = "destroy"
  depends_on = [bigip_net_selfip.sync_selfIP]
}

resource "bigip_command" "trust_configuration" {
  count = var.create_ha
  commands = [
    "modify cm trust-domain add-device { device-ip ${var.ip_address_peer} device-name ${var.hostname_peer}.${var.domain} username ${var.username} password ${var.password} }"
  ]
  depends_on = [bigip_command.ha_configuration]
}

resource "bigip_command" "delete_trust" {
  commands = [
    "modify cm trust-domain remove-device ${var.hostname_peer}.${var.domain}"
  ]
  when = "destroy"
}

resource "bigip_cm_devicegroup" "HA_Group" {
  count             = var.create_ha
  name              = "HA_Group"
  auto_sync         = "enabled"
  network_failover  = "enabled"
  full_load_on_sync = "false"
  save_on_auto_sync = "false"
  type              = "sync-failover"
  device {
    name = "${var.hostname}.${var.domain}"
  }
  device {
    name = "${var.hostname_peer}.${var.domain}"
  }
  depends_on = [
    bigip_command.trust_configuration
  ]
}

resource "bigip_command" "initial_config_sync" {
  count = var.create_ha
  commands = [
    "run cm config-sync to-group ${bigip_cm_devicegroup.HA_Group[0].name}"
  ]
  depends_on = [bigip_cm_devicegroup.HA_Group]
}

Still it would be very nice to be able to use normal terraform resources to create clusters rather than making use of bigip_command resources.

pr0c4 commented 2 years ago

+1 on this request, would be nice to avoid using DO altogether thanks @Otimun for sharing, was building this on my own