Service Discovery

This section contains declarations that discover pool members automatically or dynamically. This includes declarations that automatically discover members in Cloud deployments, as well as declarations that use an FQDN pool to enable pool member addresses to dynamically follow DNS changes.

Important

You must be running BIG-IP version 13.0 or later to use service discovery.

Use the index under Current Page on the left to locate specific examples.

1: Using Service Discovery to automatically populate a pool

This example uses the service discovery feature to populate a pool based on tagged resources in AWS. For information on this feature, see the Service Discovery page. In this example, the pool contains two static members on port 443, and then members in our us-west-1 region in AWS that are tagged with foo and bar.

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_sd_01.
  • A virtual server named serviceMain.
  • A pool named web_pool monitored by the default http health monitor. The pool members are autodiscovered from AWS.
{
    "class": "ADC",
    "schemaVersion": "3.0.0",
    "id": "urn:uuid:33045210-3ab8-4636-9b2a-c98d22ab425d",
    "controls": {
      "class": "Controls",
      "trace": true,
      "logLevel": "debug"
    },
    "label": "AWS Service Discovery",
    "remark": "Simple HTTP application with a pool using AWS service discovery",
    "Sample_sd_01": {
      "class": "Tenant",
      "verifiers": {
        
      },
      "A1": {
        "class": "Application",
        "template": "http",
        "serviceMain": {
          "class": "Service_HTTP",
          "virtualAddresses": [
            "192.0.2.14"
          ],
          "pool": "web_pool"
        },
        "web_pool": {
          "class": "Pool",
          "monitors": [
            "http"
          ],
          "members": [
            {
              "servicePort": 80,
              "addressDiscovery": "aws",
              "updateInterval": 1,
              "tagKey": "foo",
              "tagValue": "bar",
              "addressRealm": "private",
              "region": "us-west-1"
            },
            {
              "enable": true,
              "servicePort": 443,
              "serverAddresses": [
                "192.0.2.60",
                "192.0.2.61"
              ]
            }
          ]
        }
      }
    }
  }  

Back to top


2: Using remote Service Discovery to automatically populate a pool with BIG-IP VE anywhere

This example uses the remote service discovery feature introduced in v3.4.0 to populate a pool based on tagged resources in AWS, Azure, and Google. For information on this feature, see the Service Discovery page. Remote service discovery allows your BIG-IP VE to be located anywhere, not necessarily in a specific cloud or region. In this example, the declaration runs on the local BIG-IP system, see the next example for using a declaration on a remote BIG-IP. For this feature to work properly, you must provide credentials for your cloud provider as shown in the following example.

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_sd_02.
  • A virtual server named serviceMain.
  • A pool named web_pool monitored by the default http health monitor. The pool members are autodiscovered from AWS, Azure, and Google clouds, each on a different port.

Note: This example does not include actual credentials for any of the clouds, or IDs for Azure. You must supply these items from your cloud provider.

{
    "class": "ADC",
    "schemaVersion": "3.4.0",
    "id": "urn:uuid:33045210-3ab8-4636-9b2a-c98d22ab425d",
    "label": "AWS Azure GCP Service Discovery",
    "remark": "HTTP application with a pool using local nodes and AWS, GCP, and Azure service discovery",
    "Sample_sd_02": {
      "class": "Tenant",
      "A1": {
        "class": "Application",
        "template": "http",
        "serviceMain": {
          "class": "Service_HTTP",
          "virtualAddresses": [
            "192.0.192.3"
          ],
          "pool": "web_pool"
        },
        "web_pool": {
          "class": "Pool",
          "monitors": [
            "http"
          ],
          "members": [
            {
              "servicePort": 8080,
              "addressDiscovery": "azure",
              "updateInterval": 10,
              "tagKey": "foo",
              "tagValue": "bar",
              "addressRealm": "private",
              "resourceGroup": "test_group",
              "subscriptionId": "azure subscription ID",
              "directoryId": "azure directory ID",
              "applicationId": "your azure application ID",
              "apiAccessKey": "your api access key",
              "credentialUpdate": false
            },
            {
              "servicePort": 8081,
              "addressDiscovery": "gce",
              "updateInterval": 10,
              "tagKey": "foo",
              "tagValue": "bar",
              "addressRealm": "private",
              "region": "us-west1",
              "encodedCredentials": "base 64 encoded credentials",
              "credentialUpdate": false
            },
            {
              "servicePort": 8082,
              "addressDiscovery": "aws",
              "updateInterval": 10,
              "tagKey": "foo",
              "tagValue": "bar",
              "addressRealm": "private",
              "region": "us-west-1",
              "accessKeyId": "your key id",
              "secretAccessKey": "your secret access key>",
              "credentialUpdate": false
            },
            {
              "enable": true,
              "servicePort": 80,
              "serverAddresses": [
                "10.128.0.7"
              ]
            }
          ]
        }
      }
    }
  }
    

