## StatefulSet Deployment Example

When deploying some stateful services such as Redis, MySQL, etc., we need to use the StatefulSet controller. The following introduces how to use UDisk to deploy StatefulSet services in UK8S.

### About StatefulSet

```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: db
spec:
  selector:
    matchLabels:
      app: mysql
  replicas: 5
  serviceName: mysql
  template:
    PodTemplateSpec..... # There are a large number of omissions, the same as Deployment. It is description for the Pod to be controlled.
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: ${YOUR_STORAGECLASS_NAME}
      resources:
        requests:
          storage: 10Gi
```

If you are familiar with the structure of Deployment, you will find that the key difference between Deployment and StatefulSet is **volumeClaimTemplates**. Other parts are basically the same.

Take a closer look. You may find the structure of **volumeClaimTemplates** is exactly the same as "PersistentVolumeClaim(PVC)". Actually, **volumeClaimTemplates** is a template of PVC, which is used to generate multiple PVCs with **single point read and write** access modes for Pods managed by StatefulSet.

In the above example, StatefulSet will create 5 Pods and 5 PVCs for the corresponding Pods at the same time so that each Pod has independent storage status.

### PVC example

For stateful services, SSD UDisk and RSSD UDisk are strongly recommended. You can also use LocalPV. But  most data disks of current cloud hosts are also cloud disks and there are various restrictions if you use LocalPV. Therefore, **we strongly recommend using UDisk as the storage medium**.

When the UK8S cluster is initialized, three storage classes related to UDisk have been built in. We only need to directly refer to the storage class to create PVC for Pod consumption. The following introduces how to create the corresponding PVC.

> ⚠️ **RSSD UDisks require Outstanding cloud hosts within the same RDMA region. The RDMA region scope is smaller than an availability zone, and currently hosts cannot be created with a specified RDMA region. Therefore, when using RSSD UDisks, there is a possibility that Pods may fail to schedule in the event of Pod drift. Please ensure that you can accept this risk before use.**

1. Use RSSD UDisk

```yaml
volumeClaimTemplates:
  - metadata:
      name: ${YOUR_NAME} # Needs to keep consistent with the name of VolumeMount.
    spec:
      storageClassName: csi-udisk-rssd #This is the built-in StorageClass of the cluster
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 100Gi
```

Above we use the built-in StorageClass of the cluster. We can also create a new
SC. For details, see [Use RSSD UDisk](/docs/uk8s/udisk/volume/rssdudisk)

2. Use SSD UDisk

```yaml
volumeClaimTemplates:
  - metadata:
      name: ${YOUR_NAME} 
      labels:
        name: redis-cluster
    spec:
      storageClassName: ssd-csi-udisk #This is the self-created StorageClass of SSD UDisk storage medium
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 20Gi
```

If you need to use different storage media, just declare different storageClassNames when creating PVC. 

3. Declare a custom StorageClass (UDisk type)

```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: udisk-ssd-test
provisioner: udisk.csi.ucloud.cn #Storage provider, which cannot be changed here.
parameters:
  type: "ssd"   # Storage medium, which support ssd, sata and rssd, required
  fsType: "ext4"    # File system, required
  udataArkMode: "no"   # Whether to enable Ark mode, which is by default not enabled, optional
  chargeType: "month" # Payment type, which supports dynamic, month and year, optional
  quantity: "1" # Purchase duration; dynamic does not need to be filled; you can purchase 1-9 months, or 1-10 years
reclaimPolicy: Retain  # PV recycling strategy, which supports Delete and Retain, and the default is Delete, optional
allowVolumeExpansion: true # Declare that this storage class supports expandable features
mountOptions:
  - debug
  - rw
```

The above example covers all parameters of UDisk's StorageClass. You can customize SC as you need.

### StatefulSet example

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: uhub.genesissai.com/ucloud/nginx:latest
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "csi-udisk-rssd"  # has to match a storageClassname existed in your cluster
      resources:
        requests:
          storage: 100Gi
```

In the above example, the declared StatefulSet controller named Web will create three nginx Pods and mount an RSSD UDisk for each Pod to store data.
