Skaffold can manage resource limits for your development containers, but most people use it completely wrong.
Let’s see Skaffold in action. Imagine a simple Node.js app:
// server.js
const http = require('http');
const port = process.env.PORT || 8080;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
});
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
And a package.json:
{
"name": "my-app",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Now, let’s configure Skaffold to build and deploy this. We’ll use a skaffold.yaml:
apiVersion: skaffold.dev/v2beta25
kind: Config
build:
local:
push: false
artifacts:
- image: my-dev-app
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/deployment.yaml
- k8s/service.yaml
profiles:
- name: dev-with-resources
build:
local:
push: false
artifacts:
- image: my-dev-app
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/deployment.yaml
- k8s/service.yaml
# This is where the magic happens for resource limits
portForward:
- resourceType: pod
port: 8080
localPort: 8080
containerPort: 8080
pods:
- "my-dev-app-*" # Skaffold will find the pod name
# Skaffold's intended mechanism for dev-time resource management
# This applies the specified resource limits to the pod definition
# when deploying for the 'dev-with-resources' profile.
customResources:
- name: resource-limits
sources:
- k8s/deployment.yaml # Skaffold will modify this file in memory
patches:
- path: spec.template.spec.containers[0].resources.limits
value:
cpu: "200m"
memory: "256Mi"
- path: spec.template.spec.containers[0].resources.requests
value:
cpu: "100m"
memory: "128Mi"
And a Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "start"]
Finally, a k8s/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-dev-app
spec:
selector:
matchLabels:
app: my-dev-app
template:
metadata:
labels:
app: my-dev-app
spec:
containers:
- name: my-dev-app
image: my-dev-app
ports:
- containerPort: 8080
And k8s/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: my-dev-app-service
spec:
selector:
app: my-dev-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
When you run skaffold dev --profile dev-with-resources, Skaffold will:
- Build the
my-dev-appimage using yourDockerfile. - Crucially, it will take your
k8s/deployment.yaml, and in memory, it will patch thespec.template.spec.containers[0].resources.limitsandspec.template.spec.containers[0].resources.requestsfields with the values defined incustomResources. This modified YAML is what gets applied to your Kubernetes cluster. - Deploy the modified application to your cluster.
- Set up port-forwarding for port 8080 on the pod to your local machine.
Now, if you hit http://localhost:8080 in your browser, you’ll see "Hello World!".
The mental model here is that Skaffold, when using customResources in a profile, acts as a YAML transformer before applying manifests. It doesn’t have a separate "resource limit" setting; it manipulates your existing Kubernetes resource definitions. This is powerful because it means you’re working with standard Kubernetes resources.limits and resources.requests objects, just like you would in production, but with values tailored for development.
The real power comes from the customResources block. Skaffold uses a JSON patch-like syntax to modify your deployment manifests before sending them to kubectl. This allows you to dynamically inject resource requests and limits into your development deployments without altering your source k8s/deployment.yaml. The path field uses a JSONPath-like expression to pinpoint exactly where in the YAML structure the change should occur.
What most people miss is that Skaffold doesn’t magically set resource limits in a vacuum. It patches your Kubernetes manifests. This means your k8s/deployment.yaml can be identical for dev and prod, with the profile in skaffold.yaml being the differentiator for resource settings. This keeps your Kubernetes manifests clean and source-controlled, while your development experience is optimized.
The next thing you’ll likely want to tackle is managing multiple containers within the same deployment, ensuring each gets its appropriate resource limits.