|
| 1 | +--- |
| 2 | +title: Update a Deployment Without Downtime |
| 3 | +content_type: task |
| 4 | +weight: 16 |
| 5 | +--- |
| 6 | + |
| 7 | +<!-- overview --> |
| 8 | + |
| 9 | +This page shows how to update a running Deployment to a new version using a |
| 10 | +rolling update. A rolling update gradually replaces old Pods with new ones, so |
| 11 | +your application remains available throughout the process. |
| 12 | + |
| 13 | +## {{% heading "objectives" %}} |
| 14 | + |
| 15 | +- Trigger a rolling update on a Deployment. |
| 16 | +- Monitor rollout progress. |
| 17 | +- Pause and resume the rollout. |
| 18 | +- Configure rolling update strategy parameters. |
| 19 | +- (If required) Roll back to a previous revision. |
| 20 | + |
| 21 | +## {{% heading "prerequisites" %}} |
| 22 | + |
| 23 | +{{< include "task-tutorial-prereqs.md" >}} |
| 24 | + |
| 25 | +You need an existing Deployment. If you do not have one, create the nginx |
| 26 | +Deployment from |
| 27 | +[Run a Stateless Application Using a Deployment](/docs/tasks/run-application/run-stateless-application-deployment/): |
| 28 | + |
| 29 | +```shell |
| 30 | +kubectl apply -f https://k8s.io/examples/application/deployment.yaml |
| 31 | +``` |
| 32 | + |
| 33 | +Verify the Deployment runs two Pods: |
| 34 | + |
| 35 | +```shell |
| 36 | +kubectl get deployment nginx-deployment |
| 37 | +``` |
| 38 | + |
| 39 | +The output is similar to: |
| 40 | + |
| 41 | +``` |
| 42 | +NAME READY UP-TO-DATE AVAILABLE AGE |
| 43 | +nginx-deployment 2/2 2 2 10s |
| 44 | +``` |
| 45 | + |
| 46 | +<!-- steps --> |
| 47 | + |
| 48 | +## Performing a rolling update |
| 49 | + |
| 50 | +Any change to the `.spec.template` field of a Deployment triggers a rolling |
| 51 | +update. Kubernetes creates new Pods with the updated configuration and gradually |
| 52 | +terminates old Pods. |
| 53 | + |
| 54 | +### Updating with `kubectl apply` |
| 55 | + |
| 56 | +You can trigger a rolling update by editing the Deployment manifest and applying the change. This approach works well when you keep manifests in version control. |
| 57 | + |
| 58 | +Export the current Deployment to a local file: |
| 59 | + |
| 60 | +```shell |
| 61 | +kubectl get deployment nginx-deployment -o yaml > /tmp/nginx-deployment.yaml |
| 62 | +``` |
| 63 | + |
| 64 | +Edit `/tmp/nginx-deployment.yaml` and change `.spec.template.spec.containers[0].image` |
| 65 | +from `nginx:1.14.2` to `nginx:1.16.1`. |
| 66 | + |
| 67 | +Before applying, compare your local changes against the cluster state: |
| 68 | + |
| 69 | +```shell |
| 70 | +kubectl diff -f /tmp/nginx-deployment.yaml |
| 71 | +``` |
| 72 | + |
| 73 | +The output is similar to: |
| 74 | + |
| 75 | +``` |
| 76 | +diff -u -N /tmp/LIVE/apps.v1.Deployment.default.nginx-deployment /tmp/MERGED/apps.v1.Deployment.default.nginx-deployment |
| 77 | +--- /tmp/LIVE/apps.v1.Deployment... |
| 78 | ++++ /tmp/MERGED/apps.v1.Deployment... |
| 79 | +@@ -29,7 +29,7 @@ |
| 80 | + containers: |
| 81 | +- - image: nginx:1.14.2 |
| 82 | ++ - image: nginx:1.16.1 |
| 83 | + name: nginx |
| 84 | +``` |
| 85 | + |
| 86 | +Apply the updated manifest: |
| 87 | + |
| 88 | +```shell |
| 89 | +kubectl apply -f /tmp/nginx-deployment.yaml |
| 90 | +``` |
| 91 | + |
| 92 | +### Updating only the container image |
| 93 | + |
| 94 | +To update the container image without editing a manifest file, use |
| 95 | +`kubectl set image`: |
| 96 | + |
| 97 | +```shell |
| 98 | +kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 |
| 99 | +``` |
| 100 | + |
| 101 | +The output is similar to: |
| 102 | + |
| 103 | +``` |
| 104 | +deployment.apps/nginx-deployment image updated |
| 105 | +``` |
| 106 | + |
| 107 | +Verify the image was updated: |
| 108 | + |
| 109 | +```shell |
| 110 | +kubectl get deployment nginx-deployment -o jsonpath='{.spec.template.spec.containers[0].image}' |
| 111 | +``` |
| 112 | + |
| 113 | +The output is similar to: |
| 114 | + |
| 115 | +``` |
| 116 | +nginx:1.16.1 |
| 117 | +``` |
| 118 | + |
| 119 | +## Monitoring rollout progress |
| 120 | + |
| 121 | +Use `kubectl rollout status` to watch the progress of a rolling update: |
| 122 | + |
| 123 | +```shell |
| 124 | +kubectl rollout status deployment/nginx-deployment |
| 125 | +``` |
| 126 | + |
| 127 | +The output is similar to: |
| 128 | + |
| 129 | +``` |
| 130 | +Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 2 new replicas have been updated... |
| 131 | +Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 2 new replicas have been updated... |
| 132 | +Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination... |
| 133 | +deployment "nginx-deployment" successfully rolled out |
| 134 | +``` |
| 135 | + |
| 136 | +After the rollout completes, verify the Deployment: |
| 137 | + |
| 138 | +```shell |
| 139 | +kubectl get deployment nginx-deployment |
| 140 | +``` |
| 141 | + |
| 142 | +The output is similar to: |
| 143 | + |
| 144 | +``` |
| 145 | +NAME READY UP-TO-DATE AVAILABLE AGE |
| 146 | +nginx-deployment 2/2 2 2 2m |
| 147 | +``` |
| 148 | + |
| 149 | +## Pausing and resuming a rollout |
| 150 | + |
| 151 | +You can pause a rollout to inspect a partial update or to batch multiple changes |
| 152 | +into a single rollout. |
| 153 | + |
| 154 | +### Pausing a rollout |
| 155 | + |
| 156 | +```shell |
| 157 | +kubectl rollout pause deployment/nginx-deployment |
| 158 | +``` |
| 159 | + |
| 160 | +The output is similar to: |
| 161 | + |
| 162 | +``` |
| 163 | +deployment.apps/nginx-deployment paused |
| 164 | +``` |
| 165 | + |
| 166 | +### Making additional changes while paused |
| 167 | + |
| 168 | +While the rollout is paused, you can make additional changes. These changes do |
| 169 | +not trigger a new rollout until you resume: |
| 170 | + |
| 171 | +```shell |
| 172 | +kubectl set image deployment/nginx-deployment nginx=nginx:1.17.0 |
| 173 | +``` |
| 174 | + |
| 175 | +{{< note >}} |
| 176 | +You can make multiple changes to a paused Deployment. Kubernetes applies all |
| 177 | +changes together when you resume the rollout. |
| 178 | +{{< /note >}} |
| 179 | + |
| 180 | +### Resuming a rollout |
| 181 | + |
| 182 | +```shell |
| 183 | +kubectl rollout resume deployment/nginx-deployment |
| 184 | +``` |
| 185 | + |
| 186 | +The output is similar to: |
| 187 | + |
| 188 | +``` |
| 189 | +deployment.apps/nginx-deployment resumed |
| 190 | +``` |
| 191 | + |
| 192 | +Verify the rollout completes: |
| 193 | + |
| 194 | +```shell |
| 195 | +kubectl rollout status deployment/nginx-deployment |
| 196 | +``` |
| 197 | + |
| 198 | +## Configuring rolling update strategy |
| 199 | + |
| 200 | +Deployments support two |
| 201 | +[update strategy types](/docs/concepts/workloads/controllers/deployment/#strategy): |
| 202 | + |
| 203 | +- **RollingUpdate** (default): gradually replaces old Pods with new ones. |
| 204 | +- **Recreate**: terminates all existing Pods before creating new ones. This |
| 205 | + causes downtime. |
| 206 | + |
| 207 | +For the RollingUpdate strategy, these parameters control how Kubernetes performs the update: |
| 208 | + |
| 209 | +| Parameter | Controls | Default | Example | |
| 210 | +|-----------|----------|---------|---------| |
| 211 | +| `maxUnavailable` | Maximum number of Pods that can be unavailable during the update | 25% | `1` or `25%` | |
| 212 | +| `maxSurge` | Maximum number of extra Pods that can be created during the update | 25% | `1` or `25%` | |
| 213 | + |
| 214 | +{{< note >}} |
| 215 | +`maxUnavailable` and `maxSurge` accept an absolute number or a percentage. |
| 216 | +Kubernetes calculates percentages from the desired replica count, rounding down |
| 217 | +for `maxUnavailable` and rounding up for `maxSurge`. |
| 218 | +{{< /note >}} |
| 219 | + |
| 220 | +To configure these parameters, use `kubectl patch`: |
| 221 | + |
| 222 | +```shell |
| 223 | +kubectl patch deployment nginx-deployment -p \ |
| 224 | + '{"spec":{"strategy":{"rollingUpdate":{"maxUnavailable":"25%","maxSurge":"25%"}}}}' |
| 225 | +``` |
| 226 | + |
| 227 | +You can also set these fields in a Deployment manifest under |
| 228 | +`.spec.strategy.rollingUpdate`. For detailed examples, see |
| 229 | +[max unavailable](/docs/concepts/workloads/controllers/deployment/#max-unavailable) |
| 230 | +and [max surge](/docs/concepts/workloads/controllers/deployment/#max-surge) |
| 231 | +in the Deployment concepts documentation. |
| 232 | + |
| 233 | +### Detecting a stalled rollout |
| 234 | + |
| 235 | +If a rollout does not make progress within the time specified by |
| 236 | +`.spec.progressDeadlineSeconds` (default: 600 seconds), Kubernetes marks the Deployment condition `Progressing` as `False`. You can check for this condition by describing the Deployment: |
| 237 | + |
| 238 | +```shell |
| 239 | +kubectl describe deployment nginx-deployment |
| 240 | +``` |
| 241 | + |
| 242 | +Look for the `Progressing` condition in the `Conditions` section of the output. A stalled rollout usually indicates that new Pods are failing to start. The `Events` section of the output can help diagnose the issue. |
| 243 | + |
| 244 | +## Rolling back to a previous revision {#rollback} |
| 245 | + |
| 246 | +If a new version introduces issues, you can roll back to a previous revision. |
| 247 | + |
| 248 | +### Viewing rollout history |
| 249 | + |
| 250 | +```shell |
| 251 | +kubectl rollout history deployment/nginx-deployment |
| 252 | +``` |
| 253 | + |
| 254 | +The output is similar to: |
| 255 | + |
| 256 | +``` |
| 257 | +deployment.apps/nginx-deployment |
| 258 | +REVISION CHANGE-CAUSE |
| 259 | +1 <none> |
| 260 | +2 <none> |
| 261 | +``` |
| 262 | + |
| 263 | +{{< note >}} |
| 264 | +The `CHANGE-CAUSE` column shows the value of the `kubernetes.io/change-cause` |
| 265 | +annotation at the time of each revision. This annotation is **not** set automatically, |
| 266 | +but if you are using an automated solution to manage Deployments, the tool you use |
| 267 | +may write some text into that annotation. |
| 268 | +{{< /note >}} |
| 269 | + |
| 270 | +### Rolling back to the previous revision |
| 271 | + |
| 272 | +```shell |
| 273 | +kubectl rollout undo deployment/nginx-deployment |
| 274 | +``` |
| 275 | + |
| 276 | +The output is similar to: |
| 277 | + |
| 278 | +``` |
| 279 | +deployment.apps/nginx-deployment rolled back |
| 280 | +``` |
| 281 | + |
| 282 | +### Rolling back to a specific revision |
| 283 | + |
| 284 | +```shell |
| 285 | +kubectl rollout undo deployment/nginx-deployment --to-revision=1 |
| 286 | +``` |
| 287 | + |
| 288 | +Verify the rollback completes: |
| 289 | + |
| 290 | +```shell |
| 291 | +kubectl rollout status deployment/nginx-deployment |
| 292 | +``` |
| 293 | + |
| 294 | +{{< note >}} |
| 295 | +A Deployment's revision history is stored in the ReplicaSets it controls. |
| 296 | +By default, Kubernetes retains 10 old ReplicaSets. You can change this limit |
| 297 | +by setting `.spec.revisionHistoryLimit` in the Deployment manifest. Setting it to `0` disables rollback entirely. |
| 298 | +{{< /note >}} |
| 299 | + |
| 300 | +## {{% heading "cleanup" %}} |
| 301 | + |
| 302 | +Delete the Deployment: |
| 303 | + |
| 304 | +```shell |
| 305 | +kubectl delete deployment nginx-deployment |
| 306 | +``` |
| 307 | + |
| 308 | +## {{% heading "whatsnext" %}} |
| 309 | + |
| 310 | +- Learn more about [Deployments](/docs/concepts/workloads/controllers/deployment/). |
| 311 | +- Learn how to [scale a Deployment manually](/docs/tasks/run-application/scale-deployment/). |
| 312 | +- Walk through [Horizontal Pod Autoscaling](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). |
| 313 | +- See how to [perform a rolling update on a DaemonSet](/docs/tasks/manage-daemon/update-daemon-set/). |
0 commit comments