Search code examples
microservicesconsulfabio

Consul fabio microservices


Can you clarify pls what are the main steps to make Consul run on the local machine (not in dev mode(!)) to connect e.g. a microservice from another microservice, if it's possible using Fabio as a load balancer. Should I create a datacenter with acl and ets.? Too a lot of documentation but it's still not clear from what to start. Thanks a lot!


Solution

  • Here's a step-by-step example of how you can configure Fabio to route to a microservice which is registered in a Consul server environment that is protected by ACLs.

    First, you'll need to create a few configuration files for Consul and Fabio.

    $ tree  
    .
    ├── conf.d
    │   ├── config.hcl
    │   └── web.hcl
    ├── fabio-policy.hcl
    └── fabio.properties
    

    Here's a brief overview of what we'll add to these files.

    • conf.d - Consul server configuration dir. config.hcl which defines the Consul server configuration, and web.hcl which is the service definition for our example web service.
    • fabio-policy.hcl - The Consul ACL policy which will be assigned to the token created for Fabio LB.
    • fabio.properties - The Fabio configuration file.

    Create configuration files

    conf.d/config.hcl

    This is a basic single node Consul server cluster (3 or more are recommended for production) with ACLs enabled.

    # Configure the Consul agent to operate as a server
    server = true
    
    # Expect only one server member in this cluster
    bootstrap_expect = 1
    
    # Persistent storage path. Should not be under /tmp for production envs.
    data_dir = "/tmp/consul-fabio-so"
    
    acl {
      # Enable ACLs
      enabled = true
    
      # Set default ACL policy to deny
      default_policy = "deny"
    }
    
    # Enable the Consul UI
    ui_config {
      enabled = true
    }
    

    web.hcl

    This is a service definition which registers a service named "web" into the Consul catalog.

    service {
      # Define the name of the service'
      name = "web"
    
      # Specify the listening port for the service
      port = 8080
    
      # Register a HTTP health check (requried by Fabio) for this service
      # By default Fabio will only route to healthy services in the Consul catalog.
      check {
        id = "web"
        http = "http://localhost:8080"
        interval = "10s"
        timeout = "1s"
      }
    
      # Fabio dynamically configures itself based on tags assigned to services in
      # the Consul catalog. By default, 'urlprefix-` is the prefix for tags which
      # define routes. Services which define routes publish one or more tags with
      # host/path # routes which they serve. These tags must have this prefix to be
      # recognized as routes.
      #
      # Configure Fabio to route requests to '/' to our backend service.
      tags = [
        "urlprefix-/"
      ]
    }
    

    fabio-policy.hcl

    This ACL policy allows Fabio to register itself into the Consul catalog, discover backend services, and additional Fabio configuration. This policy will be created in Consul after bootstrapping the ACL system.

    # Allow Fabio to discover which agent it is running on.
    # Can be scoped to specific node(s) if additional security is requried
    agent_prefix "" {
      policy = "read"
    }
    
    # Allow Fabio to lookup any service in Consul's catalog
    service_prefix "" {
      policy = "read"
    }
    
    # Allow Fabio to lookup nodes so that it can resolve services endpoints to the
    # correct node IP.
    node_prefix "" {
      policy = "read"
    }
    
    # Allow Fabio to register itself as a service in Consul.
    # This used for Fabio instances to be discoverable in Consul's catalog, and for
    # Consul to execute health checks against Fabio.
    service "fabio" {
      policy = "write"
    }
    
    # Allow Fabio to read configuration overrides from the KV store
    # https://github.com/fabiolb/fabio/wiki/Routing#manual-overrides
    key_prefix "fabio/config" {
      policy = "read"
    }
    

    fabio.properties

    This is the configuration file for Fabio.

    Configures the ACL token to use when authenticating to Consul.
    registry.consul.token = "<token. To be created later>"
    

    Start and configure Consul

    1. Start the Consul server (not in dev mode).

      $ consul agent -config-dir=conf.d
      ==> Starting Consul agent...
              Version: '1.9.5'
              Node ID: 'f80693eb-0f47-1f9f-e8cc-063ad28ca8da'
              Node name: 'b1000.local'
              Datacenter: 'dc1' (Segment: '<all>')
                  Server: true (Bootstrap: true)
          Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600)
          Cluster Addr: 10.0.0.21 (LAN: 8301, WAN: 8302)
              Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
      
      ==> Log data will now stream in as it occurs:
      ...
      
    2. Bootstrap the ACL system. This creates a management token with privileges for the entire cluster. Save this information.

      $ consul acl bootstrap
      AccessorID:       e135b234-2227-71fe-1999-ffb75c659110
      SecretID:         ef475ff8-5f92-6f8e-0a59-2ad3f8ed8dda
      Description:      Bootstrap Token (Global Management)
      Local:            false
      Create Time:      2021-06-05 14:26:07.02198 -0700 PDT
      Policies:
      00000000-0000-0000-0000-000000000001 - global-management
      
    3. Set the CONSUL_HTTP_TOKEN environment variable to the value of our secret ID. This will be used for subsequent administrative commands.

      $ export CONSUL_HTTP_TOKEN="ef475ff8-5f92-6f8e-0a59-2ad3f8ed8dda"
      
    4. Create the ACL policy for Fabio

      $ consul acl policy create -name=fabio-policy [email protected]
      <output snipped>
      ...
      
    5. Create a token for Fabio which utilizes this policy.

      $ consul acl token create -description="Token for Fabio LB" -policy-name="fabio-policy"
      AccessorID:       474db6b0-73b0-3149-dafc-a50bab41b574
      SecretID:         b6490a01-89a8-01a1-bbdf-5c7e9898d6ea
      Description:      Token for Fabio LB
      Local:            false
      Create Time:      2021-06-05 15:13:09.124182 -0700 PDT
      Policies:
        fc0c6a84-8633-72cc-5d59-4e0e60087199 - fabio-policy
      
    6. Update fabio.properties and set token ID.

      # registry.consul.token configures the acl token for consul.
      registry.consul.token = b6490a01-89a8-01a1-bbdf-5c7e9898d6e
      

    Start the web server and Fabio

    Start the backend web server so that it can accept connections. For this example, I'm going to use devd.

    This command instructs devd to listen on port 8080 on all IPs on the system, and serve content from the current directory.

    $ devd --all --port=8080 .
    15:21:46: Route / -> reads files from .
    15:21:46: Listening on http://devd.io:8080 ([::]:8080)
    

    Next, start Fabio.

    $ fabio -cfg fabio.properties
    2021/06/05 15:22:40 [INFO] Setting log level to INFO
    2021/06/05 15:22:40 [INFO] Runtime config
    <snip>
    ...
    2021/06/05 15:22:40 [INFO] Version 1.5.14 starting
    2021/06/05 15:22:40 [INFO] Go runtime is go1.16.2
    2021/06/05 15:22:40 [INFO] Metrics disabled
    2021/06/05 15:22:40 [INFO] Setting GOGC=100
    2021/06/05 15:22:40 [INFO] Setting GOMAXPROCS=16
    2021/06/05 15:22:40 [INFO] consul: Connecting to "localhost:8500" in datacenter "dc1"
    2021/06/05 15:22:40 [INFO] Admin server access mode "rw"
    2021/06/05 15:22:40 [INFO] Admin server listening on ":9998"
    2021/06/05 15:22:40 [INFO] Waiting for first routing table
    2021/06/05 15:22:40 [INFO] consul: Using dynamic routes
    2021/06/05 15:22:40 [INFO] consul: Using tag prefix "urlprefix-"
    2021/06/05 15:22:40 [INFO] consul: Watching KV path "/fabio/config"
    2021/06/05 15:22:40 [INFO] consul: Watching KV path "/fabio/noroute.html"
    2021/06/05 15:22:40 [INFO] HTTP proxy listening on :9999
    2021/06/05 15:22:40 [INFO] Access logging disabled
    2021/06/05 15:22:40 [INFO] Using routing strategy "rnd"
    2021/06/05 15:22:40 [INFO] Using route matching "prefix"
    2021/06/05 15:22:40 [INFO] Config updates
    + route add web / http://10.0.0.21:8080/
    2021/06/05 15:22:40 [INFO] consul: Registered fabio as "fabio"
    ...
    

    While some of the output has been omitted, we can see that Fabio is listening on port 9999, is successfully watching Consul's KV for configuration, has successfully discovered our "web" service, and registered itself into Consul's catalog.

    If you connect to Fabio at http://localhost:9999, you should see a directory listing being returned by the backend web server, devd, which is listening on port 8080.