몽고디비 샤딩
한글
https://www.youtube.com/watch?si=kaWK1Q704djrl9Ft&v=y42TXZKFfqQ&feature=youtu.be
영어
https://www.youtube.com/watch?v=1sMZ455i1PU&feature=youtu.be
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 }
# 샤딩 활성화를 위해서 샤딩하려는 키에 해시 인덱스를 생성
mongos> db.test.createIndex({"username" : "hashed"})
혹은 인덱스 생성
mongos> db.test.createIndex({"username" : 1})
# 이제 "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()})}
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()
...
# 클러스터 내 모든 샤드 정보 출력
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
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
#
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
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