Skip to content

Services

This document describes the Unikraft Cloud Services API (v1) for publishing network services and creating load balanced services. Unikraft Cloud uses services to implement this functionality.

Services

A service has a public DNS name such as my-project.fra0.kraft.host. If you do not specify a DNS name when you create a service, Unikraft Cloud generates a random DNS name of the form young-monkey-uq6dxq0u.fra0.kraft.host. When you assign an instance to a service, the instance becomes accessible from the Internet using this DNS name. Unikraft Cloud also supports custom domains like www.example.com and wildcard domains like *.example.com.

By default, a service does not publish any network ports. To allow traffic to pass to the instances in a service, you have to explicitly specify the network ports to publish. For example, if you run a web server you would publish port 443 (HTTPS) and/or port 80 (HTTP). You can also redirect port 80 (HTTP) to port 443 (HTTPS).

Connection Handlers

Unikraft Cloud uses connection handlers to decide how to forward connections from the Internet to your application. You configure the handlers for every published service port individually. The following handlers are available:

HandlerDescription
tlsTerminate the TLS connection at the Unikraft Cloud gateway using our wildcard certificate issued for the kraft.cloud domain. The gateway forwards the unencrypted traffic to your application
httpEnable HTTP mode on the load balancer to load balance on the level of individual HTTP requests. In this mode, only HTTP connections are accepted. If this option is not set the load balancer works in TCP mode and balances TCP connections
redirectRedirect traffic from the source port to the destination port

Currently, there is a set of constraints when publishing ports:

  • Port 80: Must have http and must not have tls set
  • Port 443: Must have http and tls set
  • The redirect handler can only be set on port 80 (HTTP) to redirect to port 443 (HTTPS)
  • All other ports must have tls and must not have http set

Load Balancing

Load balancing in Unikraft Cloud is very easy. As soon as you attach more than one instance to a service, Unikraft Cloud will start balancing traffic between them. Therefore, only instances publishing the same ports must be part of the same service.

You can remove instances from a service at any time. Unikraft Cloud will immediately take the instance out of the load balancing.

If you want to make sure that no existing connections are dropped when stopping an instance, use the draining feature of the PUT /v1/instances/stop endpoint.

Soft-/Hard Limits

Services have soft and hard limits for the number of concurrent requests and connections. The limits are applied per instance. For HTTP services (i.e., the http handler is set) each individual in-flight request is accounted against the limit, but not the underlying TCP connection. For TCP services the individual open connections are counted. In the following, we use the term request to refer to both requests and connections.

The soft limit is used by the Unikraft Cloud load balancer to decide when to wake up another standby instance. For example, if the soft limit is set to 5 and the service consists of 2 standby instances, one of the instances receives up to 5 concurrent requests. The 6th parallel requests wakes up the second instance. If there are no more standby instances to wake up, the number of requests assigned to each instance will exceed the soft limit. The load balancer makes sure that when the number of in-flight requests goes down again, instances are put into standby as fast as possible.

The hard limit defines the maximum number of concurrent requests that an instance can handle. The load balancer will never assign more requests to a single instance. In case there are no other instances available, excess requests fail (i.e., they are blocked and not queued).

Persistence

When a service is implicitly created as part of a new instance (see POST /v1/instances) it exists only as long as its owning instance exists.

In contrast, services that you explicitly create using the POST /v1/services endpoint are persistent and are not automatically deleted when the last instance leaves the service. You need to delete them with the DELETE /v1/services endpoint.

When you attach a second instance to an implicitly created service, Unikraft Cloud re-configures the service to be persistent from that point on.

API Endpoints

The Unikraft Cloud Services API provides the following endpoints:

MethodEndpointPurpose and Description
POST/v1/servicesCreates one or more services
GET/v1/servicesReturns the current state and configuration of services
DELETE/v1/servicesDeletes the specified services
GET/v1/services/listLists all existing services

In the following, the API endpoints are specified relative to this base URL:

https://api.X.kraft.cloud/

With X being the IATA metro code. We use fra0 as an example in the documentation. See the introduciton for more information on how to connect to the API.

Creating a New Service

Creates a new service with the given configuration. Note that the service properties like published ports can only be defined during creation. They cannot be changed later.

Each port in a service can specify a list of handlers that determine how traffic arriving at the port is handled. See Connection Handlers for a complete overview.

Request

Endpoints:
POST /v1/services

Body ParameterTypeDefaultRequiredDescription
name1Nameauto-generatedName of the service
servicesarray of objects✔️Description of exposed network services
    portint✔️Public-facing port
    destination_portintSame as portPort that the application listens on
    handlersarray of stringsSee Connection Handlers
