brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Nov 08. 2023

EKS9탄-12. EKS DB-MongoDB-12/18

몽고디비 샤딩

<1> 샤딩 vs 복제 비교

<2> 신규로 다시 설치하자. 클러스터 생성 

<3> (참고) mongodb 설치 : ubuntu 22.04 에 설치 - Docs

<4> (참고) resource-capacity - 링크

<5> 삭제



<1> 샤딩 vs 복제 비교


한글

https://www.youtube.com/watch?si=kaWK1Q704djrl9Ft&v=y42TXZKFfqQ&feature=youtu.be


영어

https://www.youtube.com/watch?v=1sMZ455i1PU&feature=youtu.be




<2> 신규로 다시 설치하자. 클러스터 생성 



1

# 신규 터미널 : 모니터링

watch kubectl get psmdb,sts,pod,svc,ep,pvc,pv



2

# 클러스터 생성 : 복제 셋 2개(rs-0, rs1), mongos 라우터 3개(파드 3개), cfg(파드 3개) >> 6분 정도 소요


kubectl get secret $MYNICK-secrets


curl -s -O https://raw.githubusercontent.com/gasida/DOIK/main/psmdb/cluster2.yaml

cat cluster2.yaml | yh

cat cluster2.yaml | sed -e "s/my-cluster-name/$MYNICK/" | kubectl apply -f -



# 클러스터 생성 정보 확인

kubectl get psmdb

kubectl get psmdb gasida -o yaml | kubectl neat | yh



# 클러스타 파드 정보 확인

kubectl get sts,pod -owide

kubectl get svc,ep

kubectl df-pv

kubectl get pvc,pv






Percona Server for MongoDB Sharding : https://docs.percona.com/percona-operator-for-mongodb/sharding.html



3

# mongos 라우터 접속 서비스 정보 확인

kubectl get svc,ep $MYNICK-mongos



# [터미널1] 클러스터 접속(ADMIN_USER)

kubectl exec ds/myclient -it -- mongo --quiet "mongodb://userAdmin:userAdmin123456@$MYNICK-mongos.psmdb.svc.cluster.local/admin?ssl=false"

mongos> db

mongos> show dbs



# 데이터베이스를 사용할 유저 생성

mongos> db.createUser({user: "doik" , pwd: "qwe123" , roles: [ "userAdminAnyDatabase", "dbAdminAnyDatabase","readWriteAnyDatabase"]})



# [터미널2] 클러스터 접속(CLUSTER_USER)


kubectl exec ds/myclient -it -- mongo --quiet "mongodb://clusterAdmin:clusterAdmin123456@$MYNICK-mongos.psmdb.svc.cluster.local/admin?ssl=false"


mongos> use config



# 샤드 목록 정보 확인

mongos> db.shards.find().pretty()

{

"_id" : "rs0",

"host" : "rs0/gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017,gasida-db-rs0-1.gasida-db-rs0.psmdb.svc.cluster.local:27017,gasida-db-rs0-2.gasida-db-rs0.psmdb.svc.cluster.local:27017",

"state" : 1,

"topologyTime" : Timestamp(1655003176, 1)

}

{

"_id" : "rs1",

"host" : "rs1/gasida-db-rs1-0.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-1.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-2.gasida-db-rs1.psmdb.svc.cluster.local:27017",

"state" : 1,

"topologyTime" : Timestamp(1655003178, 2)

}



# (옵션) 설정 서버에 저장된 메타데이터 확인

mongos> show collections

changelog  # 메타메이터가 변경된 내용을 기록한 목록

chunks     # 샤딩된 컬렉션의 청크 정보, 어떤 샤드에 어떤 범위로 있는지 확인 가능

collections   # 샤드 클러스터 컬렉션 목록

image_collection  #

lockpings  # 샤드 클러스터의 구성원이 서로의 연결상태를 확인한 일시가 있는 목록

locks      # 컬렉션 잠금에 대한 목록. 서로 다른 mongos 가 보낸 명령 충돌을 방지한다

migrations

mongos     # 실행중인 라우터 mongos 목록

reshardingOperations

settings

shards     # 샤드 클러스터에 등록된 샤드 목록

tags

transactions

version    # 샤드 클러스터 메타데이터 전체에 대한 버전 정보, 동기화를 위한 필요

mongos> db.changelog.find().pretty()  # 메타메이터가 변경된 내용을 기록한 목록

mongos> db.chunks.find().pretty()     # 샤딩된 컬렉션의 청크 정보, 어떤 샤드에 어떤 범위로 있는지 확인 가능



