Tìm hiểu về etcd trong Kubernetes

Tìm hiểu về etcd trong Kubernetes

Etcd là cơ sở dữ liệu lưu trữ dữ liệu dạng key-value được sử dụng để lưu trữ và quản lý thông tin quan trọng mà hệ thống phân tán cần. Nó cung cấp một cách đáng tin cậy để lưu trữ dữ liệu cấu hình, dữ liệu trạng thái và siêu dữ liệu trong Kubernetes. Trong bài đăng này, chúng ta sẽ xem xét kỹ hơn về etcd, tại sao nó lại cần thiết và cách truy cập nội dung của nó trong Kubernetes.

Tên “etcd” xuất phát từ quy ước đặt tên trong cấu trúc thư mục Linux: Trong UNIX, tất cả các tệp cấu hình hệ thống cho một hệ thống đều được chứa trong một thư mục có tên “/etc;” “d” là viết tắt của “distributed”.

1. Tại sao Kubernetes cần cơ sở dữ liệu?

Chúng ta biết rằng Kubernetes là một công cụ điều phối có các nhiệm vụ liên quan đến quản lý khối lượng công việc của bộ chứa ứng dụng, cấu hình, triển khai, khám phá dịch vụ, cân bằng tải, lập lịch, mở rộng quy mô và giám sát cũng như nhiều tác vụ khác có thể trải rộng trên nhiều máy ở nhiều vị trí. Kubernetes cần duy trì sự phối hợp giữa tất cả các thành phần liên quan.

Nhưng để đạt được sự phối hợp đáng tin cậy đó, k8s cần một nguồn dữ liệu có thể cung cấp thông tin về tất cả các thành phần, cấu hình yêu cầu, dữ liệu trạng thái, v.v. Dữ liệu đó phải cung cấp một nguồn sự thật nhất quán, duy nhất tại bất kỳ thời điểm nào . Trong Kubernetes, công việc đó được thực hiện bởi etcd. etcd là kho lưu trữ dữ liệu được sử dụng để tạo và duy trì phiên bản đúng (source of truth).

Nhưng tại sao lại như vậy?

Việc đóng vai trò là source of truth duy nhất cho khối lượng công việc của ứng dụng không phải là một nhiệm vụ nhỏ. Nhưng điều gì khiến etcd đáng được sử dụng?

  • Được sao chép hoàn toàn: Mọi node trong cụm etcd đều có quyền truy cập vào kho lưu trữ dữ liệu đầy đủ.
  • Tính sẵn sàng cao: etcd được thiết kế để không có điểm lỗi duy nhất (single point of failure) và xử lý tốt các lỗi phần cứng và phân vùng mạng.
  • Tính nhất quán đáng tin cậy: Mọi dữ liệu ‘đọc’ đều trả về dữ liệu ‘ghi’ mới nhất trên tất cả các cụm.
  • Nhanh: etcd đã được đánh giá ở mức 10.000 lần ghi mỗi giây.
  • Bảo mật: etcd hỗ trợ xác thực chứng chỉ máy khách lớp Transport Layer Security (TLS) tự động và lớp cổng bảo mật (SSL) tùy chọn.

Hình ảnh từ etcd.io

Nói chung, etcd được triển khai dưới dạng cụm trải rộng trên nhiều node. Một cụm nên chứa số lượng node lẻ và cần có ít nhất ba node cho môi trường production.

Vậy nếu chúng ta có nhiều nút etcd thì tính nhất quán của dữ liệu sẽ được duy trì như thế nào?

etcd được xây dựng trên thuật toán đồng thuận Raft để đảm bảo tính nhất quán trong lưu trữ dữ liệu trên tất cả các node trong một cụm cho hệ thống phân tán có khả năng chịu lỗi.

2. Thuật toán đồng thuận Raft (Raft consensus algorithm)

Trong thuật toán Raft, tính nhất quán của dữ liệu được duy trì thông qua node dẫn đầu (leader), nút này sẽ sao chép dữ liệu sang các nút khác trong cụm được gọi là nút theo dõi (followers).

Node leader tiếp nhận các yêu cầu từ client/người dùng, sau đó sẽ chuyển tiếp cho những followers. Sau khi phần lớn những followers gửi lại một mục đã được xác nhận, người đứng đầu sẽ viết mục đó. Nếu followers gặp sự cố, leader sẽ thử lại cho đến khi tất cả followers lưu trữ dữ liệu một cách nhất quán.

Nếu followers không nhận được tin nhắn từ leader , một cuộc bầu cử mới leader sẽ được tiến hành.

Bạn có thể tìm thấy hình ảnh động giải thích tuyệt vời về thuật toán Raft tại đây: http://thesecretlivesofdata.com/raft/

