- vừa được xem lúc

Sử dụng Dragonfly để tối ưu hoá việc phân tán Docker Image giữa các node trên Kubernetes cluster

0 0 17

Người đăng: Dao Thai Son

Theo Viblo Asia

Giới thiệu Dragonfly

Dragonfly là một dự án mã nguồn mở quan trọng và đột phá được phát triển bởi Alibaba Group, nhằm giải quyết các thách thức về việc quản lý và phân tán Docker image hiệu quả trên môi trường Kubernetes (k8s). Với mục tiêu tối ưu hóa hiệu suất tải và chia sẻ Docker image trong các môi trường mạng phức tạp, Dragonfly đã mang đến những giải pháp đột phá, giúp giảm bớt tải trên nguồn chính và tăng tốc quá trình tải xuống. Bài viết này sẽ giới thiệu về Dragonfly, từ mục tiêu, nguyên tắc hoạt động đến cách tích hợp và tận dụng trong môi trường Kubernetes.

Mục tiêu của Dragonfly

Một trong những thách thức chính của việc quản lý Docker image trong môi trường Kubernetes là vấn đề tải xuống và chia sẻ hiệu quả. Khi có nhiều container đang chạy trên cùng một node hoặc trên các node khác nhau, việc tải xuống lại và lưu trữ lặp đi lặp lại các Docker image có thể gây lãng phí băng thông mạng và tài nguyên hệ thống. Mục tiêu của Dragonfly là giảm tải trên nguồn gốc và tối ưu hóa việc chia sẻ Docker image giữa các container trên cùng một node hoặc giữa các node khác nhau.

Nguyên tắc hoạt động của Dragonfly

Dragonfly hoạt động dựa trên mô hình peer-to-peer (P2P). Nó tận dụng sức mạnh cộng đồng để chia sẻ và tải xuống Docker image một cách hiệu quả. Khi một Docker image được yêu cầu, Dragonfly sẽ kiểm tra xem có bản cache của image đó trên các nút khác trong mạng không. Nếu có, nó sẽ tải image từ cache đó thay vì từ nguồn chính, giúp giảm tải trên nguồn chính và tăng tốc độ tải xuống.

Đặc biệt, Dragonfly cung cấp tính năng P2P Caching, cho phép lưu trữ cache của các Docker image trên các nút trong mạng. Điều này giúp tối ưu hóa việc chia sẻ và lưu trữ image trên các nút, từ đó cải thiện hiệu suất và giảm áp lực lên nguồn gốc.

Một số tính năng quan trọng của Dragonfly khi được sử dụng để phân tán Docker image trên một Kubernetes cluster có thể kể tới như:

  • Tăng tốc tải Docker image: Dragonfly tận dụng việc chia sẻ Docker image đã tải trước đó giữa các nút trong mạng, giúp giảm tải trên nguồn gốc và giảm thời gian tải xuống.

  • P2P Caching: Dragonfly sử dụng mô hình peer-to-peer (P2P) để lưu trữ cache của các Docker image trên các nút trong mạng, giúp tăng tốc quá trình tải và chia sẻ image.

  • Sự linh hoạt và mở rộng: Dragonfly có thể linh hoạt tích hợp vào môi trường Kubernetes và mở rộng theo nhu cầu, giúp quản lý tài nguyên hiệu quả trong môi trường phức tạp.

  • Quản lý băng thông: Dragonfly giúp kiểm soát băng thông và giới hạn lưu lượng mạng được sử dụng trong quá trình tải và chia sẻ image.

Thực hành triển khai Dragonfly lên Kubernetes cluster

Để tiến hành triển khai Dragonfly cho Kubernetes cluster chúng ta cần chuẩn bị trước các công cụ cần thiết, trong bài viết này mình sẽ demo cách cấu hình trên 1 cụm được dựng từ Kind. Trước tiên bạn cần cài đặt các công cụ dưới đây:

  • Kind (Kubernetes IN Docker): một dự án mã nguồn mở giúp tạo và quản lý các cluster Kubernetes sử dụng Docker container như các node
  • Docker
  • Helm: Helm là một công cụ quản lý gói và triển khai ứng dụng trên Kubernetes

