我的 ElasticSearch 進化之旅

smalltown
Starbugs Weekly 星巴哥技術專欄
15 min readDec 23, 2019

Background

自己第一次接觸到 ElasticSearch 好像是六七年前了(遠目) 一路走來一直都是使用它來儲存 Log,畢竟 ELK 可是窮人版的 Splunk,這幾年來好像也沒有可以跟它匹敵的對手出現 (最近好像有個新的挑戰者受到不小的關注程度叫做 Grafana Loki),而對他的印象從一開始到現在都沒有變過,就是…它相當地吃資源,不管是在 CPU, Memory 或是 Disk 上,而且隨著 Log 量級的成長會需要一直去升級和調整它,不然它一發起脾氣來可是很恐怖的,而今天這篇文章主要想分享從我一開始架設 ElasticSearch 到目前為止的心得,並且會花比較多的篇幅講解目前的架設方式,總共有四個階段,用一句話來總結就是如何讓花費越來越低

  • Private Cloud
  • AWS ElasticSearch Service
  • ElasticSearch Operator in Kubernetes
  • Open Distro for ElasticSearch in Kubernetes

Private Cloud

自己第一次維護的正式 ElasticSearch Cluster 是在公司的 Private Cloud 內,常常需要隨著 Log 數量的增長去增加資源,那時候是大公司內的小員工,吃米不知道米價,而且私有雲的成本也沒有那麼透明,該加什麼就請別的部門的同事幫忙加一下,Charge Back 回來自己部門是多少錢其實我也不知道XD

優點:相對於使用 Public Cloud 來說,公司內規模化的 Private Cloud 其實是相對便宜的才對

缺點:每次要增加機器資源,不像 Public Cloud 那麼方便可以自動化動態調整,需要由維運 Private Cloud 的同事幫忙

AWS ElasticSearch Service

後來在新創一開始是直接使用 AWS 的 ElasticSearch Service,會採用的原因當然就是沒有時間去架設,但需要馬上使用,點下去馬上就有又穩又好用的 ElasticSearch 可以把 Log 丟進去

優點:完全不需要花時間去架設 ElasticSearch,直接花錢解決問題就可以

缺點:跟自己在 AWS 使用 EC2 架設當然就是貴,不過時間就是金錢,當下決定用錢換時間

ElasticSearch Operator in Kubernetes

隨著 Log 的量級逐漸增加,在 AWS ElasticSearch 花的錢也越來越多,所以決定研究自己架設的方案,公司內有的部門是只使用 K8S 在做任何的事情,為了不增加更多技術學習障礙與成本,所以直接使用 ElasticSearch Operator 部署進去 K8S 內

優點:K8S 使用公司的開源專案 Vishwakarma 在 AWS 內架設完成,不管是 Master 或是 Worker Node 都全部採用 Spot Instance,比直接用 On Demand EC2 架設來得更省錢,ElasticSearch Operator 也滿方便的,一個下午就可以安裝好

缺點:隨著 Log 的量逐漸增加,想要自己去調整 ElasticSearch Cluster 內不同 Node 的細部設定時,開始發現 Operator 辦不到XD

Open Distro for ElasticSearch in Kubernetes

為了讓自己可以更方便地客製化 ElasticSearch Cluster 內的各種設定,決定參考官方的 Helm Chart 來部署 ;加上看到 AWS 推出的 Open Distro for ElasticSearch 裡面有了一些 X-Pack 付費版才有的功能,所以決定來用用看

優點:可以隨自己開心拆解 ElasticSearch Cluster 內 Node 的各種細部設定,而且還有免費的加值功能可以使用,K8S Cluster 內的 Node 一樣全部採用 Spot Instance 來降低成本

缺點:不知道用了是不是在殘害開源軟體 T_T (Reference: AWS被指「露天開採」開源軟體,Amazon:因應客戶要求) 然後要自己花時間把如何設定 Open Distro for ElasticSearch 搞定,因為自己這幾年在把玩這種 AWS 釋出的開源專案,發現在文件上都會比較沒那麼平易近人且可藹可親,不過花點時間搞定後,都真的可以跑就是了XD

Open Distro for ElasticSearch in Kubernetes

Introduction

講白一點,這是 AWS 使用 ElasticSerch OSS 版本當做基底,然後逐漸把 X-Pack 的功能一個一個加進來的版本,目前擁有的功能:Security, Alerting, SQL, Performance Analyzer, Index Management,未來準備增加 Anomaly Detection, k-NN Search, Security integration with alerting…等,詳細說明可以參閱官網

自己最主要看上的是 Security 功能,我透過它將 ElasticSearch 與公司員工的帳號系統整合在一起 (支援各種 Protocol,自己是 POC SAML),這樣一來 Kibana 就可以讓員工使用日常的帳號登入,使用者體驗大大的提升,還可以根據工作角色給予不同的權限,其他的功能也都不錯,例如 Alerting, SQL…等,不過還沒有時間詳細把玩

Prerequisite

  • 準備好 AWS 帳號,設定好 AWS 組態,讓自己的本地端環境有辦法去透過 Terraform 去創建 AWS Cloud Resource,因為我們會將 ElasticSearch 安裝在自己架設於 AWS 內的 K8S
  • 為了存取架設在 AWS 內的 EC2,請先在 AWS Region US West (Oregon) us-west-2 內先設定好一把 Key Pair
  • 接著來安裝 terraform ,這邊使用目前最新版 0.12.18
~$ brew install terraform
...
~$ terraform version
Terraform v0.12.18
  • 把此篇文章使用到的 GitHub Repository 給抓下來
~$ git clone https://github.com/smalltown/odfe.git

而本文章是使用 Open Distro for ElasticSearch 內附的 Demo 組態,所以用到的 Certificate 或是帳密都是內附寫死的,只供 Playground 使用,要部署到正式環境之前,記得要全部換掉一輪

Kubernetes Setup

首先開始來把自架的 K8S 給架設起來

# 切換到 terraform 的資料夾內
~$ cd odfe/terraform
# 透過初始化來下載所有需要的 terraform providers 跟 modules
~$ terraform init

建立好 K8S Cluster 需要的基本網路架構

~$ terraform apply -target=module.network -auto-approve -var key_pair_name=#{請填入自己建立的 Key Pair 名稱}...Apply complete! Resources: 34 added, 0 changed, 0 destroyed.Outputs:bastion_public_ip = 6.6.6.6

接著建立 K8S Master 跟 Etcd

~$ terraform apply -target=module.kubernetes -auto-approve -var key_pair_name=#{請填入自己建立的 Key Pair 名稱}...Apply complete! Resources: 72 added, 0 changed, 0 destroyed.Outputs:bastion_public_ip = 6.6.6.6
ignition_s3_bucket = test-elastikube-xxxxxxxx

最後再把 K8S Cluster 所需要的 Worker Group 給建立出來

~$ terraform apply -auto-approve -var key_pair_name=#{請填入自己建立的 Key Pair 名稱}...Apply complete! Resources: 7 added, 0 changed, 0 destroyed.Outputs:bastion_public_ip = 6.6.6.6
ignition_s3_bucket = test-elastikube-xxxxxxxx

接著 ssh 到 Bastion 裡面驗證 K8S 安裝有沒有成功,也順便把等等 ElasticSearch 會用到的東西裝好

~$ ssh ubuntu@6.6.6.6 -i ~/.ssh/#{請填入自己建立的 Key Pair 名稱}~$ git clone https://github.com/smalltown/odfe.git~$ cd odfe~$ ./setup_bastion.sh

要驗證之前,先來把 kubeconfig 弄到手,terraform 的 outputs 有提到 ignition_s3_bucket = test-elastikube-xxxxxxxx ,在裡面可以找到 kubeconfig,請自行把它將他複製到 Bastion 內

$ export KUBECONFIG=#{存放路徑}/kubeconfig~$ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-10-0-54-53.us-west-2.compute.internal Ready spot 13m v1.14.10
ip-10-0-66-39.us-west-2.compute.internal Ready master 19m v1.14.10
ip-10-0-88-202.us-west-2.compute.internal Ready spot 12m v1.14.10

ElasticSearch Setup

操作到這邊的話,省錢目標已經達成一半,就是我們使用全部都是 Spot Instance 的機器將 K8S Cluster 建立完成;接著來進行另外一半,就是開始安裝理論上要企業版才有的加值功能的 ElasticSearch a.k.a. Open Distro for ElasticSearch

~$ kubectl create namespace elastic
namespace/elastic created
~$ kubectl create secret generic odfe-certs --namespace=elastic --from-file=./secrets
secret/odfe-certs created
~$ helmfile --selector component=aws-storage-class sync
~$ helmfile --selector component=elasticsearch-master sync
~$ helmfile --selector component=elasticsearch-data sync

ElasticSearch Cluster 應該已經安裝完成,但是還必須要初始化 Security Configuration 之後,才算是真的設定完成

