Published on

Cài đặt và thiết lập SSO (Microsoft Entra ID) cho Minio trên Kubernetes

MinIO là một hệ thống lưu trữ đối tượng hiệu suất cao dựa trên Kubernetes và tương thích với API theo chuẩn S3. MinIO Operator là một công cụ đơn giản dành cho Kubernetes để triển khai các MinIO Tenant.

Giới thiệu

  • Mỗi MinIO Tenant đại diện cho một MinIO Object Store độc lập trong cụm Kubernetes.
  • MinIO Console cung cấp giao diện đồ họa cho việc tương tác với các MinIO Tenant. Nó cho phép quản trị viên thực hiện nhiều tác vụ như tạo người dùng, cấu hình chính sách và sao chép bucket.
  • MinIO Operator cài đặt và cấu hình MinIO Console cho mỗi tenant mặc định.

Cài đặt MinIO bằng Argo CD

MinIO Operator

application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: minio-operator
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  syncPolicy:
    automated:
      selfHeal: true
      prune: true
      allowEmpty: false
    syncOptions:
      - Validate=false
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - RespectIgnoreDifferences=true
      - Replace=true
      - ServerSideApply=true
  project: default
  sources:
    - chart: operator
      repoURL: https://operator.min.io
      targetRevision: 5.*
      helm:
        releaseName: operator
        passCredentials: false
        parameters:
          - name: "operator.replicaCount"
            value: "1"
            forceString: true
          - name: "console.env[0].name"
            value: "MINIO_SERVER_URL"
          - name: "console.env[0].value"
            value: "minio-storage.your-domain.com"
    - repoURL: https://github.com/my-private-repo/gitops
      targetRevision: HEAD
      path: deploys/minio-operator/manifests
  destination:
    server: "https://kubernetes.default.svc"
    namespace: minio-operator
  revisionHistoryLimit: 3

Phần cấu hình cài đặt MinIO Operator bằng Argo CD của mình sẽ bao gồm 2 phần:

  • Đầu tiên là Helm chart, minh sử dụng chart được cung cấp trên trang chủ Deploy Operator With Helm
  • Phần còn lại là các file cấu hình, cũng như các tài nguyên không có sẵn trong Helm chart mà mình sử dụng. Nó được lưu trên Git.

Ở ví dụ của mình, phần cấu hình thiết lập sử dụng Gateway API xử lý HTTP request đến cluster thay vì sử dụng Ingress, và như đã nói ở trên, mình sẽ lưu ở trên GitHub và Arg CD sẽ sử dụng các file YAML trên đó để cài đặt trên cluster.

Chi tiết hơn, các bạn có thể xem thêm tại bài viết Sử dụng Gateway API trên Kubernetes. Còn dưới đây là cấu hình HTTPRoute dùng để truy cập vào MinIO Operator Console.

httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httproute
  namespace: minio-operator
spec:
  parentRefs:
    - group: gateway.networking.k8s.io	
      kind: Gateway	
      name: istio-gateway
      namespace: istio-ingress
      sectionName: minio-console
  hostnames:
    - minio-storage.your-domain.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: console
          port: 9090
          group: ""
          kind: Service
          weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: tls-redirect
  namespace: minio-operator
spec:
  parentRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: istio-gateway
      namespace: istio-ingress
      sectionName: http
  hostnames:
    - minio-storage.your-domain.com
  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
            port: 443
            statusCode: 301
      matches:
        - path:	
            type: PathPrefix
            value: /

Một vài diễn giải cho file httproute.yaml:

  • Dòng 8-12: Khai báo đế phần Listener trên Gateway mà nó sẽ xử lý.
  • Dòng 13-14: Khai báo tên miền của ứng dụng.
  • Dòng 20-25: Khai báo thông tin của backend mà HTTPRoute sẽ điều hướng traffic tới. Cụ thể ở đây là service minio console
  • Dòng 27-51: Phần này cấu hình HTTPRoute nhằm nhiệm vụ điều hướng HTTP sang HTTPS

Sau khi deploy thành công, chúng ta dùng kubectl -n minio-operator get all để kiểm tra