Việc cài đặt các công cụ trên khá đơn giản chúng ta chỉ cần follow theo docs để setup

Dựng Kubernetes cluster bằng Kind

Để tạo một cluster Kubernetes sử dụng Kind (Kubernetes IN Docker), bạn chỉ cần làm theo các bước sau:

  1. Tạo file kind-config.yaml chứa cấu hình của cụm cần tạo
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes: - role: control-plane - role: worker - role: worker

mình sẽ sử dụng cụm có 3 nodes, trong đó có 2 worker node.

  1. Sau cho chạy command để Kind dựng Kubernetes cluster
$ kind create cluster --config kind-config.yaml
Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.27.3) 🖼 ✓ Preparing nodes 📦 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind"
You can now use your cluster with: kubectl cluster-info --context kind-kind Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂

kết quả như trên là thành công, ở bước này bạn đã có cho mình 1 K8s cluster dưới local

$ kubectl get node
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 77s v1.27.3
kind-worker Ready <none> 55s v1.27.3
kind-worker2 Ready <none> 56s v1.27.3

Cài đặt Dragonfly bằng Helm

Helm là một công cụ quản lý gói và triển khai ứng dụng trên Kubernetes. Bằng việc sử dụng Helm, ta sẽ dễ dàng cài đặt Dragonfly qua các bước sau:

  1. Khởi tạo namespace trên Kubernetes cho Dragonfly
$ kubectl create namespace dragonfly namespace/dragonfly created
  1. Thêm Helm Repository của Dragonfly
$ helm repo add dragonfly https://dragonflyoss.github.io/helm-charts/
  1. Cài đặt Dragonfly

Ở bước này, thay vì sử dụng Helm values mặc định của Dragonfly chart, mình sẽ cấu hình lại 1 chút để giải quyết vấn đề

  • Kubernetes phiên bản mới hiện không còn sử dụng Docker làm container runtime nữa, thay vào đó sẽ dùng Containerd nên chúng ta cần cập nhật config của Containerd daemon.
  • Ngoài ra, để cache được các Docker Image từ Docker Hub thì mình cần chỉnh sửa lại 1 chút config để khi Kubelet pull 1 image từ Docker Hub, khi không tìm thấy cache ở trong Dragonfly, nó sẽ pull tiếp từ Registry https://index.docker.io thay vì https://docker.io.

Mọi người có thể tham khảo file dragonfly-config.yaml của mình:

containerRuntime: extraInitContainers: - name: setup-mirror image: dragonflyoss/openssl command: - /bin/sh - -cx - |- echo "inject config_path into /etc/containerd/config.toml" if grep -q '\[plugins."io.containerd.grpc.v1.cri".registry\]' /etc/containerd/config.toml}; then sed -i 's|\[plugins."io.containerd.grpc.v1.cri".registry\]|\[plugins."io.containerd.grpc.v1.cri".registry\]\nconfig_path = "/etc/containerd/certs.d"|g' /etc/containerd/config.toml else cat << EOF >> /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d" EOF fi echo "Registry config_path $config_path added" mkdir -p /etc/containerd/certs.d mkdir -p /etc/containerd/certs.d/docker.io cat << EOF >> /etc/containerd/certs.d/docker.io/hosts.toml server = "https://docker.io" [host."http://127.0.0.1:65001"] capabilities = ["pull", "resolve"] [host."http://127.0.0.1:65001".header] X-Dragonfly-Registry = ["https://index.docker.io"] [host."https://index.docker.io"] capabilities = ["pull", "resolve"] EOF mkdir -p /etc/containerd/certs.d/ghcr.io cat << EOF >> /etc/containerd/certs.d/ghcr.io/hosts.toml server = "https://ghcr.io" [host."http://127.0.0.1:65001"] capabilities = ["pull", "resolve"] [host."http://127.0.0.1:65001".header] X-Dragonfly-Registry = ["https://ghcr.io"] [host."https://ghcr.io"] capabilities = ["pull", "resolve"] EOF echo "Restart containerd\n" nsenter -t 1 -m -- systemctl restart containerd.service volumeMounts: - name: containerd-conf mountPath: /etc/containerd/ securityContext: privileged: true containerd: enable: true injectConfigPath: true
scheduler: tag: latest replicas: 1 metrics: enable: true config: verbose: true pprofPort: 18066
redis: replicas: 1
seedPeer: replicas: 1 metrics: enable: true config: verbose: true pprofPort: 18066 dfdaemon: tag: latest metrics: enable: true config: verbose: true console: true pprofPort: 18066 manager: tag: latest replicas: 1 metrics: enable: true config: verbose: true pprofPort: 18066 jaeger: enable: true

