[컴][db] mongodb 를 production 에서 배포시 확인할 사항

deployment checklist / check list / 체크리스트 /배포전 / 배포 / 몽고db

mongodb 를 production 에서 배포전 확인할 사항

  • unix 계열 os(linux, macOS) 에서 ulimit 의 기본 setting 값을 변경해 줄 필요가 있다.
    • Install MongoDB Community Edition on Red Hat or CentOS — MongoDB Manual
    • UNIX ulimit Settings — MongoDB Manual
    • unix 계열 os 에서는 user 당 또는 process 당 threads, files, network connections 등과 같은 시스템 리소스를 제한하는 방법을 제공한다. ulimit 은 한 user 가 너무 많은 시스템 리소스를 사용하지 않게 막는다. 이것이 너무 낮은 경우 mongodb 의 일반적인 작업 과정동안에 이슈가 발생하게 만들 수 있다.
    • mongodb 4.4 부터는 ulimit 값이 64000 아래면 시작시 error 를 보여준다.
  • mongodb 마다 다른 machine 을 사용
  • 되도록 표준 MongoDB port 인 27017 을 사용
  • 가능하다면, replica set 또는 sharded cluster member 들을 설정할때 ipaddress 대신에 logical DNS hostname 을 사용하자. 그러면 ip address 가 변경돼도, 설정을 다시 하지 않아도 된다.
  • ---bind_ip option 은 MongoDB 가 실행되고 있는 ip address 에 mongodb instance 를 bind 한다고 보면 된다.
    • 3.6 버전 이후부터는 localhost 가 default 이다. --ipv6 옵션이 들어가면, localhost 의 IPv6 주소도 같이 listen 을 하게 된다. localhost 에만 bind 되면, 3.6 binary들은 같은 machine 에서 돌고 있는 clients로 부터 오는 connections 만 받을 수 있다. 외부 client 들은 binary들에 접속할 수 없다.
      다른 ip address 를 bind 하려면, configuration file 에서 net.bindIp를 설정하거나 --bind_ip option 을 사용해서 hostname들이나 ip address 들을 명시할 수 있다. (예: --bind_ip localhost,myhostname2,myhostname1)
    • 참고: MongoDB - Bind_IP Breaking changes and Replica set broken - Server Fault

보안

보안, 설치전 고려해야 할 사항

  • TLS/SSL 사용 : Configure mongod and mongos for TLS/SSL — MongoDB Manual
  • direct ssh root access 를 disable
  • security.clusterIpSourceAllowlist : 이것도 --auth를 사용해야 동작, 원하는 source ip address 나 ip address range 를 적을 수 있다.
  • trusted client 만 mongodb instance 가 사용하는 network interface에 접근가능하도록 한다.
  • db.createUser() 를 할 때 user 의 source ip address 도 정해준다.
  • mongodb 실행시에 dedicated user 계정으로 실행한다. 이 계정은 data 에만 접근할 수 있으면 된다.

계정, 인증

  • role, user 관련 commands : mongosh Methods — MongoDB Manual
  • 기본적으로 community version 에서 2개의 authentication mechanism 들을 제공, 기본값은 SCRAM 이다.
  • role 을 만드는 법
    • MongoDB what are the default user and password? - Stack Overflow
    • Use SCRAM to Authenticate Clients — MongoDB Manual
    • 처음에 user administrator 를 만들고, 추가적인 user 들을 만든다. 각 application 마다 고유한 mongodb 계정을 만들자.
    • role 을 만들때는 least privilege 원리를 따르자.그렇게 role 을 만들고, 각 user 가 필요한 만큼만 assign 해준다. user 는 여러개의 role 을 assign 받을 수 있다.
    • privileges : role 안에 privileges 를 설정하게 되어 있다.
    • database, collection, collection들의 set, cluster 같은 resource 를 적고, 그 resource 에 어떤 action 이 가능한지를 적게 된다.

