TLDR: When deploying FME Server to Azure Kubernetes Service set storage.fmeserver.size to at least 100Gi in values.yaml to meet Azure File Storage minimum requirements.
When deploying FME Server to Azure Kubernetes using Azure Files as per the documentation, the default 10Gi setting fails to meet Azure minimum size requirement for a file share in a Premium_LRS type sku storage account.
The default values.yaml file has the following settings:
storage:
useHostDir: false
reclaimPolicy: Delete
postgresql:
size: 1Gi
class:
path:
fmeserver:
accessMode: ReadWriteOnce
size: 10Gi
class: azurefiles-fmeserver
path:
When applied, the following pods will fail to be scheduled:
- engine-standard-group x2
- core
- queue
- websocked
However fmeserver-postgresql, will be scheduled successfully and should run. Looking into a failed pods description, for example the core pod:
kubectl describe pods core-0
We can see the issue is due to an unmet persistent volume claim.
Conditions:
Type Status
PodScheduled False
Volumes:
fmeserverdata:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: fmeserver-data
ReadOnly: false
default-token-8fpkj:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-8fpkj
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 6s (x7 over 4m32s) default-scheduler 0/1 nodes are available: 1 pod has unbound immediate PersistentVolumeClaims.
Upon further inspection of the persistent volume claim request, we see that it is stuck on pending due to an invalid header.
kubectl describe pvc fmeserver-data
Results in the following output:
Name: fmeserver-data
Namespace: default
StorageClass: azurefiles-fmeserver
Status: Pending
Volume:
Labels: app=fmeserver-2021.0.3
app.kubernetes.io/managed-by=Helm
chart=fmeserver-2021.0.3-0.2.29
heritage=Helm
release=fmeserver
safe.k8s.fmeserver.build=21326
safe.k8s.fmeserver.component=data
Annotations: meta.helm.sh/release-name: fmeserver
meta.helm.sh/release-namespace: default
volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/azure-file
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: core-0
engine-standard-group-c9965f769-4jhxq
engine-standard-group-c9965f769-s2dg5
queue-0
websocket-0
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ProvisioningFailed 7m49s persistentvolume-controller Failed to provision volume with StorageClass "azurefiles-fmeserver": failed to create share kubernetes-dynamic-pvc-37b1fbf1-5174-45e9-85f4-69bc5b67916d in account fmedatastorebroken: storage.FileSharesClient#Create: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="InvalidHeaderValue" Message="The valuefor one of the HTTP headers is not in the correct format.\nRequestId:9a9d1d3e-601a-0029-7326-971af7000000\nTime:2021-08-22T07:22:23.6903962Z"
Azure/AKS GitHub issue 5156 highlights that this message is erroneous and actually due to Azure Premium File Storage having a minimum size requirement of 100gb for the sku type Premium_LRS - which is required in order to have File Storage.
The simple solution is to modify the values.yaml file for your deployment so that storage.fmeserver.size is at least 100Gi.
storage:
useHostDir: false
reclaimPolicy: Delete
postgresql:
size: 1Gi
class:
path:
fmeserver:
accessMode: ReadWriteOnce
size: 100Gi
class: azurefiles-fmeserver
path:
This parameter is used in Safe's Helm charts to define a persistent volume claim, which provisions the file share within the storage account created in step 3:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
safe.k8s.fmeserver.component: data
{{- include "fmeserver.common.labels" . | indent 4 }}
name: fmeserver-data
spec:
{{- with .Values.storage }}
accessModes:
- {{ .fmeserver.accessMode }}
{{- if and (not .useHostDir) .fmeserver.class }}
storageClassName: {{ .fmeserver.class }}
{{- end }}
resources:
requests:
storage: {{ .fmeserver.size }}
{{- end }}