# 샤드 클러스터 상태 확인 : 기본 정보, 샤드 정보, 밸런서 정보, 샤딩 설정이 된 컬렉션 정보, 청크 정보 등 출력

mongos> sh.help()

mongos> sh.status({"verbose":1})  # 모든 정보 출력

mongos> sh.status()

--- Sharding Status ---

  sharding version: {

  "_id" : 1,

  "minCompatibleVersion" : 5,

  "currentVersion" : 6,

  "clusterId" : ObjectId("62a557d217d6c043a26e39c8")

  }

  shards:           # 샤드 정보, 샤드의 상태 state 정보

        {  "_id" : "rs0",  "host" : "rs0/gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017,gasida-db-rs0-1.gasida-db-rs0.psmdb.svc.cluster.local:27017,gasida-db-rs0-2.gasida-db-rs0.psmdb.svc.cluster.local:27017",  "state" : 1,  "topologyTime" : Timestamp(1655003176, 1) }

        {  "_id" : "rs1",  "host" : "rs1/gasida-db-rs1-0.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-1.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-2.gasida-db-rs1.psmdb.svc.cluster.local:27017",  "state" : 1,  "topologyTime" : Timestamp(1655003178, 2) }

  active mongoses:  # 라우터 정보

        "5.0.7-6" : 3

  autosplit:

        Currently enabled: yes

  balancer:         # 밸런서 정보 : 활성화 여부, 현재 작동 여부, 밸런싱 실패한 횟수나 24시간 이내에 몇번이나 '청크 이동 migration'이 있었는지 확인 >> 불필요한 청크 이동 점검 확인

        Currently enabled: yes

        Currently running: no

        Failed balancer rounds in last 5 attempts: 0

        Migration results for the last 24 hours:

                512 : Success

  databases:        # 데이터베이스 정보 : 샤드 클러스터에서 admin 과 config 를 제외한 데이터베이스 정보를 표시

        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }

                config.system.sessions

                        shard key: { "_id" : 1 }

                        unique: false

                        balancing: true

                        chunks:

                                rs0512

                                rs1512

...



3

샤딩 테스트


# [터미널1] 클러스터 접속(doik)

kubectl exec ds/myclient -it -- mongo --quiet "mongodb://doik:qwe123@$MYNICK-mongos.psmdb.svc.cluster.local/admin?ssl=false"

mongos> db

mongos> show dbs



# doik 테이터베이스 선택(없으면 데이터베이스 생성됨)

mongos> use doik



# 도큐먼트 추가

mongos> db.test.insertOne({ hello: 'world' })



# 콜렉션에서 도큐먼트 조회

mongos> db.test.find()

mongos> db.test.find({},{_id:0})

{ "hello" : "world" }




# [터미널2] 클러스터 접속(CLUSTER_USER)

kubectl exec ds/myclient -it -- mongo --quiet "mongodb://clusterAdmin:clusterAdmin123456@$MYNICK-mongos.psmdb.svc.cluster.local/admin?ssl=false"

mongos> use config



# 샤드 클러스터 상태 확인 : 기본 정보, 샤드 정보, 밸런서 정보, 샤딩 설정이 된 컬렉션 정보, 청크 정보 등 출력

mongos> sh.status({"verbose":1})  # 모든 정보 출력

mongos> sh.status()



# doik 데이터베이스에서 샤딩을 활성화

mongos> sh.enableSharding("doik")


# chunks 사이즈가 64MB(기본값)을 테스트를 위해서 1M 줄이기 - 링크

# 기본 청크사이즈가 64MB 여서 10만 도큐먼트(레코드)는 분할이 되지 않았습니다.

# 그래서 테스트를 위해 청크사이즈를 1MB로 변경하고 테스트 하시면 분할 확인이 가능합니다.


mongos> db.settings.save({_id: "chunksize", value: 1})

WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize" })

혹은

db.settings.updateOne(

   { _id: "chunksize" },

   { $set: { _id: "chunksize", value: 1 } },

   { upsert: true }

)

{

"acknowledged" : true,

"matchedCount" : 0,

"modifiedCount" : 0,

"upsertedId" : "chunksize"

}



# chunks 사이즈 설정 정보 확인 

mongos> db.settings.find()

{ "_id" : "chunksize", "value" : 1 }





# [터미널1] 클러스터 접속(doik)



# 샤딩 활성화를 위해서 샤딩하려는 키에 해시 인덱스를 생성

mongos> db.test.createIndex({"username" : "hashed"})

혹은 인덱스 생성

mongos> db.test.createIndex({"username" : 1})




# [터미널2] 클러스터 접속(CLUSTER_USER)