Back to top

3: Using remote Service Discovery and sending the declaration to a remote BIG-IP

This example uses the remote service discovery feature to populate a pool based on tagged resources in AWS, Azure, and Google, but in this declaration we are sending the declaration to a remote BIG-IP system. You must use the targetHost, targetUserName, and targetPassphrase parameters to set the information for the target BIG-IP device. For information on service discovery, see the Service Discovery page.

For this feature to work properly, you must provide credentials for your cloud provider as shown in the following example.

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_sd_03.
  • A virtual server named serviceMain.
  • A pool named web_pool monitored by the default http health monitor. The pool members are autodiscovered from AWS.

Note: This example does not include actual AWS credentials, you must supply these items.

{
    "class": "AS3",
    "targetHost": "192.0.2.212",
    "targetUsername": "admin",
    "targetPassphrase": "admin",
    "declaration": {
        "class": "ADC",
        "schemaVersion": "3.1.0",
        "id": "TEST_Service_HTTP",
        "Sample_sd_03": {
            "class": "Tenant",
            "Generic_Http": {
                "class": "Application",
                "template": "generic",
                "vghSimple": {
                    "class": "Service_HTTP",
                    "virtualAddresses": [
                    "10.1.88.1"
                    ],
                    "pool": "web_pool"
                },
                "web_pool": {
                    "class": "Pool",
                    "monitors": [
                        "http"
                    ],
                    "members": [
                        {
                            "servicePort": 8082,
                            "addressDiscovery": "aws",
                            "updateInterval": 10,
                            "tagKey": "foo",
                            "tagValue": "bar",
                            "addressRealm": "private",
                            "region": "us-west-2",
                            "accessKeyId": "your-access-key",
                            "secretAccessKey": "your-secret-key",
                            "credentialUpdate": false
                        },
                        {
                            "enable": true,
                            "servicePort": 80,
                            "serverAddresses": [
                                "10.128.0.7"
                            ]
                        }
                    ]
                }
            }
        }
    }
  }

Back to top

4: Using an FQDN pool to identify pool members

This example uses an FQDN pool on the BIG-IP VE, which allows the pool member addresses to dynamically follow DNS changes. For complete information on FQDN pools, see https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/ltm-implementations-13-1-0/22.html. You must have DNS configured on your BIG-IP system before FQDN pools will function properly. See the BIG-IP documentation for details.

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_sd_04.
  • A virtual server named serviceMain.
  • A pool named fqdn_pool. The pool member addresses are discovered using DNS.
{
    "class": "ADC",
    "schemaVersion": "3.4.0",
    "id": "demo",
    "label": "FQDN pool example",
    "remark": "Example of using an FQDN pool",
    "Sample_sd_04": {
        "class": "Tenant",
        "fqdn_app": {
            "class": "Application",
            "template": "http",
            "serviceMain": {
                "class": "Service_HTTP",
                "virtualAddresses": [
                    "192.0.2.241"
                ],
                
                "pool": "fqdn_pool",
                "virtualPort": 80,
                "persistenceMethods": [
                    "cookie"
                ],
                "profileHTTP": "basic",
                "layer4": "tcp",
                "profileTCP": "normal",
                "snat": "auto"
            },
            "fqdn_pool": {
                "class": "Pool",
                "members": [
                    {
                        "servicePort": 80,
                        "addressDiscovery": "fqdn",
                        "autoPopulate": true,
                        "hostname": "demo.example.com"
                    }
                ]
            }
        }
    }
}
          

Back to top

5: Event-Driven Service Discovery for use in the Docker Container

