brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Nov 08. 2023

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

몽고디비 복제

<1> 실습을 위한 터미널 접속 정보

<2> 복제 셋 확인 : 오피로그 확인

<3> 장애 발생 1 및 동작 확인: 강제로 rs0-Y 프라이머리 파드 1개 삭제

<4> 장애 발생 2 : 강제로 프라이머리 파드가 있는 노드를 drain

<5> 장애 발생 3 및 동작 확인 : 강제로 노드 2개를 drain : 직접 테스트

<6> 삭제







<1> 실습을 위한 터미널 접속 정보


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


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



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


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



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


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




<2> 복제 셋 확인 : 오피로그 확인


1


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


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

rs0:PRIMARY>



# 복제 셋 정보 확인 : 구성원 상태 확인


rs0:PRIMARY> rs.status()

rs0:PRIMARY> rs.status()['members']

[

{

"_id" : 0,

"name" : "gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017",

"health" : 1,

"state" : 1,

"stateStr" : "PRIMARY",

"uptime" : 6217,

"optime" : {

"ts" : Timestamp(1654993085, 1),

"t" : NumberLong(1)

},

...



# 복제 셋 정보 확인* : 간략히 확인, 자주 확인하는 명령어


rs0:PRIMARY> db.isMaster()

{

"topologyVersion" : {

"processId" : ObjectId("62a5187aac216c48b5515735"),

"counter" : NumberLong(8)

},

"hosts" : [

"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"

],

"setName" : "rs0",

"setVersion" : 120025,

"ismaster" : true,

...



# 오피로그 정보 확인 : 크기, 연산 시간


rs0:PRIMARY> rs.printReplicationInfo()

configured oplog size:   1794.9248046875MB

log length start to end: 27832secs (7.73hrs)

oplog first event time:  Fri Jun 10 2022 04:23:06 GMT+0000 (UTC)

oplog last event time:   Fri Jun 10 2022 12:06:58 GMT+0000 (UTC)

now:                     Fri Jun 10 2022 12:07:02 GMT+0000 (UTC)



# 동기화 상태 확인 : 세컨더리 구성원이 프라이머리의 어디까지 정보를 동기화했는지 확인


rs0:PRIMARY> rs.printSecondaryReplicationInfo()

source: my-db-psmdb-db-rs0-1.my-db-psmdb-db-rs0.psmdb.svc.cluster.local:27017

syncedTo: Fri Jun 10 2022 01:32:51 GMT+0000 (UTC)

0 secs (0 hrs) behind the primary

source: my-db-psmdb-db-rs0-2.my-db-psmdb-db-rs0.psmdb.svc.cluster.local:27017

syncedTo: Fri Jun 10 2022 01:32:51 GMT+0000 (UTC)

0 secs (0 hrs) behind the primary



# 복제 옵션 정보 확인


rs0:PRIMARY> rs.conf()

{

"_id" : "rs0",    # 복제 세트 이름

"version" : 99912,

"members" : [

{

"_id" : 0,

"host" : "my-db-psmdb-db-rs0-0.my-db-psmdb-db-rs0.psmdb.svc.cluster.local:27017",   # 구성원 호스트

"arbiterOnly" : false,

"buildIndexes" : true,

"hidden" : false,

"priority" : 2,

"tags" : {

"podName" : "my-db-psmdb-db-rs0-0",

"serviceName" : "my-db-psmdb-db"

},

"secondaryDelaySecs" : NumberLong(0),

"votes" : 1

},




2

oplog : 오피로그 상세 확인


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


rs0:PRIMARY> use local

switched to db local



rs0:PRIMARY> db

local



# 오피로그 사이즈 확인

rs0:PRIMARY> db.oplog.rs.stats().maxSize

1882136320



# 오피로그 확인

rs0:PRIMARY> db.oplog.rs.find().limit(2).pretty()

{

"op" : "n",

"ns" : "",

"o" : {

"msg" : "initiating set"

},

"ts" : Timestamp(1654814641, 1),   # 오피로그의 타임스탬프 값, 동기화 기준값으로 중복되지 않음

"v" : NumberLong(2),

"wall" : ISODate("2022-06-09T22:44:01.228Z")

}

{

"op" : "c",   # Operation Type 어떤 종류의 작업 수행, i 삽입, u 수정, d 삭제, c 명령, n 아무 작업도 안함

"ns" : "config.$cmd",   # 이 작업으로 영향ㅂ다은 데이터베이스와 컬렉션

"ui" : UUID("718f318e-1bf2-445e-bf17-dfc5d6e2b987"),

"o" : {

"create" : "transactions",

"idIndex" : {

"v" : 2,

"key" : {

"_id" : 1

},

"name" : "_id_"

}

},

"ts" : Timestamp(1654814641, 3),

"t" : NumberLong(1),              # Primary Term 현재 복제세트에서 몇 번째로 선출된 프라이머리인지 구분하는 값

"v" : NumberLong(2),

"wall" : ISODate("2022-06-09T22:44:01.259Z")

}

...

{

"op" : "i",

"ns" : "admin.system.keys",

"ui" : UUID("b237feb9-2ab1-46c4-92f7-12b91ad5ece8"),

"o" : {

"_id" : NumberLong("7107462145146617861"),

"purpose" : "HMAC",

"key" : BinData(0,"2ynIIoLIe+kzTe7hG6ZhqeNOCFA="),

"expiresAt" : Timestamp(1662610986, 0)

},

"ts" : Timestamp(1654834986, 10),

"t" : NumberLong(1),

"v" : NumberLong(2),

"wall" : ISODate("2022-06-10T04:23:06.051Z")

}



3

복제 테스트* :


 rs0:PRIMARY> rs.status()['members'] 에서 프라이머리 파드 확인해두기



# [터미널1] 프라이머리 파드 접속(doik) : 헤드리스 서비스 주소


mongo db로 접속한다.


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


rs0:PRIMARY> use doik

rs0:PRIMARY> db.test.insertOne({ reptest: 1 })

rs0:PRIMARY> db.test.find()

rs0:PRIMARY> db.test.count()




# [터미널2] 세컨더리 파드1 접속(doik) : 헤드리스 서비스 주소


kubectl exec ds/myclient -it -- bash -il

--------------------------------------

# 변수 지정

MYNICK=<각자 자신의 닉네임>

MYNICK=masterseo


echo $'rs.secondaryOk()\nuse doik\ndb.test.count()' | mongo --quiet "mongodb://doik:qwe123@$MYNICK-rs0-1.$MYNICK-rs0.psmdb.svc/admin?ssl=false"


while true; do echo $'rs.secondaryOk()\nuse doik\ndb.test.count()' | mongo --quiet "mongodb://doik:qwe123@$MYNICK-rs0-1.$MYNICK-rs0.psmdb.svc/admin?ssl=false" | grep -v Error; date; sleep 1; done

--------------------------------------



# [터미널3] 세컨더리 파드2 접속(doik) : 헤드리스 서비스 주소


kubectl exec ds/myclient -it -- bash -il

--------------------------------------


# 변수 지정

MYNICK=<각자 자신의 닉네임>

MYNICK=masterseo


echo $'rs.secondaryOk()\nuse doik\ndb.test.count()' | mongo --quiet "mongodb://doik:qwe123@$MYNICK-rs0-2.$MYNICK-rs0.psmdb.svc/admin?ssl=false"


while true; do echo $'rs.secondaryOk()\nuse doik\ndb.test.count()' | mongo --quiet "mongodb://doik:qwe123@$MYNICK-rs0-2.$MYNICK-rs0.psmdb.svc/admin?ssl=false" | grep -v Error; date; sleep 1; done

--------------------------------------



# [터미널1] 프라이머리 파드 접속(doik) : 대량의 도큐먼트 생성 및 복제 확인


rs0:PRIMARY> for (i=0; i<100; i++) {db.test.insert({count: i, "created_at" : new Date()})}

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

...

Type "it" for more






<3> 장애 발생 1 및 동작 확인: 강제로 rs0-Y 프라이머리 파드 1개 삭제


1

# [터미널3] 세컨더리 파드2 접속(doik) : 헤드리스 서비스 주소


kubectl exec ds/myclient -it -- bash -il

--------------------------------------


# 변수 지정

MYNICK=<각자 자신의 닉네임>

MYNICK=masterseo


echo $'rs.secondaryOk()\nuse doik\ndb.test.count()' | mongo --quiet "mongodb://doik:qwe123@$MYNICK-rs0-2.$MYNICK-rs0.psmdb.svc/admin?ssl=false"

while true; do echo $'rs.secondaryOk()\nuse doik\ndb.test.count()' | mongo --quiet "mongodb://doik:qwe123@$MYNICK-rs0-2.$MYNICK-rs0.psmdb.svc/admin?ssl=false" | grep -v Error; date; sleep 1; done

--------------------------------------



# [터미널1] 모니터링

watch -d "kubectl get psmdb;echo; kubectl get pod,pvc -l app.kubernetes.io/component=mongod -owide"



# [터미널2] 클러스터 접속(CLUSTER_USER) : 프라이머리 파드 확인

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


rs0:PRIMARY> rs.status()['members']

rs0:PRIMARY> db.isMaster()



# 오퍼레이터 로그

kubectl logs -l name=percona-server-mongodb-operator -f



# 프라이머리 파드가 배포 정보 확인

kubectl get pod -l app.kubernetes.io/instance=$MYNICK -owide



# 강제로 rs0-Y 프라이머리 파드 1개 삭제

kubectl delete pod $MYNICK-rs0-0

kubectl delete pod $MYNICK-rs0-1

kubectl delete pod $MYNICK-rs0-2



# [터미널2] 클러스터 접속(CLUSTER_USER) : 프라이머리 파드 확인

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

rs0:PRIMARY> rs.status()['members']

rs0:PRIMARY> db.isMaster()




<4> 장애 발생 2 : 강제로 프라이머리 파드가 있는 노드를 drain



1

# 오퍼레이터 로그

kubectl logs -l name=percona-server-mongodb-operator -f



# [터미널2] 클러스터 접속(CLUSTER_USER) : 프라이머리 파드 확인

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


rs0:PRIMARY> rs.status()['members']

rs0:PRIMARY> db.isMaster()



# 프라이머리 파드가 배포 정보 확인

kubectl get psmdb

kubectl get pod -l app.kubernetes.io/instance=$MYNICK -owide



# 워커노드 drain

# kubectl drain <<노드>> --ignore-daemonsets --delete-emptydir-data

kubectl get node

NODE=<각자 자신의 EC2 노드 이름 지정>

NODE=ip-192-168-3-96.ap-northeast-2.compute.internal

kubectl drain $NODE --delete-emptydir-data --force --ignore-daemonsets && kubectl get node -w



# [터미널1] 클러스터 접속(CLUSTER_USER) : 장애 상태 확인


rs0:PRIMARY> rs.status()['members']

[

{

"_id" : 0,

"name" : "gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017",

"health" : 0,

"state" : 8,

"stateStr" : "(not reachable/healthy)",

"uptime" : 0,

"optime" : {

"ts" : Timestamp(0, 0),

"t" : NumberLong(-1)

},

"optimeDurable" : {

"ts" : Timestamp(0, 0),

"t" : NumberLong(-1)

},

"optimeDate" : ISODate("1970-01-01T00:00:00Z"),

"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),

"lastAppliedWallTime" : ISODate("2022-06-12T01:32:45.665Z"),

"lastDurableWallTime" : ISODate("2022-06-12T01:32:45.665Z"),

"lastHeartbeat" : ISODate("2022-06-12T01:33:37.678Z"),

"lastHeartbeatRecv" : ISODate("2022-06-12T01:32:50.668Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "Error connecting to gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017 :: caused by :: Could not find address for gasida-db-rs0-0.gasida-db-rs0.psmdb.svc.cluster.local:27017: SocketException: Host not found (authoritative)",

"syncSourceHost" : "",

"syncSourceId" : -1,

"infoMessage" : "",

"configVersion" : 120025,

"configTerm" : -1

},



# 동작 확인 후 uncordon 설정

kubectl get psmdb

kubectl uncordon $NODE




<5> 장애 발생 3 및 동작 확인 : 강제로 노드 2개를 drain : 직접 테스트


1대만 정상일경우

insert 됨?

read 가능?




<6> 삭제


kubectl delete psmdb $MYNICK 삭제 후 1분 정도 후 입력 ⇒ 

kubectl delete pvc -l app.kubernetes.io/instance=$MYNICK





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

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



다음

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


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