실습환경 구성
kind create cluster --name myk8s --image kindest/node:v1.33.4 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
- containerPort: 30003
hostPort: 30003
EOF
# minio-operator : https://github.com/minio/operator/blob/master/helm/operator/values.yaml
helm install --namespace minio-operator --create-namespace minio-operator minio-operator/operator --set operator.replicaCount=1
kubectl get all -n minio-operator
# tenant values : https://github.com/minio/operator/blob/master/helm/tenant/values.yaml
cat << EOF > minio-tenant-1-values.yaml
tenant:
name: tenant1
configSecret:
name: tenant1-env-configuration
accessKey: minio
secretKey: minio123
pools:
- servers: 1
name: pool-0
volumesPerServer: 4
size: 1Gi
storageClassName: standard
env:
- name: MINIO_STORAGE_CLASS_STANDARD
value: "EC:1"
- name: MINIO_PROMETHEUS_AUTH_TYPE
value: public
features:
bucketDNS: true
metrics:
enabled: true
port: 9000
protocol: http
EOF
helm install --namespace tenant1 --create-namespace --values minio-tenant-1-values.yaml tenant1 minio-operator/tenant \
&& kubectl get tenants -A -w
#
kubectl describe tenants -n tenant1
kubectl get pvc -n tenant1
kubectl describe pvc -n tenant1
kubectl get sts,pod,svc,ep,pvc,secret -n tenant1
kubectl get pod -n tenant1 -l v1.min.io/pool=pool-0 -owide
kubectl describe pod -n tenant1 -l v1.min.io/pool=pool-0
kubectl stern -n tenant1 -l v1.min.io/pool=pool-0
kubectl exec -it -n tenant1 sts/tenant1-pool-0 -c minio -- id
kubectl exec -it -n tenant1 sts/tenant1-pool-0 -c minio -- env
kubectl exec -it -n tenant1 sts/tenant1-pool-0 -c minio -- cat /tmp/minio/config.env
kubectl get secret -n tenant1 tenant1-env-configuration -o jsonpath='{.data.config\.env}' | base64 -d ; echo
kubectl get secret -n tenant1 tenant1-tls -o jsonpath='{.data.public\.crt}' | base64 -d
kubectl get secret -n tenant1 tenant1-tls -o jsonpath='{.data.public\.crt}' | base64 -d | openssl x509 -noout -text
#
kubectl patch svc -n tenant1 tenant1-console -p '{"spec": {"type": "NodePort", "ports": [{"port": 9443, "targetPort": 9443, "nodePort": 30001}]}}'
kubectl patch svc -n tenant1 minio -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 9000, "nodePort": 30002}]}}'
# 기본키(minio , minio123)
open "https://127.0.0.1:30001"
# mc alias
mc alias set k8s-tenant1 https://127.0.0.1:30002 minio minio123 --insecure
mc alias list
mc admin info k8s-tenant1 --insecure
# alias
MYALIAS=k8s-tenant1
mc ls $MYALIAS --recursive --insecure
# 신규 터미널 : 모니터링 -> mc cli 와 웹 브라우저에서 인가 출력 정보 비교
mc admin trace $MYALIAS --verbose --insecure
or
mc admin trace $MYALIAS --verbose --all --insecure
## mc cli 와 웹 브라우저에서 인가 출력 정보 비교
127.0.0.1:30002 Authorization: AWS4-HMAC-SHA256 Credential=minio/20250921/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=7a4a96a7cbe71edaa070c14843b89ce51fb24be3ab121a5f264bdba88b43c6e0
## mc cli 와 웹 브라우저에서 인가 출력 정보 비교
minio.tenant1.svc.cluster.local X-Amz-Security-Token: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJJSThUTlQ3UVFJMURPWktSTDVFTiIsImV4cCI6MTc1ODQ3MTc4NiwicGFyZW50IjoibWluaW8ifQ.vgrUYX7HJLHpZDg4bwXwZ255AQUXuOXkg30ov8kiS05olImLLiOz-pvR6RcFDPMsq0GTDhycse36iAxxmFqONg
minio.tenant1.svc.cluster.local Authorization: AWS4-HMAC-SHA256 Credential=II8TNT7QQI1DOZKRL5EN/20250921/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=a58c10ff7b9a6507a6b09d0cd20d87abef905048bed245443c5ac768d65ab9e2
# 버킷 생성
mc mb $MYALIAS/mybucket --insecure
mc ls $MYALIAS --insecure
# object 업로드
echo hello > hello.txt
mc cp hello.txt $MYALIAS/mybucket --insecure
# 웹 콘솔에서 확인 후 trace 확인
인증
- 클라이언트의 신원을 확인하는 과정.
- MinIO는 AWS Signature Version 4 프로토콜을 사용하여 인증을 요구합니다.
- 클라이언트는 유효한 Access Key와 Secret Key를 제시해야 하며,
- S3 API 요청 (예: PUT, GET, DELETE)
- MinIO 관리 API 요청
모두 인증을 거쳐야만 접근 가능합니다.
인가
- 인증된 클라이언트가 어떤 작업과 리소스를 사용할 수 있는지 제한하는 과정.
- PBAC (Policy-Based Access Control) 모델을 사용합니다.
- 정책은 특정 사용자 또는 그룹에 부여되며,
- 허용되는 S3 작업(action)
- 특정 조건(conditions)
등을 정의할 수 있습니다.
- 기본 정책은 거부(Deny by default) 이므로, 정책에 명시되지 않은 작업이나 리소스는 접근할 수 없습니다.
ID 관리: 내장 관리 기능 vs 외부 관리 기능
- 내장 ID 공급자(Minio Internal IDP)
MinIO가 자체 내장한 ID 관리 기능으로, 사용자 계정을 직접 생성·관리하며, 사용자와 그룹에 명시적으로 정책을 연결해야 합니다. 내장 IDP 사용 시 정책 할당과 사용자·그룹 관리를 MinIO 명령어를 통해 수행합니다. - 외부 ID 공급자(External IDP)
MinIO는 다음과 같은 외부 IDP 연동을 지원하여 ID 관리를 위임할 수 있습니다.- OpenID Connect (OIDC) 호환 서비스
- Active Directory / LDAP
- MinIO 인증 플러그인을 활용한 커스텀 외부 ID 관리자
이를 통해 기존 조직의 인증 시스템과 통합할 수 있습니다.
접근 관리
- MinIO는 정책 기반 접근 제어(PBAC)를 사용하며, 인증된 사용자에게 권한 있는 작업과 리소스만 접근하도록 정책으로 정의합니다.
- PBAC 정책은 사용자 또는 그룹에 할당되며, 내장 IDP 사용 시 명령으로 직접 연결해야 합니다.
- 외부 IDP 사용 시 정책 할당 방법은 IDP 종류에 따라 다릅니다.
- MinIO의 PBAC 정책은 AWS IAM 정책 구문과 호환되도록 설계되어 있어, AWS IAM 정책 작성 문서를 참고해 정책을 작성할 수 있습니다.
- 기본 원칙은 명시적으로 허용된 작업이나 리소스만 접근 가능하며, 명시되지 않은 요청은 기본적으로 거부됩니다 (Deny by default).
- MinIO는 정책 기반 접근 제어(PBAC)를 이용해 사용자의 권한 있는 작업과 접근 리소스를 정의하며, 정책은 사용자 또는 그룹에 할당됩니다.
- PBAC는 AWS IAM 정책 문법, 구조, 동작과 호환되며, 조건문을 통해 특정 태그가 있는 객체에만 액세스를 제한하는 태그 기반 정책 조건도 지원합니다.
- 기본 제공 내장 정책으로는 consoleAdmin(전체 권한), readonly(읽기 전용), readwrite(읽기/쓰기), diagnostics(진단 권한), writeonly(쓰기 전용) 등이 있으며, 명시적 거부(Deny)가 허용(Allow)를 OVERRIDE합니다.
PBAC 정책 생성 / 삭제 실습
#기본 정책 확인
#
MYALIAS=k8s-tenant1
mc ls $MYALIAS --insecure
#
mc admin policy list $MYALIAS --insecure
readwrite
writeonly
consoleAdmin
diagnostics
readonly
#신규 정책 생성
#
mc admin policy info $MYALIAS readonly --insecure | jq
{
"PolicyName": "readonly",
"Policy": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
}
# 기본 정책을 정책 부분만 파일로 저장
mc admin policy info $MYALIAS readonly --insecure --policy-file new.json
#
cat new.json| jq
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
# Action 추가
vi new.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
# 정책 생성
mc admin policy create $MYALIAS readlist new.json --insecure
#
mc admin policy list $MYALIAS --insecure
mc admin policy info $MYALIAS readlist --insecure | jq
정책제거
#
mc admin policy remove $MYALIAS diagnostics --insecure
... # admin trace 에 출력 정보 확인
127.0.0.1:30002 [RESPONSE] [2025-09-21T15:02:56.901] [ Duration 1.213ms TTFB 1.211833ms ↑ 93 B ↓ 303 B ]
127.0.0.1:30002 500 Internal Server Error
127.0.0.1:30002 {"Code":"InternalError","Message":"We encountered an internal error, please try again. (inbuilt policy `diagnostics` not allowed to be deleted)","Resource":"/minio/admin/v3/remove-canned-policy","RequestId":"186736EE5CE4E52F","HostId":"dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8"}
#
mc admin policy remove $MYALIAS readlist --insecure
#
mc admin policy list $MYALIAS --insecure
신규 유저 생성
# user 없음 확인
mc admin user list $MYALIAS --insecure
# user1 생성 : 시크릿키 mypassword
mc admin user add $MYALIAS user1 mypassword --insecure
mc admin user list $MYALIAS --insecure
enabled user1
user1 에 PBAC 정책 할당
#
mc admin policy list $MYALIAS --insecure
mc admin policy info $MYALIAS readwrite --insecure | jq
...
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
...
mc admin policy attach $MYALIAS readwrite --user user1 --insecure
Attached Policies: [readwrite]
To User: user1
#
mc admin policy entities $MYALIAS --policy readwrite --insecure
Query time: 2025-09-20T06:21:14Z
Policy -> Entity Mappings:
Policy: readwrite
User Mappings:
user1
Group 에 user 할당 및 정책 부착
#
mc admin group list $MYALIAS --insecure
#
mc admin group add $MYALIAS devteam user1 --insecure
mc admin group info $MYALIAS devteam --insecure
Group: devteam
Status: enabled
Policy:
Members: user1
#
mc admin policy attach $MYALIAS readonly --group devteam --insecure
Attached Policies: [readonly]
To Group: devteam
#
mc admin group info $MYALIAS devteam --insecure
Group: devteam
Status: enabled
Policy: readonly
Members: user1
현재 Group 에 두 번째 정책 추가 후 동작 확인
# 참고로 3번째 줄 정책이 위 1,2 모두 포함됨
cat << EOF > s3-list.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
EOF
# lister 정책 생성
mc admin policy create $MYALIAS lister s3-list.json --insecure
mc admin policy list $MYALIAS --insecure
# devteam 그룹에 추가 부착
mc admin policy attach $MYALIAS lister --group devteam --insecure
# devteam 그룹에 2개의 정책 부착 확인
mc admin group info $MYALIAS devteam --insecure
Group: devteam
Status: enabled
Policy: lister,readonly
Members: user1
LDAP
배포할 Open LDAP 의 조직도를 LDIF로 만들예정
LDIF 구조는 다음과 같다.
# 전체 그림
## Users OU는 아직 사용자가 안 들어가 있지만 컨테이너만 생성
## Groups OU 안에 Admins/ Maintainers 그룹이 있고 사용자 DN이 멤버로 들어감
dc=minio,dc=io
├── cn=developer (사용자)
├── cn=maintainer (사용자)
├── cn=admin_root (사용자)
├── ou=Users (OU)
└── ou=Groups
├── cn=Admins (groupOfUniqueNames, member=admin_root)
└── cn=Maintainers (groupOfUniqueNames, member=maintainer,developer)
# 사용자 엔트리들
dn: cn=developer,dc=minio,dc=io # dn: 엔트리의 Distinguished Name(LDAP 경로)
changetype: add # changetype: add : 새 엔트리를 추가
objectclass: inetOrgPerson # 속성(attribute)을 나열
cn: developer
givenname: developer
sn: Developer
displayname: Developer User
mail: developer@minio.io
userpassword: developer_pass
dn: cn=maintainer,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson # LDAP에서 사람을 나타낼 때 쓰는 표준 객체 클래스
cn: maintainer # cn : Common Name (로그인 ID 같은 것)
givenname: maintainer
sn: Maintainer
displayname: Maintainer User # displayname : LDAP UI 등에서 보여줄 이름
mail: maintainer@minio.io
userpassword: maintainer_pass # userpassword : 사용자 비밀번호
...
# 조직 단위(OU) 생성
dn: ou=Groups,dc=minio,dc=io # ou=Groups : 그룹들을 담는 컨테이너(Organizational Unit)
changetype: add
objectclass: organizationalUnit
ou: Groups
dn: ou=Users,dc=minio,dc=io # ou=Users : 사용자를 담는 컨테이너
changetype: add
objectclass: organizationalUnit
ou: Users # 사용자들이 dc=minio,dc=io에 직접 만들어졌지만, 별도 OU로도 구분 가능
# 그룹 엔트리들
dn: cn=Admins,ou=Groups,dc=minio,dc=io
changetype: add
cn: Admins # cn=Admins 라는 그룹을 만들고
objectclass: groupOfUniqueNames # objectclass: groupOfUniqueNames : 고유 멤버 DN을 갖는 그룹
uniqueMember: cn=admin_root,dc=minio,dc=io # uniqueMember: 로 admin_root 사용자를 그룹 멤버로 추가
dn: cn=Maintainers,ou=Groups,dc=minio,dc=io
changetype: add
cn: Maintainers # Maintainers라는 그룹을 만들고
objectclass: groupOfUniqueNames
uniqueMember: cn=maintainer,dc=minio,dc=io # maintainer와 developer 두 명을 멤버로 지정
uniqueMember: cn=developer,dc=minio,dc=io
openldap 관리자 암호화 LDIF configmap 작성
#
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: openldap-admin-secret
type: Opaque
stringData:
admin-password: "admin123"
EOF
#
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: openldap-bootstrap
namespace: default
data:
bootstrap.ldif: |
dn: cn=developer,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: developer
givenname: developer
sn: Developer
displayname: Developer User
mail: developer@minio.io
userpassword: developer_pass
dn: cn=maintainer,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: maintainer
givenname: maintainer
sn: Maintainer
displayname: Maintainer User
mail: maintainer@minio.io
userpassword: maintainer_pass
dn: cn=admin_root,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: admin_root
givenname: admin_root
sn: AdminRoot
displayname: Admin User
mail: admin_root@minio.io
userpassword: admin_pass
dn: ou=Groups,dc=minio,dc=io
changetype: add
objectclass: organizationalUnit
ou: Groups
dn: ou=Users,dc=minio,dc=io
changetype: add
objectclass: organizationalUnit
ou: Users
dn: cn=Admins,ou=Groups,dc=minio,dc=io
changetype: add
cn: Admins
objectclass: groupOfUniqueNames
uniqueMember: cn=admin_root,dc=minio,dc=io
dn: cn=Maintainers,ou=Groups,dc=minio,dc=io
changetype: add
cn: Maintainers
objectclass: groupOfUniqueNames
uniqueMember: cn=maintainer,dc=minio,dc=io
uniqueMember: cn=developer,dc=minio,dc=io
EOF
openldap 디플로이먼트/서비스 생성
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: openldap
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: openldap
template:
metadata:
labels:
app: openldap
spec:
initContainers:
- name: copy-bootstrap
image: busybox
command: ['sh', '-c', 'cp /config/bootstrap.ldif /ldif/bootstrap.ldif']
volumeMounts:
- name: configmap-ldif
mountPath: /config
- name: writable-ldif
mountPath: /ldif
containers:
- name: openldap
image: osixia/openldap:1.5.0
env:
- name: LDAP_ORGANISATION
value: "MinIO"
- name: LDAP_DOMAIN
value: "minio.io"
- name: LDAP_ADMIN_PASSWORD
value: "admin123"
- name: LDAP_REMOVE_CONFIG_AFTER_SETUP
value: "false"
ports:
- containerPort: 389
- containerPort: 636
volumeMounts:
- name: writable-ldif
mountPath: /container/service/slapd/assets/config/bootstrap/ldif/custom
- name: phpldapadmin
image: osixia/phpldapadmin:0.9.0
env:
- name: PHPLDAPADMIN_LDAP_HOSTS
value: "localhost"
- name: PHPLDAPADMIN_HTTPS
value: "false" # 기본 HTTP로 사용, HTTPS 쓰려면 true
ports:
- containerPort: 80
volumes:
- name: configmap-ldif
configMap:
name: openldap-bootstrap
- name: writable-ldif
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: openldap
namespace: default
spec:
selector:
app: openldap
ports:
- name: ldap
port: 389
targetPort: 389
- name: ldaps
port: 636
targetPort: 636
- name: http
port: 80
targetPort: 80
EOF
배포 확인
#
kubectl get deploy,pod,svc,ep,cm,secret
# 컨테이너가 시작되면 /container/service/slapd/assets/config/bootstrap/ldif/custom/bootstrap.ldif 를 읽어서 자동으로 ldapadd 적용.
# 결과적으로 LDAP 서버가 처음 뜰 때 바로 사용자를 생성해 둡니다. 이후 kubectl exec로 들어가서 ldapsearch로 확인할 수 있습니다:
# 관리자 DN(암호)로 ldapsearch 확인
kubectl exec -it deploy/openldap -c openldap -- \
ldapsearch -x -H ldap://localhost -D "cn=admin,dc=minio,dc=io" -w admin123 -b "dc=minio,dc=io"
AD/LDAP 액세스 관리
- MinIO는 외부 ID 관리를 위해 단일 AD 또는 LDAP 서비스를 지원하며, 이를 활성화하면 내부 IDP는 비활성화됩니다.
- 외부 AD/LDAP에서 관리되는 사용자의 고유 이름(DN)을 기반으로 MinIO 내 기존 정책에 매핑하고, 그룹 멤버십 역시 정책 매핑에 활용됩니다.
- 인증 시 MinIO는 AD/LDAP 자격증명을 확인하고, DN 및 그룹 DN과 매칭되는 정책을 찾아 인증된 사용자에게 할당하며, 이를 기반으로 임시 자격증명(STS)을 생성합니다.
- 명시된 정책이 없으면 모든 리소스 및 작업에 대한 접근이 거부되며, AD/LDAP 사용자는 정책에 연결된 액세스 키도 생성할 수 있습니다.
사용자 DN에 대한 정책 매핑
mc idp ldap policy attach myminio consoleAdmin \
--user='cn=sisko,cn=users,dc=example,dc=com'
mc idp ldap policy attach myminio readwrite,diagnostics \
--user='cn=dax,cn=users,dc=example,dc=com'
- **cn=sisko,cn=users,dc=example,dc=com**MinIO는 정책 과 일치하는 DN을 가진 인증된 사용자를 할당하여 consoleAdmin MinIO 서버에 대한 완전한 액세스 권한을 부여합니다.
- MinIO는 및 정책 cn=dax,cn=users,dc=example,dc=com모두와 일치하는 DN을 가진 인증된 사용자를 할당하여 MinIO 서버에 대한 일반적인 읽기/쓰기 액세스 권한 과 진단 관리 작업에 대한 액세스 권한을 부여합니다.
- MinIO는 DN이 일치하는 인증된 사용자에게 정책을 할당하지 않으며 **cn=quark,cn=users,dc=example,dc=com**API 작업에 대한 모든 액세스를 거부합니다.
그룹 DN에 대한 정책 매핑
mc idp ldap policy attach myminio consoleAdmin \
--group='cn=ops,cn=groups,dc=example,dc=com'
mc idp ldap policy attach myminio diagnostics \
--group='cn=engineering,cn=groups,dc=example,dc=com'
- **cn=ops,cn=groups,dc=example,dc=com**MinIO는 AD/LDAP 그룹 의 멤버십을 가진 모든 인증 사용자에게 consoleAdmin정책을 할당하여 MinIO 서버에 대한 완전한 액세스 권한을 부여합니다.
- **cn=engineering,cn=groups,dc=example,dc=com**MinIO는 AD/LDAP 그룹 의 멤버십을 가진 모든 인증 사용자에게 diagnostics정책을 할당하여 진단 관리 작업에 대한 액세스 권한을 부여합니다.
MinIO 에 LDAP 설정
dc=minio,dc=io
├── cn=developer (사용자)
├── cn=maintainer (사용자)
├── cn=admin_root (사용자)
├── ou=Users (OU)
└── ou=Groups
├── cn=Admins (groupOfUniqueNames, member=admin_root)
└── cn=Maintainers (groupOfUniqueNames, member=maintainer,developer)
##위 정보의 LDAP을 등록할 예정
- Server Insecure : Enabled
- Server Address : openldap.default.svc.cluster.local:389
- Lookup Bind DN* : cn=admin,dc=**minio**,dc=io
- Lookup Bind Password* : admin123
- User DN Search Base* : **dc**=minio,dc=io
- User DN Search Filter* : (cn=%s)
그룹 맵핑 검색 설정
#
mc idp ldap update $MYALIAS \
group_search_filter="(&(objectClass=groupOfUniqueNames)(uniqueMember=%d))" \
group_search_base_dn="dc=minio,dc=io" --insecure
mc admin service restart $MYALIAS --insecure
#
mc idp ldap info $MYALIAS --insecure
╭─────────────────────────────────────────────────────────────────────────────╮
│ enable: on │
│ group_search_base_dn: dc=minio,dc=io │
│ group_search_filter: (&(objectClass=groupOfUniqueNames)(uniqueMember=%d)) │
│ lookup_bind_dn: cn=admin,dc=minio,dc=io │
│ server_addr: openldap.default.svc.cluster.local:389 │
│ server_insecure: on │
│user_dn_search_base_dn: dc=minio,dc=io │
│ user_dn_search_filter: (cn=%s) │
╰─────────────────────────────────────────────────────────────────────────────╯
그룹맵핑 정책 설정
# 전체 그림
dc=minio,dc=io
├── cn=developer (사용자)
├── cn=maintainer (사용자)
├── cn=admin_root (사용자)
├── ou=Users (OU)
└── ou=Groups
├── cn=Admins (groupOfUniqueNames, member=admin_root)
└── cn=Maintainers (groupOfUniqueNames, member=maintainer,developer)
#
mc idp ldap policy attach $MYALIAS readwrite \
--group="cn=Maintainers,ou=Groups,dc=minio,dc=io" --insecure
Attached Policies: [readwrite]
To Group: cn=Maintainers,ou=Groups,dc=minio,dc=io
#
mc admin user list $MYALIAS --insecure
enabled cn=admin_root,dc=... consoleAdmin
#
mc admin group list $MYALIAS --insecure
cn=Maintainers,ou=Groups,dc=minio,dc=io
devteam
dn: cn=developer,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: developer
givenname: developer
sn: Developer
displayname: Developer User
mail: developer@minio.io
userpassword: developer_pass
SDK(실습에선 Python으로 진행)
기본 설정
#
docker exec -it myk8s-control-plane bash
-----------------------------------------
#
python3 -V
#
apt update && apt install -y python3-pip nano git tree
#
pip3 list
pip3 install minio --break-system-packages
pip3 show minio
#
git clone https://github.com/minio/minio-py
cd minio-py/examples
tree
|-- append_object.py
|-- bucket_exists.py
...
#
cat list_buckets.py
from minio import Minio
client = Minio(
"play.min.io",
access_key="Q3AM3UQ867SPQQA43P2F",
secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
)
buckets = client.list_buckets()
for bucket in buckets:
print(bucket.name, bucket.creation_date)
#
python3 list_buckets.py
...
-----------------------------------------
minio 제공되는 기본 버킷을 확인할 수 있다.
devuser 생성
# user 확인
MYALIAS=k8s-tenant1
mc admin user list $MYALIAS --insecure
# devuser 생성 : 시크릿키 devpassword
mc admin user add $MYALIAS devuser devpassword --insecure
mc admin user list $MYALIAS --insecure
# devuser 에 readwrite 정책 부착
mc admin policy attach $MYALIAS readwrite --user devuser --insecure
mc admin policy entities $MYALIAS --policy readwrite --insecure
Python SDK를 활용하여 버킷 목록 조회
# 아래는 myk8s-controller-plane 컨테이너 내부에서 실행
kubectl get secret -n tenant1 tenant1-tls -o jsonpath='{.data.public\.crt}' | base64 -d > tenant1.crt
kubectl get secret -n tenant1 tenant1-tls -o jsonpath='{.data.public\.crt}' | base64 -d | openssl x509 -noout -text
cp tenant1.crt /usr/local/share/ca-certificates/tenant1.crt
update-ca-certificates
#
echo "127.0.0.1 minio.tenant1.svc.cluster.local" >> /etc/hosts
#
cat << EOF > my_list_bucket.py
from minio import Minio
client = Minio(
"minio.tenant1.svc.cluster.local:30002",
access_key="devuser",
secret_key="devpassword",
secure=True,
cert_check=False
)
buckets = client.list_buckets()
for bucket in buckets:
print(bucket.name, bucket.creation_date)
EOF
cat my_list_bucket.py
# 버킷 목록 조회
python3 my_list_bucket.py
mybucket 2025-09-21 04:24:16.252000+00:00
# mc admin trace $MYALIAS --verbose --all --insecure
minio.tenant1.svc.cluster.local:30002 [REQUEST s3.ListBuckets] [2025-09-21T17:36:30.032] [Client IP: 10.244.0.1]
minio.tenant1.svc.cluster.local:30002 GET /
minio.tenant1.svc.cluster.local:30002 Proto: HTTP/1.1
minio.tenant1.svc.cluster.local:30002 Host: minio.tenant1.svc.cluster.local:30002
minio.tenant1.svc.cluster.local:30002 Authorization: AWS4-HMAC-SHA256 Credential=devuser/20250921/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=b73e560231834d88820360e3304ee9fa7ec9f9f26b75de8ed6aef389458fc86d
Python SDK를 활용하여 객체 업로드
# 바로 위 sample.json 에서 파일 작성 후 json 파일 확인
cat sample.json | jq
#
cat << EOF > labf.py
from urllib import request
def rprint(result):
print(
"Object name: {0}; last modified: {1}".format(
result.object_name, result.last_modified
)
)
def opensky_stream():
return request.urlopen(
"https://opensky-network.org/api/states/all",
)
def obj_head(response):
print("Object head: {0}".format(response.read(100)))
def eprint(errors):
for error in errors:
print("Error occurred while deleting object", error)
EOF
#
cat << EOF > my_put_object.py
from minio import Minio
from minio.credentials import LdapIdentityProvider
from minio.commonconfig import CopySource
from minio.deleteobjects import DeleteObject
from time import sleep
import labf
# Create a client.
client = Minio(
"minio.tenant1.svc.cluster.local:30002",
access_key="devuser",
secret_key="devpassword",
secure=True,
cert_check=False
)
result = client.fput_object("mybucket", "sample.json", "sample.json", "application/json")
labf.rprint(result)
EOF
#
python3 my_put_object.py
Object name: sample.json; last modified: None
#
mc ls $MYALIAS --recursive --insecure
[2025-09-21 17:53:11 KST] 6.1KiB STANDARD mybucket/sample.json