{
    "roles" : [ 
        {
            "role" : "enableSharding",
            "db" : "userhabit",
            "isBuiltin" : true,
            "roles" : [],
            "inheritedRoles" : [],
            "privileges" : [ 
                {
                    "resource" : {
                        "db" : "",
                        "collection" : ""
                    },
                    "actions" : [ 
                        "enableSharding", 
                        "refineCollectionShardKey", 
                        "reshardCollection"
                    ]
                }
            ],
            "inheritedPrivileges" : [ 
                {
                    "resource" : {
                        "db" : "",
                        "collection" : ""
                    },
                    "actions" : [ 
                        "enableSharding", 
                        "refineCollectionShardKey", 
                        "reshardCollection"
                    ]
                }
            ]
        }, 
        ...
}

user administrator 만드는 법

use admin
db.createUser(
  {
    user: "myUserAdmin",
    pwd: passwordPrompt(), // or cleartext password
    roles: [
      { role: "userAdminAnyDatabase", db: "admin" },
      { role: "readWriteAnyDatabase", db: "admin" }
    ]
  }
)

// permission 을 추가하는 법
use admin
db.grantRolesToUser(
   "myUserAdmin",
   [ { role: "userAdminAnyDatabase", db: "admin" }, 
     { role: "dbAdminAnyDatabase", db: "admin" }, 
     { role: "readWriteAnyDatabase", db: "admin" } ]
)

mongodb 에서 auth 가 동작하도록 하기

이렇게 계정을 만들고 난후 --auth 를 사용하면 된다. --auth 를 사용하면 그때부터 mongodb 에 접속하면, 인증을 하고 사용해야 한다. configuration file을 사용할 수도 있다. (참고)

mongod --auth --port 27017 --dbpath /var/lib/mongodb

또는 configuration file 에 설정을 해줄 수도 있다.

# mongod.conf

...
#processManagement:

security:
  authorization: enabled
...

role 을 확인하는 법


db.runCommand(
    {
      rolesInfo: [
         { role: "associate", db: "products" },
         { role: "manager", db: "resources" }
      ],
      showPrivileges: true,
      showBuiltinRoles: true
    }
)

// role 을 볼 수 있다.
db.runCommand(
    {
      rolesInfo: 1,
      showPrivileges: true,
      showBuiltinRoles: true
    }
)

replica set 에서는 아래처럼 rs.secondaryOk() 를 해줘야 할 수 있다. 이건 session 당 한번 해주면 된다. [ref. 1]

mongo
> rs.secondaryOk()

See Also

  1. 쿠…sal: [컴][db] mongodb replica set 설정 절차
  2. 쿠...sal: [컴][db] mongo db 의 auth 활성화 및 계정 생성
  3. 쿠...sal: [컴][[db] mongodb 의 계정관련 보안 

References

  1. amazon ec2 - mongodb, replicates and error: { "$err" : "not master and slaveOk=false", "code" : 13435 } - Stack Overflow

[컴] SAN 이 없이 GFS2를 사용한다면?

 

SAN 이 없이 GFS2를 사용한다면?

최초의 의문점은 GFS2 를 사용해서 HDD 하나를 여러 pc에서 mount 하도록 하는 것이 과연 의미가 있을까? 였다.

이 궁금증을 풀기전에 먼저 GFS2 가 무엇인가 하면 Red Hat 에서 만든 Shared-disk file system 이다.

이것은 그럼 우리 일반적인 집 pc 에서 사용할 수 있는가?

위의 Hardware 부분을 보면, 아래처럼 그냥 single node filesystem 을 사용할 수도 있지만, 완전한 기능을 사용하려면 SAN(Storage Area Network) 이 지원돼야 한다고 한다.

The design of GFS and of GFS2 targets SAN-like environments. Although it is possible to use them as a single node filesystem, the full feature-set requires a SAN.

wiki 의 Shared-disk file system 설명에서도 shared-disk file system 은 storage area network 를 사용한다고 되어 있다.

A shared-disk file system uses a storage area network (SAN) to allow multiple computers to gain direct disk access at the block level

SAN 에 대한 설명은 다음 link 에서 사진과 함께 글을 읽으면 이해가 쉬울 듯 하다.

결과적으로 local pc 를 single node 로 삼아서 사용은 해볼 수 있을 듯 하다. 하지만 추측컨데 clustered file system 이 아니라면, 여러개의 node들이 동시에 write 를 할 때 병목현상을 피할 수 없을 것 같다. 이유는 아래 글에서 유추해 볼 수 있다.

from : 1.3. Before Setting Up GFS2 Red Hat Enterprise Linux 7 | Red Hat Customer Portal

You may see performance problems with GFS2 when many create and delete operations are issued from more than one node in the same directory at the same time. If this causes performance problems in your system, you should localize file creation and deletions by a node to directories specific to that node as much as possible.

같은 directory 에서 여러 node가 쓰기, 지우기 를 많이 하면 느려진다고 한다. 이것은 아마도 clustered file system 에서 같은 영역의 hw 부분에서 write, delete 가 발생해서 결국 동시에 쓰고, 지우는 것이 hw 의 제한에 걸리기 때문에 느려지는 것이 아닐까 라고 추측해본다.

from : Attach a volume to multiple instances with Amazon EBS Multi-Attach - Amazon Elastic Compute Cloud Standard file systems, such as XFS and EXT4, are not designed to be accessed simultaneously by multiple servers, such as EC2 instances. Using Multi-Attach with a standard file system can result in data corruption or loss, so this is not safe for production workloads. You can use a clustered file system to ensure data resiliency and reliability for production workloads.

결과적으로 사용은 해볼 수 있으나, 큰 의미는 없을 듯 싶다. 결국 gfs2 의 모든 기능을 쓸 수 없다는 건 그냥 일반적인 file system(ext4 같은)을 쓰는 것과 차이가 있을까 궁금하다.

See Also

  1. Chapter 2. GFS2 Configuration and Operational Considerations Red Hat Enterprise Linux 7 | Red Hat Customer Portal

Reference

[컴] CentOS 8 에서 nginx 설치

 

RHEL 8 에서 설치 / nginx

CentOS 8 에서 nginx 설치

copy nginx.repo /etc/yum.repos.d/
dnf install nginx

nginx.repo

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

참고로 RedHat 은 다음 주소를 사용한다.

https://nginx.org/packages/rhel/8/x86_64/

실행 계정 설정

useradd nginx
usermod -s /sbin/nologin nginx

실행

sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl reload nginx
sudo systemctl restart nginx

reload 를 하면, configuration file 를 reload 하면서도 reload 하면서도 nginx 는 계속 살이있다. 만약 config file 의 syntax error 가 있으면, reload 가 abort 되고, 서버는 옛날 config 로 계속 돈다.

그외의 방법은 아래처럼 init.d 를 사용하거나, nginx cli 를 사용하는 것이 있다. 자세한 내용은 ref. 3 에서 볼 수 있다.

sudo /etc/init.d/nginx stop
sudo nginx -s stop

nginx 를 booting 할 때 자동으로 실행 하도록

sudo systemctl enable nginx
sudo systemctl disable nginx

systemctl

기본적으로 nginx.service 가 만들어지지만, 수동으로 만들고 싶다면 다음 방법을 이용하자.

vi /lib/systemd/system/nginx.service

참고로 centos8 에서 가져온 내용이다.

다른 내용은 여기 를 참고하자.

[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"

[Install]
WantedBy=multi-user.target

See Also

  1. CommandLine | NGINX :
    • nginx 가 동작중, 새로운 binary 로 변경하는 법이 나와 있다. 기존의 binary를 새로운 것으로 바꾸고, master process 에 USR2 signal 을 주면 된다고 한다. 자세한 것은 링크를 확인하자.

Reference

  1. Install | NGINX
  2. Install NGINX on Centos 7 Without Internet Connection · GitHub
  3. How to Start, Stop, and Restart Nginx (systemctl & Nginx Commands)

[컴][java] openjdk package 별 설명

 

openjdk package 별 설명

openjdk-8-jre :

  • JRE(java runtime environment)를 구성하는 패키지들, JRE 는 java application 을 실행하는데 필요한 최소한의 요구사항을 제공한다.
  • 구성요소

openjdk-8-jre-headless :

  • openjdk-8-jre 에서 graphical components들과 관련된 dependency 들을 뺀 package이다.

Reference

  1. openjdk - what is the minumim required packages for installing open java 8 - Ask Ubuntu

[컴][os] linux package offline 설치 하는 법

리눅스에서 package를 인터넷 없이 설치하는 법 / 오프라인 설치 / 패키지 다운로드 / package download with dependecies

linux package offline 설치 하는 법

windows10 에서 작업한 내용이다.

centOS 7

이전 centos 7 에서는 아래처럼 yumdownloader 를 사용할 수 있었다.

yumdownloader --assumeyes --destdir=/var/rpm_dir/docker-ce --resolve docker-ce
tar -czvf d4r-k8s.tar.gz /var/rpm_dir

# Upload files
scp d4r-k8s.tar.gz root@YOUR-IP:/root

# Connect to your server
ssh root@YOUR-IP
tar -xzvf /root/d4r-k8s.tar.gz -C /

# install Docker:
yum install -y --cacheonly --disablerepo=* /var/rpm_dir/docker-ce/*.rpm

Dockerfile

docker pull centos:centos8
docker run -d --rm -it --name centos --entrypoint bash -v d:\a\prog\docker\hmsec\rpm_dir:/var/rpm_dir centos:centos8
docker exec -it centos /bin/bash

# 또는 detach 를 하지 않고 아래처럼 바로 접속해도 된다.
docker run --rm -it --name centos --entrypoint bash -v d:\a\prog\docker\hmsec\rpm_dir:/var/rpm_dir centos:centos8

dnf 로 package download

ref. 3 을 보면 dnf 에서 download 하는 법을 알려준다. centos8 부터는 dnf 를 사용해야 한다. centos7 에서는 yumdownloader 를 사용하자.

--resolve option 을 사용하면 dependency 까지 download 할 수 있다.

dnf install 'dnf-command(download)'
dnf download curl --resolve --destdir /var/rpm_dir

만약 repository 를 추가할 일이 있다면, 아래처럼 dnf config-manager 를 이용해서 할 수 있다.

dnf config-manager --add-repo http://nginx.org/packages/centos/8/x86_64/
dnf config-manager --add-repo http://nginx.org/packages/rhel/8/x86_64/

설치

rpm option 관련 설명은 다음 글에 나와 있다.

보통 아래와 같은 명령어로 실행하면 된다.

rpm -ivh package_name_x85_64.rpm

See Also

  1. Linux package management with YUM and RPM | Enable Sysadmin: RHEL 8.x, CentOS8, Fedora 22 부터 기본 package manager 는 DNF(Dandified YUM) 이 되었다고 한다. command 를 사용할 때 yum 대신 dnf 를 사용하면 되는 듯 하다.(ex: dnf install curl)
  2. 쿠…sal: [컴] docker commands
  3. How to install the latest stable Nginx version on CentOS 8? | DigitalOcean : centos8 에서 nginx 최신버전 설치방법
  4. 쿠…sal: [컴] CentOS 8 에서 nginx 설치

References

  1. linux - How to install a rpm package and its dependencies offline - Stack Overflow
  2. Installing Kubernetes and Docker in offline scenarios
  3. How to Download Packages Using Yum/DNF without Installing on Linux

[컴] datamaps.world.js 사용하기

d3로 세계지도 world map / d3 world map / datamaps

datamaps.world.js

아래 예제에서 사용법을 확인하자.

with d3 v5

datamaps 가 나온지 오래됐다. 6년전에 마지막으로 update 되고는 멈췄다. 그래서 최근의 d3 의 함수이름이 바뀌었는데, 그것에 대응되지 못하고 있다.

그래서 간단하게 d3-v5 에서 동작하도록 수정했다. 완전히 동작하는 것은 아니지만 개인적으로 error 가 난 부분만 수정했다.

그래서 아래처럼 사용하면 된다. 주의할 부분은 projection 부분의 string 이 ‘대문자’ 로 시작해야만 한다.

const geo_map = new Datamap({
    scope: 'world',
    element: document.getElementById('container1'),
    projection: 'Mercator', // 'mercator' -> 'Mercator'
    height: 500,
    fills: {
      defaultFill: '#f0af0a',
      lt50: 'rgba(0,244,244,0.9)',
      gt50: 'red'
    },
    
    data: {
      USA: {fillKey: 'lt50' },
      RUS: {fillKey: 'lt50' },
      CAN: {fillKey: 'lt50' },
      BRA: {fillKey: 'gt50' },
      ARG: {fillKey: 'gt50'},
      COL: {fillKey: 'gt50' },
      AUS: {fillKey: 'gt50' },
      ZAF: {fillKey: 'gt50' },
      MAD: {fillKey: 'gt50' }
    })
  },