MinIO is a high-performance object storage solution with native support for Kubernetes deployments. minIO provides an API compatible with Amazon Web Services S3 and supports all core S3 features. MinIO is released under the GNU General Public License v3.0.

MinIO is different in that it was designed from the beginning as a private/hybrid cloud object storage. Because MinIO is built specifically to serve objects, the single-tier architecture allows for all the necessary functionality. It is a cloud-native object server that is simultaneously high-performance, scalable, and lightweight.

Table of Contents

StorageClass

The persistent volume used in this test is bare host directory, Since this is just a test, no additional StorageClass is prepared.

...
volumeMounts:
  - name: data
    mountPath: /data
volumes:
  - name: data
    hostPath:
      path: /storage/minio

Create Minio Headless Service

Headless Service controls the domain within which StatefulSets are created. The domain managed by this Service takes the form: $(service name).$(namespace).svc.cluster.local (where cluster.local is the cluster domain), and the pods in this domain take the form: $(pod-name-{i}).$(service name).$(namespace).svc.cluster.local. This is required to get a DNS resolvable URL for each of the pods created within the Statefulset.

This is the Headless service description:

---
apiVersion: v1
kind: Service
metadata:
  name: minio
  labels:
    app: minio
spec:
  clusterIP: None
  ports:
    - name: minio
      port: 9000
    - name: console
      port: 9001
  selector:
    app: minio

Create the headless service

kubectl apply -f headless-svc.yaml

Create Minio StatefulSet

A StatefulSet provides a deterministic name and a unique identity to each pod, making it easy to deploy stateful distributed applications. To launch distributed Minio user need to pass drive locations as parameters to the minio server command. Then the user need to run the same command on all the participating pods. StatefulSets offer a perfect way to handle this requirement.

This is the StatefulSet description.

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minio
spec:
  serviceName: minio
  podManagementPolicy: Parallel
  updateStrategy:
    type: RollingUpdate
  replicas: 4
  selector:
    matchLabels:
      app: minio
  template:
    metadata:
      labels:
        app: minio
    spec:
      nodeSelector:
        minio_role: distributed
      containers:
        - name: minio
          env:
            - name: MINIO_SERVER_URL
              value: http://minio.idocker.io
            - name: MINIO_BROWSER_REDIRECT_URL
              value: http://console.minio.idocker.io
            - name: MINIO_ROOT_USER
              value: "admin"
            - name: MINIO_ROOT_PASSWORD
              value: "passwd_for_admin"
          image: minio/minio:RELEASE.2022-01-08T03-11-54Z
          imagePullPolicy: IfNotPresent
          args:
            - server
            - http://minio-{0...3}.minio.minio.svc.cluster.local/data
            - "--console-address=:9001"
          ports:
            - name: api
              containerPort: 9000
              hostPort: 9000
              protocol: TCP
            - name: console
              containerPort: 9001
              hostPort: 9001
              protocol: TCP
          resources:
            limits:
              cpu: 2000m
              memory: 2Gi
            requests:
              cpu: 1000m
              memory: 1Gi
          livenessProbe:
            exec:
              command: ["curl", "-f", "http://localhost:9000/minio/health/live"]
            initialDelaySeconds: 3
            periodSeconds: 3
            timeoutSeconds: 3
          readinessProbe:
            exec:
              command: ["curl", "-f", "http://localhost:9000/minio/health/live"]
            initialDelaySeconds: 3
            periodSeconds: 2
            timeoutSeconds: 1
          volumeMounts:
            - name: data
              mountPath: /data
      volumes:
        - name: data
          hostPath:
            path: /storage/minio

Create the StatefulSet.

kubectl apply -f minio-dist-statefulset.yaml

Expose Service using Ingress

Now that a MinIO StatefulSet running, user may either want to access it internally (within the cluster) or expose it as a Service onto an external (outside of the cluster, maybe public internet) IP address, depending on the use case. This can be achieved using Services.

There are many service types - default type is ClusterIP, which exposes a service to connection from inside the cluster. NodePort and LoadBalancer are two types that expose services to external traffic. At here, We will use Traefik Ingress to expose the service.

This is the service description.

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: minio-router
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`minio.idocker.io`)
      kind: Rule
      services:
        - name: minio
          port: 9000
    - match: Host(`console.minio.idocker.io`)
      kind: Rule
      services:
        - name: minio
          port: 9001

Create the IngressRoute

kubectl apply -f ingress-router.yaml

Access Minio

Use the following URL to access MinIO: http://console.minio.idocker.io

Reference