3. Etcd và Kubernetes

Trong cụm Kubernetes, etcd được triển khai dưới dạng các pod trên control plane. Để tăng mức độ bảo mật và khả năng phục hồi, nó cũng có thể được triển khai dưới dạng cụm bên ngoài.

Đối với bài viết này, tôi đang sử dụng cài đặt trên cụm control plane. Khi cài đặt cụm, nó cũng sẽ cài đặt etcd dưới dạng pod trong name space là kube-system.

kubectl get pods -n kube-system

NAME READY STATUS RESTARTS AGE
coredns-76f75df574-bs2jb 1/1 Running 3 (43m ago) 13d
coredns-76f75df574-g2lvr 1/1 Running 3 (43m ago) 13d
etcd-master01 1/1 Running 3 (43m ago) 13d
etcd-master02 1/1 Running 3 (43m ago) 13d
etcd-master03 1/1 Running 3 (43m ago) 13d

kube-apiserver-master01 1/1 Running 3 (43m ago) 13d
kube-apiserver-master02 1/1 Running 3 (43m ago) 13d
kube-apiserver-master03 1/1 Running 4 (43m ago) 13d
kube-controller-manager-master01 1/1 Running 3 (43m ago) 13d
kube-controller-manager-master02 1/1 Running 3 (43m ago) 13d
kube-controller-manager-master03 1/1 Running 3 (43m ago) 13d
kube-proxy-dkhc5 1/1 Running 3 (42m ago) 13d
kube-proxy-k9tk6 1/1 Running 3 (41m ago) 13d
kube-proxy-p5hwd 1/1 Running 3 (42m ago) 13d
kube-proxy-q829c 1/1 Running 3 (43m ago) 13d
kube-proxy-s29q6 1/1 Running 3 (43m ago) 13d
kube-proxy-vvs8x 1/1 Running 3 (42m ago) 13d
kube-proxy-xzxgh 1/1 Running 3 (41m ago) 13d
kube-proxy-zqsh8 1/1 Running 3 (43m ago) 13d
kube-scheduler-master01 1/1 Running 4 (43m ago) 13d
kube-scheduler-master02 1/1 Running 3 (43m ago) 13d
kube-scheduler-master03 1/1 Running 3 (43m ago) 13d

Chúng ta có thể tìm thấy nhiều nhóm trong không gian tên kube-system, nhưng điều chúng ta quan tâm nhất là etcd-master01 phiên bản nào đang chạy phiên bản của etcd và nó được sử dụng để lưu trữ trạng thái của cụm.

4. Tương tác với etcd

Lệnh sau giúp tương tác với etcd-master01 nhóm thông qua kubectl exec. Và ETCDCTL_APIphiên bản API mà chúng tôi muốn tương tác với etcd --cacert, --key and --certcó phải là dành cho chứng chỉ TLS mà chúng tôi sẽ nhận được từ việc thực hiện phần describe commandtrình bày ở trên và get / --prefix --keys-onlysẽ cung cấp tất cả các khóa có trong etcd.SAO CHÉP

kubectl exec etcd-master01 -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt  --key /etc/kubernetes/pki/etcd/server.key --cert  /etc/kubernetes/pki/etcd/server.crt  get / --prefix --keys-only" > etcdkeys.txt

ETCDCTL_APIlà phiên bản API mà chúng tôi sử dụng để etcd tương tác với nó. --cacert, --key and --certdành cho chứng chỉ TLS mà chúng tôi cần và get / --prefix --keys-onlysẽ cung cấp tất cả các khóa có trong etcd.

Sự tương tác ở trên với nhóm etcd đã mang lại cho tôi khoảng 277 khóa, khóa này sẽ xác định cấu hình và trạng thái của tất cả các tài nguyên trong cụm.

Vì vậy, bây giờ hãy tạo một nhóm với image nginx và chúng ta sẽ xem điều gì xảy ra trong cụm etcd.

Vì vậy, về cơ bản, run kubectl run my-pod --image=nginx sẽ kéo và chạy image nginx. Chúng tôi sử dụng cùng một lệnh mà chúng tôi đã sử dụng trước đây để lấy tất cả các khóa được lưu trữ trong etcd và chúng tôi sẽ lưu trữ nó vào một tệp có tên etcd-after-pod.txt.

kubectl exec etcd-master01 -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt get / --prefix --keys-only" > etcd-after-pod.txt

So sánh giữa hai tệp, một tệp trước khi tạo nhóm và một tệp sau khi tạo nhóm, cho tôi thấy những điều sau đây.

Một số sự kiện mới đã được tạo ra. Chúng tôi có 6 sự kiện được tạo riêng cho nhóm của chúng tôi my-pod. Chúng ta hãy xem xét kỹ hơn những sự kiện đó.

Lệnh sau cung cấp cho bạn đầu ra JSON cho sự kiện

/registry/events/default/my-pod.17dba8e9d780e08a

/registry/events/default/my-pod.17dba8ea135e6a2c

/registry/events/default/my-pod.17dba8f56f901142

/registry/events/default/my-pod.17dba8f5717e61d8

/registry/events/default/my-pod.17dba8f58300ead8

Nhưng theo mặc định, tất cả các giá trị của etcd đều được mã hóa.

kubectl exec etcd-master01 -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt get \"/registry/events/default/my-pod.17dba8f58300ead8\" -w json"
{"header":{"cluster_id":5408320426833334523,"member_id":6355510390793779753,"revision":53037,"raft_term":7},"kvs":[{"key":"L3JlZ2lzdHJ5L2V2ZW50cy9kZWZhdWx0L215LXBvZC4xN2RiYThmNTgzMDBlYWQ4","create_revision":52602,"mod_revision":52602,"version":1,"value":"azhzAAoLCgJ2MRIFRXZlbnQStgQK5AIKF215LXBvZC4xN2RiYThmNTgzMDBlYWQ4EgAaB2RlZmF1bHQiACokNmIwZTk4YjUtNzVhYy00M2ViLWI0NDItM2JhMjgwNWEyZTk0MgA4AEIICK/m4LMGEACKAYYCCgdrdWJlbGV0EgZVcGRhdGUaAnYxIggIr+bgswYQADIIRmllbGRzVjE62AEK1QF7ImY6Y291bnQiOnt9LCJmOmZpcnN0VGltZXN0YW1wIjp7fSwiZjppbnZvbHZlZE9iamVjdCI6e30sImY6bGFzdFRpbWVzdGFtcCI6e30sImY6bWVzc2FnZSI6e30sImY6cmVhc29uIjp7fSwiZjpyZXBvcnRpbmdDb21wb25lbnQiOnt9LCJmOnJlcG9ydGluZ0luc3RhbmNlIjp7fSwiZjpzb3VyY2UiOnsiZjpjb21wb25lbnQiOnt9LCJmOmhvc3QiOnt9fSwiZjp0eXBlIjp7fX1CABJgCgNQb2QSB2RlZmF1bHQaBm15LXBvZCIkYzMxNjM2NDMtYjhmOC00YWEzLTkyMjctYjAyMjZiMThmNDI1KgJ2MTIFNTI0NzU6F3NwZWMuY29udGFpbmVyc3tteS1wb2R9GgdTdGFydGVkIhhTdGFydGVkIGNvbnRhaW5lciBteS1wb2QqEwoHa3ViZWxldBIId29ya2VyMDMyCAiv5uCzBhAAOggIr+bgswYQAEABSgZOb3JtYWxSAGIAcgdrdWJlbGV0egh3b3JrZXIwMxoAIgA=","lease":4191039555762830400}],"count":1}
kubectl exec etcd-master01 -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt get \"/registry/events/default/my-pod.17dba8f58300ead8\" -w json" | jq '.kvs[0].value'| cut -d "'" -f2 | base64 --decode

Nếu chúng ta giải mã giá trị được liên kết với khóa, kết quả trả về cũng không thể đọc được nhiều nhưng chúng ta có thể hiểu được một phần.

Trong kết quả trên, bạn có thể tìm thấy một số thông tin thú vị -  started container my-pod.tôi đã giải mã tất cả các sự kiện trong nhóm và đây là những sự kiện xảy ra theo trình tự thời gian.

Scheduled":Successfully assigned default/my-pod to kind-control-plane*
Pulling"Pulling image "nginx"*
Pulled"2Successfully pulled image "nginx" in 35.579712695s
Created"Created container my-pod*
Started"Started container my-pod*

Khóa cuối cùng, /registry/pods/default/my-pod, cung cấp tất cả thông tin liên quan đến Pod mới được tạo:

  • Cấu hình được áp dụng lần cuối
  • Mã thông báo của nó
  • Tình trạng của nó, v.v.

5. Backup restore

5.1 Cài đặt etcdctl

Thực hiện trên node master1.

mkdir -p /tmp/etcd && cd /tmp/etcd
curl -s https://api.github.com/repos/etcd-io/etcd/releases/latest | grep browser_download_url | grep linux-amd64 | cut -d '"' -f 4 | wget -qi -
tar xvf *.tar.gz
sudo mv etcd*/* /usr/local/bin/
cd ~
rm -rf /tmp/etcd

5.2 Kiểm tra file manifests

cat /var/lib/kubelet/config.yaml |grep manifests
sudo cat /etc/kubernetes/manifests/etcd.yaml
ETCDCTL_API=3 etcdctl snapshot backup -h

5.3 Thực hiện backup ra file snapshot.db

sudo ETCDCTL_API=3 etcdctl snapshot save snapshot.db --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key
sudo ETCDCTL_API=3 etcdctl snapshot status --write-out=table snapshot.db
 kubectl -n kube-system get pod
NAME                               READY   STATUS    RESTARTS      AGE
coredns-76f75df574-bs2jb 1/1 Running 3 (75m ago) 13d
coredns-76f75df574-g2lvr 1/1 Running 3 (75m ago) 13d
etcd-master01 1/1 Running 3 (75m ago) 13d
etcd-master02 1/1 Running 3 (75m ago) 13d
etcd-master03 1/1 Running 3 (75m ago) 13d
kube-apiserver-master01 1/1 Running 3 (75m ago) 13d
kube-apiserver-master02 1/1 Running 3 (75m ago) 13d
kube-apiserver-master03 1/1 Running 4 (75m ago) 13d
kube-controller-manager-master01 1/1 Running 3 (75m ago) 13d
kube-controller-manager-master02 1/1 Running 3 (75m ago) 13d
kube-controller-manager-master03 1/1 Running 3 (75m ago) 13d
kube-proxy-dkhc5 1/1 Running 3 (74m ago) 13d
kube-proxy-k9tk6 1/1 Running 3 (73m ago) 13d
kube-proxy-p5hwd 1/1 Running 3 (74m ago) 13d
kube-proxy-q829c 1/1 Running 3 (75m ago) 13d
kube-proxy-s29q6 1/1 Running 3 (75m ago) 13d
kube-proxy-vvs8x 1/1 Running 3 (74m ago) 13d
kube-proxy-xzxgh 1/1 Running 3 (73m ago) 13d
kube-proxy-zqsh8 1/1 Running 3 (75m ago) 13d
kube-scheduler-master01 1/1 Running 4 (75m ago) 13d
kube-scheduler-master02 1/1 Running 3 (75m ago) 13d
kube-scheduler-master03 1/1 Running 3 (75m ago) 13d
kubectl -n kube-system get pod kube-apiserver-master01 -o=jsonpath='{.spec.containers[0].command}' |jq |grep etcd
"--etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt",
"--etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt",
"--etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key",
"--etcd-servers=https://127.0.0.1:2379"
sudo ETCDCTL_API=3 etcdctl member list --endpoints=https://127.0.0.1:2379 --cert=/etc/kubernetes/pki/a
piserver-etcd-client.crt --cacert=/etc/kubernetes/pki/etcd/ca.crt --key=/etc/kubernetes/pki/apiserver-etcd-client.key
58334f0709913a29, started, master01, https://10.1.1.11:2380, https://10.1.1.11:2379, false
78680569136cdf45, started, master02, https://10.1.1.12:2380, https://10.1.1.12:2379, false
d084c1a988cd8b66, started, master03, https://10.1.1.13:2380, https://10.1.1.13:2379, false

Có thể thiết lập backup bằng cách viết script crontab hoặc viết ứng dụng chạy trên K8s.
Tham khảo: https://braindose.blog/2022/02/09/etcdctl-backup-kubernetes/
https://github.com/nickkeyzer/etcd-backup

5.4. Backup các file cấu hình và certificates

sudo tar -zcvf etcd.tar.gz /etc/kubernetes/pki/etcd

5.5 Restoring Etcd từ file Snapshot & kiểm tra:

kubectl get all
kubectl create ns demo-backup-restore
kubectl run testing-restore --image=nginx
kubectl get pods
ETCDCTL_API=3 etcdctl snapshot restore -h
sudo cat /etc/kubernetes/manifests/etcd.yaml

5.6 Thực hiện xóa nội dung trong ETCD và restore

rm -rf /var/lib/etcd
ETCDCTL_API=3 etcdctl snapshot restore snapshot.db --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --name=master01 --data-dir=/var/lib/etcd --initial-cluster=master01=https://10.1.1.11:2380 --initial-cluster-token=master01 --initial-advertise-peer-urls=https://10.1.1.11:2380

6. Tài liệu tham khảo:

https://blog.kubesimplify.com/understanding-etcd-in-kubernetes-a-beginners-guide

https://raft.github.io/raft.pdf

https://etcd.io/docs/v3.6/op-guide/clustering

https://braindose.blog/2022/02/09/etcdctl-backup-kubernetes

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply