跳到主要內容

發表文章

目前顯示的是 1月, 2020的文章

FluentD 存取 File Log

其他文章參考 FluentD 存取 Nginx Access Log (1/2) FluentD 存取 Nginx Access Log (2/2) 以上是 Nginx + FluentD + (ES|Mongo) Demo 針對access.log 做解析 現在以Log4X 產生的日誌檔作為範例說明 會遇到的問題有 日誌內容會有多行的情況 # multiline 希望每條日誌內容加入 UUID 以便追蹤 # https://github.com/chaeyk/fluent-plugin-add-uuid 使用 Slack 作為通知的通道 # https://github.com/sowawa/fluent-plugin-slack Log4X Layout Format Example <?xml version="1.0" encoding="utf-8" ?> <configuration> <log4net> <appender name="All" type="log4net.Appender.RollingFileAppender"> <file value="/var/log/web.log" /> <appendToFile value="true" /> <rollingStyle value="Size" /> <datePattern value="yyyy-MM-dd" /> <maximumFileSize value="5MB" /> <maxSizeRollBackups value="10" /> <staticLogFileName value="true" /> <PreserveLogFileNameExtension value=&qu

安裝 MySQL Docker 時,目錄夾權限問題

在設定 docker 容器的外掛目錄時,常會遇到權限問題 在這記錄一下看到的一個 tricky 解法 來源連結 主要就是使用 # 找到 mysql 的 User ID docker run -ti --rm --entrypoint="/bin/bash" ${docker image} -c "cat /etc/group" # change volume permission sudo chown -R ${user id} ${target path}

申請免費 SSL,自動續訂

參考 acme.sh 搭配 GoDaddy 自動續期 Let's Encrypt 免費萬用憑證 使用 acme.sh + Cloudflare 申請免費 Wildcard SSL (Let’s Encrypt) 節略如下 安裝 acme.sh # 安裝 acme.sh ,安裝後重新登入 curl https://get.acme.sh | sh # 自動更新 acme.sh --upgrade --auto-upgrade acme.sh 設定存取 Goddy vi ~/.acme.sh/account.conf # Goddy API GD_Key="" GD_Secret="" acme.sh 設定存取 Cloudflare # Cloudflare API Keys # Global API Key [View] export CF_Key="" export CF_Email="" 申請網域(Domain)的萬用憑證,成功後會顯示憑證存放的路徑 $> acme.sh --issue --dns dns_gd -d ${domain} -d *.${domain} 安裝憑證 # 建立 /etc/nginx/ssl/${domain} 路徑 $> acme.sh --install-cert -d ${domain} --key-file /etc/nginx/ssl/${domain}/key.pem --fullchain-file /etc/nginx/ssl/${domain}/cert.pem --reloadcmd "sudo nginx -s reload"

DotNet Core 專案部署腳本

DotNet core SDK 首先在 Server 上準備編譯環境 Dockerfile #2.2 3.0 3.1 FROM mcr.microsoft.com/dotnet/core/sdk:3.1 RUN mkdir /web WORKDIR /web build docker image shell script docker build -t dotnetcoresdk:3.1 . start docker container shell script docker run -it -d \ --name dotnet-core-sdk-3.1 \ -v /opt/web:/web \ dotnetcoresdk:3.1 Jenkins Execute shell script on remote hosting using ssh #切換至專案目錄 cd /opt/web/project/path #取得最新版本 git pull #切換至專案目錄 && 刷新 Dotnet Library docker exec -i dotnet-core-sdk-3.1 bash -c "cd project/path && dotnet restore" #切換至專案目錄 && 刪除上一次編譯的檔案 && 編譯 docker exec -i dotnet-core-sdk-3.1 bash -c "cd project/path && rm -rf bin/Release && dotnet publish -c Release" #docker-compose.yml 參 DotNet core Runtime Section #!--rmi all 將原本執行的容器關閉並移除Image docker-compose down --rmi all #將新版程式包入 Image 並開始容器 docker-compose up -d DotNet core Runtime 專案中包含 Dockerfile & docker-compose.yml d

Grafana