domains2array of objectsauto-generatedDescription of domains to associate with the service
    name3string✔️Publicly accessible domain name
    certificate4objectauto-generatedTLS certificate to use for the domain
        uuid | name5UUID | Name✔️UUID or name of the certificate
soft_limitint1Per-instance connection soft limit
hard_limitint65535Per-instance connection hard limit

1If no name is specified a random name of the form <word>-<word>-<random> is auto-generated, where <random> is an 8 characters long random alphanumeric suffix.
2If name is specified without also providing a domain, a domain is derived from name by appending an 8 characters long random alphanumeric suffix and the metro’s domain name. For example, setting the name to my-project without also providing a domain results in an auto-generated domain of my-project-<random>.fra0.kraft.host.
3The services published by the service will be accessible under the given domain names. If name is a fully-qualified domain name, that is it ends with a dot (.), the domain name is taken as-is. Otherwise, the metro’s domain name is appended (e.g., my-project expands to my-project.fra0.kraft.host). If the given domain name is already in use by the current or a different user the operation fails. In addition, certain domain names cannot be used (e.g., www.fra0.kraft.host).
4Only allowed for FQDNs, not for subdomains. Subdomains like my-project inherit the wildcard *.<metro>.kraft.host certificate. If you specify an FQDN like www.example.com., Unikraft Cloud will automatically pick the certificate with the matching CN or trigger a certificate request (see here).
5You need to specify either uuid or name.

Example of creating a service that publishes HTTP port 8080 at HTTPS port 443
curl -X POST \
-H "Authorization: Bearer ${UKC_TOKEN}" \
-H "Content-Type: application/json" \
"https://api.fra0.kraft.cloud/v1/services" \
-d '{
"services": [
{
"port": 443,
"destination_port": 8080,
"handlers": [
"tls",
"http"
]
}
],
"domains": [
{
"name": "my-project"
},
{
"name": "example.com."
}
]
}'

Response

The response is embedded in a JSON object as described in API Responses.

FieldTypeDescription
statusstringsuccess on success, or error if the request failed
uuidUUIDUUID of the newly created service
nameNameName of the newly created service
domainsarray of objectsDescription of domains associated with the service
    fqdnstringPublic fully-qualified domain name under which the service is accessible from the Internet
    certificate1objectTLS certificate used for the domain
        uuidUUIDUUID of the certificate
        nameNameName of the certificate
        stateStateState of the certificate

1 Not for subdomains of <metro>.kraft.host.

Status 200 OK
{
"status": "success",
"data": {
"service_groups": [
{
"status": "success",
"uuid": "3b5b4c36-2c9b-46e4-80c6-7e5b561938c2",
"name": "young-monkey-uq6dxq0u",
"domains": [
{
"fqdn": "my-project.fra0.kraft.host"
},
{
"fqdn": "example.com",
"certificate": {
"uuid": "0b8fda39-d326-426e-827e-093e4c173dc8",
"name": "example.com-x9d9k",
"state": "valid"
}
}
]
}
]
}
}

Getting the Status of a Service

Returns the current status and the configuration of a particular service if a UUID or name is specified. Otherwise, returns the current status and configuration of all services.

Request

Endpoints:
GET /v1/services
GET /v1/services/<UUID>

Query ParameterTypeDefaultRequiredDescription
detailsbooltrueWhether to provide detailed status and configuration information
name1string | list of stringsNames of services to return as comma-separated list
uuid1string | list of stringsUUIDs of services to return as comma-separated list
Body ParameterTypeDefaultRequiredDescription
uuid | name1,2UUID | Name✔️UUID or name of the service to get the status for

1 Not allowed in local scope.
2 You need to specify either uuid or name within the same body object.

Example of getting the status of services
curl -X GET \
-H "Authorization: Bearer ${UKC_TOKEN}" \
"https://api.fra0.kraft.cloud/v1/services/3b5b4c36-2c9b-46e4-80c6-7e5b561938c2"
Terminal window
curl -X GET \
-H "Authorization: Bearer ${UKC_TOKEN}" \
"https://api.fra0.kraft.cloud/v1/services" \
-d '[
{
"uuid": "3b5b4c36-2c9b-46e4-80c6-7e5b561938c2"
},
{
"name": "my-service"
}
]'
Terminal window
curl -X GET \
-H "Authorization: Bearer ${UKC_TOKEN}" \
"https://api.fra0.kraft.cloud/v1/services?name=my-service,my-other-service"
Terminal window
curl -X GET \
-H "Authorization: Bearer ${UKC_TOKEN}" \
"https://api.fra0.kraft.cloud/v1/services?details=false"

Response

The response is embedded in a JSON object as described in API Responses.

FieldTypeDescription
status1stringsuccess on success, or error if the request failed
uuidUUIDUUID of the service
nameNameName of the service
created_atstringDate and time of creation in ISO8601
persistentboolIndicates if the service will stay alive even after the last instance detached
autoscaleboolIndicates if the service has autoscale enabled
soft_limitintPer-instance connection soft limit
hard_limitintPer-instance connection hard limit
servicesarray of objectsDescription of published network services
    portintPublic-facing port
    destination_portintApplication port to which inbound traffic is redirected
    handlersarray of stringsSee Connection Handlers
domainsarray of objectsDescription of domains associated with the service
    fqdnstringPublic fully-qualified domain name under which the service is accessible from the Internet
    certificateobjectTLS certificate used for the domain (not for subdomains of <metro>.kraft.host)
        uuidUUIDUUID of the certificate
        nameNameName of the certificate
        stateStateState of the certificate
instancesarray of objectsInstances attached to this service
    uuidUUIDUUID of the instance
    nameNameName of the instance

1 Not when listing all existing services.

Status 200 OK
{
"status": "success",
"data": {
"service_groups": [
{
"status": "success",
"uuid": "3b5b4c36-2c9b-46e4-80c6-7e5b561938c2",
"name": "young-monkey-uq6dxq0u",
"created_at": "2023-08-21T16:38:15Z",
"persistent": false,
"autoscale": false,
"soft_limit": 1,
"hard_limit": 65535,
"services": [
{
"port": 443,
"destination_port": 8080,
"handlers": [
"tls",
"http"
]
}
],
"domains": [
{
"fqdn": "my-project.fra0.kraft.host"
},
{
"fqdn": "example.com",
"certificate": {
"uuid": "0b8fda39-d326-426e-827e-093e4c173dc8",
"name": "example.com-x9d9k",
"state": "valid"
}
}
],
"instances": [
{
"uuid": "77d0316a-fbbe-488d-8618-5bf7a612477a",
"name": "myapp"
}
]
}
]
}
}

Deleting a Service

Deletes the specified service. Fails if there are still instances attached to the service. After this call the IDs associated with the service are no longer valid and the domain name is released.

Request

Endpoints:
DELETE /v1/services
DELETE /v1/services/<UUID>

Query ParameterTypeDefaultRequiredDescription
name1string | list of stringsNames of services to delete as comma-separated list
uuid1string | list of stringsUUIDs of services to delete as comma-separated list
Body ParameterTypeDefaultRequiredDescription
uuid | name1,2UUID | Name✔️UUID or name of the service to delete

1 Not allowed in local scope.
2 You need to specify either uuid or name within the same body object.

Example of deleting a specific service
curl -X DELETE \
-H "Authorization: Bearer ${UKC_TOKEN}" \
"https://api.fra0.kraft.cloud/v1/services/3b5b4c36-2c9b-46e4-80c6-7e5b561938c2"

Response

The response is embedded in a JSON object as described in API Responses.

FieldTypeDescription
statusstringsuccess on success, or error if the request failed
uuidUUIDUUID of the service
nameNameName of the service
Status 200 OK
{
"status": "success",
"data": {
"service_groups": [
{
"status": "success",
"uuid": "3b5b4c36-2c9b-46e4-80c6-7e5b561938c2",
"name": "young-monkey-uq6dxq0u"
}
]
}
}

List Existing Services

Lists all existing services. You can filter by persistence and domain name. The latter can be used to lookup the UUID of the service that owns a certain domain name. The returned services fulfill all provided filter criteria. No particular value is assumed if a filter is not part of the request.

Request

Endpoints:
GET /v1/services/list

Body ParameterTypeDefaultRequiredDescription
persistentboolDesired persistence value for filtering
fqdnstringFully-qualified domain name of the service to look up
Example of listing all existing services
curl -X GET \
-H "Authorization: Bearer ${UKC_TOKEN}" \
"https://api.fra0.kraft.cloud/v1/services/list"
Example of looking up the service for a DNS name
curl -X GET \
-H "Authorization: Bearer ${UKC_TOKEN}" \
-H "Content-Type: application/json" \
"https://api.fra0.kraft.cloud/v1/services/list" \
-d '{
"fqdn": "young-monkey-uq6dxq0u.fra0.kraft.host"
}'

Response

The response is embedded in a JSON object as described in API Responses.

FieldTypeDescription
uuidUUIDUUID of the service
nameNameName of the service
Status 200 OK
{
"status": "success",
"data": {
"service_groups": [
{
"uuid": "3b5b4c36-2c9b-46e4-80c6-7e5b561938c2",
"name": "young-monkey-uq6dxq0u"
},
{
"uuid": "d3a7fe17-0a44-4862-836f-d5f9a6a0b2f8",
"name": "patient-butterfly-9br0p9e5"
}
]
}
}