처음 DB를 접한것은 학생이던 시절(?) 오라클이었던가
어떤 서버에 접속해서 알수 없는 명령을 내려서 테이블 만들고
테이블에 데이터 입력하고, 삭제하고 .. (CRUD)

그 후 본격적(현업?)으로 써보기 시작한 것은 MySQL 이었던것 같다.
스타트업에 있었던 터라 본의(?) 아니게 그랬던것인지, 오픈소스라는 매력, 오라클에 대한 반감 등 여러요소가 있었던 것 같다.

그러다가 MySQL 이 오라클로 넘어가는 사건이 발생한다.
그 후로는 MariaDB 를 사용하게 되었다.
그 사이 서비스에 사용하는 MySQL 을 PgSQL 에 호환되도록 코드를 리팩토링해서 어! 잘 작동하네 정도로 postgre 를 써본 경험정도

그래서 postgres 에 대한 역사는 드문드문 아는정도
(역사 요약은 여기서 https://news.hada.io/topic?id=10344 )

 

Postgres는 언제부터 멋있어졌을까 | GeekNews

VC 펀딩도, DevRel 팀도 없이 25년간 천천히 진화함Ingres(UC 버클리, 1970~1985) —> Postgres95 —> PostgreSQLPostgres = "Post Ingres"첫 언어는 SQL도 아닌 QUEL 이었음. SQL 지원은 Postgres95가 출시된 1995년에 추가됨1996

news.hada.io

읽다보면, 드문드문 아! 그랬었지 라는 기억이 난다.

...

언제부터인가 MongoDB 를 필두로 NoSQL 이 유행하던 때 도 있었다.

사실 요즘은 어떤게 핫한지 잘 모른다. 이미 핫했지만, 이제서야 알게 된 것일지도 모르겠다.
아! 요즘 언어로는 힙한 postgres 인가!

DB 관련에는 어떤것들이 있나! https://news.hada.io/topic?id=16365 에서 살펴볼수 있다.

 

그냥 Postgres 쓰세요 | GeekNews

대부분의 웹 애플리케이션은 지속적인 데이터 저장이 필요하므로, 새로운 애플리케이션을 만들 때 기본적으로 Postgres를 선택하는 것이 좋음왜 sqlite가 아닌가?sqlite는 좋은 DB지만, 데이터가 하나

news.hada.io

사실 한가지에 익숙하다보면, 모든 것을 그 하나로 처리하고 싶은 욕구가 본능인듯 싶다.
나도 MySQL 을 NoSQL 처럼 사용하려 json 타입으로 만들어 사용하기도 한다.

왜! 지금 postgres 에 관심을 갖는지는 사실 supabase 라는 서비스에 있다. https://supabase.com/
요즘 구글 Firebase 대항마(?)로 뜨고 있는 서비스이다.(나온지 얼마되지 않은 듯 한데...)

 

Supabase | The Open Source Firebase Alternative

Build production-grade applications with a Postgres database, Authentication, instant APIs, Realtime, Functions, Storage and Vector embeddings. Start for free.

supabase.com

이 supabase 가 postgres 기반이라고 한다.
서비스지만, 오픈소스 기반이라 종속되지 않고, 서비스를 이용하다가, 본인서버로 마이그레이션 할수도 있는 듯 하다
물론 그정도로 서비스가 커져야 겠지만.

앱을 만들면서 supabase 를 쓰게 될 듯 하다.
돌아돌아 다시 만나게 된 postgres

이번에는 오래 쓰게 될지, 또 다시 찍먹하고 MySQL 으로 돌아갈지, 같이 쓸지는 모르겠다.

기억에 남기기 위해 포스팅 해본다.

postgres 로 할 수 있는 것들 - https://news.hada.io/topic?id=13231

 

PostgreSQL로 충분하다 | GeekNews

PostgreSQL을 각 분야에 사용하는 방법에 대한 링크를 정리한 페이지백그라운드잡, 메시지 큐, GIS, Audit Log, 접근 제어, 권한 관리, 검색, 시계열, 그래프 데이터, 외부 데이터, HTTP, API, 이벤트/복제/CD

news.hada.io

 

반응형

WRITTEN BY
1day1
하루하루 즐거운일 하나씩, 행복한일 하나씩 만들어 가요.

,

몽고db 데이터를 이전하기 위해 mongodump / mongorestore 로 백업 / 복구 하였다.

그런데, 원래 그런지, 어떤 설정이 있는 것인지 인덱스 가 생성되지 않았다.
> ( 기본은 인덱스가 재 생성 되는 듯 한데, --noIndexRestore 을 주면 인덱스 미생성 )

dump / restore 중에 뭔가 이상이 있는 것인가?  또는 --gzip / --archive 옵션으로 하면 생성이 안되는 것일까?

정확한 이유는 체크해봐야 할 듯 하다.

암튼 그래서 createIndex 로 생성하려하는데, 다음과 같은 에러가 발생하였다.

2020-04-18T06:14:45.987+0000 I  NETWORK  [js] DBClientConnection failed to receive message from 127.0.0.1:27017 - HostUnreachable: Connection closed by peer
command terminated with exit code 137

몽고db - POD 에 접속을 못하는 듯 하다. 좀더 체크해보니 인덱스 생성도중에 mongod POD 가 중지 Down 되어 버린다.

해당 이슈에 대한 검색으로는 특별한 원인을 찾지 못했다. 몽고db 리플리카 셋은 kubernetes(microk8s) 로 세팅하였다.

예상되는 부분은  restore 과정중에 뭔가 데이터가 깨진것이 아닌가 예상이 된다.
그래서 pvc 를 삭제하면, 리플리카 셋이 자동으로 재생성(초기화) 되면서 pod 가 재실행되도록 하였다.

위 조치로 해결이 되었다. (일단 예상은 맞는 듯 하다)

그런데, 근본적인 작업이었던  백업 / 복구 방식이 문제였을까? ( mongodump => mongorestore )

그냥 데이터 디렉토리를 그대로 복사하는 방법으로 해야할까? 좀더 테스트를 해봐야 겠다.

[추가]

좀더 체크해보니, mongorestore 메시지에 이상이 있었다. (몽고db - pod 가 이상이 있어서 인덱스 생성 실패 케이스)

[정상]

2020-04-20T00:16:08.550+0900	restoring indexes for collection test.product from metadata
2020-04-20T00:19:35.655+0900	finished restoring test.product (5522171 documents, 0 failures)
2020-04-20T00:19:35.655+0900	restoring users from archive '/restore/restore/restore-archive.gz'
2020-04-20T00:19:35.881+0900	5522171 document(s) restored successfully. 0 document(s) failed to restore.

[이상있는 경우]
2020-04-18T07:11:49.926+0900	restoring indexes for collection test.product from metadata
2020-04-18T07:12:44.169+0900	finished restoring test.product (5522171 documents, 0 failures)
2020-04-18T07:12:44.170+0900	Failed: test.product: error creating indexes for test.product: createIndex error: connection(mongod-2.mongodb-service:27017[-11]) incomplete read of message header: EOF
2020-04-18T07:12:44.170+0900	5522171 document(s) restored successfully. 0 document(s) failed to restore.

 

반응형

WRITTEN BY
1day1
하루하루 즐거운일 하나씩, 행복한일 하나씩 만들어 가요.

,

지난번 kubernetes 에서 mongodb replica set 세팅 하는 방법을 정리했다. ( https://blog.1day1.org/598 )

그런데, 이제 mongo db 내부에서 replica set 을 설정한다.

(kube => pod 접속)
$ kubectl exec -ti mongod-0 -c mongod-container bash
   or
$ kubectl exec -ti mongod-0 -- bash

(pod 내에서 mongo console 실행)
# mongo

처음에는 다음처럼 나온다.

rs.status()
{
	"ok" : 0,
	"errmsg" : "no replset config has been received",
	"code" : 94,
	"codeName" : "NotYetInitialized"
}

리플리카 셋을 설정한다.

config = {_id: "MainRepSet", version: 1, members: [
       { _id: 0, host : "mongod-0.mongodb-service:27017" },
       { _id: 1, host : "mongod-1.mongodb-service:27017" },
       { _id: 2, host : "mongod-2.mongodb-service:27017" },
       { _id: 3, host : "mongod-3.mongodb-service:27017" }
 ]}
 rs.initiate(config)

초기 설정 후 관리계정을 만들어 준다.

use admin
db.createUser({user:"admin",pwd:passwordPrompt(),roles:[{role:"root",db:"admin"}]})

(사용은)
db.getSiblingDB('admin').auth("admin", passwordPrompt())

(수정)
db.updateUser("admin", {pwd:passwordPrompt()})

정상 세팅은 다음 처럼 나온다.

더보기

MainRepSet:PRIMARY> rs.status()
{
"set" : "MainRepSet",
"date" : ISODate("2020-02-20T08:39:06.434Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 3,
"writeMajorityCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2020-02-20T08:39:02.691Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"readConcernMajorityWallTime" : ISODate("2020-02-20T08:39:02.691Z"),
"appliedOpTime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2020-02-20T08:39:02.691Z"),
"lastDurableWallTime" : ISODate("2020-02-20T08:39:02.691Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1582187912, 3),
"lastStableCheckpointTimestamp" : Timestamp(1582187912, 3),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2020-02-20T08:38:32.108Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1582187901, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 3,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2020-02-20T08:38:32.690Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2020-02-20T08:38:33.290Z")
},
"members" : [
{
"_id" : 0,
"name" : "mongod-0.mongodb-service:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 805,
"optime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-02-20T08:39:02Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1582187912, 1),
"electionDate" : ISODate("2020-02-20T08:38:32Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "mongod-1.mongodb-service:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 44,
"optime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-02-20T08:39:02Z"),
"optimeDurableDate" : ISODate("2020-02-20T08:39:02Z"),
"lastHeartbeat" : ISODate("2020-02-20T08:39:06.193Z"),
"lastHeartbeatRecv" : ISODate("2020-02-20T08:39:05.256Z"),
"pingMs" : NumberLong(1),
"lastHeartbeatMessage" : "",
"syncingTo" : "mongod-0.mongodb-service:27017",
"syncSourceHost" : "mongod-0.mongodb-service:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "mongod-2.mongodb-service:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 44,
"optime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-02-20T08:39:02Z"),
"optimeDurableDate" : ISODate("2020-02-20T08:39:02Z"),
"lastHeartbeat" : ISODate("2020-02-20T08:39:06.187Z"),
"lastHeartbeatRecv" : ISODate("2020-02-20T08:39:05.581Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "mongod-0.mongodb-service:27017",
"syncSourceHost" : "mongod-0.mongodb-service:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "mongod-3.mongodb-service:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 44,
"optime" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1582187942, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-02-20T08:39:02Z"),
"optimeDurableDate" : ISODate("2020-02-20T08:39:02Z"),
"lastHeartbeat" : ISODate("2020-02-20T08:39:06.201Z"),
"lastHeartbeatRecv" : ISODate("2020-02-20T08:39:05.256Z"),
"pingMs" : NumberLong(1),
"lastHeartbeatMessage" : "",
"syncingTo" : "mongod-0.mongodb-service:27017",
"syncSourceHost" : "mongod-0.mongodb-service:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1582187942, 1),
"signature" : {
"hash" : BinData(0,"pHhOTNJaI3y8hvPOpgcOs9zJ7I8="),
"keyId" : NumberLong("6795445338166525955")
}
},
"operationTime" : Timestamp(1582187942, 1)
}


이후에 primary 에서 데이터를 등록하면 secondary 에 반영된다.

kubernetes 에서  delete / apply 등으로 새로 세팅하거나 했을때 기존 설정이 정상 동작 하지 않는 경우.
Primary 가 없거나 하는 경우.

Our replica set config is invalid or we are not a member of it

설정을 재등록(?) 해준다. 

conf = rs.conf()
rs.reconfig(conf, {force:true})

 

[추가] 몇몇 주요 명령

1. replica set 추가

rs.add("mongod-3.mongodb-service:27017")

2. sync 상태 보기

PRIMARY> rs.printSlaveReplicationInfo()

source: mongod-1.mongodb-service:27017
	syncedTo: Fri Feb 28 2020 02:56:26 GMT+0000 (UTC)
	0 secs (0 hrs) behind the primary 
source: mongod-2.mongodb-service:27017
	syncedTo: Fri Feb 28 2020 02:56:26 GMT+0000 (UTC)
	0 secs (0 hrs) behind the primary 
source: mongod-3.mongodb-service:27017
	syncedTo: Fri Feb 28 2020 02:56:26 GMT+0000 (UTC)
	0 secs (0 hrs) behind the primary 

3. 특정노드 에러메시지 (해결책 - 찾는 중)

PRIMARY> rs.status()
..
"stateStr" : "(not reachable/healthy)",
..
"lastHeartbeatMessage" : "Our replica set configuration is invalid or does not include us",
..

PRIMARY> rs.printSlaveReplicationInfo()
...
...
source: mongod-0.mongodb-service:27017
	syncedTo: Thu Jan 01 1970 00:00:00 GMT+0000 (UTC)
	1584736418 secs (440204.56 hrs) behind the primary 

원인이 뭘까? 특별히 비정상 종료 같은 것은 없던 것 같은데. config 서버를 따로 두지 않는 문제일까?

  해결책 1) 해당 pvc / pod 를 삭제한다 => 쿠버네티스 가 알아서 재가동 하면서 정상 처리 된다. (옳은 방법인지는 의문)

kubectl delete pvc mongodb-persistent-storage-claim-mongod-0
kubectl delete pod/mongod-0

 

 

 

반응형

WRITTEN BY
1day1
하루하루 즐거운일 하나씩, 행복한일 하나씩 만들어 가요.

,

몽고디비를 서비스에 도입해보려고 테스트 중이다.

여러가지 설치 방법이 있지만, 쿠버네티스 를 활용해서 하려한다.

1. microk8s 를 설치한다.
https://microk8s.io/docs/ 설치방법은 너무 쉽다.
몇몇 서비스를 활성화 시킨다.

microk8s.enable dns storage ingress registry

 

microk8s.kubectl 은 링크걸어두면 편하다.

sudo ln -s microk8s.kubectl /snap/bin/kubectl

or

sudo snap alias microk8s.kubectl kubectl

 

2. 몽고디비 replica set 설정을 사용한다.
https://maruftuhin.com/blog/mongodb-replica-set-on-kubernetes/ 의 설정을 참조

$ openssl rand -base64 741 > ./replica-set-key.txt
$ kubectl create secret generic shared-bootstrap-data \
  --from-file=internal-auth-mongodb-keyfile=./replica-set-key.txt

3. 설정을 사용해 몽고디비를 가동한다.

kubectl apply -f replica-sets/mongodb-rc.yaml

다음과 같은 명령으로 상황을 모니터링 하면 좋다.

kubectl get all -o wide
kubectl get pvc -o wide
kubectl get nodes -o wide

정상적으로 실행되지 않고, pending 으로 시간이 걸린다면, 삭제했다가 다시 실행해본다.

(전체 삭제)
kubectl delete -f replica-sets/mongodb-rc.yaml

(pvc 삭제)
kubectl delete pvc mongodb-persistent-storage-claim-mongod-0

 

정상적이라면 다음처럼 나온다.

kubectl get pods -o wide

NAME       READY   STATUS    RESTARTS   AGE     IP            NODE            
mongod-0   1/1     Running   0          6m45s   10.1.32.109   192.168.77.20   
mongod-1   1/1     Running   0          6m43s   10.1.70.10    kube-mk8s       
mongod-2   1/1     Running   0          6m42s   10.1.32.110   192.168.77.20   
mongod-3   1/1     Running   0          6m41s   10.1.70.11    kube-mk8s       

 

4. mongo 접속하여 replica set 설정한다. (세부 설정은 별도로 정리 예정)

(kube => pod 접속)
kubectl exec -ti mongod-0 -c mongod-container bash

(pod 내에서 mongo console 실행)
mongo

 

해당 replica set 의 몽고 서버에 접속하기 위해 dns 설정이 잘 되었는지 확인해본다.

kubectl apply -f https://k8s.io/examples/admin/dns/busybox.yaml
kubectl exec -ti busybox -- nslookup mongod-0.mongodb-service

설정을 확인해서 정상적으로 pod IP 가 나와야 한다.

이런식으로 나오면 실패.

Server:    127.0.0.53
Address 1: 127.0.0.53

nslookup: can't resolve 'mongod-0.mongodb-service'

아래처럼 나와야 정상.

Server:    10.152.183.10
Address 1: 10.152.183.10 kube-dns.kube-system.svc.cluster.local

Name:      mongod-0.mongodb-service
Address 1: 10.1.32.109 mongod-0.mongodb-service.default.svc.cluster.local

 

 

[추가]

혹시 microk8s 설치시 다음과 같은 메시지나 나오고 진행이 안된다면.

error: too early for operation, device not yet seeded or device model not acknowledged

snapd 를 삭제했다가 다시 설치해본다.

sudo apt purge snapd
sudo apt install snapd
반응형

WRITTEN BY
1day1
하루하루 즐거운일 하나씩, 행복한일 하나씩 만들어 가요.

,