anh@Anh-Nguyen:~$ kubectl -n minio-operator get all
NAME                                  READY   STATUS    RESTARTS       AGE
pod/console-58fd6cc8bb-9b6mz          1/1     Running   3 (4d6h ago)   15d
pod/minio-operator-69986bb674-w2vn6   1/1     Running   4 (2d8h ago)   18d

NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
service/console    ClusterIP   10.96.161.114   <none>        9090/TCP,9443/TCP   18d
service/operator   ClusterIP   10.98.19.110    <none>        4221/TCP            18d
service/sts        ClusterIP   10.104.218.27   <none>        4223/TCP            18d

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/console          1/1     1            1           18d
deployment.apps/minio-operator   1/1     1            1           18d

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/console-58fd6cc8bb          1         1         1       15d
replicaset.apps/console-6476df675           0         0         0       15d
replicaset.apps/console-7fcfdb8d98          0         0         0       18d
replicaset.apps/minio-operator-69986bb674   1         1         1       18d

Bây giờ chúng ta có thể truy cập vào MinIO Operator console

Token để đăng nhập lấy từ:

kubectl -n minio-operator get secrets/console-sa-secret --template={{.data.token}} | base64 -D

Tới bước này, bạn có thể sử dụng Operator console để tạo các tenant mới, tuy nhiên khi cài đặt thiết lập các ứng dụng trên Kubernetes chúng ta nên triển khai thông qua các công cụ GitOps. Bước tiếp theo mình sẽ giới thiệu cách thiết lập một Tenant mới bằng Helm Chart MinIO tenant

MinIO Tenant

Sau khi đã cài đặt và thiết lập MinIO operator trên Kubernetes cluster, thì đến bước này chúng ta sẽ deploy một Tenant mới bằng Helm chart và sử dụng công cụ GitOps là Argo CD

application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: minio-nas
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  syncPolicy:
    automated:
      selfHeal: true
      prune: true
      allowEmpty: false
    syncOptions:
      - Validate=false
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - RespectIgnoreDifferences=true
      - Replace=true
      - ServerSideApply=true
  project: default
  sources:
    - chart: tenant
      repoURL: https://operator.min.io
      targetRevision: 5.*
      helm:
        releaseName: nas
        passCredentials: false
        parameters:
          - name: "tenant.name"
            value: "nas"
          - name: "tenant.pools[0].servers"
            value: "1"
          - name: "tenant.pools[0].name"
            value: "pool-0"
          - name: "tenant.pools[0].volumesPerServer"
            value: "1"
          - name: "tenant.pools[0].size"
            value: "256Gi"
          - name: "tenant.pools[0].storageClassName"
            value: "nas-storage"
          - name: "tenant.metrics.enable"
            value: "true"
          - name: "tenant.certificate.requestAutoCert"
            value: "false"
          - name: "tenant.configuration.name"
            value: "minio-nas-config"
          - name: "tenant.configuration.existingSecret"
            value: "true"
          - name: "tenant.env[0].name"
            value: "MINIO_SERVER_URL"
          - name: "tenant.env[0].value"
            value: "https://minio-tenant.your-domain.com"
    - repoURL: https://github.com/my-private-repo/gitops
      targetRevision: HEAD
      path: deploys/minio-nas/manifests
  destination:
    server: "https://kubernetes.default.svc"
    namespace: minio-nas
  revisionHistoryLimit: 3

Mình diễn giải vài cấu hình cơ bản:

  • Dòng 33-38: là cấu hình số pod của tenant này cũng như số volume, nếu bạn chạy trên môi trường production không nên sử dụng cấu hình này
  • Dòng 51-54: là cấu hình minio url của tenant này. Nó sẽ khác với url của MinIO operator console.
  • Dòng 55-57: là GitHub repo nơi mình chứa các cấu hình không nằm trong Helm chart, cụ thể mình có 2 file httproute.yamlsecrets.yaml
httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httproute-nas
  namespace: minio-nas