~$ ./update_security_config.sh
Update the open distro for ElasticSearch security configuration...
Open Distro Security Admin v7
Will connect to localhost:9300 ... done
Connected as CN=kirk,OU=client,O=client,L=test,C=de
Elasticsearch Version: 7.3.2
Open Distro Security Version: 1.3.0.0
...Done with success

最後來驗證一下剛剛架設好的 ElasticSearch Cluster,假如有成功回覆類似底下的 json 資料的話,那就代表設定都沒有問題

# 將 K8S 內的 Port 9200 Forward 到 Bastion 的 Port 9200
~$ kubectl -n elastic port-forward svc/elasticsearch-data 9200:9200
# 打開另外一個 termainal 連線到 Bastion 內,並且使用 curl 來驗證一下
~$ curl -k https://admin:admin@127.0.0.1:9200
{
"name" : "elasticsearch-data-1",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "PRtEyyNoQqCzB2eTw5KGzA",
"version" : {
"number" : "7.3.2",
"build_flavor" : "oss",
"build_type" : "tar",
"build_hash" : "1c1faf1",
"build_date" : "2019-09-06T14:40:30.409026Z",
"build_snapshot" : false,
"lucene_version" : "8.1.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}

Kibana Setup

最後一個要安裝的東西,當然就是大家每天都賴以為生的 Kibana

~$ helmfile --selector component=kibana sync# 這次換成把 K8S 內的 Port 5601 Forward 到 Bastion 的 5601 來
~$ kubectl -n elastic port-forward svc/kibana-kibana 5601:5601

為了使用本機端的瀏覽器,所以這邊比較麻煩一點,需要建立一個臨時的 ssh tunnel,所以最後在本機端打開另外一個 terminal 執行下面的指令來讓本機端可以讀到 Bastion 的 Port 5601

~$ ssh -L 5601:localhost:5601 -i ~/.ssh/#{請填入自己建立的 Key Pair 名稱} ubuntu@6.6.6.6

然後打開用瀏覽器開啟 http://127.0.0.1:5601,應該就可以看到 Kibana 美麗的登入畫面,輸入預設的帳號密碼 admin/admin

進行到這邊就算是大功告成了,使用 AWS Spot Instance 架設出最便宜的 K8S Cluster,再加上擁有付費功能的免費 Open Distro for ElasticSearch,達成最省錢又設定起來相當富有彈性的解決方式

最後不要忘記把剛剛建立的東西給清掉,不然 AWS 可是會時時刻刻扣錢的

# 在 Bastion 上執行
~$ helmfile destroy
# 在本機端執行
~$ cd terraform
~$ terraform destroy -target=module.worker_spot -auto-approve -var key_pair_name=#{請填入自己建立的 Key Pair 名稱}
...Destroy complete! Resources: 7 destroyed.~$ terraform destroy -target=module.kubernetes -auto-approve -var key_pair_name=#{請填入自己建立的 Key Pair 名稱}...Destroy complete! Resources: 72 destroyed.~$ terraform destroy -target=module.network -auto-approve -var key_pair_name=#{請填入自己建立的 Key Pair 名稱}...Destroy complete! Resources: 34 destroyed.

Conclusion

一路走來跌跌撞撞,想做的就是建立一個強壯健康,而且成本相對低的 ElasticSearch Cluster;不過這些年來,發現大家常常把不需要或是奇怪的東西也往裡面丟,最後 Cluster 裝很多的垃圾導致效能低落,或是 Index 內發生問題導致整個 Cluster 無法正常使用,因此雖然 ELK 已經算是標配的 Log Central System,不過在將 Log 往裡面丟之前最好先做一下正規化 (例如透過 Elastic Common Schema),並且也考量一下不是什麼東西都必須要丟進去,有時候可能只需要放到 S3 備份起來就好也說不一定

此篇文章只有提到如何把東西架設起來,一些更細節的東西並沒有提到,譬如效能要怎麼調校,Index 怎麼備分跟還原,Index 的 Retention Policy,Cluster Health Status Monitoring,怎麼跟 LDAP 或是 SAML 整合,不同的角色權限該怎麼規劃…等,假如大家有興趣的話,幫我鼓個掌讓我知道 ^^

--

--

smalltown
Starbugs Weekly 星巴哥技術專欄

原來只是一介草 QA,但開始研究自動化維運雲端服務後,便一頭栽進 DevOps 的世界裏,熱愛鑽研各種可以提升雲端服務品質及增進團隊開發效率的開源技術