kubernetes - K8s - 在 K8s 升级之前无法升级 statefulset API
问题描述
我正在将 K8s 从 1.15 升级到 1.16。在此之前,我必须将我的 statefulset yaml API 迁移到 apps/v1 版本。但是 K8s 不允许我这样做。
以前版本的 yamls 在这里(变量存储在另一个文件中):
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: {{ .NAME_KAFKA }}
namespace: {{ .NS }}
spec:
serviceName: {{ .NAME_KAFKA }}-service
replicas: {{ .CLUSTER_SIZE_KAFKA }}
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: {{ .NAME_KAFKA }}
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9009"
spec:
priorityClassName: {{ .PRIORITY_HIGHEST }}
nodeSelector:
lifecycle: OnDemand
terminationGracePeriodSeconds: 301
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- {{ .NAME_KAFKA }}
topologyKey: "kubernetes.io/hostname"
containers:
- name: local-{{ .NAME_KAFKA }}
imagePullPolicy: Always
image: {{ .REPO }}/{{ .IMAGE_KAFKA }}:{{ .VERSION_KAFKA }}
resources:
requests:
memory: 768Mi
cpu: 500m
limits:
memory: 768Mi
cpu: 500m
ports:
- containerPort: 9092
name: server
- containerPort: 9009
name: prometheus
volumeMounts:
- name: datadir
mountPath: /var/lib/kafka
env:
- name: KAFKA_HEAP_OPTS
value : "-Xmx512M -Xms512M"
- name: KAFKA_OPTS
value: "-Dlogging.level=INFO"
readinessProbe:
tcpSocket:
port: 9092
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 5
securityContext:
runAsUser: 1000
fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 20Gi
我将 yaml 文件中的 api-version 从apps/v1beta1 更改为apps/v1并尝试应用。可以预见的是,我收到了这个错误。
error: error validating "STDIN": error validating data: ValidationError(StatefulSet.spec): missing required field "selector" in io.k8s.api.apps.v1.StatefulSetSpec; if you choose to ignore these errors, turn validation off with --validate=false
所以我添加了 StatefulSet.spec.selector 字段
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .NAME_KAFKA }}
namespace: {{ .NS }}
spec:
selector:
matchExpressions:
- key: "app"
operator: In
values:
- {{ .NAME_KAFKA }}
serviceName: {{ .NAME_KAFKA }}-service
replicas: {{ .CLUSTER_SIZE_KAFKA }}
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: {{ .NAME_KAFKA }}
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9009"
spec:
priorityClassName: {{ .PRIORITY_HIGHEST }}
nodeSelector:
lifecycle: OnDemand
terminationGracePeriodSeconds: 301
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- {{ .NAME_KAFKA }}
topologyKey: "kubernetes.io/hostname"
containers:
- name: local-{{ .NAME_KAFKA }}
imagePullPolicy: Always
image: {{ .REPO }}/{{ .IMAGE_KAFKA }}:{{ .VERSION_KAFKA }}
resources:
requests:
memory: 768Mi
cpu: 500m
limits:
memory: 768Mi
cpu: 500m
ports:
- containerPort: 9092
name: server
- containerPort: 9009
name: prometheus
volumeMounts:
- name: datadir
mountPath: /var/lib/kafka
env:
- name: KAFKA_HEAP_OPTS
value : "-Xmx512M -Xms512M"
- name: KAFKA_OPTS
value: "-Dlogging.level=INFO"
readinessProbe:
tcpSocket:
port: 9092
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 5
securityContext:
runAsUser: 1000
fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 20Gi
但是当我尝试应用它时,我收到了这个错误:
The StatefulSet "kafka-name" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden
根据 K8s 文档,应该有一种方法可以在此 yaml 中更新 API,而无需重建 K8s 中的所有状态集。但是我该怎么做呢?
提前致谢。
解决方案
升级到 1.16 后,您可以转换您的资源。
正如博客中所写,您可以使用 kubectl convert。迁移建议转换。请参阅kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16
kubectl convert -f ./my-statefulset.yaml --output-version apps/v1
另一种选择是使用 cascade=false 删除 statefulset。
它会删除 statefulset 并使 pod 保持正常运行。现在您应该能够再次应用新的 statefulset 文件。
kubectl delete statefulset/<your-statefulset> --cascade=false