# 이제 "username" 으로 컬렉션을 샤딩할 수 있다

mongos> sh.shardCollection("doik.test", {"username" : "hashed"})

혹은

mongos> sh.shardCollection("doik.test", {"username" : 1})



# 몇 분 기다렸다가 다시 샤드 클러스터 상태 확인 : 휠씬 많은 정보가 표시됨

mongos> sh.status()



# [터미널1] 클러스터 접속(doik)

# 대량의 도큐먼트 생성 : 20분 넘게 시간 소요

mongos> for (i=0; i<10; i++) {db.test.insert({"username" : "user"+i, "created_at" : new Date()})}

mongos> for (i=10; i<100000; i++) {db.test.insert({"username" : "user"+i, "created_at" : new Date()})}




# [터미널3] 클러스터 접속(doik)


kubectl exec ds/myclient -it -- mongo --quiet "mongodb://doik:qwe123@$MYNICK-mongos.psmdb.svc.cluster.local/admin?ssl=false"

mongos> use doik

mongos> db.test.find({},{_id:0})

mongos> db.test.count()



# 데이터가 여러 샤드에 분산됐으므로 몇 가지 쿼리를 시도해서 확인 : 쿼리 정상 작동 확인

mongos> db.test.find({username: "user1234"})



# 쿼리 내부 수행 작업 확인

mongos> db.test.find({username: "user1234"}).explain()