Khi đã có file chứa Helm values cho Dragonfly thì chúng ta chỉ cần install chart lên Kubernetes cluster thôi

$ helm upgrade --install -n dragonfly dragonfly dragonfly/dragonfly -f dragonfly-config.yaml Release "dragonfly" does not exist. Installing it now.
NAME: dragonfly
LAST DEPLOYED: Fri Sep 29 15:56:41 2023
NAMESPACE: dragonfly
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the scheduler address by running these commands: export SCHEDULER_POD_NAME=$(kubectl get pods --namespace dragonfly -l "app=dragonfly,release=dragonfly,component=scheduler" -o jsonpath={.items[0].metadata.name}) export SCHEDULER_CONTAINER_PORT=$(kubectl get pod --namespace dragonfly $SCHEDULER_POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") kubectl --namespace dragonfly port-forward $SCHEDULER_POD_NAME 8002:$SCHEDULER_CONTAINER_PORT echo "Visit http://127.0.0.1:8002 to use your scheduler" 2. Get the dfdaemon port by running these commands: export DFDAEMON_POD_NAME=$(kubectl get pods --namespace dragonfly -l "app=dragonfly,release=dragonfly,component=dfdaemon" -o jsonpath={.items[0].metadata.name}) export DFDAEMON_CONTAINER_PORT=$(kubectl get pod --namespace dragonfly $DFDAEMON_POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") You can use $DFDAEMON_CONTAINER_PORT as a proxy port in Node. 3. Configure runtime to use dragonfly: https://d7y.io/docs/getting-started/quick-start/kubernetes/ 4. Get Jaeger query URL by running these commands: export JAEGER_QUERY_PORT=$(kubectl --namespace dragonfly get services dragonfly-jaeger-query -o jsonpath="{.spec.ports[0].port}") kubectl --namespace dragonfly port-forward service/dragonfly-jaeger-query 16686:$JAEGER_QUERY_PORT echo "Visit http://127.0.0.1:16686/search?limit=20&lookback=1h&maxDuration&minDuration&service=dragonfly to query download events"

Giờ chúng ta chỉ cần chờ cho việc deploy hoàn thành và test thôi. Kết quả như dưới đây là chúng ta đã setup thành công

NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dragonfly-dfdaemon-h42jz 1/1 Running 0 5m34s 10.244.2.5 kind-worker <none> <none>
dragonfly-dfdaemon-pz8sl 1/1 Running 0 5m34s 10.244.1.2 kind-worker2 <none> <none>
dragonfly-jaeger-c7947b579-gxq92 1/1 Running 0 5m34s 10.244.2.3 kind-worker <none> <none>
dragonfly-manager-86d4874c55-pv5pl 1/1 Running 0 5m34s 10.244.2.4 kind-worker <none> <none>
dragonfly-mysql-0 1/1 Running 0 5m34s 10.244.1.8 kind-worker2 <none> <none>
dragonfly-redis-master-0 1/1 Running 0 5m34s 10.244.1.9 kind-worker2 <none> <none>
dragonfly-redis-replicas-0 1/1 Running 2 (3m24s ago) 5m34s 10.244.1.7 kind-worker2 <none> <none>
dragonfly-redis-replicas-1 1/1 Running 0 3m4s 10.244.2.8 kind-worker <none> <none>
dragonfly-redis-replicas-2 1/1 Running 0 99s 10.244.2.10 kind-worker <none> <none>
dragonfly-scheduler-0 1/1 Running 0 5m34s 10.244.1.3 kind-worker2 <none> <none>
dragonfly-seed-peer-0 1/1 Running 1 (2m ago) 5m34s 10.244.2.6 kind-worker <none> <none>

Kiểm tra tốc độ pull image trên các Node sau khi triển khai Dragonfly

Trên Dragonfly đã tích hợp công cụ Jaeger để tracing, chúng ta có thể vào đó để theo dõi thời gian pull image. Để sử dụng Jaeger, chúng ta forward-port từ trong Kubernetes ra máy host thông qua command

$ kubectl port-forward svc/dragonfly-jaeger-query 16686:16686

sau đó truy cập localhost:16686 để sử dụng Jaeger.

Pull image trên node kind-worker

Để thực hiện pull image, chúng ta sẽ exec vào docker container của Node và pull image về. Trong lần đầu tiên pull image trên Node, Dragonfly sẽ chưa có ảnh hưởng, nó sẽ chỉ hỗ trợ lưu image vào cache.

$ docker exec -it kind-worker bash
# Sau khi exec vào container worker, chúng ta sẽ tiến hành pull image thông qua command dưới
$ root@kind-worker:/# time (crictl pull node:16)
Image is up to date for sha256:1ddc7e4055fdb6f6bf31063b593befda814294f9f904b6ddfc21ab1513bafa8e real	2m19.398s
user	0m0.307s
sys	0m0.042s

như bạn thấy, image node:16 được pull về node kind-worker tốn 2m19s.

Trong Jaeger cũng thể hiển rõ

Pull image trên node kind-worker2 để xem hiệu quả cải thiện sau khi có Dragonfly

Chúng ta tiếp tục exec vào docker container của node kind-worker2 và tiến hành pull image. Tuy nhiên, trong lần pull image này, thời gian pull sẽ giảm rõ rệt do Dragonfly đã caching lại các layer.

$ docker exec -it kind-worker2 bash
# Sau khi exec vào container worker 2, chúng ta sẽ tiến hành pull image thông qua command dưới
$ root@kind-worker2:/# time (crictl pull node:16)
Image is up to date for sha256:1ddc7e4055fdb6f6bf31063b593befda814294f9f904b6ddfc21ab1513bafa8e real	0m20.095s
user	0m0.035s
sys	0m0.031s

lần pull ở node worker 2 này, chúng ta chỉ mất 20s. Một cải thiện đáng kể. Bạn có thể xem lại trace trên Jaeger

So sánh giữa 2 lần pull trên 2 node

Kết luận

Dragonfly đóng vai trò quan trọng trong việc giải quyết vấn đề tải xuống và quản lý Docker image trong môi trường Kubernetes. Bằng cách tận dụng mô hình P2P và khả năng lưu trữ cache, Dragonfly mang lại lợi ích lớn cho việc tối ưu hóa hiệu suất và giảm tải trên nguồn gốc, đồng thời tăng tốc quá trình tải xuống và chia sẻ Docker image. Sự tích hợp linh hoạt và mở rộng của Dragonfly giúp tối ưu hóa môi trường Kubernetes, mang lại hiệu suất và hiệu quả lớn cho quản lý Docker image.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 414

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 467

- vừa được xem lúc

Sử dụng Swagger để xây dựng API documentation

Giới thiệu về Swagger. RESTful API là một tiêu chuẩn dùng trong việc thiết kế API cho các ứng dụng web (thiết kế Web services) để tiện cho việc quản lý các resource.

0 0 1k

- vừa được xem lúc

So sánh Interface và Abstract trong lập trình hướng đối tượng.

Tổng quan. Interface và Abstract class là 2 khái niệm cơ bản trong lập trình OOP.

0 0 63

- vừa được xem lúc

CURL và cách sử dụng trong PHP

Giới Thiệu. CURL là bộ thư viện được sử dụng để giúp thực hiện việc chuyển dữ liệu thông qua nhiều giao thức khác nhau (như HTTP, FPT...). Với giao thức HTTP, cURL hỗ trợ việc gửi dữ liệu sử dụng tất cả các phương thức hiện có như GET, POST, PUT, DELETE... cURL cũng hỗ trợ việc chuyền dữ liệu sử dụn

0 0 93

- vừa được xem lúc

Thêm dòng dữ liệu mới (MySQL) trong Laravel

Chào các bạn, Laravel hiện đang là hot trend trong "thế giới PHP". 1. Cấu hình cơ bản ban đầu. .

0 0 51