How to increase/decrease the number count via API on K8s instead of kubectl apply -f?

Now, I only increase/decrease in the number count by kubectl apply -f

Example:
I create with count is 1

cat <<EOF | kubectl apply -f -
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: quickstart
spec:
  version: 7.8.0
  nodeSets:
  - name: default
    count: 1
    config:
      node.master: true
      node.data: true
      node.ingest: true
      node.store.allow_mmap: false
    volumeClaimTemplates:
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: longhorn
EOF

After, I increase/ scale out to 3, then edit count is 3 and kubectl apply -f

cat <<EOF | kubectl apply -f -
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: quickstart
spec:
  version: 7.8.0
  nodeSets:
  - name: default
    count: 3
    config:
      node.master: true
      node.data: true
      node.ingest: true
      node.store.allow_mmap: false
    volumeClaimTemplates:
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: longhorn
EOF

After, I decrease 2, then edit count is 2 and kubectl apply -f

cat <<EOF | kubectl apply -f -
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: quickstart
spec:
  version: 7.8.0
  nodeSets:
  - name: default
    count: 2
    config:
      node.master: true
      node.data: true
      node.ingest: true
      node.store.allow_mmap: false
    volumeClaimTemplates:
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: longhorn
EOF

Can I increase/decrease the number count via API on K8s?
I try kubectl scale statefulsets quickstart-es-default --replicas=3, but ECK automation remove.
I try API Rancher then appear error:

{
"baseType": "error",
"code": "Invalid",
"message": "StatefulSet.apps \"hulk-es-master\" is invalid: [spec.template.spec.activeDeadlineSeconds: Forbidden: activeDeadlineSeconds in StatefulSet is not Supported, spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden]",
"status": 422,
"type": "error"
}

Please help me.

kubectl scale only applies to core controllers (Deployment, ReplicaSet, Replication Controller, or StatefulSet).

If you are looking for a "oneliner" to control the count field of a nodeSet maybe you can try something along those lines:

kubectl patch elasticsearch quickstart --patch '{"spec": {"nodeSets": [{"name": "default","count": 3}]}}' --type merge

Hi @michael.morello
I tried, but it appear error:

"Error from server (Elasticsearch.elasticsearch.k8s.elastic.co "quickstart" is invalid: spec.nodeSet[0].volumeClaimTemplates: Invalid value: []v1.PersistentVolumeClaim(nil): Volume claim templates cannot be modified): admission webhook "elastic-es-validation-v1.k8s.elastic.co" denied the request: Elasticsearch.elasticsearch.k8s.elastic.co "quickstart" is invalid: spec.nodeSet[0].volumeClaimTemplates: Invalid value: []v1.PersistentVolumeClaim(nil): Volume claim templates cannot be modified"

kubectl get statefulset quickstart-es-default -o yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  creationTimestamp: "2020-06-23T17:31:39Z"
  generation: 1
  labels:
    common.k8s.elastic.co/template-hash: "3420587845"
    common.k8s.elastic.co/type: elasticsearch
    elasticsearch.k8s.elastic.co/cluster-name: quickstart
    elasticsearch.k8s.elastic.co/statefulset-name: quickstart-es-default
  name: quickstart-es-default
  namespace: default
  ownerReferences:
  - apiVersion: elasticsearch.k8s.elastic.co/v1
    blockOwnerDeletion: true
    controller: true
    kind: Elasticsearch
    name: quickstart
    uid: b998502e-eab8-4ce8-8555-da866ec9621f
  resourceVersion: "22735765"
  selfLink: /apis/apps/v1/namespaces/default/statefulsets/quickstart-es-default
  uid: b5b4e33a-b269-4a58-a9df-72ad953240c6