This example uses a event-driven service discovery, introduced in AS3 3.9.0. With event-driven service discovery, you POST a declaration with the addressDiscovery property set to event. This creates a new endpoint which you can use to add nodes that does not require an AS3 declaration, so it can be more efficient than using PATCH or POST to add nodes. This also enables the ability to configure a service (such as AWS Lambda) to use the event endpoint any time it detects instance changes.

When you use the event value for addressDiscovery, the system creates the new endpoint with the following syntax: https://<host>/mgmt/shared/appsvcs-discovery/task/~<tenant name>~<application name>~<pool name>/nodes.

For example, in the following declaration, assuming 192.0.2.14 is our BIG-IP, the endpoint that is created is: https://192.0.2.14/mgmt/shared/appsvcs-discovery/task/~Sample_event_sd~My_app~My_pool/nodes

Once the endpoint is created, you can use it to add nodes to the BIG-IP pool.

First we show the initial declaration to POST to the BIG-IP system.

{
    "class": "ADC",
    "schemaVersion": "3.9.0",
    "id": "Pool",
    "Sample_event_sd": {
        "class": "Tenant",
        "My_app": {
            "class": "Application",
            "template": "generic",
            "My_pool": {
                "class": "Pool",
                "members": [
                    {
                        "servicePort": 8080,
                        "addressDiscovery": "static",
                        "serverAddresses": [
                            "192.0.2.2"
                        ]
                    },
                    {
                        "servicePort": 8080,
                        "addressDiscovery": "event"
                    }
                ]
            }
        }
    }
}

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_event_sd.
  • A pool named My_pool that is a part of the My_app application. The pool currently contains one member, 192.0.2.2 on port 8080.