安裝請參考 Grafana 設定 1. Datasource > add > Prometheus > url ${http://172.28.1.3:9090} > Save & Test 2. Users Invite > ${email} 3. Plugins Pie Chart 4. Dashboards Grafana 資源 Grafana Dashboard Grafana Plugins 套用別人建立好的 Dashboard 在 https://grafana.com/grafana/dashboards 過濾 Data Source 為 Prometheus 的套件 找到適合的套件記下 ID 在自己的 Grafana => Create => Import 5. import! Alerting 參考資料 add notification channel use slack as example ( Slack 新增 app 請參考 ) 取得 App Token 取得 Incoming Webhooks URL 填入 URL ${webhook URL} & token token 為 xoxb- 6. 建立磁碟空間警報 Add Panel > Add Query # Queries (node_filesystem_avail_bytes/node_filesystem_size_bytes) * 100 # Visualization # import ! user "Graph" # Alert just like this

Slack 新增 Bot App

Create New App 1. Create New App 填入 App Name 及 選擇 workspace 2. 維護 Base Information 維護 App Name & Short description & App icon & background color 3. 維護 Oauth & Permissions Add an Oauth Scope incoming-webhook  channels:read This scope lets an app "View basic information about public channels in the workspace" chat:write:bot This scope lets an app "Send messages as your slack app" 4. Install App into your workspace Code Example Send messages example DotNet Code Send Message 2 Slack private void send2stalck(string path,string query,string header,string body,string message) { Dictionary dictQuery = new Dictionary (); dictQuery.Add("channel", @" slack channel "); dictQuery.Add("token", @" slack token "); dictQuery.Add("text", message); JArray jaFields = new JArray(); var joEnv = new JObject() { { "title", "env" }, { "value",

Prometheus + Grafana + Exporters = Server Monitor

Grafana 功能強大且美觀的Dashboard Prometheus 用來作為數據收集及儲存,透過設定至各 exporter 端"拉"資料回來 exporter Prometheus exporter 環境建置 使用 docker-compose 時,會依所在目錄建立 ${path}-default docker network 純粹為了賞心悅目 建立一個 monitor-net 集中堆放 Grafana , Prometheus , xxxx exporter 建立 docker network docker network create monitor-net Grafana + Prometheus docker-compose.yml version: '3' services: grafana: image: grafana/grafana ports: - 9000:9000 - 9010:3000 environment: - GF_SERVER_ROOT_URL= - GF_SECURITY_ADMIN_PASSWORD= volumes: # copy grafana.ini to /etc/grafana - /etc/grafana/grafana.ini:/etc/grafana/grafana.ini - /var/lib/grafana:/var/lib/grafana - /var/log/grafana:/var/log/grafana container_name: my-grafana restart: always networks: - myonitornet prometheus: image: prom/prometheus ports: - 9090:9090 volumes: # copy prometheus.yml to /etc/prometheus - /etc/prometheus/prometheus.yml:/etc/prome

Kibana(2/2)

安裝完畢後 立馬登入Kibana 瞧瞧 1. 建立 Index Pattern ${domain:port}/app/kibana#/management/kibana/index_patterns?_g=() 2. Discover Data ${domain:port}/app/kibana#/discover 3. Create New Visualization ${domain:port}/app/kibana#/visualize 情境1 顯示最長被存取的文章 前 10 筆統計 [Data Table] 1. split table > field ${path} > advanced > include > ${/api/article} 2. split row > field $(article id) 情境2 哪段時間是 API 存取巔峰 [Vertical] 1. x-Axis > field ${timestamp} > interval (10m) 情境3 Http request fail rate [Pie] 1. split slices > field ${http status code} 情境4 特定關鍵字的統計 [Metric] Filter語法可參考 Kibana 上方工具列的 Filter 選項產生 1. split group > aggregation = Filters > filter1 {"match_phrase":{"path":"/tracking/url/path"}} 4. 將建立的 visualization 加入 Dashboard ${domain:port}/app/kibana#/dashboard

Kibana(1/2)

前面已經提了 FluentD(1/2) FluentD(2/2) Elasticsearch 最後一哩路就是視覺化 Kibana 出場 Dockerfile FROM kibana:7.2.0 Build Image Shell Script docker build -t mykibana . kibana.yml Sample # Kibana is served by a back end server. This setting specifies the port to use. server.port: 5601 # Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values. # The default is 'localhost', which usually means remote machines will not be able to connect. # To allow connections from remote users, set this parameter to a non-loopback address. server.host: "0.0.0.0" # Enables you to specify a path to mount Kibana at if you are running behind a proxy. # Use the `server.rewriteBasePath` setting to tell Kibana if it should remove the basePath # from requests it receives, and to prevent a deprecation warning at startup. # This setting cannot end in a slash. #server.basePath: "" # Specifies whether Kibana should rewrite

Elasticsearch

Elasticsearch Install Dockerfile FROM elastic/elasticsearch:7.2.0 Build Image Shell Script docker build -t myelasticsearch . Prepare yours ES config copy elasticsearch.yml jvm.options log4j2.properties to /es/conf/path Docker start Shell Script # 由於沒有安全保護,因此設計上希望 ES 不對外,使用 --network 串在已建立的 docker network 中 docker run -it -d --name myelasticsearch --restart=unless-stopped --network=my-dev_mydemonet -v /es/conf/path:/usr/share/elasticsearch/config -v /es/data/path:/usr/share/elasticsearch/data -v /es/plugin/path:/usr/share/elasticsearch/plugins -e "discovery.type=single-node" -p 9300:9300 -p 9200:9200 myelasticsearch 安裝中文分詞 參考來源 docker exec -it myelasticsearch sh elasticsearch-plugin install analysis-smartcn 補充 定時刪除Index Shell Script 由於架構中 ES 屬於 短期、快速 查詢使用,僅保留七日的紀錄,因此需準備一組 Script 每日清理過期 Index 可以使用任何排程工具執行以下 Script idx_date=$(date +%Y.%m.%d -d "$DATE - 7 day") echo "curl -XDELETE http://localhost:9200/fluent

FluentD 實作 Nginx Access Log 補充

FluentD 實作 Nginx Access Log 補充 前一篇針對 FluentD 安裝 及 Nginx Access log format 設定提供範例 本篇補充 1. 將 access_log 存入 MySQL 2. 針對Input 加工,ex 解析 Path 拆成不同欄位,在傳入 Output 延伸閱讀 FluentD 參數說明 FluentD 實作 Nginx Access Log 將 access_log 存入 MySQL <worker 0> <source> ... 略 </source> <match nginx.web.access> @type copy ... 略 <store> @type sql host ${MySQL Host address} port ${MySQL Port} adapter mysql2 database ${MySQL Database} username ${MySQL User Name} password ${MySQL Password} <table> table ${MySQL table} column_mapping 'logtime:logtime,method:method,path:path,code:code,size:size,resptime:resptime,token:token,path_url:path_url,timestamp:created_at' </table> </store> </match> </worker> 針對Input 加工,ex 解析 Path 拆成不同欄位,在傳入 Output 情境: 以下 access log 範例,需要針對 Query Parameter 拆解並存入新欄位,以利分析. [27/Dec/2019:07:14:10

FluentD 參數說明

FluentD 高效、統一的日誌收集器 延伸閱讀 FluentD 實作 Nginx Access Log FluentD 實作 Nginx Access Log 補充 FluentD 安裝 Dockerfile FROM fluent/fluentd:v1.8.1-1.0 # Use root account to use apk USER root # below RUN includes plugin as examples elasticsearch is not required # you may customize including plugins as you wish RUN apk add --no-cache --update --virtual .build-deps \ sudo build-base ruby-dev \ && apk add mariadb-dev \ && sudo gem install fluent-plugin-elasticsearch \ && sudo gem install fluent-plugin-mongo \ && sudo gem install fluent-plugin-sql \ && sudo gem install mysql2 -v 0.5.2 \ && sudo gem sources --clear-all \ && apk del .build-deps \ && rm -rf /home/fluent/.gem/ruby/2.5.0/cache/*.gem VOLUME ["/fluentd/etc","/fluentd/log","/var/log"] docker-compose.yml version: '3' services: fluentd: build: context: . dockerfile: ./Dockerfile image: my/flue

使用 RobotsTxtCore 建立 robot.txt & sitemap.xml

Nuget Link 透過 nuget 安裝 RobotsTxtCore >dotnet add package RobotsTxtCore --version 1.1.0 //Startup.cs public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseRobotsTxt(builder =>builder .AddSection(section => section .AddComment("Allow Googlebot") .AddUserAgent("Googlebot") .AddUserAgent("Googlebot-News") .AddUserAgent("Googlebot-Image") .AddUserAgent("Googlebot-Mobile") .AddUserAgent("Googlebot-Video") .AddUserAgent("Mediapartners-Google") .AddUserAgent("Adsbot-Google") .Allow("/") ) .AddSection(section => section .AddComment("Disallow the rest") .AddUserAgent("*") .AddCrawlDelay(TimeSpan.FromSeconds(10)) .Disallow("/") ) .AddSitemap("https://${domain}/sitemap.xml") ); }

meta tag 說明

meta tag 說明 1. <title></title> *建議中文保持在 30 個字元、英文 60 個字元以內 *可以用以下格式: 主要關鍵字  -  次要關鍵字 | 廠牌名稱 *每個頁面的 Title 都是唯一的 <title>MyDemo-@ViewData["Title"]</title> 2. <meta name='description' content='@ViewData["PageDescript"]' /> *建議中文保持在 80 個字元、英文 160 個字元以內 3. og 社群相關 tag og 全名為: Open Graph Protocol *在 og:title 設定的文字會當作分享 FB 時的標題。 3.1 og:image *大小不要超過 8 m *尺寸要大於 200px * 200px,否則連圖都抓不到 *如果圖片為長方形 建議最小尺寸 600px * 315px *如果圖片為正方形 建議最小尺寸 600px * 600px 程式化新增 meta tag //在DotNet Core Project中 新增目錄夾 Filters ,並新增MetaTagFilter.cs 檔案 using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc; namespace WebProject.Filters { public class MetaTagAttribute : TypeFilterAttribute { public MetaTagAttribute( ) : base( typeof( MetaTagFilter ) ) { } public class MetaTagFilter : IActionFilter { private string title { get; set; } private string des

在 GCP 新增 VM 執行個體的儲存空間

GCP 文件連結 建立 GCP VM instance 時,預設磁碟空間為10GB,可在建立時自行調整, 也可另外新增永久磁碟供VM 掛載使用 在建立永久磁區前,請先參考  儲存空間儲存空間的類型及效能 地區與區域的區別為: 地區 是 區域 的集合 並且參考其  磁碟定價 來做為你要新增儲存空間的依據 以下以新增區域永久磁碟做說明 1. 增加新磁碟 前往 VM 執行個體   頁面 VM 執行個體詳細資料 點擊 編輯 在磁碟標籤標籤下 點擊 增加新磁碟 指定名稱、類型、來源 等屬性後 點擊儲存 2. 格式化和掛接新磁碟 //在終端機中,使用 lsblk 指令列出連接到執行個體的磁碟,並搜尋您要格式化和掛接的磁碟 sudo lsblk //格式化磁碟 以下用 sdb 取代 [DEVICE_ID] sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/[DEVICE_ID] //建立做為新磁碟掛接點的目錄 以下用 extra 取代 [MNT_DIR] sudo mkdir -p /mnt/disks/[MNT_DIR] //使用掛接工具,將磁碟掛接到已啟用 discard 選項的執行個體 sudo mount -o discard,defaults /dev/[DEVICE_ID] /mnt/disks/[MNT_DIR] //設定裝置上的讀取與寫入權限。在此範例中,授予所有使用者對裝置的寫入存取權 sudo chmod a+w /mnt/disks/[MNT_DIR] //可用單一指令完成此步驟。舉例來說,下列指令會在 /etc/fstab 中建立項目,以永久磁碟的 UUID 將 /dev/sdb 永久磁碟掛接到 /mnt/disks/[MNT_DIR] echo UUID=`sudo blkid -s UUID -o value /dev/[DEVICE_ID]` /mnt/disks/[MNT_DIR] ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab 補充 將 Docker 遷移至新磁碟 參考來源 //編