spec:
  parentRefs:
    - group: gateway.networking.k8s.io	
      kind: Gateway	
      name: istio-gateway
      namespace: istio-ingress
      sectionName: minio-nas
  hostnames:
    - minio-tenant.your-domain.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: minio
          port: 80
          group: ""
          kind: Service
          weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: tls-redirect-nas
  namespace: minio-nas
spec:
  parentRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: istio-gateway
      namespace: istio-ingress
      sectionName: http
  hostnames:
    - minio-tenant.your-domain.com
  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
            port: 443
            statusCode: 301
      matches:
        - path:	
            type: PathPrefix
            value: /
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httproute-nas-console
  namespace: minio-nas
spec:
  parentRefs:
    - group: gateway.networking.k8s.io	
      kind: Gateway	
      name: istio-gateway
      namespace: istio-ingress
      sectionName: nas-console
  hostnames:
    - minio-tenant-console.your-domain.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: nas-console
          port: 9090
          group: ""
          kind: Service
          weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: tls-redirect-nas-console
  namespace: minio-nas
spec:
  parentRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: istio-gateway
      namespace: istio-ingress
      sectionName: http
  hostnames:
    - minio-tenant-console.your-domain.com
  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
            port: 443
            statusCode: 301
      matches:
        - path:	
            type: PathPrefix
            value: /

Bởi vì cluster của mình không sử dụng Ingress nên đây là file cấu hình HTTPRoute dành cho Tenant server và Tenant console.

Cấu hình SSO

Microsoft Entra ID Application

Trong ví dụ này, mình tiến hành cấu hình SSO cho Minio Tenant thông qua Microsoft Entra ID, vì vậy đầu tiên bạn cần đăng ký một ứng dụng trên Entra ID, cách làm có thể tham khảo trên bài viết Thiết lập Jenkins SSO dùng Azure AD. Môt vài cấu hình cần thiết:

  • Redirect URIs: https://minio-tenant-console.your-domain.com/oauth_callback
  • ID tokens (used for implicit and hybrid flows)
  • Group claim: Groups assigned to the application (recommended for large enterprise companies to avoid exceeding the limit on the number of groups a token can emit)
  • Group claim: Customize token properties by type: sAMAccountName

MinIO sử dụng Policy-Based Access Control (PBAC) để phần cấp, phân quyền truy cập các resource, Built-In Policies, mặc định sẽ có các policy cơ bản:

  • consoleAdmin
  • writeonly
  • diagnostics
  • readwrite
  • readonly

Vì vậy trên Microsoft Entra ID, mình cũng cần tạo các role tương ứng

Sau khi thiết lập xong mọi thứ, chúng ta tạo một resource loại Secret với tên minio-nas-config

secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: minio-nas-config
  namespace: mino-nas
type: Opaque
stringData:
  config.env: |-
    export MINIO_ROOT_USER=<tenant-root-username>
    export MINIO_ROOT_PASSWORD=<tenant-root-pass>
    export MINIO_IDENTITY_OPENID_ENABLE=on
    export MINIO_IDENTITY_OPENID_CONFIG_URL=https://login.microsoftonline.com/<ad-tenant-id>/v2.0/.well-known/openid-configuration
    export MINIO_IDENTITY_OPENID_CLIENT_ID=<client-id>
    export MINIO_IDENTITY_OPENID_SCOPES="openid,email,profile"
    export MINIO_IDENTITY_OPENID_CLAIM_USERINFO="on"
    export MINIO_IDENTITY_OPENID_CLAIM_NAME="roles"
    export MINIO_IDENTITY_OPENID_DISPLAY_NAME="Microsoft Entra ID"
    export MINIO_IDENTITY_OPENID_REDIRECT_URI="https://minio-tenant-console.your-domain.com/oauth_callback"
    export MINIO_IDENTITY_OPENID_COMMENT="Microsoft Entra ID"
    export MINIO_IDENTITY_OPENID_CLIENT_SECRET="client-secret"
    export MINIO_BROWSER_REDIRECT_URL=https://minio-tenant-console.your-domain.com  

Mọi thứ đến đây đã xong, chúng ta có thể deploy resource.

Chúc thành công,

ANH NGUYỄN