Once the declaration has been sent to the BIG-IP, we send the following code to the BIG-IP endpoint (https://192.0.2.14/mgmt/shared/appsvcs-discovery/task/~Sample_event_sd~My_app~My_pool/nodes). Both id and ip are required.

[
    {
        "id": "newNode1",
        "ip": "192.0.2.3"
    },
    {
        "id": "NewNode2",
        "ip": "192.0.2.4"
    }
]

This creates two new named nodes in My_pool, newNode1 and newNode2 at the IP addresses specified.

Note

The list of nodes for this event-driven task are replaced with the list you post, so you should always include all nodes with each request.

Back to top

6: Service Discovery using HashiCorp Consul

This example uses Consul (specifically HashiCorp Consul) for service discovery. For more information HashiCorp Consul, see https://www.consul.io/. This declaration includes an optional Base 64 encoded bearer token required to make requests to the Consul API with the ACL system enabled (stored in the declaration in an encrypted format).

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_consul_SD.
  • A virtual server named serviceMain.
  • A pool named web_pool monitored by the default http health monitor. The pool members are autodiscovered via the Consul API.
{
    "class": "ADC",
    "schemaVersion": "3.7.0",
    "id": "urn:uuid:33045210-3ab8-4636-9b2a-c98d22ab425d",
    "label": "Consul Service Discovery",
    "Sample_consul_SD": {
      "class": "Tenant",
      "A1": {
        "class": "Application",
        "template": "http",
        "serviceMain": {
          "class": "Service_HTTP",
          "virtualAddresses": [
            "198.0.2.3"
          ],
          "pool": "web_pool"
        },
        "web_pool": {
          "class": "Pool",
          "monitors": [
            "http"
          ],
          "members": [
            {
              "servicePort": 80,
              "addressDiscovery": "consul",
              "updateInterval": 10,
              "uri": "http://demo.exmample.com:8500/v1/catalog/nodes",
              "encodedToken": "base 64 encoded token",
              "credentialUpdate": false
            },
            {
              "enable": true,
              "servicePort": 80,
              "serverAddresses": [
                "192.0.2.7"
              ]
            }
          ]
        }
      }
    }
}
  

Back to top

7: Service Discovery using HashiCorp Consul and CA Certificates

This example is very similar to the previous example, although in this case, it uses Consul for service discovery with a CA Certificate. See Pool Member in the Schema Reference for a description of trustCA used in this declaration. This declaration also includes an optional Base 64 encoded bearer token required to make requests to the Consul API with the ACL system enabled (stored in the declaration in an encrypted format).

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_Consul_SD_CA.
  • A virtual server named serviceMain.
  • A pool named web_pool The pool members are autodiscovered via the Consul API.
  • A CA Bundle to validate server certificates (note the CA Bundle in the declaration is not valid and you will receive an error if you use it as is)
{
    "class": "ADC",
    "schemaVersion": "3.11.0",
    "id": "Consul_Service_Discovery",
    "Sample_Consul_SD_CA": {
        "class": "Tenant",
        "Application": {
            "class": "Application",
            "template": "http",
            "serviceMain": {
                "class": "Service_HTTP",
                "virtualAddresses": [
                    "192.0.2.60"
                ],
                "pool": "web_pool"
            },
            "web_pool": {
                "class": "Pool",
                "members": [
                    {
                        "servicePort": 8080,
                        "addressDiscovery": "consul",
                        "updateInterval": 10,
                        "uri": "https://192.0.2.100:8500/v1/catalog/nodes",
                        "trustCA": {
                            "use": "my_ca_bundle"
                        }
                    }
                ]
            },
            "my_ca_bundle": {
                "class": "CA_Bundle",
                "bundle": "-----BEGIN CERTIFICATE-----\nMAAFgDFFA2gCCQC8f9aw8Cs6YDANBgjoekiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1BMQ8wDQYDVQQHDAZCb3N0b24xEzARBgNVBAoMCkV4YW1wbGUgQ28xEDAOBgNVBAsMB3RlY2hvcHMxCzAJBgNVBAMMAmNhMSAwHgYJKoZIhvcNAQkBFhFjZXJ0c0BleGFtcGxlLmNvbTAeFw0xOTA0MTAxODA0NTJaFw00NjA4MjUxODA0NTJaMIGBMQswCQYDVQQGEwJVUzELMAkGA1UECAwCTUExDzANBgNVBAcMBkJvc3RvbjETMBEGA1UECgwKRXhhbXBsZSBDbzEQMA4GA1UECwwHdGVjaG9wczELMAkGA1UEAwwCY2ExIDAeBgkqhkiG9w0BCQEWEWNlcnRzQGV4YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2PAdx8/Gyceo92wU8qQT+pHBZc2ndYIB+sZ00giaKAS9ImHTtHzAgNfHHjDfrev1w5CzVq8Zd4NqmgLTfvb8TvI2Ratdpz8UiRVUo+uKy5eQHwV27Uphk0xV6aipAZCuRt4B8IMeZYJXCN9z+HlyGG2EehkLhCGXDP30o4ps67WKg8B1Qn5hVP9zx4KWIxtgVbpFO5OMjlVAQn7N+BAMAKjlhMhuok+eJCSU/cDfel2FACUngCE0N5fbJQvKXKbUHujmHE/kqBanVGIYMCktcxUC/HJxB/92cCkUc/yMYUBIH9jguixYxeKMeqmgdG3qO1PZ6y1I2uQD9RP1U/goQYaV6Jl14oHrAmz62EgG+KSu8ujMWgZQ9IKswwLjLc20OfpvxsHFiAq/B4vqcY2EFpqOhflMW+EcAeG2zXuKzZLWoDVYF1JozHdmY4NatZuNx3UKi0/4eRGjro9zVIuCCUpLmUR5zFtLoMDsriXcWRb4rTpGpO80DKUtaK5icK3L8t3V5jKt9X1sKcIDbuq+bHnXfp+eeqX6931QZzQ4XVQyOlYxKQF5+kzGE3KwJRNqF5pNDJRvXvKNh0FC54QNiVJvv9994kFdTkbAiLEWUMAqegYxVPElo8IZvL/vbonL7MUrO512trPEMa5zgYufAX5dJNQELVYfj5tRMFmQy2kCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAe1yRYbSRWorlai4/SQidERv/k1L/86drS544SmjiTBQEooOM3VZIHpeDNRd/8s0htCQoCNWNL7M0SH8G7XZjUirvFYSGigZ+ICWvDCUq1NZg7mRYGbC9W/18M5LO21LMlABUUsp8lLkc3rmOCN6/3dFhpUMyTUujI/bo+4wDo/Gw9rMcKAEJ1nWjPMo4JhlIEMe1uas91FXULU/1/Pi36YSBw0owRQasvuuKQCpkgwaTbht5dUjw+vR3WkoBSqL7EEC0mzimo0F45VblgUuU7NdBdfDQWs3f1Zw6tgB9Ucagerld1Bf4S20DiOL7CggbKNEld4txzzhBPJWQ/LP38W2hmiYvk4YcX8lVrUGhWA1a+65XJLyX60zxEoxbC495NoTHK7Ss92lZ0/6Oo+vr283RJfL3JATL6ZyH31K3PfvE/Dt0d/2cg1Sp+6G/4wJIvRoDLfvP+3vENCnyyLsGG3RO7NQHd10tTTIysP7STuhsCLP0xgdJOHUEHNSZ2070ixn8El6PgwsjRmHTwf4435kgSmzunhqToO6frYCp/i+q3BERviJPe2XrbLIETbuiKk8aXOmEIB29KKfH7GjRvZkrQMTYJp054wxG+B2ogwAUezsL8AS4BqNnVmSA23KknoRIn9UH0lF0VhzByGLb5N72H77wR1bDtBu0wZJHl4U=\n-----END CERTIFICATE-----"
            }
        }
    }
}

Back to top

8: Service Discovery using HashiCorp Consul without certificate validation

This is another example that uses Consul for service discovery, but in this example, there is no certificate validation. This declaration uses the rejectUnauthorized property set to false so the server certificate is not validated. This declaration includes an optional Base 64 encoded bearer token required to make requests to the Consul API with the ACL system enabled (stored in the declaration in an encrypted format). See Pool Member in the Schema Reference for a description of rejectUnauthorized used in this declaration.

This declaration creates the following objects on the BIG-IP:

  • Partition (tenant) named Sample_Consul_SD_no_validation.
  • A virtual server named serviceMain.
  • A pool named web_pool The pool members are autodiscovered via the Consul API.
  • The rejectUnauthorized is set to false, so there is no server certificate validation.
{
    "class": "ADC",
    "schemaVersion": "3.11.0",
    "id": "Consul_Service_Discovery",
    "controls": {
        "class": "Controls",
        "trace": true,
        "logLevel": "debug"
    },
    "Sample_Consul_SD_no_validation": {
        "class": "Tenant",
        "Application": {
            "class": "Application",
            "template": "http",
            "serviceMain": {
                "class": "Service_HTTP",
                "virtualAddresses": [
                    "192.0.2.60"
                ],
                "pool": "web_pool"
            },
            "web_pool": {
                "class": "Pool",
                "members": [
                    {
                        "servicePort": 8080,
                        "addressDiscovery": "consul",
                        "updateInterval": 10,
                        "uri": "https://192.0.2.100:8500/v1/catalog/nodes",
                        "rejectUnauthorized": false
                    }
                ]
            }
        }
    }
}

Back to top

9: Service Discovery for virtual servers in GSLB Servers

This simple example shows how you can use Service Discovery to automatically discover virtual servers in GSLB Servers. You must have BIG-IP DNS (formerly GTM) provisioned to use these features. See GSLB Server in the Schema Reference for usage options and additional features for GSLB.

Warning

When using GSLB features, you must be aware of the items pointed out in Warnings, notably AS3 completely overwrites non-AS3 topologies when a declaration is submitted.

This declaration creates the following objects on the BIG-IP (note that this declaration doesn’t not create a tenant, but uses the Common tenant as required for some GSLB features):

  • A GSLB data center named testDataCenter.
  • A GSLB server named testServer with one device, virtualServerDiscoveryMode set to enabled-no-delete (which only allows Service Discovery to add or modify, but not delete), and exposeRouteDomainsEnabled set to true (which allows virtual servers from all route domains to be auto-discovered).
{
    "class": "ADC",
    "schemaVersion": "3.11.0",
    "id": "GSLB_VS_Discovery",
    "Common": {
        "class": "Tenant",
        "Shared": {
            "class": "Application",
            "template": "shared",
            "testDataCenter": {
            	"class": "GSLB_Data_Center"
            },
            "testServer": {
                "class": "GSLB_Server",
                "dataCenter": {
                    "use": "testDataCenter"
                },
                "devices": [{ "address": "10.10.10.10"}],
                "virtualServerDiscoveryMode": "enabled-no-delete",
                "exposeRouteDomainsEnabled": true
            }
        }
    }
}

Back to top