Container Deployments¶
This example demonstrates how to create, manage, and monitor container deployments in Verda.
Container Deployments¶
"""Example script demonstrating container deployment management using the Verda API.
This script provides a comprehensive example of container deployment lifecycle,
including creation, monitoring, scaling, and cleanup.
"""
import os
import time
from verda import VerdaClient
from verda.containers import (
ComputeResource,
Container,
ContainerDeploymentStatus,
ContainerRegistrySettings,
Deployment,
EnvVar,
EnvVarType,
GeneralStorageMount,
HealthcheckSettings,
QueueLoadScalingTrigger,
ScalingOptions,
ScalingPolicy,
ScalingTriggers,
SecretMount,
SharedFileSystemMount,
UtilizationScalingTrigger,
)
from verda.exceptions import APIException
# Configuration constants
DEPLOYMENT_NAME = 'my-deployment'
IMAGE_NAME = 'your-image-name:version'
# Get client secret and id from environment variables
CLIENT_ID = os.environ.get('VERDA_CLIENT_ID')
CLIENT_SECRET = os.environ.get('VERDA_CLIENT_SECRET')
# Verda client instance
verda = None
def wait_for_deployment_health(
client: VerdaClient,
deployment_name: str,
max_attempts: int = 10,
delay: int = 30,
) -> bool:
"""Wait for deployment to reach healthy status.
Args:
client: Verda API client
deployment_name: Name of the deployment to check
max_attempts: Maximum number of status checks
delay: Delay between checks in seconds
Returns:
bool: True if deployment is healthy, False otherwise
"""
for _attempt in range(max_attempts):
try:
status = client.containers.get_deployment_status(deployment_name)
print(f'Deployment status: {status}')
if status == ContainerDeploymentStatus.HEALTHY:
return True
time.sleep(delay)
except APIException as e:
print(f'Error checking deployment status: {e}')
return False
return False
def cleanup_resources(client: VerdaClient) -> None:
"""Clean up all created resources.
Args:
client: Verda API client
"""
try:
# Delete deployment
client.containers.delete_deployment(DEPLOYMENT_NAME)
print('Deployment deleted')
except APIException as e:
print(f'Error during cleanup: {e}')
def main() -> None:
"""Main function demonstrating deployment lifecycle management."""
try:
# Initialize client
global verda
verda = VerdaClient(CLIENT_ID, CLIENT_SECRET)
# Create container configuration
container = Container(
image=IMAGE_NAME,
exposed_port=80,
healthcheck=HealthcheckSettings(enabled=True, port=80, path='/health'),
volume_mounts=[
GeneralStorageMount(mount_path='/data'),
# Optional: Fileset secret
SecretMount(
mount_path='/path/to/mount',
secret_name='my-fileset-secret', # This fileset secret must be created beforehand
),
# Optional: Mount an existing shared filesystem volume
SharedFileSystemMount(mount_path='/sfs', volume_id='<ID-OF-THE-SFS-VOLUME>'),
],
env=[
# Secret environment variables needed to be added beforehand
EnvVar(
name='HF_TOKEN',
# This is a reference to a secret already created
value_or_reference_to_secret='hf-token',
type=EnvVarType.SECRET,
),
# Plain environment variables can be added directly
EnvVar(
name='VERSION',
value_or_reference_to_secret='1.5.2',
type=EnvVarType.PLAIN,
),
],
)
# Create scaling configuration
scaling_options = ScalingOptions(
min_replica_count=1,
max_replica_count=5,
scale_down_policy=ScalingPolicy(delay_seconds=300),
scale_up_policy=ScalingPolicy(delay_seconds=300),
queue_message_ttl_seconds=500,
concurrent_requests_per_replica=1,
scaling_triggers=ScalingTriggers(
queue_load=QueueLoadScalingTrigger(threshold=1),
cpu_utilization=UtilizationScalingTrigger(enabled=True, threshold=80),
gpu_utilization=UtilizationScalingTrigger(enabled=True, threshold=80),
),
)
# Create registry and compute settings
registry_settings = ContainerRegistrySettings(is_private=False)
compute = ComputeResource(name='General Compute', size=1)
# Create deployment object
deployment = Deployment(
name=DEPLOYMENT_NAME,
container_registry_settings=registry_settings,
containers=[container],
compute=compute,
scaling=scaling_options,
is_spot=False,
)
# Create the deployment
created_deployment = verda.containers.create_deployment(deployment)
print(f'Created deployment: {created_deployment.name}')
# Wait for deployment to be healthy
if not wait_for_deployment_health(verda, DEPLOYMENT_NAME):
print('Deployment health check failed')
cleanup_resources(verda)
return
# Update scaling configuration
try:
deployment = verda.containers.get_deployment_by_name(DEPLOYMENT_NAME)
# Create new scaling options with increased replica counts
deployment.scaling = ScalingOptions(
min_replica_count=2,
max_replica_count=10,
scale_down_policy=ScalingPolicy(delay_seconds=300),
scale_up_policy=ScalingPolicy(delay_seconds=300),
queue_message_ttl_seconds=500,
concurrent_requests_per_replica=1,
scaling_triggers=ScalingTriggers(
queue_load=QueueLoadScalingTrigger(threshold=1),
cpu_utilization=UtilizationScalingTrigger(enabled=True, threshold=80),
gpu_utilization=UtilizationScalingTrigger(enabled=True, threshold=80),
),
)
updated_deployment = verda.containers.update_deployment(DEPLOYMENT_NAME, deployment)
print(f'Updated deployment scaling: {updated_deployment.name}')
except APIException as e:
print(f'Error updating scaling options: {e}')
# Demonstrate deployment operations
try:
# Pause deployment
verda.containers.pause_deployment(DEPLOYMENT_NAME)
print('Deployment paused')
time.sleep(60)
# Resume deployment
verda.containers.resume_deployment(DEPLOYMENT_NAME)
print('Deployment resumed')
# Restart deployment
verda.containers.restart_deployment(DEPLOYMENT_NAME)
print('Deployment restarted')
# Purge queue
verda.containers.purge_deployment_queue(DEPLOYMENT_NAME)
print('Queue purged')
except APIException as e:
print(f'Error in deployment operations: {e}')
# Clean up
cleanup_resources(verda)
except Exception as e:
print(f'Unexpected error: {e}')
# Attempt cleanup even if there was an error
try:
cleanup_resources(verda)
except Exception as cleanup_error:
print(f'Error during cleanup after failure: {cleanup_error}')
if __name__ == '__main__':
main()