EKS ML Deployment
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Advanced Deployment: Machine Learning on Amazon EKS
Introduction: The Intersection of Scale and Intelligence
Deploying machine learning (ML) models into production is fundamentally different from deploying standard web applications. While a typical API might focus on latency and throughput, ML deployment involves complex dependency management, hardware acceleration (such as GPUs or specialized inference chips), and the need for sophisticated model versioning. Amazon Elastic Kubernetes Service (EKS) has emerged as the industry standard for managing these workloads because it provides the flexibility of Kubernetes combined with the managed infrastructure of AWS.
In this lesson, we will explore how to architect, deploy, and scale ML models on EKS. We will move beyond the basics of "running a container" and look at how to handle high-performance inference, manage GPU resources, and ensure that your models remain available even under heavy load. By mastering these concepts, you shift from being a developer who writes code to an engineer who builds resilient, intelligent systems that can handle the unpredictable nature of real-world data science.
The Architecture of ML on EKS
When you deploy an ML model on EKS, you are essentially creating a bridge between your data science workflow and your production infrastructure. At the core, this involves packaging your model artifacts—weights, configuration files, and inference scripts—into a container image. Once containerized, this image is deployed as a Kubernetes Pod, which communicates with the outside world through a Service or Ingress controller.
However, ML workloads often require more than just CPU. Many deep learning models require NVIDIA GPUs to function within reasonable latency requirements. EKS handles this through the Device Plugin framework, which allows Kubernetes to schedule pods onto nodes that have specific hardware attached. Understanding how to request these resources in your manifest files is the first step toward effective ML deployment.
Containerizing the Model
Before you can deploy anything to EKS, you must ensure your model is wrapped in an environment that guarantees reproducibility. You should avoid hardcoding model paths or configuration values within your container image. Instead, use environment variables to inject these details at runtime. This allows you to update your model by simply updating the image tag in your deployment manifest, rather than rebuilding the entire application.
Callout: The "Model-as-Code" Philosophy In traditional software, we treat code as the source of truth. In ML, the source of truth is a combination of the code, the model weights, and the training data. By containerizing your model artifacts alongside your serving code, you treat the entire inference engine as an immutable unit. This prevents the "it works on my machine" problem, as the environment inside the container is identical across development, testing, and production.
Setting Up the Infrastructure: Node Groups and GPUs
To run ML models effectively, you need an EKS cluster configured with the right hardware. While you can run small models on standard CPU instances, anything involving deep learning, natural language processing, or computer vision will likely require GPU support.
Configuring GPU Nodes
When creating your node groups in EKS, you must specify an instance type that supports NVIDIA GPUs, such as the p3, g4dn, or g5 series. You also need to ensure that the NVIDIA Device Plugin is installed on your cluster. This plugin is what allows Kubernetes to "see" the GPUs and assign them to your pods.
- Install the NVIDIA Device Plugin: This is typically done via a DaemonSet that runs on every node in your cluster. It monitors the available GPUs and reports them to the Kubernetes API server.
- Define Resource Limits: In your deployment manifest, you must explicitly request GPU resources. If you do not include these limits, Kubernetes will not know that your pod requires specialized hardware and will likely schedule it on a standard CPU node, causing the model to crash or run extremely slowly.
apiVersion: v1
kind: Pod
metadata:
name: ml-inference-pod
spec:
containers:
- name: model-server
image: my-registry/model-image:v1
resources:
limits:
nvidia.com/gpu: 1 # Request one GPU
Note: Always ensure that your EKS AMI (Amazon Machine Image) is "GPU-optimized." These AMIs come pre-installed with the necessary NVIDIA drivers, saving you significant time during cluster initialization.
Advanced Serving Patterns
Once your infrastructure is ready, you need to choose an inference pattern that fits your use case. You can serve models as simple REST APIs, but as complexity grows, you may need more advanced strategies.
1. The Sidecar Pattern
In this pattern, you run the model server in one container and a proxy or pre-processing container in another within the same Pod. The proxy can handle authentication, logging, or input validation, while the model server focuses strictly on inference. This modular approach allows you to update your pre-processing logic without touching the model serving code.
2. Model Mesh or Multi-Model Serving
If you have dozens of small models, running one Pod per model is wasteful. Multi-model serving allows you to load several models into the memory of a single server. This significantly reduces the resource footprint but requires careful management of memory limits to prevent one model from starving others of resources.
3. Queue-Based Inference
For asynchronous tasks, such as generating an image or processing a large batch of documents, you shouldn't use a synchronous REST API. Instead, use a queue-based system. Your application places a request in an Amazon SQS queue, and a worker pod on EKS pulls the request, processes it, and saves the result to an S3 bucket. This pattern is highly resilient to traffic spikes.
Scaling: The Horizontal Pod Autoscaler (HPA)
Traditional web applications scale based on CPU or memory usage. However, ML models often have different scaling triggers. A model might be compute-bound on the GPU but have very low CPU usage. If you only scale based on CPU, your model will be overwhelmed by requests before the system decides to add more pods.
To solve this, use the Custom Metrics API. You can configure your EKS cluster to monitor metrics like:
- Request Latency: If the time to process a request exceeds a certain threshold, trigger a scale-out.
- GPU Utilization: If GPU usage is consistently high, add more pods.
- Queue Depth: If the number of pending tasks in your queue grows, spin up more worker pods.
Implementing Custom Metrics
To implement this, you will need to install the Prometheus adapter. Prometheus collects metrics from your inference server (e.g., how many requests are being processed per second), and the adapter exposes these to the Kubernetes HPA.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: model-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: model-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: gpu_utilization
target:
type: AverageValue
averageValue: 80
Best Practices for Production ML
Deploying to production is only the beginning. Maintaining the health and performance of your models requires a rigorous set of standards.
1. Versioning Everything
Never deploy a model tagged simply as "latest." Use specific versions or commit hashes. This ensures that if a new model version performs poorly, you can perform an instant rollback to the previous known-good version.
2. Health Checks and Liveness Probes
An ML model server might report as "ready" even if the model weights failed to load into memory. Always implement a custom liveness probe that checks not just if the web server is running, but if the model is actually loaded and ready to accept inference requests.
3. Monitoring and Observability
You cannot improve what you do not measure. Use tools like CloudWatch or managed Prometheus to track:
- Inference Latency (P95/P99): Crucial for user experience.
- Model Drift: Are the inputs to your model changing over time?
- Error Rates: Are there specific types of requests that cause the model to crash?
Warning: Avoid "over-monitoring." Collecting too many metrics can actually introduce latency into your inference pipeline. Focus on the metrics that directly impact performance and reliability.
Common Pitfalls and How to Avoid Them
Even experienced engineers often stumble when moving ML to EKS. Here are the most common mistakes and how to avoid them.
- Ignoring Cold Starts: When a new pod spins up, it must download the model weights (which can be several gigabytes) from S3. This causes a massive delay. Solution: Use an init-container to pull weights during the pod startup phase or mount an EFS (Elastic File System) volume that contains the model artifacts.
- Lack of Resource Quotas: Without quotas, a rogue process could consume all the memory on a node, causing other pods to be evicted. Solution: Always define
requestsandlimitsfor CPU, memory, and GPU in your deployment manifests. - Hardcoding Infrastructure: Trying to manage the cluster manually instead of using Infrastructure-as-Code (IaC) tools like Terraform or AWS CDK. Solution: Treat your EKS cluster configuration as code so that it can be versioned and replicated easily.
Comparison: CPU vs. GPU Inference
| Feature | CPU Inference | GPU Inference |
|---|---|---|
| Cost | Lower | Higher |
| Throughput | Moderate | Very High |
| Best For | Simple models, low traffic | Complex models, real-time |
| Setup Complexity | Low | High (Driver management) |
| Latency | Higher | Very Low |
Step-by-Step Deployment Workflow
To give you a practical path forward, follow this workflow when deploying your next model on EKS:
- Prepare the Artifacts: Package your model file (e.g.,
.onnx,.pt, or.pb) with your serving script (e.g., Flask, FastAPI, or TorchServe). - Containerize: Build the Docker image, test it locally, and push it to Amazon ECR (Elastic Container Registry).
- Define Manifests: Write your Deployment, Service, and HPA manifests. Ensure you include the necessary GPU resource requests.
- Apply to Cluster: Use
kubectl apply -f .to deploy your resources to the EKS cluster. - Verify: Check the logs of your pod (
kubectl logs <pod-name>) to ensure the model loaded correctly. - Load Test: Before opening the service to traffic, use a tool like
locustorghzto simulate traffic and verify that your autoscaling policies trigger as expected.
Deep Dive: Handling Model Weights at Scale
One of the most persistent challenges in EKS ML deployment is moving large model weights into the pod's filesystem. If you include the weights inside the Docker image, your image size becomes massive, making deployments slow and expensive.
The "S3-Mount" Strategy
Instead of baking weights into the image, mount an S3 bucket directly to your pod's file system using the CSI (Container Storage Interface) driver for S3. This allows the pod to access the weights as if they were local files without the overhead of downloading them during the startup sequence.
Using EFS for Shared Weights
If you have multiple pods that need to access the same large model, store the weights on an Amazon EFS volume. You can mount the same EFS volume to multiple pods in read-only mode. This is significantly more efficient than each pod downloading its own copy of the weights.
# Example of mounting EFS in a Pod
spec:
volumes:
- name: model-storage
efs:
fileSystemId: fs-12345678
containers:
- name: model-server
volumeMounts:
- name: model-storage
mountPath: /var/models
readOnly: true
Security Considerations
When running ML on EKS, your security posture must be tighter than a standard web app. ML models are valuable intellectual property and often process sensitive user data.
- IAM Roles for Service Accounts (IRSA): Never use the node's IAM role for your pods. Use IRSA to assign a specific, least-privilege IAM role to each pod. This ensures that your model container can only access the specific S3 buckets or databases it needs.
- Network Policies: Use Kubernetes Network Policies to restrict which pods can talk to each other. Your model server should only accept traffic from your API gateway or internal load balancer.
- Image Scanning: Enable ECR image scanning to automatically check your model containers for vulnerabilities in the underlying OS or Python dependencies.
The Future: Serverless Inference on EKS
While we have focused on managing our own pods, the industry is trending toward "serverless" patterns even within Kubernetes. Projects like Knative allow you to deploy models that scale to zero when not in use. This is a game-changer for cost management. If your model is only used during business hours, Knative can scale your deployment to zero pods at night and spin them up instantly when a request arrives the next morning.
Callout: When to use EKS vs. SageMaker Many students ask why they should use EKS instead of Amazon SageMaker. The answer is control. SageMaker provides a very easy, managed experience for common tasks. EKS is for when you need to customize the underlying infrastructure, run specific versions of libraries, or integrate your model into a larger, complex Kubernetes-based system. If your team already has deep Kubernetes expertise, EKS is often the more flexible choice.
Troubleshooting Common Errors
Even with the best configuration, things will fail. Here is how to approach common errors:
- CrashLoopBackOff: This is the most common error. Usually, it means your application is crashing immediately upon startup. Check the logs with
kubectl logs <pod-name> --previous. Often, this is caused by a missing environment variable or an incompatible library version. - ImagePullBackOff: This indicates the cluster cannot pull your image. Check your ECR permissions. Does the EKS node role have the
ecr:GetDownloadUrlForLayerpermission? - OOMKilled: Your pod is running out of memory. Kubernetes kills it to protect the node. Increase your
limits.memoryin your deployment manifest. - Pending State: The pod is stuck in "Pending." This usually means there are no nodes available with the resources (CPU, RAM, or GPU) that your pod requested. Check your node pool configuration.
Key Takeaways
- Treat ML as Immutable Infrastructure: Containerize your model and its dependencies together to ensure consistency. Use environment variables to handle configuration, never hardcode values.
- Master Resource Management: Learn how to request and limit resources, especially for GPUs. Use the NVIDIA Device Plugin to ensure your pods land on the correct hardware.
- Scale Based on Inference Needs: Move beyond CPU-based scaling. Use custom metrics like request latency or GPU utilization to trigger the Horizontal Pod Autoscaler.
- Optimize the Startup Path: Use init-containers, EFS, or S3-mounts to avoid the "cold start" problem of downloading massive model weights every time a pod scales up.
- Prioritize Security: Use IAM Roles for Service Accounts (IRSA) to ensure your model containers follow the principle of least privilege.
- Observability is Non-Negotiable: Implement robust monitoring for latency, drift, and error rates to maintain a healthy production service.
- Know Your Tools: Understand the difference between managing your own infrastructure on EKS versus using managed services like SageMaker. Choose the tool that matches your team's operational capacity.
By following these principles, you will be able to build ML systems on EKS that are not only performant and scalable but also maintainable and secure. The transition from a local notebook to a production-grade EKS cluster is a significant milestone in any data engineer’s career. Keep experimenting with different serving patterns, and always prioritize the reliability of your inference pipeline.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons