Giới thiệu
Ở bài này chúng ta sẽ tìm hiểu về cách triển khai Elasticsearch Cluster lên trên môi trường Cloud, cùng với đó là cách sao lưu và khôi phục dữ liệu của Elasticsearch.
Để triển khai Elasticsearch thì có rất nhiều cách (bài này bàn về triển khai Elasticsearch trên AWS):
- Xài AWS Opensearch (Elasticsearch Service): với Opensearch thì AWS sẽ quản lý việc mở rộng và HA cho ta, ưu điểm là dễ quản lý tuy nhiên tiền khá cao (hơn $400 tháng)
- Triển khai Elasticsearch lên trên Kubernetes: giá tiền thì chắc chắn sẽ ít hơn so với AWS Opensearch, ưu điểm là dễ mở rộng và quản lý, tuy nhiên yêu cầu là cần phải biết Kubernetes
- Triển khai Elasticsearch lên thẳng EC2: cách này thì sẽ không có HA sẵn và yêu cần ta phải tự cấu hình. Bitnami nó có một ELK AMI sẵn ở đây, ta chỉ cần tạo EC2 từ AMI này là được. Cách này thì giá tiền là ít nhất, chỉ cần con EC2
t3a.medium
với 30GB. Nhưng về vấn đề HA, mở rộng, sao lưu, khôi phục dữ liệu thì ta phải tự làm
Tùy thuộc vào điều kiện thì ta sẽ chọn cách phù hợp, bài này sẽ hướng dẫn cách triển khai Elasticsearch lên trên Kubernetes.
Elastic Cloud on Kubernetes
Bình thường để triển khai Elasticsearch thì ta sẽ viết tệp tin cấu hình StatefulSet cho Elasticsearch, hoặc dùng Helm Chart để triển khai Elasticsearch lên trên K8S. Tuy việc này không có gì sai nhưng để quản lý việc mở rộng và cấu hình bảo mật cho cụm Elasticsearch thì không đơn giản. Nên Elasticsearch Official có cung cấp cho ta sẵn một Kubernetes Operator dùng cho Elasticsearch, tên là Elastic Cloud on Kubernetes (ECK). ECK giúp ta triển khai Elasticsearch lên trên K8S một cách rất dễ dàng.
Để sử dụng ECK đầu tiên ta phải cài CRDs và RBAC Rules của nó.
Cài đặt ECK
Cài CRDs và RBAC:
kubectl create -f https://download.elastic.co/downloads/eck/1.9.1/crds.yaml
Cài Operator Controller cho ECK:
kubectl apply -f https://download.elastic.co/downloads/eck/1.9.1/operator.yaml
Kiểm tra Operator đã hoạt động chưa:
$ kubectl get sts elastic-operator
NAME READY AGE
elastic-operator 1/1 99s
Nếu cột READY là 1/1 thì ECK đã cài thành công.
Triển khai Elasticsearch với ECK
Để triển khai Elasticsearch Cluster với ECK, ta sẽ dùng apiVersion
là elasticsearch.k8s.elastic.co/v1
với kind
là Elasticsearch
. Tạo một tệp tin tên là elasticsearch.yaml
:
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
version: 7.16.3
nodeSets:
- name: default
count: 1
kubectl apply -f elasticsearch.yaml
Thuộc tính version
để ta chọn version
của Elasticsearch mà ta muốn dùng, thuộc tính nodeSets
dùng để định nghĩa cụm Node cho Elasticsearch, ở trên ta chỉ định cụm Node có tên là default
và số lượng Node là 1.
Kiểm tra Elasticsearch đã chạy chưa.
$ kubectl get elasticsearch
NAME HEALTH NODES VERSION PHASE AGE
elasticsearch yellow 1 7.16.3 Ready 4m53s
Nếu cột PHASE
là Ready
thì Elasticsearch đã chạy.
Về bản chất khi ta tạo một Elasticsearch bằng ECK thì ECK sẽ tự động tạo StatefulSet ở bên dưới, kiểm tra thử.
$ kubectl get sts
NAME READY AGE
elasticsearch-es-default 1/1 4m53s
Như bạn thấy sử dụng ECK giúp ta triển khai một cụm Elasticsearch cực kì dễ dàng, tuy nhiên nhược điểm là nó chỉ xài dễ dàng trên Cloud thôi 😂.
Truy cập Elasticsearch
Để truy cập cụm Elasticsearch, ta có thể dùng port-forward
như sau.
kubectl port-forward service/elasticsearch-es-http 9200
Sử dụng curl để gửi yêu cầu tới Elasticsearch.
$ curl -k https://localhost:9200 ; echo
{"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}}],"type":"security_exception","reason":"missing authentication credentials for REST request [/]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}},"status":401}
Ta sẽ thấy Elasticsearch báo lỗi 401
. Vì khi ta tạo Elasticsearch dùng ECK thì mặc định nó sẽ bật chế độ Security lên, nên để truy cập tới nó ta cần phải có mật khẩu. Ta lấy mật khẩu của cụm Elasticsearch bằng câu lệnh sau.
kubectl get secret elasticsearch-es-elastic-user -o jsonpath={.data.elastic} | base64 --decode ; echo
Kết quả của câu lệnh trên sẽ in ra mật khẩu cho ta, gọi lại Elasticsearch với mật khẩu.
PASSWORD=$(kubectl get secret elasticsearch-es-elastic-user -n persistent -o jsonpath={.data.elastic} | base64 --decode)
curl -u "elastic:$PASSWORD" https://localhost:9200
{
"name" : "elasticsearch-es-default-0",
"cluster_name" : "default",
"cluster_uuid" : "XqWg0xIiRmmEBg4NMhnYPg",
"version" : {...},
"tagline" : "You Know, for Search"
}
Vậy là ta đã triển khai Elasticsearch lên trên K8S thành công.
Chỉnh sửa Persistent Volume
Mặc định ECK sẽ tạo ra PVC với kích thước là 1GB cho mỗi Pod.
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
elasticsearch-data-elasticsearch-es-default-0 Bound 1Gi RWO gp2 4m53s
Nếu ta muốn thay đổi kích thước PVC thì ta phải chỉ định thông qua trường volumeClaimTemplates
Cập nhật lại PVC của tệp tin elasticsearch.yaml
.
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
version: 7.16.3
nodeSets:
- name: default
count: 1
volumeClaimTemplates:
- metadata:
name: elasticsearch-data # Do not change this name unless you set up a volume mount for the data path.
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
kubectl apply -f elasticsearch.yaml
Kiểm tra PVC.
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
elasticsearch-data-elasticsearch-es-default-0 Bound 10Gi RWO gp2 1m52s
Lúc này bạn sẽ thấy kích thước của PVC đã tăng lên 10GB.
Public Elasticsearch
Để mở Elasticsearch cho bên ngoài có thể truy cập được thì ta sẽ dùng Ingress loại AWS Load Balancer. Để cài Ingress, các bạn xem hướng dẫn sau đây EKS Ingress.
Mặc định ECK tạo ra cho Elasticsearch Cluster bên dưới ba Service.
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch-es-default ClusterIP None <none> 9200/TCP 7m52s
elasticsearch-es-http ClusterIP 172.20.86.41 <none> 9200/TCP 7m52s
elasticsearch-es-transport ClusterIP None <none> 9300/TCP 7m52s
Service mà nhận Request của người dùng là elasticsearch-es-http
, ta sẽ tạo một Ingress chỉa tới nó. Tạo một tệp tin tên là ingress-elasticsearch.yaml
.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: elasticsearch
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-protocol: HTTPS
alb.ingress.kubernetes.io/success-codes: '401'
alb.ingress.kubernetes.io/backend-protocol: HTTPS
alb.ingress.kubernetes.io/certificate-arn: <acm-arn>
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
spec:
rules:
- host: elastic.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ssl-redirect
port:
name: use-annotation
- path: /
pathType: Prefix
backend:
service:
name: elasticsearch-es-http
port:
number: 9200
alb.ingress.kubernetes.io/healthcheck-protocol: HTTPS
sẽ cấu hình phương thức AWS Load Balancer dùng để Health Check là HTTPSalb.ingress.kubernetes.io/success-codes: '401'
vì khi ta dùng ECK để triển khai Elasticsearch, mặc định nó sẽ bật chế độ Security nên tất cả các đường dẫn đều cần Authenticate mới gọi được. Vì hiện tại ALB không cho cấu hình truyềnbody
vào trong ALB Health Check, nên ta phải thay đổi mã HTTP thành 401alb.ingress.kubernetes.io/backend-protocol: HTTPS
giao thức ALB gọi tới Pod sẽ là HTTPSalb.ingress.kubernetes.io/certificate-arn
là ACM ARN, nhớ nhập chính xác nhé, ở trên chỉ là giá trị ví dụalb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
ALB lắng nghe ởport
80 và 443
Truy cập Elasticsearch thông qua url elastic.example.com
.
Sao lưu và phôi phục
Với Elasticsearch để thực hiện sao lưu và phôi phục, ta sẽ sử dụng cơ chế Snapshot and Restore. Elasticsearch cho phép ta tạo Snapshot từ dữ liệu hiện tại, và có thể khôi phục dữ liệu từ Snapshot đó. Snapshot này ta có thể tự tạo bằng tay hoặc cấu hình cho Elasticsearch tự động tạo Snapshot trong một khoảng thời gian nhất định. Ta có thể lưu Snapshot ở Server hoặc ở trên Cloud đều được.
Sao lưu
Vì ta triển khai ECK ở trên AWS nên ta sẽ lưu Snapshot ở trên S3. Để thực hiện tạo Snapshot và lưu nó trên S3 ta cần làm các bước sau đây:
- Cài Elasticsearch Plugin cho S3
- Thêm Credentials vào Elasticsearch để nó quyền lưu dữ liệu vào S3
- Đăng ký Snapshot Repository bằng Elasticsearch API
- Tạo Snapshot bằng tay hoặc cấu hình cho Elasticsearch tự động tạo Snapshot
Cài S3 Plugin
Để cài Plugin bằng ECK khá đơn giản, ta chỉ cần thêm vào tệp tin cấu hình Elasticsearch một initContainers
và cho nó thực hiện câu lệnh cài plugin, cập nhật lại tệp tin elasticsearch.yaml
:
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
version: 7.16.3
nodeSets:
- name: default
count: 1
podTemplate:
spec:
initContainers:
- name: install-plugins
command:
- sh
- -c
- |
bin/elasticsearch-plugin install --batch repository-s3
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Đây là đoạn dùng để cài Plugin.
initContainers:
- name: install-plugins
command:
- sh
- -c
- |
bin/elasticsearch-plugin install --batch repository-s3
Thêm S3 Credentials
Để thêm Credentials vào Elasticsearch ta tạo một IAM User có quyền trên S3, sau đó lấy access_key
và secret_key
của IAM User đó và thêm vào Elasticsearch, các bước như sau:
- Truy cập IAM Console
- Bấm vào mục Users chọn Add Users
- Nhập User Name và ở mục Select AWS Credential Type chọn vào Access Key - Programmatic Access, bấm Next Permission
- Chọn Attach Existing Policies Directly kiếm
AmazonS3FullAccess
, bấm Next Tags và bấm Next Review, sau đó tạo IAM User, nhớ tải xuống hoặc sao chép lạiACCESS_KEY
vàSECRET_KEY
.
Sau đó tạo hai tệp tin với với tên là s3.client.default.access_key
và s3.client.default.secret_key
, sao chéo ACCESS_KEY
dán vào tệp tin s3.client.default.access_key
và SECRET_KEY
dán vào tệp tin s3.client.default.secret_key
, chạy câu lệnh sau để tạo Secret và gán nó vào Elasticsearch.
kubectl create secret generic s3-credentials --from-file=s3.client.default.access_key --from-file=s3.client.default.secret_key
Cập nhật lại tệp tin elasticsearch.yaml
thêm vào đoạn cấu hình sau:
...
spec:
version: 7.16.3
secureSettings:
- secretName: s3-credentials
entries:
- key: s3.client.default.access_key
- key: s3.client.default.secret_key
...
kubectl apply -f elasticsearch.yaml
Vậy là ta đã thêm Credentials thành công.
Đăng ký Snapshot Repository
Tiếp theo là ta sẽ tạo một Repository để chứa toàn bộ Snapshot. Kiểm tra toàn bộ Repository hiện tại.
$ curl -u "elastic:$PASSWORD" https://localhost:9200/_snapshot/_all
{}
Tạo Repository.
$ curl -XPUT -u "elastic:$PASSWORD" https://localhost:9200/_snapshot/s3_snapshot -d '{
"type": "s3",
"settings": {
"client": "default",
"bucket": "<your-bucket>",
"region": "<region>"
}
}'
{
"acknowledged": true
}
Lúc này khi liệt kệ Repository ta sẽ thấy Repository ta vừa tạo.
$ curl -u "elastic:$PASSWORD" https://localhost:9200/_snapshot/_all
{
"s3_snapshot" : {
"type" : "s3",
"settings" : {
"bucket" : "<your-bucket>",
"region" : "<region>",
"client" : "default"
}
}
}
Tạo Snapshot bằng tay.
curl -XPUT -u "elastic:$PASSWORD" https://localhost:9200/_snapshot/s3_snapshot/<snapshot-name>
Với snapshot-name
là tên Snapshot, liệt kê toàn bộ Snapshot.
curl -u "elastic:$PASSWORD" https://localhost:9200/_snapshot/s3_snapshot/_all
Khôi phục
Nếu ta có lỡ xóa đi dữ liệu hoặc máy chủ ta bị chết, để khôi phục dữ liệu từ Snapshot ta chỉ việc gọi API như sau:
curl -XPOST -u "elastic:$PASSWORD" https://localhost:9200/_snapshot/s3_snapshot/<snapshot-name>/_restore
Elasticsearch sẽ khôi phục dữ liệu lại từ Snapshot.
Tự động Snapshot
Để tự động tạo Snapshot ta cần sử dụng Kibana. Truy cập vào Kibana, di chuyển tới phần Management -> Snapshot and Restore -> Policies, sau đó bấm tạo Policies và cấu hình thời gian tạo Snapshot.
Hoàn thành việc cấu hình Snapshot tự động.
Kết luận
Vậy là ta đã tìm hiểu xong cách triển khai Elasticsearch lên trên Kubernetes bằng cách sử dụng ECK, sử dùng ECK giúp ta triển khai Elasticsearch rất dễ dàng.
Tác giả @Quân Huỳnh
Nếu bài viết có gì sai hoặc cần cập nhật thì liên hệ Admin.
Tham gia nhóm chat của DevOps VN tại Telegram.
Kém tiếng Anh và cần nâng cao trình độ giao tiếp: Tại sao bạn học không hiệu quả?