David Essien
David Essien

Reputation: 1633

field is immutable k8s

I am trying to deploy an application to GCP on kubernetes, however, the deployment fails with the error the job spec is invalid ... the field is immutable.

In the migration job, I have a section of bash in the following format:

args:
        - |
          /cloud_sql_proxy -instances=xxxxxxxxxxx:europe-west1:xxxxxxxxxxx=tcp:5432 -credential_file=/secrets/cloudsql/credentials.json -log_debug_stdout=true &
          CHILD_PID=$!
          (while true; do echo "waiting for termination file"; if [[ -f "/tmp/pod/main-terminated" ]]; then kill ; echo "Killed  as the main container terminated."; fi; sleep 1; done) &
          wait 
          if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; echo "Job completed. Exiting..."; fi

but when the file is executed, in the yaml on GCP I see that the command has been enclosed in quotes and then it returns the above mention error.

Upvotes: 24

Views: 48581

Answers (4)

Dominik Filipiak
Dominik Filipiak

Reputation: 1272

I got field is immutable error when I tried to run jobs in my cluster with the following command:

$ kubectl apply -f config.yml

where config.yml was defined as follows:

apiVersion: batch/v1
kind: Job
metadata:
  name: my-job-name
spec:
  # (...)

It worked for the first time, but the other ones with modified parameters did not. Turned out the completed job was not deleted automatically and it still figured in the job list:

$ kubectl get jobs | grep my-job-name
my-job-name                                              1/1           4m29s      22h

So, you have to delete the old one as follows:

$ kubectl delete job my-job-name

Now you can send a new job with the same name using kubectl apply -f config.yml.

EDIT As @CloudWatcher said in his comment, this can apparently hit different resource types. In his case, it was a secret that needed deletion.

Upvotes: 12

Lukasvan3L
Lukasvan3L

Reputation: 731

I got the message the job spec is invalid ... the field is immutable for a different reason and wanted to briefly share it here.

I was trying to apply this yaml file:

apiVersion: extensions/v1beta1
kind: Deployment
spec:
  selector:
    matchLabels:
      app: application-name
...

Turns out that this yaml was going to replace a previous version of the same Deployment. When I ran kubectl get deployment application-name -o yaml I saw this:

apiVersion: extensions/v1beta1
kind: Deployment
spec:
  selector:
    matchLabels:
      app: application-name
      track: stable
...

Apparently the spec.selector.matchLabels is currently an array, and I was trying to replace that with a single string. My fix was deleting the deployment and re-deploying it.

Upvotes: 35

David Essien
David Essien

Reputation: 1633

So this issue was resolved. I had to wrap the values of the environment variables in the yaml file in quotes. That resolved the issue.

- name: DATABASE_URL:
  value: "${DATABASE_URL}"

Upvotes: 1

Rico
Rico

Reputation: 61651

If you are using args in a Pod definition it's meant to be an array with single-string items. (It doesn't run the command in a shell) For example:

args:
        - /cloud_sql_proxy
        - -instances
        - ...

or

args:  [ "/cloud_sql_proxy", "-instances", "..." ]

The way to get around this is to run the command in a shell:

command: [ "/bin/sh" ]
args: 
        - -c
        - |
          /cloud_sql_proxy -instances=xxxxxxxxxxx:europe-west1:xxxxxxxxxxx=tcp:5432 -credential_file=/secrets/cloudsql/credentials.json -log_debug_stdout=true &
          CHILD_PID=$!
          (while true; do echo "waiting for termination file"; if [[ -f "/tmp/pod/main-terminated" ]]; then kill ; echo "Killed  as the main container terminated."; fi; sleep 1; done) &
          wait 
          if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; echo "Job completed. Exiting..."; fi

The quotes(") on the array are for readability, they can be no quotes or single quotes(') too (As seen in the YAML specs)

Hope it helps.

Upvotes: 3

Related Questions