Short answer
Rollout a new version
Using a kubectl patch one-liner, using the current rollout strategy:
kubectl patch deployment $DEPLOYMENT \
-p'{"spec":{"template":{"spec":{"containers":[{"name":"site","image":"$HOST/$USER/$IMAGE:$VERSION"}]}}}}'
Note
You should have tested it before, but if you have the right configuration (see details below) in your rollout strategy and your health checks are correctly setup, you won't have any downtime and the old containers won't be terminated before the new ones kicked in (as in, «answers successfully to health checks»).
Check the rollout status
kubectl rollout status deployment/$DEPLOYMENT
Read the deployment history
kubectl rollout history deployment/$DEPLOYMENT
kubectl rollout history deployment/$DEPLOYMENT --revision 42
Rollback to the previous deployed version
kubectl rollout undo deployment/$DEPLOYMENT
Rollback to a specific previously deployed version
kubectl rollout undo deployment/$DEPLOYMENT --to-revision 21
Details
Kubernetes will upgrade your deployment by creating a new ReplicaSet. New pods will be created according to your update strategy, here is an example configuration that will create new version pods one by one, and wait for a new pod to be available before destroying one of the old pods.
spec:
# ...
replicas: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
# ...
Now what does "available" means? It means that your readinessProbe found your new pod healthy, here is an example configuration to use an http probe on an hypothetic backend service that is meant to listen to the pod's 8080 port:
spec:
# ...
containers:
- # ...
readinessProbe:
failureThreshold: 3
httpGet:
path: /ping
port: 8080
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 2
successThreshold: 1
timeoutSeconds: 1
As soon as the new version pod's will answer a 200 to a GET /ping on the 8080 port, kubernetes will consider it healthy and destroy its ancestor, then proceed with the next pods if the rolling update is not finished.
Bonus
You can combine those techniques with a few git and GNU Make features to make rollouts easy as hell (adapt this to your environment):
NAME ?= awebsome
STAGE ?= staging
K8S_DEPLOYMENT ?= $(NAME)-$(STAGE)
VERSION ?= $(shell git describe)
.PHONY: rollout rollback
rollout:
kubectl patch deployment $(K8S_DEPLOYMENT) \
-p'{"spec":{"template":{"spec":{"containers":[{"name":"$(NAME)","image":"$(DOCKER_REGISTRY)/$(DOCKER_REGISTRY_USER)/$(NAME):$(VERSION)"}]}}}}'
rollback:
kubectl rollout undo deployment/$(K8S_DEPLOYMENT)
Now, you can rollout to current git version...
make rollout
Then maybe rollback...
make rollback