背景
Javashop電商系統的商品索引是使用的elasticsearch,對於高可用的要求有兩個重要的考量:
1、集群化
2、可擴容
3、冗災
冗災就要實現es的持久化,要考慮到es宕機的情況,當es因不可抗因素掛掉了,當我們再恢復了es的運行后,商品索引也要隨之 一起恢復。
本文着重討論elasticsearch的持久化部署方案,當然提供在方案也支持了集群及擴容。
思路
1、數據的存儲
在k8s中的持久化部署不可避免的要用到持久卷,我們采用nfs方式的持久卷來存儲es數據。
持久卷的詳細介紹請見這里:
2、節點規划
默認啟動5個節點,3主2數據。
根據es官方推薦每個節點的智能要分離,因此maseter節點不存儲數據,只用來協調。
3、多節點的權限問題
es的數據目錄默認只允許一個節點訪問,但在k8s上采用了持久卷,所有節點的數據都存儲在這個卷上,這會導致es的訪問權限問題。
報錯如下:
java.io.IOException: failed to obtain lock on /usr/share/elasticsearch/data/nodes/0",
當然可以通過更改es的配置max_local_storage_nodes來允許多個節點訪問同一個數據目錄,但es官方不推薦這樣做。
所以我們的方案是更改每個節點的數據存儲目錄來解決
ps:指定es配置項path.data來實現
舉例說明:
節點名 | 存儲目錄 |
es-data-1 | /usr/share/elasticsearch/data/es-data-1 |
es-data-2 | /usr/share/elasticsearch/data/es-data-2 |
部署過程
一、pv(持久卷的建立)
先要建立nfs服務器
對於持久卷的結構規划如下:
目錄 | 內容 |
---|---|
/nfs/data/esmaster | es master節點的數據 |
/nfs/data/esdata | es 數據節點的數據 |
關於索引的磁盤占用:
請根據業務的數據量情況來規划持久卷硬件的情況
根據我們實際測算1000個商品大約需要1MB/每節點
默認情況
在默認的規划中,我們使用使用k8s的master節點作為nfs服務器,為上述卷准備了10G的空間,請確保k8s master node 不少於10G的空閑磁盤。
請根據您的具體業務情況選擇nfs服務器,如果條件允許最好是獨立的nfs服務器。
根據如上規划建立nfs服務:
#master節點安裝nfs
yum -y install nfs-utils #創建nfs目錄 mkdir -p /nfs/data/{mqdata,esmaster,esdata} #修改權限 chmod -R 777 /nfs/data/ #編輯export文件 vim /etc/exports 粘貼如下內容: /nfs/data/esmaster *(rw,no_root_squash,sync) /nfs/data/esdata *(rw,no_root_squash,sync) #配置生效 exportfs -r #查看生效 exportfs #啟動rpcbind、nfs服務 systemctl restart rpcbind && systemctl enable rpcbind systemctl restart nfs && systemctl enable nfs #查看 RPC 服務的注冊狀況 rpcinfo -p localhost #showmount測試,這里的ip輸入master節點的局域網ip showmount -e <your ip>
如果成功可以看到可被掛載的目錄:
# showmount -e 172.17.14.73
Export list for 172.17.14.73: /nfs/data/esmaster * /nfs/data/mqdata *
接下來,要在每一個節點上安裝nfs服務以便使k8s可以掛載nfs目錄
#所有node節點安裝客戶端
yum -y install nfs-utils systemctl start nfs && systemctl enable nfs
這樣就為k8s的持久卷做好了准備。
建立持久卷
有了nfs的准備,我就可以建立持久卷了:
我們分享了javashop內部使用的yaml倉庫供大家參考:
https://gitee.com/enation/elasticsearch-on-k8s
在您的k8s maseter節點服務器上 clone我們准備好的yaml文件
git clone https://gitee.com/javashop/elasticsearch-on-k8s
修改yaml目錄中的pv.yaml
修改其中的server配置為nfs服務器的IP:
nfs:
server: 192.168.1.100 #這里請寫nfs服務器的ip
在k8s master節點上執行下面的命令創建namespace:
kubectl create namespace ns-elasticsearch
通過下面的命令建立持久卷:
kubectl create -f pv.yaml
通過以下命令查看持久卷是否建立成功:
kubectl get pv
部署elasticsearch
執行下面的命令創建es集群
kubectl create -f elasticsearch.yaml
通過以上部署我們建立了一個ns-elasticsearch的namespace,並在其中創建了相應的pvc、角色賬號,有狀態副本集以及服務。
有狀態副本集:
服務:
鏡像
使用的是javashop自己基於es:6做的,加入了ik分詞插件,其他沒有變化。
服務
我們默認開啟了對外nodeport端口,對應關系:
32000->9200
32100->9300
k8s內部可以通過下面的服務名稱訪問:
elasticsearch-api-service.ns-elasticsearch:9300
elasticsearch-service.ns-elasticsearch:9200
等待容器都啟動成功后驗證。
驗證
1、生成索引
2、刪除副本集:
kubectl delete -f elasticsearch.yaml
3、建立副本集
kubectl create -f elasticsearch.yaml
4、查看之前的索引是否恢復
關鍵技術點
1、集群發現:
- name: "discovery.zen.ping.unicast.hosts"
value: "elasticsearch-discovery"
建立了elasticsearch-discovery服務
2、映射持久卷
映射到:/usr/share/elasticsearch/data/
3、自定義數據目錄
- name: "path.data"
value: "/usr/share/elasticsearch/data/$(MY_POD_NAME)"
其中MY_POD_NAME是讀取的容器名稱,通過有狀態副本集保證唯一性的綁定:
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
歡迎關注Javashop技術分享公眾號,觀看更多的視頻講解: