Managing Routes

This section describes how to manage routes, including:

You use the apc route command or Web Console to manage your cluster's routes. You can add or delete routes, map routes to jobs, show applications that are using a particular route. For applications that share a route you can also control the proportion of traffic delivered per-route, or route weighting.

Adding HTTP Routes

You use apc route add to add an HTTP or TCP route on a job's exposed port. You can specify the route type explicitly with the --type flag, or by including the protocol (http or tcp) in the route's endpoint.

For example, the following creates an HTTP route with the endpoint myapp.example.me that is mapped to port 5000 on the application myapp:

apc route add http://myapp.example.me --app myapp --port 5000

If you don't specify a --port parameter when adding a route (or specify the special value of 0) then the platform will select an available port on your application when it's started. Your application can read the port number selected by the platform from its PORT environment variable. For example, the following creates a new HTTP route and maps it to an available port on myapp:

apc route add http://myapp.example.me --app myapp

NOTE: Note that if no process is listening at the mapped port then your application will fail to start.

Equivalently, you can use the --type parameter to specify the route type:

apc route add myapp.example.me --app myapp --type http

You can also substitute the --http boolean for --type http, for example:

apc route add myapp.example.me --app myapp --http

By default, clients can access a route using either http or https protocols (assuming your cluster is configured for HTTPS). You can optionally enforce that requests for a specific endpoint use https, only.

You can enforce this at the Apcera router so that any requests for a route over http are automatically redirected to the https endpoint via a HTTP 301 Redirect. To do this you set the --https-only flag when mapping a route to a job. For example, the follow command maps a new HTTPS-only route to the application myapp:

apc route add http://www.example.com --https-only --port 1234 --app myapp

Alternatively, an application can enforce HTTPS itself by inspecting HTTP request headers to see if the request to the Apcera router was over a secure connection or not.

For details, see Enforcing HTTPS on Routes.

Auto-generated HTTP Endpoints

To have the platform automatically generate a route endpoint for your application pass auto as the second argument to apc route add:

apc route add auto --app myapp --type http

Auto-generated URLs are constructed from the application name, a random six-character string, and the cluster's domain, for example, my-app-a1yxwy.example.com.

Adding TCP Routes

You use apc route add <IP-ADRESSS> --port <PORT> to open a TCP route at the specified IP address and port, or apc route add auto to have the platform select the IP address and port automatically. The first form of the command requires that you know the IP address of the TCP router component in your cluster.

Note: To create TCP routes, you must have deployed one or more TCP routers in your cluster, and you must have configured public-to-private IP mapping for the TCP router in cluster.conf.

The TCP router has a public and private IP address. To create a publicly accessible TCP route you must use the public IP. The following creates a TCP route using the TCP router's public IP:

apc route add tcp://50.23.234.23 --app myTcpServer --p 1998

You can add a TCP route using the auto keyword. In the following example Apcera selects an available public IP address on the TCP (tcp://35.165.159.234) and assigns it to a random public port (35792). The target app is listening on port 514. Apcera automatically routes the traffic from the TCP router to the destination app instance and port:

$ apc route add auto --tcp --app sumo --port 514
╭────────────────────────╮
│ Route Add Settings     │
├─────────────────┬──────┤
│ App Name:       │ sumo │
│ App Port:       │ 514  │
│ Route Type:     │ tcp  │
│ Route Endpoint: │ auto │
│ Route Weight:   │ 0%   │
╰─────────────────┴──────╯

Is this correct? [Y/n]:
Adding route tcp://auto to app sumo... done
Autoprovisioned TCP route "tcp://35.165.159.234:35792"
Success!

Mapping and Unmapping Routes to Jobs

To map an existing route endpoint to an exposed port on a job you use the apc route map <endpoint> command. For example, the following command maps the job named mysite to the HTTP route endpoint site.apcera.com on exposed port 4000:

apc route map http://site.apcera.me --job mysite --weight 50 --port 4000

The following command maps the job named mydb to the TCP route endpoint 10.0.0.1:1212 on port 8080.

apc route map 10.0.0.1:1212 --job mydb --type tcp --port 8080

To unmap a route from a job at a specific port you use the apc route unmap <endpoint> command:

apc route unmap console.statler13.apcera-platform.io --port 5000

Deleting Routes

The apc route delete <route-endpoint> command removes a route.

For example:

apc route delete http://site.apcera.me --http

You cannot delete a route that has a job mapped to it. To remove a job mapping use the route unmap command.

Listing Routes

The apc route list commands lists the endpoints and types (HTTP or TCP) of routes assigned to jobs in the current namespace, and the number of jobs that use each route. For example, the output below shows that the app-route.foo.com route endpoint is being used by two applications and my-route.foo.com is being used by one app:

$ apc route list
Working in "/sandbox/admin"
╭──────┬───────────────────┬──────────────╮
│ Type │ Endpoint          │ # Times Used │
├──────┼───────────────────┼──────────────┤
│ http │ app-route.foo.com │ 2            │
│ http │ my-route2.foo.com │ 1            │
╰──────┴───────────────────┴──────────────╯

To show the FQN and UUID of the jobs assigned to each route, and the weight assigned to each route, include -l command flag. For example, the following shows that /sandbox/admin::app1 and /sandbox/admin::app2 both use the app-route.foo.com route endpoint, while the other route is used by job::/dev::app2:

apc route list -l
╭──────┬───────────────────┬────────┬───────────────────────────┬──────────────────────────────────────╮
│ Type │ Endpoint          │ Weight │ Job FQN                   │ Job UUID                             │
├──────┼───────────────────┼────────┼───────────────────────────┼──────────────────────────────────────┤
│ http │ app-route.foo.com │ auto   │ job::/sandbox/admin::app1 │ 3b0a6209-5dcf-408c-8941-cf9f44295f58 │
│ http │ app-route.foo.com │ auto   │ job::/sandbox/admin::app2 │ 0512b2a3-18a9-4d0e-9a45-717b525921dc │
│ http │ my-route2.foo.com │ auto   │ job::/dev::app2           │ 0512b2a3-18a9-4d0e-9a45-717b525921dc │
╰──────┴───────────────────┴────────┴───────────────────────────┴──────────────────────────────────────╯

Managing Route Weights

Multiple jobs can share the same route endpoint. Traffic is split among jobs that share a route according to each route's weight. A common use case for route weighting is in blue-green deployments.

A route's weight is specified as a percentage between 0 and 100. The weights of all apps on a given route are normalized to total 100%. For example, if you map a route with a weight of 0% to one or more jobs then traffic will be split evenly among the routes. If you map two jobs to same route with a weight of 0 then traffic will be split 50/50 among the jobs. If you map a third job to the same route then traffic would be split evenly into thirds (33.3/33.3/33.3).

If a route is mapped to jobs with both zero and non-zero weights, jobs with non-zero route weighting will receive the difference between the sum of all non-zero routes and 100%. For example, consider three applications (A, B, and C) that share a route. The route weights for application A and app B are both set to 45%, while app C is set to 0%. In this case, application A and B will each receive 45% of traffic to that route, while app C will receive 10%.

You can manage route weights using [APC] or Web Console.

Managing Route Weights Using APC

You can specify a route's weight using the --weight flag with the route add and route map commands. For example, the following command creates a new HTTP route with the endpoint http://site.apcera.me that is mapped to the mysite application with a route weight of 75%:

apc route add http://site.apcera.me --app mysite --weight 75

The following maps the same endpoint to another app (my-newsite) that doesn't specify a weight, so it will receive the remainder of the traffic that doesn't go to mysite:

apc route map http://site.apcera.me --app my-newsite

To update the weight of an existing route on a job you use the same apc route map command. For example, the following adjusts the weighting of the same endpoint between the my-site and my-newsite to 60/40, respectively:

apc route map http://site.apcera.me --app my-site --weight 60
apc route map http://site.apcera.me --app my-newsite --weight 40

To view a route's weightings you use the apc route show <endpoint> command, for example:

apc route show http://site.apcera.me
Route Type: http
HTTPS Only: false
Number of jobs: 2
╭───────────────────────────────────────────╮
│             Jobs using route              │
├─────────────────┬────────────────┬────────┤
│ Name            │ Namespace      │ Weight │
├─────────────────┼────────────────┼────────┤
│ static-site     │ /sandbox/admin │ 60.00  │
│ static-site-new │ /sandbox/admin │ 40.00  │
╰─────────────────┴────────────────┴────────╯

Managing Routes Weight Using the Web Console

The Web Console lets you map routes to jobs and set route weights. It also shows the calculated percentage of traffic going to each job based on the applied weightings.

Default weight single route mapping:

drawing

Default weight multiple route mapping:

drawing

75/25 traffic split:

drawing

50/50 traffic split:

drawing

25/75 traffic split:

drawing

100% traffic:

drawing

Normalized traffic:

drawing

Showing Route Details

You can use the apc route show <route-endpoint> command to list what apps are using a route, as well the route weights assigned to each app.

apc route show http://site.apcera.me
Route Type: http
HTTPS Only: false
Number of jobs: 2
╭───────────────────────────────────────────╮
│             Jobs using route              │
├─────────────────┬────────────────┬────────┤
│ Name            │ Namespace      │ Weight │
├─────────────────┼────────────────┼────────┤
│ static-site     │ /sandbox/admin │ 60.00  │
│ static-site-new │ /sandbox/admin │ 40.00  │
╰─────────────────┴────────────────┴────────╯

Policy Requirements

Route policy permissions are required to create and consume routes.

At a minimum, both the job::/ and the route::/ must permit route mapping. For example:

on job::/sandbox/user {
  if (auth_server@apcera.me->name == "user")
  {
    permit map
  }
}

on route::/http/com/example/cluster {
  if (job fqnMatch "job::/sandbox/user")
  {
    permit map
  }
}

Route endpoint URLs can be used by multiple apps. If you want to use a route that is already in use by another app, to prevent eavesdropping on the route, you must have policy permission (permit update) for each job. If there is more than one app using a route, you must have permit update for each job that uses that route.

As a best practice, use policy to require a unique route name for your environment, for example:

    route::/http/io/skanderna/sandbox/[name]
    {
        if (job nameMatch "job::/sandbox/[name]")
        {
            permit map
        }
    }

If you use the default route scheme you can customize the cluster value, that is, the domain name portion of the route. This is done using the defaultRouteSuffix policy claim type on the permitted job::/ resource.

For example, if your cluster-name is cluster.example.com, you can set foo.bar.com as the route suffix using the following policy on the host job:

on job::/sandbox/user {
  { defaultRouteSuffix foo.bar.com }

}

Refer to route policy examples for more information.

Using Route Paths and Wildcards

An HTTP route can include a path component that is used to determine where to route requests. For example, suppose you have one job (job::/api::v1_server) that serves v1 of a REST API at https://apiserver.example.com/v1/, and another job (job::/api::v2_server) that serves v2 API endpoints https://apiserver.example.com/v2/. In this case, both jobs are listening on port 5000. You can map

Create and map /v1/ route:

apc route add http://apiserver.example.com/v1/ --job /api::v1_server --port 5000

Create and map /v2/ route:

apc route add http://apiserver.example.com/v2/ --job /api::v2_server --port 5000

Or, equivalently, you could have a single job (/api::server) that handles v1 and v2 requests on different ports, for example:

apc route map http://apiserver.example.com/v1/ --job /api::server --port 5000
apc route map http://apiserver.example.com/v2/ --job /api::server --port 5001

A wildcard character (*) can be used in the left-most segments of the route endpoint's hostname, or the right-most segments of the path. For example, the following are valid wildcard routes:

*.apcera.com/foo/*/*
*.*.foo.bar/*

However, the following are invalid wildcard routes:

apcera.*/
apcera.*.com/foo/*/bar

Note the following rules and restrictions about route paths and wildcards:

  • The route path must end with a forward slash (/) for it to be routed to the target job. For example, the endpoint in the following route mapping command does not end with a /:
    apc route add http://apiserver.example.com/v2 --job /api::v2_server --port 5000
    

    To resolve, unmap and delete the invalid route and repeat the command route add or route map command with a forward slash at the end of the route's endpoint.

    apc route add http://apiserver.example.com/v2/ --job /api::v2_server --port 5000
    
  • You can't use a wildcard for the host name on the cluster's primary domain. For example, if your cluster is deployed to example.com then the following command will fail with the error Endpoint "*.example.com" is reserved.
    apc route add http://\*.example.com/v1/ --port 5000 --job my-app
    

Controlling Route Access by Client IP

By default, all client traffic to a job's defined routes is allowed access. You can optionally define an access control list (ACL) that allows or denies access to a job's routes based on a the client's IP address. A route ACL is defined by one or more rules, each of which defines an IP range in CIDR notation. When a client makes a request for a job route, the Apcera router compares the client's IP to each rule. Once a match is found, the client is allowed or denied access to the job route, based on the rule's definition. If no match is found, the client is allowed access by default.

To specify client IPs to allow or deny, you use the --client-acl parameter when creating an application with the apc app create/update, apc app from package, apc capsule create, apc docker run, and apc job update commands. This parameter takes a string that consists of one or more rules separated by commas. Each rule is composed of the string "allow" or "deny" followed by an IP range in CIDR notation.

For example, the following defines an ACL for the app named webapp that allows traffic from clients in the 128.66.3.0/24 IP range, and another that denies traffic from clients in the 128.66.0.0/16 IP range.

apc app create webapp --client-acl="allow 128.66.3.0/24, deny 128.66.0.0/16"

When the Apcera router handles a request from a client, it compares the client's IP to each rule, from left to right, until it finds a match. If no match is found, the request is allowed. If a match is found, the request is allowed or denied based on the rule's defined action.

If not specified, the first rule assigned to --client-acl is assumed to be an allow. For instance, the following is equivalent to the rules defined above:

apc app create webapp --client-acl="128.66.3.0/24, deny 128.66.0.0/16"

To create a rule that only allows in a specific IP or range and denies all others, you can add deny 0.0.0.0/0 at the end of the list. For example, the following rule will allow access only to 127.0.0.1.

allow 127.0.0.1/32, deny 0.0.0.0/0

Appending deny 0.0.0.0/0 has the effect of making the rule "opt-in" rather than "opt-out".