MeteorJS、Nginx、mongodb、iptables ...生産

こんにちは、私の名前はAlexander Zeleninで、私は ウェブ開発者 システム管理者。







残念ながら、MeteorJSでのアプリケーションの完全な展開に関するすべての情報はかなり散在しており、100万のタスクを手動で解決する必要があります。 この記事では、最も基本的な(ただし実稼働環境での安全な作業にはすでに十分な)サーバー構成と、その後の手動展開のプロセスを分析します。







Ubuntu 16に展開しますが、一般的に、スキームはDebian 8でも99%同じです。







実際、私はシステム管理者の近くにいないので、提案された変更には非常に満足していますが、一般的にこのスキームは非常に機能しています。







インストール中にファイルシステムとしてXFSを選択します-MongaはXFSの良い友達です。







クッキングSSH

ルートアクセスがある場合は、最初にユーザーを作成します。







adduser zav #   %username%  zav apt-get install sudo usermod -aG sudo zav #      sudo, #       -  vi /etc/ssh/sshd_config #       vi —   nano  vi. #     — apt-get install nano
      
      





ポートを任意のランダムに変更する必要があります-これにより、sshサーバーへの攻撃の一部から即座に保護されます。







 Port 355 #    Port 22 PermitRootLogin no #    
      
      





SSHを再起動する







 /etc/init.d/ssh restart
      
      





次に、SSHを介して新しいポート(355)に、新しく作成された新しいユーザーに再接続します。







2番目のディスクとtmpfsを準備します(monguをメモリに配置するため)

障害の可能性を最小限に抑えるために、2つの個別の物理ディスクを使用します。

あなたはすべて自分の危険とリスクで1に置くことができます、これからのスキームは変わりません。

この場合、同じように/ secondaryフォルダーを使用できますが、ディスクをマウントしないでください。







 sudo cfdisk /dev/sdb #    (sdb)  . #   , 100% ,  sudo mkfs.xfs /dev/sdb1 #      sudo mkdir /secondary sudo vi /etc/fstab #  -   
      
      





最後に追加(2番目のディスクがない場合-最初の行を省略)

tmpfs-ファイルシステムはRAMに配置されます。 つまり / data / inmemoryセクションへの書き込みは、ディスクではなくRAMに書き込みます。 再起動するとクリアされることを理解しておく必要があります。 sizeは、この領域のサイズを設定します。 あなたの仕事は、すべてのインデックスでモンガを配置するだけで十分だということです。 私の場合、RAMは128Gbで、それぞれ32ギガバイトがtmpfsに割り当てられています。







 /dev/sdb1 /secondary xfs defaults 0 2 tmpfs /data/inmemory tmpfs size=25% 0 0
      
      





monguを配置し、レプリカをセットアップし、リアルタイムバックアップを準備します

現在のインストール方法は、公式Webサイトで見つけることができます。

この例では、バージョン3.4がUbuntu 16にインストールされています。







インストール:







 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list sudo apt-get update sudo apt-get install mongodb-org
      
      





フォルダー、構成を作成し、権限を設定します。







 sudo mkdir /data sudo mkdir /data/db sudo mkdir /data/inmemory sudo mkdir /secondary/data sudo mkdir /secondary/data/db sudo vi /data/mongod-memory.conf
      
      





メモリ内のプライマリが危険になる可能性があるアプローチ 突然の停電の場合、レプリカに切り替える時間がなかったデータは失われます。 私の場合、1〜2秒の損失はひどいものではありません。 すべてのポジションからの回復の可能性を考慮して、アプリケーション全体が記述されます。 財務データは、データがすでにレプリカ上(ディスク上)にあることを確認するパラメーターを使用して書き込まれます。

アプリケーションの準備が整っていない場合は、メモリセクションを拒否して、すべてを古典的に行うことができます。 一般に、これにはtmpfsマウントを削除し、構成をわずかに変更するだけで十分で、mongod-sec-d1.confに似たものになります。







mongod-memory.conf-プライマリ、メモリ内
 processManagement: fork: true pidFilePath: "/data/inmemory/mongod.pid" storage: dbPath: "/data/inmemory" journal: enabled: false #   # ..            indexBuildRetry: true wiredTiger: engineConfig: cacheSizeGB: 8 #   . # ,  ,  ,     , # ..  ,      #   ,        systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" #      . #     , #       #  ,     #    (,  ) logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 127.0.0.1 #        #  ,     —    port: 27000 # ,     , #           http: enabled: false #    http    JSONPEnabled: false RESTInterfaceEnabled: false ssl: # ssl        mode: disabled security: #       , #    ,    authorization: "enabled" keyFile: "/data/mongod-keyfile" #        javascriptEnabled: false #   JS  . replication: oplogSizeMB: 4096 #    oplog'. #         #          oplog'a. #     #     —     ? replSetName: "consulwar" enableMajorityReadConcern: false # ,      #        . operationProfiling: slowOpThresholdMs: 30 # ,     , #      #         mode: "slowOp"
      
      





 sudo vi /data/mongod-sec-d1.conf
      
      





mongod-sec-d1.conf-セカンダリ、ディスク1

ほとんどの場合、設定が繰り返されますが、違いはほんの数箇所です。

しかし、便宜のために出発







 processManagement: fork: true pidFilePath: "/data/db/mongod.pid" storage: dbPath: "/data/db" journal: enabled: true #  ,     , #       indexBuildRetry: true wiredTiger: engineConfig: cacheSizeGB: 8 # ,    -  Primary , # secondary   ,     systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 127.0.0.1 port: 27001 http: enabled: false JSONPEnabled: false RESTInterfaceEnabled: false ssl: mode: disabled security: authorization: "enabled" keyFile: "/data/mongod-keyfile" javascriptEnabled: false replication: oplogSizeMB: 4096 replSetName: "consulwar" enableMajorityReadConcern: false operationProfiling: slowOpThresholdMs: 30 mode: "slowOp"
      
      





 sudo vi /data/mongod-sec-d2.conf
      
      





mongod-sec-d2.conf-セカンダリ、ディスク2

実際、違いはデータベースへの道だけで、使用するポートに依存します。







 processManagement: fork: true pidFilePath: "/secondary/data/db/mongod.pid" storage: dbPath: "/secondary/data/db" journal: enabled: true indexBuildRetry: true wiredTiger: engineConfig: cacheSizeGB: 8 systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 127.0.0.1 port: 27002 http: enabled: false JSONPEnabled: false RESTInterfaceEnabled: false ssl: mode: disabled security: authorization: "enabled" keyFile: "/data/mongod-keyfile" javascriptEnabled: false replication: oplogSizeMB: 4096 replSetName: "consulwar" enableMajorityReadConcern: false operationProfiling: slowOpThresholdMs: 30 mode: "slowOp"
      
      





レプリカが正しく機能するようにキーを追加し、フォルダーのアクセス許可を設定します







 sudo openssl rand -base64 741 > ~/mongod-keyfile sudo mv mongod-keyfile /data/mongod-keyfile sudo chmod 600 /data/mongod-keyfile sudo chown mongodb:mongodb -R /data sudo chown mongodb:mongodb -R /secondary/data
      
      





起動スクリプトを作成する







 sudo apt-get install numactl sudo mv /lib/systemd/system/mongod.service /lib/systemd/system/mongod@.service sudo vi /lib/systemd/system/mongod@.service
      
      





mongod @ .service

サービス名の@は、パラメーターを使用して実行できることを意味します。

このスクリプトは、mongaを操作するために必要なすべてのOSパラメーターを設定します-便利です。







 [Unit] Description= Mongo Database on %i After=network.target [Service] Type=forking ExecStartPre=/bin/sh -c '/bin/echo never > /sys/kernel/mm/transparent_hugepage/enabled' ExecStartPre=/bin/sh -c '/bin/echo never > /sys/kernel/mm/transparent_hugepage/defrag' User=mongodb Group=mongodb PermissionsStartOnly=true ExecStart=/usr/bin/numactl --interleave=all /usr/bin/mongod --config /data/mongod-%i.conf LimitFSIZE=infinity LimitCPU=infinity LimitAS=infinity LimitNOFILE=64000 LimitNPROC=64000 TasksMax=infinity TasksAccounting=false [Install] WantedBy=multi-user.target
      
      





システムの起動時にデータベースを起動するように指示し、今すぐインスタンスを起動します。

パラメータは@の後に設定されます。たとえば、メモリは起動時に/data/mongod-memory.confを使用することを示します







 sudo systemctl enable mongod@memory sudo systemctl enable mongod@sec-d1 sudo systemctl enable mongod@sec-d2 sudo service start mongod@memory sudo service start mongod@sec-d1 sudo service start mongod@sec-d2
      
      





mongaに接続し、レプリカを初期化し、ユーザーを確立します







 mongo localhost:27000/admin
      
      





コンソールモンガで実施







 rs.initiate({ _id: "consulwar", //   version: 1, protocolVersion: 1, writeConcernMajorityJournalDefault: false, //      //      configsvr: false, // ,        // ( —   ) members: [ { _id: 0, // id       host: 'localhost:27000', //       arbiterOnly: false, //       buildIndexes: true, // ,     hidden: false, //  , ..      priority: 100, //    Primary —  ,   slaveDelay: 0, //  .    . votes: 1 //      Primary }, { _id: 1, host: 'localhost:27001', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 99, //   slaveDelay: 0, votes: 1 }, { _id: 2, host: 'localhost:27002', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 98, slaveDelay: 0, votes: 1 } ], settings: { chainingAllowed : true, //      ,      electionTimeoutMillis : 5000, //    , //      . ~7 . //       1  //    500,  catchUpTimeoutMillis : 2000 } }); //   ,     root' db.createUser({user: 'zav', pwd: '7Am9859dcb82jJh', roles: ['root']}); //  - ctrl+c, ctrl+c
      
      





ユーザーの下に接続します







 mongo localhost:27000/admin -u zav -p '7Am9859dcb82jJh' --authenticationDatabase admin
      
      





アプリケーションを操作するユーザーを追加します







 use consulwar //  consulwar      db.createUser({ user: 'consulwar', pwd: '37q4Re7m432dtDq', roles: [{ //        . //    ,     .. role: "readWrite", db: "consulwar" }, { //    oplog',      role: 'read', db: 'local' }] });
      
      





現在、かなり重要で難しい質問は、バックアップ用のリアルタイムレプリケーションです。 この記事では避けたいいくつかの機器を設定する必要があるため、完全には考慮されません。







リアルタイムバックアップのセットアップ

外部サーバーに複製します(それ以外の場合、バックアップのポイントは何ですか?:-))。

Mongaは同様の方法で外部サーバーにインストールする必要があります。

おおよその構成:







mongod-backup.conf
 processManagement: fork: true pidFilePath: "/data/db/mongod.pid" storage: dbPath: "/data/db" journal: enabled: true indexBuildRetry: false #    wiredTiger: engineConfig: cacheSizeGB: 0 #   systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 222.222.222.222 #       port: 27000 http: enabled: false #    http,   JSONPEnabled: false RESTInterfaceEnabled: false ssl: mode: disabled security: authorization: "enabled" keyFile: "/data/mongod-keyfile" # mongod-keyfile     javascriptEnabled: false replication: oplogSizeMB: 0 replSetName: "consulwar" enableMajorityReadConcern: false operationProfiling: mode: "off" #      
      
      





バックアップサーバーのファイアウォールでは、アプリケーションサーバー/データベースのIPからのみ27000ポートへの接続を許可します。

同じこと-bindIpのアプリケーション/データベースサーバーでは、外部インターフェイス(外部サーバーのIP)を確認するように指示し、iptablesでは、バックアップ北IPからのみ27000-27002ポートへのアクセスを許可します。







レプリカを初期化/再初期化するとき、追加します







 { _id: 4, host: '222.222.222.222:27000', //  ,     arbiterOnly: false, buildIndexes: false, //       hidden: true, // !      priority: 0, //     slaveDelay: 0, //     , //   ,       " " votes: 0 //     }
      
      





できた! これで、データは外部バックアップにもリアルタイムで注入されます。これは非常に便利です。

アプリケーションが完全にクラッシュした場合、同じ方法でレプリカを初期化でき、バックアップから回復します。

私を信じて、これはmongodump / mongorestoreよりもはるかに高速です(個人的な推定によると、25〜100倍)。







Nodejs、npm、アプリユーザー、meteorビルド

ノードをインストールし、モジュールnを配置し、ノード4.8.1のバージョン(流星によって公式にサポートされている最後のバージョン)を配置します。

pm2をインストールする プロセスを開始します。







 sudo apt-get install nodejs sudo apt-get install npm sudo npm install -gn sudo n 4.8.1 sudo npm install pm2@latest -g
      
      





すべてを開始し、展開を担当するユーザーを追加します







 sudo adduser consulwar
      
      





このユーザーのために行きます







 su consulwar mkdir app mkdir app/current
      
      





ローカルマシンで、meteorプロジェクトのあるディレクトリに移動します。

ビルド用のフォルダーを作成し、このフォルダーにプロジェクトを収集します。







 mkdir ../build meteor build ../build/ --architecture os.linux.x86_64
      
      





結果のアーカイブは、たとえばsftp経由でサーバーにアップロードされます。 アプリケーションのユーザーの下に移動します。

〜/ appフォルダーにダウンロードします。

ユーザーのためにsshでアクセスします(私は執政官です)。







 cd app mkdir 20170429 #      tar -xvzf consulwar-master.tar.gz -C 20170429 ln -s 20170429/bundle ~/app/current #  ,    (cd current/programs/server && npm install) vi pm2.config.js #     pm2
      
      





pm2.config.js
 var settings = { ... }; //     settings.json   var instances = 10; //   ?    N-1 //  N —   var apps = []; for (var i = 0; i < instances; i++) { apps.push({ "script": "/home/consulwar/app/current/bundle/main.js", //    "exec_mode": "fork", // ..    Nginx,   "name": "consulwar", //      "env": { "ROOT_URL": "http://consulwar.ru/", //   "HTTP_FORWARDED_COUNT": 1, //      //    IP    "PORT": 3000 + i, //    3000 (3000, 3001, 3002...) "MONGO_URL": "mongodb://consulwar:37q4Re7m432dtDq@localhost:27000,localhost:27001,localhost:27002/consulwar?replicaSet=consulwar&readPreference=primary&authSource=consulwar", "MONGO_OPLOG_URL": "mongodb://consulwar:37q4Re7m432dtDq@localhost:27000,clocalhost:27001,localhost:27002/local?replicaSet=consulwar&authSource=consulwar", "METEOR_SETTINGS": settings } }); } module.exports = { apps : apps }
      
      





そして走る







 pm2 startup pm2.js #  ,        ... #   pm2 start pm2.js pm2 status # ,   .      pm2 logs
      
      





完了、アプリケーションはデプロイされており、ポート付きのサーバーIP /アドレスで既に使用可能になっている必要があります(例:http://consulwar.ruhaps000)







Nginxバランシング
 sudo apt-get install software-properties-common sudo add-apt-repository ppa:nginx/stable sudo apt-get install nginx sudo vi /etc/nginx/nginx.conf
      
      





nginx.conf
 user www-data; # -   nginx worker_processes 6; #    worker_rlimit_nofile 65535; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 4000; # -    #       6 * 4000 = 24 000  #    } http { map $http_upgrade $connection_upgrade { #    - default upgrade; '' close; } include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; server_tokens off; sendfile on; #    tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; gzip on; #  gzip gzip_comp_level 6; gzip_vary on; gzip_proxied any; gzip_buffers 16 8k; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; gzip_static on; #     .gz  . , main.js.gz     main.js gzip_http_version 1.1; gzip_disable "MSIE [1-6]\.(?!.*SV1)" proxy_connect_timeout 60; proxy_read_timeout 620; proxy_send_timeout 320; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; upstream backends { #ip_hash; # ,                least_conn; #  ,       #     #    10,   10  server 127.0.0.1:3000 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3001 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3002 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3003 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3004 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3005 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3006 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3007 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3008 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3009 weight=5 max_fails=3 fail_timeout=60; # ,        server 127.0.0.1:3100 backup; } #    ssl .      ssl_certificate /etc/letsencrypt/live/consulwar.ru/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/consulwar.ru/privkey.pem; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_stapling on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!EXP:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; server { server_name consulwar.ru; #   80  443  listen 80; listen 443 ssl http2; #         location / { proxy_pass http://backends; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-For $remote_addr; } #     nginx location ~* \.(jpg|jpeg|gif|ico|png)$ { root /home/consulwar/app/current/programs/web.browser/app; } #  css  js   ,    location ~* "^/[a-z0-9]{40}\.(css|js)$" { root /home/consulwar/app/current/programs/web.browser; } location ~ "^/packages" { root /home/consulwar/app/current/programs/web.browser; } #  ,        , #    . location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all; } #   SSL  location ~ "^/.well-known" { root /home/consulwar/app/current/programs/web.browser/app/.well-known; } } include /etc/nginx/conf.d/*.conf; client_max_body_size 128m; }
      
      





nginxを再起動します







 sudo service nginx restart
      
      





Let's EnctyptからSSLを取得します。

もちろん、ドメインはすでにこのIPアドレスにバインドされている必要があります。







 sudo apt-get install letsencrypt sudo letsencrypt certonly -a webroot --webroot-path=/home/consulwar/app/current/programs/web.browser/app -d consulwar.ru sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 #    
      
      





よし! SSL Works







iptables
 sudo vi /etc/network/if-up.d/00-iptables
      
      





00-iptables
 #!/bin/sh iptables-restore < /etc/firewall.conf ip6tables-restore < /etc/firewall6.conf
      
      





 sudo chmod +x /etc/network/if-up.d/00-iptables apt-get install xtables-addons-dkms sudo vi /etc/firewall.conf
      
      





firewall.conf
 *filter :INPUT ACCEPT [193038:64086301] :FORWARD DROP [0:0] :OUTPUT ACCEPT [194475:60580083] -A INPUT -i lo -j ACCEPT #    -A INPUT -m state --state RELATED,ESTABLISHED -p all -j ACCEPT #    #  SSH -A INPUT -m state --state NEW -p tcp -m multiport --dport 355 -j ACCEPT #   Nginx -A INPUT -m state --state NEW -p tcp -m multiport --dport 80,443 -j ACCEPT #    ,    ,    -A INPUT -p tcp -m tcp -j TARPIT #    -A INPUT -p udp -j DROP COMMIT
      
      





 sudo vi /etc/firewall6.conf #     ,    sudo iptables-restore < /etc/firewall.conf
      
      





itablesが構成され、余分なポートが閉じられます。







完了!







アプローチ/フォーマットが気に入ったら、メールシステムのセットアップ、インフラストラクチャの監視、Bambooを介したCI、および使用する多くの項目を投稿します。







私が何かを見逃した可能性があります(しかし、一般的にはそれはちょうどそのように機能するはずです)-お願い、私はそれを補足します。

誰かが私のものよりも時間がかからないことを願っています:-)







PS:私たちには空席のフロントエンド開発者がいます。








All Articles