Terraform-provider-kubernetes: kubernetes_deployment: changing strategy to Recreate from Rolling breaks the update

Created on 10 Aug 2019  路  10Comments  路  Source: hashicorp/terraform-provider-kubernetes

Affected Resource(s)

Please list the resources as a list, for example:

  • kubernetes_deployment

Terraform Configuration Files

Updated to

resource "kubernetes_deployment" "blah" {
  spec {
    strategy {
      type = "Recreate"
    }
  }
}

Expected Behavior

Expect it to recreate the deployment or unset the rolling_update defaults on the strategy

Actual Behavior

If it was not set or set to RollingUpdates then the rolling_update defaults stay behind and gives an spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy type is 'Recreate'

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. Create a deployment with default strategy
  2. change the strategy to "Recreate"
  3. Watch it error out :)

Important Factoids

I imagine the easy fix is to force new for the resource, but the better fix is to unsetting rolling_update when type is set to Recreate.

help wanted needs investigation

All 10 comments

I have the same issue with provider version 1.9.0

Likewise in 1.10.0 and terraform 0.12.12

This same issue happens with kubectl as seen below:

~/test-dep 禄 kubectl apply -f testdep.yaml                                                                                                                                                    alex@alex-macbook
deployment.apps/test-dep created
------------------------------------------------------------
~/test-dep 禄 cat testdep.yaml                                                                                                                                                                 alex@alex-macbook
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test-dep
  name: test-dep
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-dep
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: Recreate
  template:
    metadata:
      labels:
        app: test-dep
    spec:
      containers:
      - image: nginx
        name: nginx
------------------------------------------------------------
~/test-dep 禄 kubectl apply -f testdep.yaml                                                                                                                                                    alex@alex-macbook
The Deployment "test-dep" is invalid: spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy `type` is 'Recreate'

Furthermore, Terraform doesn't have the ability to do cross-attribute validation which would be the only mechanism that could detect this condition. Unlikely that we can fix this on the provider side.

Bug is still there in terraform 0.12.29 and 0.12.0 provider. Workaround is terraform taint-ing the resource to force recreation

I see this in 0.13.4. Here's a snippet from the plan output where I've changed the strategy from RolllingUpdate to Recreate. I do not specify a rolling_update block and the previous terraform-generated default rolling_update block remains unchanged.

          ~ strategy {
              ~ type = "RollingUpdate" -> "Recreate"

                rolling_update {
                    max_surge       = "25%"
                    max_unavailable = "25%"
                }
            }

I apply the plan and it fails because you can't have a rolling update params with a Recreate strategy type:

module.backend.kubernetes_deployment.backend[0]: Modifying... [id=backend/backend]

Error: Failed to update deployment: Deployment.apps "backend" is invalid: spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy `type` is 'Recreate'

  on ../../modules/backend/main.tf line 56, in resource "kubernetes_deployment" "backend":
  56: resource "kubernetes_deployment" "backend" {

This PR has some promising logic that might help in cases like these.

https://github.com/hashicorp/terraform-provider-kubernetes/pull/1243/files

Specifically, this part of the PR:

    if d.HasChange(keyPrefix + "type") {
        o, n := d.GetChange(keyPrefix + "type")

        if o.(string) == "ClusterIP" && n.(string) == "ExternalName" {
            ops = append(ops, &RemoveOperation{
                Path: pathPrefix + "clusterIP",
            })
        }

If similar logic were applied to the deployment resource, this might solve the problem.

@dak1n1 was about to post above solution. if the above mentioned PR is accepted ill try to open one for this issue soon with similar logic applied (wasn't sure this was the way to go)

@DrFaust92 That's great! We definitely appreciate all the work you've been doing on these. I'm trying to get some of them reviewed this week. I like the solution, but I also haven't tested that it works going in the other direction yet (changing from ExternalName to ClusterIP). That's the only part I wanted to double-check.

@dak1n1 I added a test for the other direction and seems fine. 馃榿

Opened #1255, managed to to make it work in both directions.

Was this page helpful?
0 / 5 - 0 ratings