{

"queryPlanner" : {

"mongosPlannerVersion" : 1,

"winningPlan" : {

"stage" : "SINGLE_SHARD",

"shards" : [

{

"shardName" : "rs1",

"connectionString" : "rs1/gasida-db-rs1-0.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-1.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-2.gasida-db-rs1.psmdb.svc.cluster.local:27017",

"serverInfo" : {

"host" : "gasida-db-rs1-2",

"port" : 27017,

"version" : "5.0.7-6",

"gitVersion" : "5215aa3f853ea97640cdabf0b48861b0d53bfac3"

},

"namespace" : "doik.test",

"indexFilterSet" : false,

"parsedQuery" : {

"username" : {

"$eq" : "user1234"

}

},

"queryHash" : "379E82C5",

"planCacheKey" : "F335C572",

"maxIndexedOrSolutionsReached" : false,

"maxIndexedAndSolutionsReached" : false,

"maxScansToExplodeReached" : false,

"winningPlan" : {

"stage" : "FETCH",

"filter" : {

"username" : {

"$eq" : "user1234"

}

},

"inputStage" : {

"stage" : "IXSCAN",

"keyPattern" : {

"username" : "hashed"

},

"indexName" : "username_hashed",

"isMultiKey" : false,

"isUnique" : false,

"isSparse" : false,

"isPartial" : false,

"indexVersion" : 2,

"direction" : "forward",

"indexBounds" : {

"username" : [

"[8720327145141812260, 8720327145141812260]"

mongos> db.test.find({username: "user9851"}).explain()

mongos> db.test.find().explain()

mongos> db.test.count()

mongos> db.test.count()

mongos> db.test.count()

...




# [터미널2] 클러스터 접속(CLUSTER_USER)


# 클러스터 내 모든 샤드 정보 출력

mongos> use config

mongos> db.shards.find()



# 클러스터가 알고 있는 모든 샤딩 데이터베이스 출력 : enableSharding 실행된 데이터베이스이며, partitioned 가 true

mongos> db.databases.find()

{ "_id" : "doik", "primary" : "rs1", "partitioned" : true, "version" : { "uuid" : UUID("2257d7a8-26f5-4bdd-ae19-d380b220790d"), "timestamp" : Timestamp(1655005281, 1), "lastMod" : 1 } }




# 샤딩된 컬렉션 출력

mongos> db.collections.find().pretty()

...

{

"_id" : "doik.test",

"lastmodEpoch" : ObjectId("62a56a2f769020e0a51a1e38"),

"lastmod" : ISODate("2022-06-12T04:23:12.019Z"),

"timestamp" : Timestamp(1655007791, 8),

"uuid" : UUID("64debe3c-79c4-4fd8-9669-9ab7e75e7b44"),

"key" : {

"username" : "hashed"

},

"unique" : false,

"noBalance" : false

}



# 모든 컬렉션 내의 청크 기록

mongos> db.chunks.find().skip(1).limit(1).pretty()

mongos> db.chunks.find().skip(1).limit(10).pretty()



# 분할과 마이그레이션 기록

mongos> db.changelog.find().pretty()

mongos> use doik

mongos> db.test.getShardDistribution()

Shard rs0 at rs0/gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017,gasida-db-rs0-1.gasida-db-rs0.psmdb.svc.cluster.local:27017,gasida-db-rs0-2.gasida-db-rs0.psmdb.svc.cluster.local:27017

 data : 104B docs : 2 chunks : 2

 estimated data per chunk : 52B

 estimated docs per chunk : 1

Shard rs1 at rs1/gasida-db-rs1-0.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-1.gasida-db-rs1.psmdb.svc.cluster.local:27017,gasida-db-rs1-2.gasida-db-rs1.psmdb.svc.cluster.local:27017

 data : 3.07MiB docs : 48952 chunks : 3  # 현재 청크 3개로 분할

 estimated data per chunk : 1.02MiB      # 청크 사이즈 1MB

 estimated docs per chunk : 16317

Totals

 data : 3.07MiB docs : 48954 chunks : 5

 Shard rs0 contains 0% data, 0% docs in cluster, avg obj size on shard : 52B

 Shard rs1 contains 99.99% data, 99.99% docs in cluster, avg obj size on shard : 65B





<3> (참고) mongodb 설치 : ubuntu 22.04 에 설치 - Docs


1

# 설치

echo "[TASK 9] Install mongodb"

echo "deb http://security.ubuntu.com/ubuntu impish-security main" | tee /etc/apt/sources.list.d/impish-security.list

apt-get update -qq >/dev/null 2>&1

apt-get install libssl1.1 -y -qq >/dev/null 2>&1

wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add - >/dev/null 2>&1

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list >/dev/null 2>&1

apt-get update -qq >/dev/null 2>&1

apt-get install -y mongodb-org -qq >/dev/null 2>&1

systemctl start mongod



# 확인

mongo --eval 'db.runCommand({connectionStatus: 1})'



# (옵션)

systemctl status mongod

cat /etc/mongod.conf

sed -i 's/127.0.0.1/0.0.0.0/g' /etc/mongod.conf

systemctl restart mongod



# 몽고셸 접근

mongosh

-------



# admin 데이터베이스 사용

use admin



# (옵션) 사용자 생성

db.createUser( 

    {   user: "doik",

        pwd: "qwe123",

        roles: [ "userAdminAnyDatabase",

        "dbAdminAnyDatabase",

        "readWriteAnyDatabase"] 

    } 

)



# 빠져나오기

exit

-------



# 원격지 접속 1

mongo --host 'host_address' --port 'port'

예) mongo --host 192.10.21.3 --port 27017



# 원격지 접속 2

mongosh mongodb://admin:password@External-IP:27017/database




<4> (참고) resource-capacity - 링크


#

kubectl krew install resource-capacity

kubectl krew list



# 노드 정보

kubectl resource-capacity



## CPU Usage with Sort options

kubectl resource-capacity --sort cpu.limit

kubectl resource-capacity --sort cpu.request

kubectl resource-capacity --sort cpu.util



## Memory Usage with Sort options

kubectl resource-capacity --sort mem.util

kubectl resource-capacity --sort mem.request

kubectl resource-capacity --sort mem.limit



# 파드 정보

kubectl resource-capacity --sort cpu.util --util --pods



# 파드에 컨테이너 정보

kubectl resource-capacity --sort cpu.util --util --pods --containers



# 특정 네임스페이스 내에 정보

kubectl resource-capacity -n kube-system --pods --containers

kubectl resource-capacity -n psmdb --pods

kubectl resource-capacity -n psmdb --pods --containers --sort mem.util  



# Label 필터

# --pod-labels – Pod Level Labels

# --namespace-labels – Labels used at the Namespace Level

# --node-labels – Labels used at the node level

kubectl resource-capacity --node-labels node.kubernetes.io/instance-type=t3a.large



# Output 출력 포맷 : YAML, JSON, TABLE(default)

kubectl resource-capacity -o yaml | head

kubectl resource-capacity -o json | head




<5> 삭제


1

클러스터 삭제


cat cluster2.yaml | sed -e "s/my-cluster-name/$MYNICK/" | kubectl delete -f -

kubectl delete pvc --all && kubectl delete pv --all



2

삭제 방안 : 장점(1줄 명령어로 완전 삭제), 단점(삭제 실행과 완료까지 SSH 세션 유지 필요)


eksctl delete cluster --name $CLUSTER_NAME && aws cloudformation delete-stack --stack-name $CLUSTER_NAME



3

삭제 완료 후 남아 있는 “myeks-dynamic-pvc-##” EC2 볼륨들은 선택 후 삭제 할 것






위 내용은  주말 CloudNet  스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  


다음

https://brunch.co.kr/@topasvga/3528



브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari