Convox provides powerful tools to control where your applications and build processes run within your Kubernetes cluster. By leveraging node group configurations and service placement rules, you can optimize resource usage, improve cost efficiency, and ensure the right workloads run on the right infrastructure.
Workload placement in Convox is achieved through these key features:
These capabilities allow for sophisticated infrastructure optimization strategies, such as:
At the rack level, you can define custom node groups:
additional_node_groups_config
: Creates general-purpose node groupsadditional_build_groups_config
: Creates node groups specifically for build processesThese parameters allow you to specify:
Note: These configurations are independent of each other. You can use either one or both depending on your needs. If you only configure additional node groups, builds will continue using the rack’s primary build node (if build_node_enabled is set) or the primary rack nodes. If you only configure build node groups, your services will continue running on the standard rack nodes while builds will be isolated according to your build configuration.
While you can set configuration directly using a JSON string, most users find it more manageable to use a JSON file, especially for complex configurations.
Create a JSON file (e.g., node-groups.json
) with your configuration:
[
{
"id": 101,
"type": "t3.medium",
"capacity_type": "ON_DEMAND",
"min_size": 1,
"max_size": 5,
"label": "critical-services",
"tags": "environment=production,team=frontend"
},
{
"id": 102,
"type": "c5.large",
"capacity_type": "SPOT",
"min_size": 0,
"max_size": 10,
"label": "batch-workers",
"disk": 100,
"tags": "environment=production,team=data,workload=batch"
}
]
Note the use of:
id
field to uniquely identify each node grouptags
field to apply AWS resource tags for organization and cost trackingThen apply the configuration using:
$ convox rack params set additional_node_groups_config=/path/to/node-groups.json -r rackName
Important Note on AWS Rate Limits: When adding or removing multiple node groups, it’s recommended to modify no more than three node groups at a time to avoid hitting AWS API rate limits. If you receive a rate limit error during an update simply run the parameter set command again. The operation will resume from where it left off, creating the remaining node groups without duplicating the ones that were already successfully created.
Similarly, create a JSON file (e.g., build-groups.json
) for build node configuration:
[
{
"id": 201,
"type": "c5.xlarge",
"capacity_type": "SPOT",
"min_size": 0,
"max_size": 3,
"label": "app-build",
"disk": 100,
"tags": "environment=build,team=devops"
}
]
Apply it with:
$ convox rack params set additional_build_groups_config=/path/to/build-groups.json -r rackName
If you prefer to set configuration directly in the command line without creating a file, you can use a JSON string:
$ convox rack params set 'additional_node_groups_config=[{"id":101,"type":"t3.medium","capacity_type":"ON_DEMAND","min_size":1,"max_size":5,"label":"critical-services","tags":"environment=production,team=frontend"}]' -r rackName
$ convox rack params set 'additional_build_groups_config=[{"id":201,"type":"c5.xlarge","capacity_type":"SPOT","min_size":0,"max_size":3,"label":"app-build","disk":100,"tags":"environment=build,team=devops"}]' -r rackName
This approach is useful for automation scripts or when making quick changes, though it becomes unwieldy for more complex configurations.
Each node group configuration supports the following fields:
Field | Required | Description | Default |
---|---|---|---|
id |
No | Unique integer identifier for the node group | Auto-generated |
type |
Yes | The EC2 instance type to use for the node group | |
disk |
No | The disk size in GB for the nodes | Same as main node disk |
capacity_type |
No | Whether to use on-demand or spot instances | ON_DEMAND |
min_size |
No | Minimum number of nodes | 1 |
max_size |
No | Maximum number of nodes | 100 |
label |
No | Custom label value for the node group. Applied as convox.io/label: <label-value> |
None |
tags |
No | Custom AWS tags as comma-separated key-value pairs | None |
dedicated |
No | When true , only services with matching node group labels will be scheduled on these nodes |
false |
ami_id |
No | Custom AMI ID to use | EKS-optimized AMI |
id
fieldThe id
field provides important benefits:
Without the id
field, Convox generates a random identifier that changes when the configuration is updated, potentially causing unnecessary node group recreation.
At the application level, you can control where specific workloads run:
BuildLabels
: Directs build pods to specific node groupsBuildCpu
and BuildMem
: Sets resource requests for build podsnodeSelectorLabels
in convox.yml
: Directs service pods to specific node groupsIn your convox.yml
file, you can specify node selectors for each service:
services:
web:
nodeSelectorLabels:
convox.io/label: app-workers
worker:
nodeSelectorLabels:
convox.io/label: batch-workers
This example creates a cost-optimized infrastructure with dedicated node pools for different workload types:
Rack Configuration:
$ convox rack params set additional_node_groups_config=/path/to/node-groups.json -r production
$ convox rack params set additional_build_groups_config=/path/to/build-groups.json -r production
With node groups config:
[
{
"id": 101,
"type": "t3.medium",
"capacity_type": "ON_DEMAND",
"min_size": 1,
"max_size": 5,
"label": "critical-services",
"tags": "department=frontend,environment=production,cost-center=web"
},
{
"id": 102,
"type": "c5.large",
"capacity_type": "SPOT",
"min_size": 0,
"max_size": 10,
"label": "batch-workers",
"tags": "department=data,environment=production,cost-center=analytics"
}
]
And build groups config:
[
{
"type": "c5.xlarge",
"capacity_type": "SPOT",
"min_size": 0,
"max_size": 5,
"label": "app-build",
}
]
Application Configuration:
$ convox apps params set BuildLabels=convox.io/label=app-build -a myapp
$ convox apps params set BuildCpu=1024 BuildMem=4096 -a myapp
Service Configuration (in convox.yml
):
services:
web:
build: .
port: 3000
nodeSelectorLabels:
convox.io/label: critical-services
worker:
build: ./worker
nodeSelectorLabels:
convox.io/label: batch-workers
This configuration creates:
To create dedicated node groups that exclusively run specific services:
Create a JSON file for your node group configuration:
[
{
"id": 103,
"type": "m5.large",
"capacity_type": "ON_DEMAND",
"min_size": 2,
"max_size": 5,
"label": "database-workers",
"dedicated": true,
"tags": "environment=production,team=datastore,criticality=high"
}
]
Apply the configuration:
$ convox rack params set additional_node_groups_config=/path/to/dedicated-nodes.json -r production
Service Configuration (in convox.yml
):
services:
db-processor:
build: ./processor
nodeSelectorLabels:
convox.io/label: database-workers
With dedicated:true
, only services that explicitly select the node group will run on it, ensuring isolation for sensitive workloads.
Convox allows you to implement different levels of customization based on your needs:
Build Isolation Only: Configure only additional_build_groups_config
to isolate build processes while keeping services on standard nodes:
$ convox rack params set additional_build_groups_config=/path/to/build-groups.json -r production
$ convox apps params set BuildLabels=convox.io/label=app-build -a myapp
Service Placement Only: Configure only additional_node_groups_config
to customize service placement while letting builds run on standard nodes:
$ convox rack params set additional_node_groups_config=/path/to/node-groups.json -r production
In your convox.yml
:
services:
web:
nodeSelectorLabels:
convox.io/label: critical-services
Complete Workload Management: Implement both configurations for full control over placement of both services and build processes.
Match Node Resources to Workload Requirements:
Cost Optimization:
Build Process Optimization:
min_size: 0
to allow build nodes to scale down when not in useService Isolation:
dedicated
flag for node groups that need strict isolationNode Group Identity Management:
id
to each node groupTagging Strategy:
If builds fail with scheduling errors, verify:
BuildLabels
parameter matches the node group’s labelsIf services won’t deploy, check:
convox.yml
match existing node groupsIf nodes aren’t scaling as expected:
If node groups are being recreated unexpectedly:
id
fieldEffective workload placement is a powerful tool for optimizing your Convox infrastructure. By leveraging custom node groups with preserved identities, service placement rules, and AWS tagging, you can create an infrastructure that balances performance, cost, and isolation requirements for your specific application needs.
For more detailed information, refer to: