目的
目前手上專案系統的 Log 仍然存在 MS SQL Server 裡。原因是因為系統後台一開始就建置了 Log 查詢的頁面功能。讓管理人員可以查詢系統登入、運作狀況以及 API 交換的每一筆訊息紀錄。這功能讓技術克服人員與開發人員很方便的進來系統撈取 Debug 錯誤時所需的有用資訊。
在初期快速開發的階段這些功能都是用 Entity Framework 建造以求開發迅速。但當系統上線後每日運轉下來 Log 的成長量也已大大超乎預期。雖然已經因為資料庫負荷沉重把 Log 搬離主要的交易資料庫放在較為次級的 SQL Server。但每日都有相當成長量讓我們不得不面對找尋完善的 Log 管理機制。
這個測試,我們需要在不改變系統功能的前提下評估:
- Elasticsearch 的 REST API 是否足夠讓我們建置客製化的 API 來包裝讓並使用現有系統後台 Log 查詢機制來查詢 (不再用 Linq + Entity Framework 查 SQL Server)。
- Elasticsearch 完全替代 MS SQL 來存 Log:
- 備份與資料維護
- Clustering
- Failover 機制
- SSRS 報表的替代方案
相關應用
- Docker
- Elasticsearch
- Kibana
- Logstash
動手
首先我們需要把 Elasticsearch 與 Kibana 設定好,然後倒一些 Log 進 Elasticsearch 並且試試 Kibana 上的查詢功能。
這篇先寫第一部分,關於 Docker 的使用與設定。
設定 Docker
用 Docker 來測試 ELK。可以避免在日常開發機器上裝太多不常用的系統服務。
Docker Repository 上已經有許多 ELK 的 Image, 我選了 sebp/elk
,並有提供詳細的 文件說明
這個 docker image 上有所有 ELK Stack,啟動時需要指定開啟各服務所需要的連接埠讓本機可與 Container 溝通。執行方式如下:
docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --name elk sebp/elk
指定三個連接埠 (-p) 分別代表:
- 9200: Elasticsearch
- 5601: Kibana
- 5044: Logstash beats
Dockerfile
這個測試主要的目的是學習如何使用 ELK 達成目的。在不修改任何程式的前提下,第一階段要取得Log 資料須由 MS SQL 匯出到 Logstash。
因為有些 Container 相關的設定,所以我用了 Dockerfile
來把設定檔塞到 Container 裡:
FROM sebp/elk # 在Container 建立一個工作資料夾,我們在本機編輯好的設定檔與其他必要檔案都可透過這個資料夾與Container交換 RUN mkdir /workspace WORKDIR /workspace ADD . /workspace #另外我在本機有編輯了 logstash 的設定檔需要一開始就塞進 Container 裡。這邊可以將檔案加到指定的 Container 上的路徑 ADD logstash-mssql.conf /etc/logstash/conf.d/logstash-mssql.conf #這個測試會用到 logstash 的 JDBC plugin。用以下這個步驟安裝 RUN gosu logstash /opt/logstash/bin/logstash-plugin install logstash-input-jdbc
logstash-input-jdbc
並沒有包含不同資料庫所需要的驅動程式。我們所使用的資料庫是 SQL Server。我們需要自己 下載 JDBC 驅動程式。
下載後解開壓縮檔把 sqljdbc42.jar 跟 Dockerfile 放在同一個資料夾。
docker-compose
目前只有一個 image/container,應該是用不到 docker-compose 來管理。但用 docker-compose 可以幫助我們記得要指定的連接埠。省的啟動 container 得打一大串指令。
version: '2' services: elk: build: . # 要 docker-compose 執行時建置同目錄下的 Dockerfile container_name: elk # 幫 Container 命名,之後比較好打指令 volumes: - .:/workspace # 將本地資料夾掛在Container的 /workspace 資料夾下 [host:container] ports: - "9200:9200" # 對應本地與 Container 的連接埠 - "5601:5601" - "5044:5044"
同樣跟 Dockerfile 放一起。在該資料夾下執行
docker-compose up
就可以啟動 container
設定 Logstash
sebp/elk
裡已經設定好一些 Logstash 設定檔。可以抓 beats, 系統記錄檔等等,並會把結果輸出在 localhost:9200 的 Elasticsearh 。在 container 裡的 /etc/logstash/conf.d/
可以找到這些設定檔。之前提到需要撈 SQL Server 的設定檔也需要放在 /etc/logstash/conf.d/ Logstash
啟動時方可一併載入。
Docerfile 裡的 ADD logstash-mssql.conf /etc/logstash/conf.d/logstash-mssql.conf
這行就是要幫我們在 container 建立時把同資料夾裡的 logstash-mssql.conf 塞到 Container 的 /etc/logstash/conf.d/
資料夾。
以下是我們設定 Logstash 撈取 SQL Server 資料庫的設定檔:
input{ jdbc { jdbc_driver_library => "/workplace/sqljdbc42.jar" jdbc_driver_class => "com.microsoft.sqlserver.jdbc.SQLServerDriver" jdbc_connection_string => "jdbc:sqlserver://10.0.75.1:1433;databaseName=LogDatabase" jdbc_user => "sa" jdbc_password => "sa" jdbc_validate_connection => true statement => "SELECT * FROM Logs" } } output { elasticsearch { hosts => "localhost:9200" index => "apilogs" document_id => "%{id}" document_type => "ApiLog" } }
jdbc 區段可設定資料抓取方式。以及 SQL Server 伺服器的連線資訊。這邊要注意 SQL Server 是在本機 (Windows) 上執行的 SQL Server Express。從 Container 裡面用 JDBC 連線到 SQL Server 需要透過 HTTP 通訊協定,但 SQL SERVER 預設是禁止 HTTP 連線存取的。所以我們還需要修改一下 SQL SERVER 的設定:
Sql Server Configuration Manager
> SQL Server Network Configuration
> Protocols for MSSQLSERVER
> TCP/IP
設為 Enabled
後重新啟動資料庫服務即可。
另外,我的 docker container 與本機 連線的方式 用的是 Bridge Driver。可以在本機使用 docker network inspect bridge
指令來查看網路介面的設定狀況。
回到 Logstash config 檔:
jdbc_connection_string => "jdbc:sqlserver://10.0.75.1:1433;databaseName=LogDatabase"
在這裡我直接將連線資訊指向 Docker 在 Host 機器上安裝的網路介面。
statement => "SELECT * FROM Logs"
撈資料時使用的 SQL Statement
設定檔好之後,可以使用 Logstash 的指令來跑跑看︰
首先我們要取得 Container 的 Shell 指令介面,在Windows 的指令模式下輸入:
docker exec -it elk /bin/bash
首先確保 Dockerfile 所執行複製進 Container 是正確的 Logstash .conf 檔,可用 vim 等純文字編輯程式開來看看:
vim /etc/logstash/conf.d/logstash-mssql.conf
無誤後 :q! 退出 vim 就可跑跑 Logstash 看看效果如何了
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/logstash-mssql.conf