Trong bối cảnh công nghệ không ngừng phát triển như hiện nay, các công ty đang tìm kiếm những phương thức đáng tin cậy và có khả năng mở rộng để vận hành và quản lý phần mềm. Container đã cách mạng hóa cách chúng ta phân phối phần mềm.
Trong bối cảnh công nghệ không ngừng phát triển như hiện nay, các công ty đang tìm kiếm những phương thức đáng tin cậy và có khả năng mở rộng để vận hành và quản lý phần mềm. Container đã cách mạng hóa cách chúng ta phân phối phần mềm.
Các nền tảng điều phối container đã giúp cho việc triển khai và quản lý các ứng dụng được đóng gói trở nên khả thi. Kubernetes là một trong những nền tảng như vậy, nó đã tạo ra một cuộc cách mạng cho các nhà phát triển, những người đang phải đối mặt với những thách thức trong việc triển khai ứng dụng.
Kubernetes đã giúp cho việc quản lý và mở rộng quy mô triển khai theo nhu cầu của bạn trở nên dễ dàng hơn rất nhiều. Trong hướng dẫn này, tôi sẽ giúp bạn hiểu được sự đơn giản của Kubernetes, vì vậy hãy sẵn sàng.
Đầu tiên, chúng ta sẽ lấy một ứng dụng Node và đóng gói nó bằng Docker. Sau đó, tôi sẽ chỉ cho bạn cách sử dụng Kubernetes – từ việc thiết lập cụm, tạo triển khai và dịch vụ đến mở rộng quy mô ứng dụng. Hãy chắc chắn rằng bạn sẽ theo dõi đến cuối bài viết để nhận được giá trị tối đa. Nó sẽ rất tuyệt vời đấy.
Bạn có thể tìm thấy mã nguồn đầy đủ trong GitHub Repo này.
Tôi sẽ bắt đầu với một lưu ý về điều phối container.
Điều phối container là gì?
Container cung cấp một môi trường hiệu quả và biệt lập cho ứng dụng của bạn. Nhưng khi ứng dụng của bạn phát triển, số lượng container cũng vậy.
Việc xử lý các container trong môi trường production có thể nhanh chóng trở thành một vấn đề nan giải, đặc biệt nếu bạn đang sử dụng microservices. Việc triển khai nhanh hơn, giám sát, mở rộng quy mô, kết nối mạng và cân bằng tải đột nhiên trở thành những nhiệm vụ khó khăn.
Đó là lúc cần đến sự điều phối container. Nó tự động hóa những thách thức này và đảm bảo rằng các container đang hoạt động trơn tru. Nó đơn giản hóa quy trình triển khai và mở rộng quy mô, do đó hợp lý hóa quy trình làm việc của bạn.
Thêm vào đó, điều phối đóng vai trò quan trọng trong kết nối mạng và tạo điều kiện thuận lợi cho việc giao tiếp giữa các container trên nhiều máy chủ. Bạn muốn hiển thị các container của mình với thế giới bên ngoài? Điều phối container sẽ giúp bạn thực hiện điều đó một cách dễ dàng.
Chuẩn bị ứng dụng đóng gói
Nhiệm vụ đầu tiên của bạn là thiết lập một ứng dụng Node và đóng gói nó thành một image Docker. Đối với việc này, bạn cần cài đặt Node.js trong hệ thống của mình. Nếu chưa, hãy làm theo hướng dẫn này để cài đặt Node trên Mac và Windows.
Bạn không cần phải quen thuộc với Node.js hoặc JavaScript để thực hiện theo hướng dẫn này. Chỉ cần làm theo các bước được đề cập dưới đây. Trọng tâm chính của bài đăng này là Kubernetes.
Thiết lập ứng dụng Node
Để thiết lập ứng dụng Node của bạn, hãy tạo một thư mục có tên là sample-node-application và điều hướng bên trong nó. Chạy lệnh npm init và nhập giá trị cho từng trường tương ứng với entrypoint là server.js.
... Lệnh npm init ...
Một tệp package.json sẽ được tạo ra để chỉ định các dependency cần thiết mà ứng dụng của bạn cần. Tạo một tệp server.js, tệp này sẽ chứa các API của bạn.
const express = require("express");
const data = require("./data.json")
const app = express();
app.get("/", (req, res) => res.send("Hello, Welcome to the Node App") )
app.get("/data", (req, res) => res.json(data) )
app.listen(8000, () => console.log("App is running") );
Tạo một tệp data.json riêng biệt và thêm một số dữ liệu giả vào đó. Bạn có thể tạo dữ liệu giả từ Mockaroo.
Chạy lệnh node server để kiểm tra xem ứng dụng có đang chạy hay không.
Xây dựng Image Docker
Trước khi xây dựng image, hãy kiểm tra xem bạn đã cài đặt Docker trong hệ thống của mình chưa. Nếu chưa, hãy tham khảo hướng dẫn cài đặt cho các hệ điều hành khác nhau. Chạy docker --version để xác nhận rằng Docker đã được cài đặt.
Đây là cách Dockerfile của chúng ta sẽ trông như thế nào:
FROM node:18-alpine
WORKDIR /sample-node-app
COPY server.js /sample-node-app/
COPY package.json /sample-node-app/
COPY data.json /sample-node-app/
RUN npm install
CMD ["node", "server"]
Chạy lệnh sau để xây dựng image Docker:
docker build -t node-image .
Kiểm tra xem image của bạn đã được tạo bằng lệnh docker images hay chưa. Bây giờ, hãy đẩy image này lên Docker Hub. Truy cập Docker Hub và đăng nhập. Nếu bạn chưa có tài khoản, hãy tiếp tục và đăng ký một tài khoản.
Khi bạn đã đăng nhập, hãy tạo một repository có tên node-image và đặt nó ở chế độ công khai. Bây giờ, quay lại terminal của bạn, chạy docker login và nhập tên người dùng và mật khẩu của bạn. Sau đó, gắn thẻ image với tên người dùng của bạn.
docker image tag react-example-image <username>/node-image
Đẩy image này lên Docker Hub bằng lệnh sau:
docker push <username>/node-image
Image của bạn sẽ được đẩy lên Docker Hub.
Ở đây, tôi đã giải thích ngắn gọn các bước tạo image. Nếu bạn muốn có giải thích chi tiết hơn, bạn có thể đọc hướng dẫn của tôi về Cách Dockerize một Ứng dụng React.
Trước khi đi sâu vào các bước tiếp theo, trước tiên chúng ta hãy hiểu Kubernetes là gì, tại sao cần nó và một số khái niệm chính.
Kubernetes là gì và tại sao bạn lại cần nó?
Kubernetes (viết tắt là K8s) là một nền tảng điều phối container mã nguồn mở. Điều phối là tất cả về việc tự động hóa triển khai, mở rộng quy mô và quản lý các container.
Kubernetes sử dụng cách tiếp cận khai báo, trong đó bạn xác định trạng thái mong muốn của ứng dụng của mình trong tệp YAML. Sau đó, Kubernetes sẽ hoạt động để đạt được trạng thái đó và đảm bảo rằng trạng thái đó được duy trì.
Nó cho phép sự hợp tác chặt chẽ giữa các nhóm phát triển và vận hành, đồng thời giúp kích hoạt các phương pháp DevOps hiệu quả.
Các vấn đề mà Kubernetes giúp bạn giải quyết
Theo truyền thống, nhiều ứng dụng được triển khai trên các máy chủ vật lý. Điều này đặt ra một số vấn đề.
Nếu một ứng dụng cuối cùng chiếm nhiều dung lượng hơn dự kiến, thì các ứng dụng khác sẽ không nhận đủ tài nguyên. Ngoài ra, việc mở rộng quy mô rất khó khăn và tốn kém cho các tổ chức.
Sau đó là máy ảo (VM). Chúng cho phép sử dụng tài nguyên tốt hơn so với hệ thống vật lý và cũng giúp việc mở rộng quy mô dễ dàng và rẻ hơn. Nhưng container cung cấp một giải pháp nhẹ hơn nhiều so với máy ảo.
Để chạy và quản lý các container này, chúng ta cần Kubernetes để cung cấp khả năng tự động hóa cần thiết với các tính năng sau:
- Khám Phá Dịch Vụ và Cân Bằng Tải cho phép các ứng dụng giao tiếp với nhau bất kể chúng đang chạy ở đâu.
- Mở Rộng Quy Mô Tự Động cho phép Kubernetes tự động mở rộng quy mô số lượng container tùy thuộc vào cấu hình được cung cấp.
- Với Tự Phục Hồi, Kubernetes có thể khởi động lại bất kỳ container nào đã ngừng chạy hoặc không chạy được.
- Kubernetes cho phép Gắn Bộ Nhớ vào triển khai của bạn một cách tự động.
- Triển Khai Tự Động: Kubernetes tuân theo cơ chế khai báo để đạt được và duy trì trạng thái mong muốn của ứng dụng.
- Quản Lý Bí Mật và Cấu Hình: Bạn có thể thêm cấu hình và bí mật vào triển khai để ứng dụng của bạn có thể sử dụng bất kỳ cấu hình nào mà nó cần dựa trên môi trường mà nó được triển khai (dev hoặc prod).
Nếu bạn muốn biết thêm về Kubernetes và các thành phần của nó, hãy truy cập tài liệu trên trang chủ của nó nhé.
Các khái niệm chính của Kubernetes
Sau đây là các khái niệm chính mà bạn cần biết để sử dụng Kubernetes hiệu quả trong các dự án của mình.
Pod Là Gì?
Pod là một đơn vị triển khai duy nhất trong Kubernetes chứa một hoặc nhiều container. Pod chịu trách nhiệm chạy các container của ứng dụng của bạn trong cụm Kubernetes. Nó là một phiên bản duy nhất của một ứng dụng đang chạy.
Bạn có thể tạo một pod bằng cấu hình YAML đơn giản. Thông thường, bạn không cần phải tạo chúng một cách rõ ràng. Thay vào đó, bạn có thể sử dụng cấu hình Triển khai để tạo pod. Chúng ta sẽ sớm tìm hiểu cách thực hiện điều đó.
Mặc dù một pod có thể chạy nhiều container, nhưng thông lệ phổ biến là chạy một container duy nhất trong một pod. Đọc thêm về pod tại đây.
Triển khai hoạt động như thế nào?
Kubernetes nhằm mục đích duy trì trạng thái mong muốn của ứng dụng mọi lúc. Triển khai mô tả trạng thái mong muốn thông qua cấu hình YAML.
Cấu hình triển khai được sử dụng để quyết định số lượng bản sao của pod của bạn, sửa đổi cấu hình pod, khôi phục về trạng thái trước đó, tăng/giảm quy mô ứng dụng của bạn và hơn thế nữa.
Khi bạn tạo một triển khai, nó sẽ tạo ra các pod chạy các container mà bạn đã chỉ định. Khi bạn đã tạo cấu hình triển khai, bạn không cần phải tạo tệp cấu hình riêng cho pod. Bạn sẽ hiểu rõ hơn trong phần thực hành.
Dịch vụ là gì?
Giả sử bạn có nhiều ứng dụng được triển khai dưới dạng pod. Các ứng dụng này có thể cần giao tiếp với nhau. Mỗi pod có địa chỉ IP duy nhất của nó, vì vậy chúng có thể chỉ cần sử dụng cùng một địa chỉ IP để giao tiếp, phải không? Trên thực tế, điều này đặt ra một số vấn đề.
Pod có tuổi thọ tương đối ngắn hơn. Nếu có bất kỳ sự cố nào xảy ra và pod bị chấm dứt, Kubernetes sẽ khởi động một pod mới vì nó cần duy trì trạng thái mong muốn của việc triển khai.
Pod mới này sẽ có một địa chỉ IP khác. Nhưng các pod khác vẫn đang sử dụng IP của pod cũ để giao tiếp. Vì vậy, pod mới này sẽ không thể được khám phá trừ khi tất cả các pod khác cập nhật IP mà chúng đang giao tiếp.
Đây là lúc dịch vụ phát huy tác dụng. Dịch vụ giúp hiển thị các nhóm pod qua mạng bằng cách thêm một lớp trừu tượng. Sự trừu tượng này cung cấp một điểm cuối ổn định để các pod giao tiếp với nhau.
Chúng ta hãy xem xét một khái niệm cuối cùng, Cụm Kubernetes. Tôi biết nó có vẻ giống như rất nhiều lý thuyết, nhưng đừng lo lắng, phần thực hành sắp đến rồi.
Cụm Kubernetes
Cụm K8s là một nhóm các máy (hoặc nút) chạy và quản lý các ứng dụng của bạn. Cụm bao gồm các nút worker và một mặt phẳng điều khiển kiểm soát và quản lý những worker này.
Mặt phẳng điều khiển đưa ra một số quyết định như lên lịch, khởi động một pod mới, v.v. Nó bao gồm các thành phần sau:
- api-server: Tiếp xúc với Kubernetes API
- etcd: Kho lưu trữ giá trị khóa cho dữ liệu cụm
- scheduler: Theo dõi các pod mới được tạo và chỉ định một nút worker để chạy chúng.
- controller-manager: Chạy một vòng lặp điều khiển theo dõi trạng thái của cụm thông qua api-server và nếu cần, di chuyển trạng thái hiện tại sang trạng thái mong muốn.
Các Nút Worker chịu trách nhiệm chạy và duy trì các pod. Mỗi nút worker bao gồm các thành phần sau:
- kubelet: Đảm bảo rằng các container đang hoạt động bình thường và chạy trong Pod.
- kube-proxy: Proxy mạng chạy trên mỗi nút và cho phép giao tiếp với nút worker từ bên trong và bên ngoài cụm.
- container-runtime: Chịu trách nhiệm chạy các container
Đó là tất cả cho các khái niệm chính - chúng ta hãy đi sâu vào phần thực hành.
Cho đến nay, chúng ta đã tạo ra một image Docker của ứng dụng Node và đẩy nó lên Docker Hub. Image có thể được truy cập từ bất cứ đâu.
Bây giờ, hãy xem cách bạn có thể lấy ứng dụng này và chạy nó trong Cụm Kubernetes.
Cài đặt
Hãy cài đặt tiện ích dòng lệnh Kubernetes, kubectl. Bạn sẽ tìm thấy hướng dẫn cài đặt trên Linux, Mac và Windows tại đây.
Sau khi làm theo các bước được đề cập, hãy chạy lệnh sau để kiểm tra xem kubectl đã được cài đặt chưa:
kubectl version --client
Thiết lập Cụm Kubernetes
Để triển khai ứng dụng của bạn, bạn cần thiết lập một Cụm Kubernetes sẽ chạy các pod và dịch vụ của bạn. Có rất nhiều cụm được cung cấp bởi nhiều nhà cung cấp đám mây như Google, Amazon và Microsoft. Đối với ứng dụng này, chúng tôi sẽ sử dụng Minikube.
Minikube là một công cụ cho phép bạn chạy một cụm K8s nút đơn trên máy tính của mình. Nó là một sân chơi cá nhân để thử nghiệm Kubernetes trong hệ thống của bạn.
Tham khảo hướng dẫn này để thiết lập minikube trên Mac hoặc Windows. Kiểm tra xem Minikube đã được cài đặt bằng cách chạy lệnh minikube version.
Chạy lệnh minikube start để khởi động một cụm Kubernetes cục bộ.
Viết cấu hình YAML
Bây giờ, hãy viết cấu hình triển khai và dịch vụ của chúng ta trong các tệp YAML.
Đầu tiên, hãy xem cách tạo cấu hình triển khai, từng bước một.
apiVersion: apps/v1
kind: Deployment
metadata: name: sample-node-app namespace: default
Trong đó:
- apiVersion: Chỉ định phiên bản API của tài nguyên,
- kind: Xác định loại tài nguyên, là Triển khai.
- metadata: Chứa siêu dữ liệu về triển khai. Ở đây, chúng ta đã chỉ định tên của triển khai và đặt không gian tên mặc định.
spec: replicas: 2 selector: matchLabels: app: sample-node-app template: metadata: labels: app: sample-node-app spec: containers: - name: sample-node-app image: kunalmac25/node-image imagePullPolicy: Always ports: - containerPort: 8000
Trong đó:
- spec: Mô tả trạng thái mong muốn của triển khai.
- replicas: Chỉ định số lượng bản sao (phiên bản) mong muốn của ứng dụng để chạy, trong trường hợp này là 1.
- Các trường selector và matchLabels chỉ định các nhãn mà triển khai có thể xác định các pod.
- template: Xác định một mẫu cho pod của bạn. Bạn có thể chỉ định một số siêu dữ liệu trong trường metadata. Đề cập đến nhãn mà pod nên được xác định.
- Trường spec trong template mô tả trạng thái mong muốn của pod, bao gồm danh sách các container.
- Đối với mỗi container, bạn có thể chỉ định tên, image mà nó nên lấy từ đó và cổng mà nó được hiển thị. imagePullPolicy chỉ định chính sách lấy image. Ở đây, tôi đã sử dụng Always (luôn lấy image mới nhất từ registry).
Đây là nội dung của tệp deployment.yaml. Bây giờ, hãy viết service.yaml của chúng ta.
apiVersion: v1
kind: Service
metadata: name: node-service namespace: default
Tương tự như triển khai, hãy bắt đầu với phiên bản API và một số siêu dữ liệu về dịch vụ.
spec: type: LoadBalancer selector: app: sample-node-app ports: - port: 80 targetPort: 8000
Trong đó:
- Ở đây, trường spec mô tả trạng thái mong muốn của Dịch vụ thuộc loại LoadBalancer.
- selector: Chỉ định nhãn xác định với pod mà dịch vụ nên chuyển hướng lưu lượng đến.
- ports: Chỉ định danh sách các cổng mà dịch vụ nên hiển thị.
- port: Chỉ định cổng mà dịch vụ lắng nghe. Lưu lượng truy cập bên ngoài sẽ đến cổng này, trong khi targetPort chỉ định cổng trên các pod mà dịch vụ nên chuyển tiếp lưu lượng đến. Trong trường hợp của chúng ta, lưu lượng truy cập đến trên cổng 80 của dịch vụ sẽ được gửi đến các pod trên cổng 8000.
Tạo Pod, triển khai và dịch vụ
Sử dụng kubectl apply để áp dụng các cấu hình trên và tạo pod, triển khai và dịch vụ.
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Ngoài ra, bạn cũng có thể đặt cả hai cấu hình này vào một tệp `manifest.yaml
kubectl apply -f manifest.yaml
Kiểm tra pod, triển khai và dịch vụ của bạn bằng cách sử dụng các lệnh kubectl get.
Hãy chắc chắn rằng bạn đã thực thi lệnh minikube start trước khi áp dụng bất kỳ tệp nào, vì bạn cần khởi động một cụm để chạy pod của mình.
Bạn có thể thấy từ kết quả đầu ra ở trên rằng cả hai bản sao của pod đều đang chạy tốt. Nếu nó hiển thị 0/2 trong READY, điều đó có nghĩa là đã có sự cố nào đó xảy ra trong khi tạo container. Bạn nên kiểm tra xem ứng dụng của mình có hoạt động bình thường hay không trước khi triển khai lại.
Bạn cũng có thể kiểm tra nhật ký pod bằng lệnh kubectl logs.
Minikube cũng cung cấp một bảng điều khiển hiển thị tất cả các pod, triển khai và dịch vụ của bạn dưới dạng giao diện người dùng web. Chạy lệnh minikube dashboard và trình duyệt của bạn sẽ hiển thị bảng điều khiển.
Truy cập ứng dụng của bạn
Để truy cập dịch vụ của bạn trong cụm Minikube, hãy chạy lệnh sau để lấy điểm cuối mà dịch vụ LoadBalancer của bạn được hiển thị:
minikube service <service-name> --url
Mở cùng một điểm cuối trong trình duyệt hoặc truy cập nó thông qua Postman.
Bạn cũng có thể sử dụng localhost thay vì địa chỉ IP, vì chúng giống nhau.
Mở rộng quy mô ứng dụng của bạn
Ứng dụng của bạn đã được thiết lập và đang chạy. Với nhu cầu ngày càng tăng, bạn có thể cần mở rộng quy mô ứng dụng của mình để đảm bảo hiệu suất tối ưu.
Để mở rộng quy mô ứng dụng của bạn, hãy tăng số lượng bản sao của triển khai của bạn bằng cách chạy lệnh sau:
kubectl scale deployment <deployment-name> --replicas=<desired-number>
Chỉ định số lượng bản sao mong muốn và nó sẽ mở rộng quy mô pod của bạn.
Sau khi chạy lệnh trên, hãy chạy kubectl get deployments để xem số lượng bản sao đã tăng lên.
Ngoài ra, bạn có thể sửa đổi tệp YAML Triển khai bằng cách thay đổi số lượng bản sao và chạy lại lệnh kubectl apply.
Nếu bạn không còn cần một số lượng lớn pod và muốn thu nhỏ ứng dụng của mình, chỉ cần chạy cùng một lệnh và chỉ định số lượng bản sao nhỏ hơn.
kubectl scale deployment sample-node-app --replicas=2
Vài lời về các nhà cung cấp dịch vụ đám mây
Cho đến nay, bạn đã tạo một image Docker và triển khai nó vào một cụm Kubernetes cục bộ. Chúng tôi đã sử dụng Minikube cho mục đích này. Nhưng nếu bạn muốn phân phối ứng dụng của mình ra thế giới bên ngoài, bạn cần sử dụng các nhà cung cấp đám mây.
Có rất nhiều tùy chọn có sẵn như AWS, Azure, GCP, Bizfly Cloud, v.v. Các nền tảng này cung cấp rất nhiều dịch vụ như Quản lý Cụm, Mở rộng quy mô, Mạng và Lưu trữ, Tích hợp CI/CD, v.v.
Các nền tảng này kết hợp khả năng của Kubernetes với điểm mạnh của hệ thống đám mây của riêng họ. Mỗi sản phẩm đi kèm với các dịch vụ và gói giá riêng, vì vậy hãy chọn bất kỳ sản phẩm nào phù hợp với yêu cầu và ngân sách của bạn.
Trong bối cảnh đám mây đang phát triển nhanh chóng, điều quan trọng là phải hiểu những gì mà mỗi nhà cung cấp đám mây cung cấp và đưa ra quyết định sáng suốt phù hợp với yêu cầu và mục tiêu của tổ chức bạn.
Kết luận
Kubernetes là một nền tảng điều phối container phổ biến và rất dễ sử dụng. Nắm vững các khái niệm của nó sẽ giúp bạn tận dụng nền tảng này cho ứng dụng của mình.
Trong hướng dẫn này, mục tiêu của tôi là cung cấp một hướng dẫn đầy đủ, từng bước về cách triển khai ứng dụng của bạn lên cụm Kubernetes. Tôi cũng đã đặt ra mục tiêu thiết lập nền tảng về một số khái niệm chính của Kubernetes bao gồm pod, triển khai, dịch vụ và bản thân cụm.
Tôi đã bắt đầu với một ứng dụng Node đơn giản và đóng gói nó thành một image Docker. Khi bạn đã nắm rõ các khái niệm chính, tôi đã đưa ra các bước chi tiết ngay từ việc cài đặt và thiết lập cụm Kubernetes đến việc triển khai ứng dụng của bạn dưới dạng pod và hiển thị chúng thông qua dịch vụ.
Kubernetes đang dần chiếm lĩnh thị trường đám mây và nó sẽ còn tồn tại trong thời gian dài. Tôi hy vọng tôi đã có thể làm cho Kubernetes trở nên dễ dàng đối với bạn. Điều này chắc chắn sẽ giúp bạn triển khai ứng dụng của mình lên bất kỳ cụm Kubernetes nào, không chỉ những cụm mà tôi đã đề cập. Cảm ơn các bạn đã theo dõi.