spec:
  podManagementPolicy: Parallel
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      common.k8s.elastic.co/type: elasticsearch
      elasticsearch.k8s.elastic.co/cluster-name: quickstart
      elasticsearch.k8s.elastic.co/statefulset-name: quickstart-es-default
  serviceName: quickstart-es-default
  template:
    metadata:
      annotations:
        co.elastic.logs/module: elasticsearch
      creationTimestamp: null
      labels:
        common.k8s.elastic.co/type: elasticsearch
        elasticsearch.k8s.elastic.co/cluster-name: quickstart
        elasticsearch.k8s.elastic.co/config-hash: "3912648559"
        elasticsearch.k8s.elastic.co/http-scheme: http
        elasticsearch.k8s.elastic.co/node-data: "true"
        elasticsearch.k8s.elastic.co/node-ingest: "true"
        elasticsearch.k8s.elastic.co/node-master: "true"
        elasticsearch.k8s.elastic.co/node-ml: "true"
        elasticsearch.k8s.elastic.co/statefulset-name: quickstart-es-default
        elasticsearch.k8s.elastic.co/version: 7.8.0
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchLabels:
                  elasticsearch.k8s.elastic.co/cluster-name: quickstart
              topologyKey: kubernetes.io/hostname
            weight: 100
      automountServiceAccountToken: false
      containers:
      - env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: status.podIP
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: PROBE_PASSWORD_PATH
          value: /mnt/elastic-internal/probe-user/elastic-internal-probe
        - name: PROBE_USERNAME
          value: elastic-internal-probe
        - name: READINESS_PROBE_PROTOCOL
          value: http
        - name: HEADLESS_SERVICE_NAME
          value: quickstart-es-default
        - name: NSS_SDB_USE_CACHE
          value: "no"
        image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
        imagePullPolicy: IfNotPresent
        lifecycle:
          preStop:
            exec:
              command:
              - bash
              - -c
              - /mnt/elastic-internal/scripts/pre-stop-hook-script.sh
        name: elasticsearch
        ports:
        - containerPort: 9200
          name: http
          protocol: TCP
        - containerPort: 9300
          name: transport
          protocol: TCP
        readinessProbe:
          exec:
            command:
            - bash
            - -c
            - /mnt/elastic-internal/scripts/readiness-probe-script.sh
          failureThreshold: 3
          initialDelaySeconds: 10
          periodSeconds: 5
          successThreshold: 1
          timeoutSeconds: 5
        resources:
          limits:
            memory: 2Gi
          requests:
            memory: 2Gi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /mnt/elastic-internal/downward-api
          name: downward-api
          readOnly: true
        - mountPath: /usr/share/elasticsearch/bin
          name: elastic-internal-elasticsearch-bin-local
        - mountPath: /mnt/elastic-internal/elasticsearch-config
          name: elastic-internal-elasticsearch-config
          readOnly: true
        - mountPath: /usr/share/elasticsearch/config
          name: elastic-internal-elasticsearch-config-local
        - mountPath: /usr/share/elasticsearch/plugins
          name: elastic-internal-elasticsearch-plugins-local
        - mountPath: /usr/share/elasticsearch/config/http-certs
          name: elastic-internal-http-certificates
          readOnly: true
        - mountPath: /mnt/elastic-internal/probe-user
          name: elastic-internal-probe-user
          readOnly: true
        - mountPath: /usr/share/elasticsearch/config/transport-remote-certs/
          name: elastic-internal-remote-certificate-authorities
          readOnly: true
        - mountPath: /mnt/elastic-internal/scripts
          name: elastic-internal-scripts
          readOnly: true
        - mountPath: /usr/share/elasticsearch/config/transport-certs
          name: elastic-internal-transport-certificates
          readOnly: true
        - mountPath: /mnt/elastic-internal/unicast-hosts
          name: elastic-internal-unicast-hosts
          readOnly: true
        - mountPath: /mnt/elastic-internal/xpack-file-realm
          name: elastic-internal-xpack-file-realm
          readOnly: true
        - mountPath: /usr/share/elasticsearch/data
          name: elasticsearch-data
        - mountPath: /usr/share/elasticsearch/logs
          name: elasticsearch-logs
      dnsPolicy: ClusterFirst
      initContainers:
      - command:
        - bash
        - -c
        - /mnt/elastic-internal/scripts/prepare-fs.sh
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: status.podIP
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: status.podIP
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
        imagePullPolicy: IfNotPresent
        name: elastic-internal-init-filesystem
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /mnt/elastic-internal/elasticsearch-config-local
          name: elastic-internal-elasticsearch-config-local
        - mountPath: /mnt/elastic-internal/elasticsearch-plugins-local
          name: elastic-internal-elasticsearch-plugins-local
        - mountPath: /mnt/elastic-internal/elasticsearch-bin-local
          name: elastic-internal-elasticsearch-bin-local
        - mountPath: /mnt/elastic-internal/transport-certificates
          name: elastic-internal-transport-certificates
          readOnly: true
        - mountPath: /mnt/elastic-internal/scripts
          name: elastic-internal-scripts
          readOnly: true
        - mountPath: /usr/share/elasticsearch/data
          name: elasticsearch-data
        - mountPath: /usr/share/elasticsearch/logs
          name: elasticsearch-logs
        - mountPath: /mnt/elastic-internal/downward-api
          name: downward-api
          readOnly: true
        - mountPath: /mnt/elastic-internal/elasticsearch-config
          name: elastic-internal-elasticsearch-config
          readOnly: true
        - mountPath: /usr/share/elasticsearch/config/http-certs
          name: elastic-internal-http-certificates
          readOnly: true
        - mountPath: /mnt/elastic-internal/probe-user
          name: elastic-internal-probe-user
          readOnly: true
        - mountPath: /usr/share/elasticsearch/config/transport-remote-certs/
          name: elastic-internal-remote-certificate-authorities
          readOnly: true
        - mountPath: /mnt/elastic-internal/unicast-hosts
          name: elastic-internal-unicast-hosts
          readOnly: true
        - mountPath: /mnt/elastic-internal/xpack-file-realm
          name: elastic-internal-xpack-file-realm
          readOnly: true
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 180
      volumes:
      - downwardAPI:
          defaultMode: 420
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.labels
            path: labels
        name: downward-api
      - emptyDir: {}
        name: elastic-internal-elasticsearch-bin-local
      - name: elastic-internal-elasticsearch-config
        secret:
          defaultMode: 420
          optional: false
          secretName: quickstart-es-default-es-config
      - emptyDir: {}
        name: elastic-internal-elasticsearch-config-local
      - emptyDir: {}
        name: elastic-internal-elasticsearch-plugins-local
      - name: elastic-internal-http-certificates
        secret:
          defaultMode: 420
          optional: false
          secretName: quickstart-es-http-certs-internal
      - name: elastic-internal-probe-user
        secret:
          defaultMode: 420
          items:
          - key: elastic-internal-probe
            path: elastic-internal-probe
          optional: false
          secretName: quickstart-es-internal-users
      - name: elastic-internal-remote-certificate-authorities
        secret:
          defaultMode: 420
          optional: false
          secretName: quickstart-es-remote-ca
      - configMap:
          defaultMode: 493
          name: quickstart-es-scripts
          optional: false
        name: elastic-internal-scripts
      - name: elastic-internal-transport-certificates
        secret:
          defaultMode: 420
          optional: false
          secretName: quickstart-es-transport-certificates
      - configMap:
          defaultMode: 420
          name: quickstart-es-unicast-hosts
          optional: false
        name: elastic-internal-unicast-hosts
      - name: elastic-internal-xpack-file-realm
        secret:
          defaultMode: 420
          optional: false
          secretName: quickstart-es-xpack-file-realm
      - name: elasticsearch-data
        persistentVolumeClaim:
          claimName: claim-name-placeholder
      - emptyDir: {}
        name: elasticsearch-logs
  updateStrategy:
    type: OnDelete
  volumeClaimTemplates:
  - metadata:
      creationTimestamp: null
      name: elasticsearch-data
      ownerReferences:
      - apiVersion: elasticsearch.k8s.elastic.co/v1
        blockOwnerDeletion: false
        controller: true
        kind: Elasticsearch
        name: quickstart
        uid: b998502e-eab8-4ce8-8555-da866ec9621f
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
      storageClassName: longhorn
      volumeMode: Filesystem
    status:
      phase: Pending
status:
  collisionCount: 0
  currentReplicas: 1
  currentRevision: quickstart-es-default-d4f8ff848
  observedGeneration: 1
  readyReplicas: 1
  replicas: 1
  updateRevision: quickstart-es-default-d4f8ff848
  updatedReplicas: 1