kubectl version --short Client Version: v1.15.0 Server Version: v1.14.10-gke.36
I am trying to update a deployment's Label Selector with apps/v1 API, which as per Kubernetes documentation (documentation) should error out. But in practice kubectl apply -f <filename>
is not throwing any error and changes are not visible in deployment.
Existing deployment kubectl get deployment my-deployment -o yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
canonical-name: my-deployment
deployment.kubernetes.io/revision: "219"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"canonical-name":"my-deployment"},"name":"my-deployment","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"my-deployment","deployment":"my-deployment"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"0%"},"type":"RollingUpdate"},"template":{"metadata":{"labels":{"app":"my-deployment","deployment":"my-deployment","enableRolling":"true","testComponent":"true","testName":"my-deployment","type":"REST"}},"spec":{"affinity":{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"node-pool-type","operator":"In","values":["rest","components"]}]}]}},"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app","operator":"In","values":["my-deployment"]}]},"topologyKey":"kubernetes.io/hostname"},"weight":100}]}},"containers":[{"env":[{"name":"HOST_IP","valueFrom":{"fieldRef":{"fieldPath":"status.hostIP"}}},{"name":"POD_IP","valueFrom":{"fieldRef":{"fieldPath":"status.podIP"}}}],"envFrom":[{"configMapRef":{"name":"cp-env"}},{"configMapRef":{"name":"gcp-project-env"}},{"secretRef":{"name":"cp-secret-env"}},{"configMapRef":{"name":"my-deployment-db-env"}},{"configMapRef":{"name":"my-deployment-env"}}],"image":"quay.io/testrd/my-deployment:latest","imagePullPolicy":"IfNotPresent","livenessProbe":{"failureThreshold":3,"httpGet":{"path":"/heathz","port":8080},"initialDelaySeconds":3700,"periodSeconds":18,"successThreshold":1},"name":"my-deployment","ports":[{"containerPort":8080}],"readinessProbe":{"failureThreshold":3,"httpGet":{"path":"/heathz","port":8080},"initialDelaySeconds":60,"periodSeconds":30,"successThreshold":1},"resources":{"limits":{"memory":"3840Mi"},"requests":{"cpu":"247m","memory":"1536Mi"}},"volumeMounts":[{"mountPath":"/var/run/secrets/kubernetes.io/accesscontrol","name":"gcp-service-admin-account"},{"mountPath":"/component","name":"host-volume"},{"mountPath":"/pinpoint-agent","name":"pinpoint-volume"}]}],"imagePullSecrets":[{"name":"mysecret"},{"name":"gcr-mysecret"}],"priorityClassName":"low-priority","volumes":[{"name":"gcp-service-admin-account","secret":{"secretName":"gcp-service-admin-key"}},{"hostPath":{"path":"/mnt/stateful_partition/component","type":"DirectoryOrCreate"},"name":"host-volume"},{"hostPath":{"path":"/mnt/stateful_partition/agent","type":"DirectoryOrCreate"},"name":"agent-volume"}]}}}}
creationTimestamp: "2019-04-26T16:43:43Z"
generation: 508
labels:
app: my-deployment
deployment: my-deployment
enableRolling: "true"
testComponent: "true"
testComponentName: my-deployment
type: REST
name: my-deployment
namespace: default
resourceVersion: "237385987"
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/my-deployment
uid: 73e059d0-6842-11e9-b98b-42010a960025
spec:
progressDeadlineSeconds: 2147483647
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: my-deployment
deployment: my-deployment
enableRolling: "true"
type: REST
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: my-deployment
deployment: my-deployment
enableRolling: "true"
testComponent: "true"
testComponentName: my-deployment
type: REST
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-pool-type
operator: In
values:
- rest
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-deployment
topologyKey: kubernetes.io/hostname
weight: 100
containers:
- env:
- name: LAST_RESTART
value: "1592331191"
- name: HOST_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: VIRTUAL_HOST
value: my-deployment.default.svc.cluster.local
envFrom:
- configMapRef:
name: my-deployment-env
image: quay.io/testrd/my-deployment:latest
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /get/healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 2700
periodSeconds: 15
successThreshold: 1
timeoutSeconds: 1
name: my-deployment
ports:
- containerPort: 8080
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /get/healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
memory: 384Mi
requests:
cpu: 247m
memory: 1536Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/accesscontrol
name: gcp-service-acc
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: mysecret
- name: gcr-mysecret
priorityClassName: low-priority
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: gcp-service-acc
secret:
defaultMode: 420
secretName: gcp-service-admin-key
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2020-06-15T18:59:25Z"
lastUpdateTime: "2020-06-15T18:59:25Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
observedGeneration: 508
readyReplicas: 1
replicas: 1
updatedReplicas: 1
New my-deployment.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
namespace: default
annotations:
canonical-name: my-deployment
labels:
type: "REST"
testComponent: "true"
testComponentName: "my-deployment"
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 15%
maxUnavailable: 0%
selector:
matchLabels:
deployment: my-deployment
app: my-deployment
template:
metadata:
labels:
app: my-deployment
type: REST
enableRolling: "true"
deployment: my-deployment
testComponent: "true"
testComponentName: my-deployment
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-pool-type
operator: In
values:
- rest
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-deployment
topologyKey: "kubernetes.io/hostname"
# scheduling and preemption priority of this pod
priorityClassName: low-priority
containers:
- name: my-deployment
image: quay.io/testrd/my-deployment:latest
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: "247m"
memory: "1536Mi"
limits:
memory: "384Mi"
readinessProbe:
httpGet:
path: /get/healthz
port: 8080
# start after 60s of container launch
initialDelaySeconds: 60
# probe every 30s
periodSeconds: 30
# declare success (ready) if 1 (default) attempt results in a success
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /get/healthz
port: 8080
# start after 45 minutes of container launch
initialDelaySeconds: 2700
# probe every 15s
periodSeconds: 15
# declare success (live) if 1 (default) attempt results in a success
successThreshold: 1
# declare failure (not live) if 3 consecutive probes result in a failure
failureThreshold: 3
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: my-deployment-env
# component specific environment variables
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
# VIRTUAL_HOST is set as the service name
- name: VIRTUAL_HOST
value: "my-deployment.default.svc.cluster.local"
volumes:
# volume carrying the Google Cloud Platform authorization key data
- name: "gcp-service-acc
secret:
secretName: "gcp-service-key"
imagePullSecrets:
- name: mysecret
- name: gcr-mysecret
kubectl apply -f my-deployment.yml
deployment.apps/my-deployment configured
Ideally it should fail with the error
The Deployment "my-deployment" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"deployment":"my-deployment"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
which is not happening in this case and new labels are not reflecting in deployment. Though they are visible in kubectl.kubernetes.io/last-applied-configuration.
Update Wed Jun 17 16:46:15 UTC 2020 Created new test deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
namespace: default
spec:
# scale com-manh-cp-remote to 1 instances
replicas: 1
selector:
matchLabels:
app: test-deployment
deployment: test-deployment
stereotype: REST
template:
metadata:
labels:
app: test-deployment
deployment: test-deployment
stereotype: REST
spec:
containers:
- name: test-deployment
image: quay.io/manhrd/kube-cp-stax:latest
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: regsecret
- name: gcr-regsecret
Applied update by changing label selector
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
namespace: default
spec:
# scale com-manh-cp-remote to 1 instances
replicas: 1
selector:
matchLabels:
deployment: test-deployment
template:
metadata:
labels:
app: test-deployment
deployment: test-deployment
stereotype: REST
spec:
containers:
- name: test-deployment
image: quay.io/manhrd/kube-cp-stax:latest
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: mysecret
- name: gcr-mysecret
Got below error.
kubectl apply -f dep.yaml
The Deployment "test-deployment" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"deployment":"test-deployment"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
It is working expected for new deployments.
This is because
extensions/v1beta1
API group where label selector is immutable.