Sổ tay Kubernetes: Các khái niệm cơ bản trong Kubernetes

Loạt bài viết sổ tay Kubernetes:

Trong hướng dẫn trước bạn đã tìm hiểu về Kubernetes, cách cài đặt Kubernetes và chạy ứng dụng đầu tiên sử dụng Kubernetes.

Sổ tay Kubernetes: Giới thiệu về Kubernetes
Hướng dẫn này giới thiệu về điều phối container và Kubernetes, cài đặt Kubernetes và chạy ứng dụng đầu tiên trong Kubernetes.

Trong hướng dẫn này, bạn sẽ tìm hiểu về kiến trúc Kubernetes và cá khái niệm cơ bản trong Kubernetes như: cluster, node, control plane, pod, service, load balancer, ... Chúng ta bắt đầu thôi!

Kiến trúc Kubernetes

Trong thế giới của Kubernetes, một nút (node) có thể là một máy vật lý hoặc một máy ảo với một vai trò nhất định. Một tập hợp các máy hoặc máy chủ như vậy sử dụng mạng chia sẻ để giao tiếp với nhau được gọi là một cụm (cluster).

Sơ đồ một cụm Kubernetes cluster với nhiều node

Trong thiết lập trên máy cục bộ của bạn, minikube là một cụm Kubernetes với một nút duy nhất. Vì vậy, thay vì có nhiều máy chủ như trong sơ đồ trên, minikube chỉ có một máy chủ đóng vai trò vừa là máy chủ chính, vừa là nút.

Sơ đồ một cụm Kuberntes minikube với chỉ một node

Mỗi máy chủ trong một cụm Kubernetes có một vai trò. Có thể có hai vai trò:

  • Control Plane - Đưa ra hầu hết các quyết định cần thiết và hoạt động như một bộ não của toàn bộ cụm. Đây có thể là một máy chủ duy nhất hoặc một nhóm máy chủ trong các dự án lớn hơn.
  • Node - Chịu trách nhiệm về việc chạy khối lượng công việc. Các máy chủ này thường được quản lý vi mô bởi Control Plane và thực hiện các tác vụ khác nhau theo chỉ dẫn được cung cấp.

Mỗi máy chủ trong cụm của bạn sẽ có một tập hợp các thành phần được thiết lập. Số lượng và loại các thành phần đó có thể khác nhau tùy thuộc vào vai trò của máy chủ trong cụm của bạn. Điều đó có nghĩa là các nút không có tất cả các thành phần mà Control Plane có.

Trong các phần sắp tới, bạn sẽ có cái nhìn chi tiết hơn về các thành phần riêng lẻ tạo nên một cụm Kubernetes.

Các thành phần của Control Plane

Control Plane trong một cụm Kubernetes bao gồm 5 thành phần sau:

  1. kube-api-server: Nó hoạt động như lối vào Control Plane của Kubernetes, chịu trách nhiệm xác thực và xử lý các yêu cầu được gửi bằng thư viện máy khách như chương trình kubectl.
  2. etcd: Đây là một kho lưu trữ key-value phân tán hoạt động như một nguồn trung thực duy nhất về cụm của bạn. Nó lưu trữ dữ liệu cấu hình và thông tin về trạng thái của cụm. etcd là một dự án mã nguồn mở và được phát triển bởi những người đứng sau Red Hat. Mã nguồn của dự án được lưu trữ trên GitHub etcd-io/etcd.
  3. kube-controller-manager: Các bộ điều khiển trong Kubernetes chịu trách nhiệm kiểm soát trạng thái của cụm. Khi bạn cho Kubernetes biết bạn muốn gì trong cụm của mình, bộ điều khiển đảm bảo rằng yêu cầu của bạn được đáp ứng. kube-controller-manager nhóm tất cả các tiến trình bộ điều khiển thành một tiến trình duy nhất.
  4. kube-scheduler: Giao nhiệm vụ cho một nút nhất định xem xét các tài nguyên sẵn có của nó và các yêu cầu của nhiệm vụ được gọi là lập lịch. kube-scheduler thực hiện nhiệm vụ lập lịch trong Kubernetes đảm bảo không có máy chủ nào trong cụm bị quá tải.
  5. cloud-controller-manager: Trong môi trường đám mây thế giới thực, thành phần này cho phép bạn kết nối cụm của mình với API (GKE/EKS) của nhà cung cấp dịch vụ đám mây của bạn. Bằng cách này, các thành phần tương tác với nền tảng đám mây đó sẽ được tách biệt khỏi các thành phần chỉ tương tác với cụm của bạn. Trong một cụm cục bộ như minikube, thành phần này không tồn tại.

Các thành phần của Node

So với Control Plane, các nút (node) có số lượng thành phần rất nhỏ. Các thành phần này như sau:

  1. kubelet: Dịch vụ này hoạt động như một cổng giữa Control Plane và mỗi nút trong một cụm. Mọi chỉ dẫn từ Control Plane đối với các nút, đều đi qua dịch vụ này. Nó cũng tương tác với etcd để cập nhật thông tin trạng thái.
  2. kube-proxy: Dịch vụ nhỏ này chạy trên mỗi máy chủ nút và duy trì các quy tắc mạng trên chúng. Bất kỳ yêu cầu mạng nào đến một dịch vụ bên trong cụm của bạn, đều đi qua dịch vụ này.
  3. Container Runtime: Kubernetes là một công cụ điều phối container do đó nó chạy các ứng dụng trong container. Điều này có nghĩa là mọi nút cần có container runtime như Docker hoặc rkt hoặc cri-o.

Object trong Kubernetes

Theo tài liệu Kubernetes -

"Object (đối tượng) là các thực thể lâu dài trong hệ thống Kubernetes. Kubernetes sử dụng các thực thể này để đại diện cho trạng thái của cụm của bạn. Cụ thể, chúng có thể mô tả những ứng dụng trong container đang chạy, các tài nguyên có sẵn cho chúng và các chính sách xung quanh hành vi của chúng."

Khi bạn tạo một đối tượng Kubernetes, bạn đang nói với hệ thống Kubernetes rằng bạn muốn đối tượng này tồn tại bất kể điều gì và hệ thống Kubernetes sẽ liên tục hoạt động để giữ cho đối tượng hoạt động.

Pod

Theo tài liệu Kubernetes -

"Pod là đơn vị máy tính có thể triển khai nhỏ nhất mà bạn có thể tạo và quản lý trong Kubernetes".

Một Pod thường bao gồm một hoặc nhiều container có liên quan chặt chẽ với nhau, chia sẻ vòng đời và các tài nguyên.

Pod trong Kubernetes

Mặc dù một Pod có thể chứa nhiều hơn một container, nhưng bạn không nên chỉ đặt các container bất kỳ vào một Pod. Các container trong một Pod phải có liên quan chặt chẽ đến mức chúng có thể được coi như một ứng dụng duy nhất.

Ví dụ: back-end API của bạn có thể phụ thuộc vào cơ sở dữ liệu nhưng điều đó không có nghĩa là bạn sẽ đặt cả hai trong cùng một Pod. Trong toàn bộ bài viết này, bạn sẽ không thấy bất kỳ Pod nào có nhiều hơn một container đang chạy.

Thông thường, bạn không nên quản lý một Pod trực tiếp. Thay vào đó, bạn nên làm việc với các đối tượng (object) cấp cao hơn có thể cung cấp cho bạn khả năng quản lý tốt hơn nhiều. Bạn sẽ tìm hiểu về các đối tượng cấp cao hơn này trong phần sau.

Service

Theo tài liệu Kubernetes -

"Một dịch vụ (service) trong Kubernetes là một cách trừu tượng để hiển thị một ứng dụng đang chạy trên một nhóm các Pod như một dịch vụ mạng".

Pod của Kubernetes có bản chất là không bền vững. Chúng được tạo ra và sau một thời gian khi chúng bị hủy, chúng sẽ không được tái sử dụng.

Thay vào đó, các Pod mới giống hệt nhau sẽ thay thế các Pod cũ. Một số đối tượng Kubernetes cấp cao hơn thậm chí còn có khả năng tạo và hủy các Pod động.

Một địa chỉ IP mới được chỉ định cho mỗi Pod tại thời điểm tạo. Nhưng trong trường hợp một đối tượng cấp cao có thể tạo, hủy và nhóm một số Pod lại với nhau, nhóm Pod đang chạy trong một thời điểm này có thể khác với nhóm Pod chạy ứng dụng đó tại một thời điểm khác.

Điều này dẫn đến một vấn đề: nếu một số nhóm Pod phụ thuộc vào nhóm Pod khác trong cụm của bạn, làm cách nào để chúng tìm ra và theo dõi địa chỉ IP của nhau?

Theo tài liệu Kubernetes -

"Một Service (dịch vụ) là một phần trừu tượng định nghĩa một tập hợp các Pod và một chính sách để truy cập chúng".

Về cơ bản, điều này có nghĩa là một Service sẽ nhóm một số Pod thực hiện cùng một chức năng và mô tả chúng dưới dạng một thực thể duy nhất.

Bằng cách này, sự nhầm lẫn trong việc theo dõi nhiều Pod sẽ không xuất hiện trong cửa sổ vì Service hoạt động như một loại thiết bị giao tiếp cho tất cả chúng.

Trong ví dụ hello-kube ở hướng dẫn trước, bạn đã tạo một loại dịch vụ là LoadBalancer cho phép các yêu cầu từ bên ngoài cụm kết nối với các Pod đang chạy bên trong cụm.

Load Balancer trong Kubernetes

Bất kỳ lúc nào bạn cần cấp quyền truy cập vào một hoặc nhiều Pod cho một ứng dụng khác hoặc một cái gì đó bên ngoài cụm, bạn nên tạo một Service.

Ví dụ: nếu bạn có một tập hợp các Pod đang chạy các máy chủ web có thể truy cập được từ internet, một Service sẽ cung cấp thông tin tóm tắt cần thiết.

Bức tranh toàn cảnh

Bây giờ bạn đã hiểu về các thành phần của Kubernetes, đây là phần trình bày trực quan về cách chúng hoạt động cùng nhau ở phía sau:

Sơ đồ các thành phần của Kubernetes

Trước khi tôi giải thích chi tiết, hãy xem tài liệu Kubernetes nói gì -

"Để làm việc với các đối tượng Kubernetes - cho dù tạo, sửa đổi hay xóa chúng - bạn sẽ cần sử dụng Kubernetes API. Khi bạn sử dụng giao diện dòng lệnh kubectl, CLI thực hiện các lệnh gọi Kubernetes API cần thiết cho bạn."

Lệnh đầu tiên mà bạn chạy là lệnh run. Nó như sau:

kubectl run hello-kube --image=fhsinchy/hello-kube --port=80

Lệnh run có trách nhiệm tạo một pod mới để chạy một image nhất định. Khi bạn thực thi lệnh này, các sự kiện sau sẽ xảy ra bên trong cụm Kubernetes:

  • Thành phần kube-api-server nhận yêu cầu, xác nhận nó và xử lý nó.
  • Sau đó kube-api-server giao tiếp với thành phần kubelet trên nút và cung cấp các chỉ dẫn cần thiết để tạo pod.
  • Sau đó thành phần kubelet bắt đầu làm việc để thiết lập và chạy pod và cũng lưu giữ thông tin trạng thái được cập nhật trong kho lưu trữ etcd.

Cú pháp chung cho lệnh run như sau:

kubectl run <pod name> --image=<image name> --port=<port to expose>

Bạn có thể chạy bất kỳ image hợp lệ nào bên trong một pod. Docker Image fhsinchy/hello-kube chứa một ứng dụng JavaScript rất đơn giản chạy trên cổng 80 bên trong container. Tùy chọn --port=80 cho phép pod để lộ cổng 80 từ bên trong container.

Pod trong Kubernetes

Pod mới được tạo chạy bên trong cụm minikube và không thể truy cập từ bên ngoài. Để hiển thị pod và làm cho nó có thể truy cập được, lệnh thứ hai mà bạn đã thực hiện như sau:

kubectl expose pod hello-kube --type=LoadBalancer --port=80

Lệnh expose có nhiệm vụ tạo ra một dịch vụ LoadBalancer trong Kubernetes cho phép người dùng truy cập vào các ứng dụng đang chạy bên trong pod.

Cũng giống như lệnh run, lệnh expose thực thi lệnh trải qua các bước tương tự bên trong cụm. Nhưng thay vì một pod, kube-api-server cung cấp các chỉ dẫn cần thiết để tạo một dịch vụ cho thành phần kubelet trong trường hợp này.

Cú pháp chung cho lệnh expose như sau:

kubectl expose <resource kind to expose> <resource name> --type=<type of service to create> --port=<port to expose>

Loại đối tượng có thể là bất kỳ loại đối tượng Kubernetes hợp lệ nào. Tên phải khớp với tên đối tượng mà bạn đang cố gắng hiển thị.

Tùy chọn --type cho biết loại dịch vụ bạn muốn. Có bốn loại dịch vụ khác nhau có sẵn cho mạng nội bộ hoặc bên ngoài.

Cuối cùng, tùy chọn --port là cổng bạn muốn hiển thị từ container đang chạy.

Khi dịch vụ đã được tạo, phần cuối cùng là truy cập vào ứng dụng đang chạy bên trong nhóm. Để làm điều đó, lệnh bạn đã thực hiện như sau:

minikube service hello-kube

Không giống như những lệnh trước, lệnh cuối cùng này không đi đến kube-api-server. Thay vào đó, nó giao tiếp với cụm cục bộ bằng cách sử dụng chương trình minikube. Lệnh service cho minikube trả về một URL đầy đủ cho một dịch vụ nhất định.

Khi bạn tạo pod hello-kube với tùy chọn --port=80, bạn đã hướng dẫn Kubernetes để pod hiển thị cổng 80 từ bên trong container nhưng nó không thể truy cập được từ bên ngoài cụm.

Sau đó, khi bạn tạo dịch vụ LoadBalancer với tùy chọn --port=80, nó đã ánh xạ cổng 80 từ container đó đến một cổng tùy ý trong hệ thống cục bộ để có thể truy cập từ bên ngoài cụm.

Trên hệ thống của tôi, lệnh service trả về URL 192.168.99.101:30848 cho pod. IP trong URL này thực sự là IP của máy ảo minikube. Bạn có thể xác minh điều này bằng cách thực hiện lệnh sau:

minikube ip

# 192.168.99.101

Để xác minh rằng cổng 30848 trỏ đến cổng 80 bên trong pod, bạn có thể thực hiện lệnh sau:

kubectl get service hello-kube

# NAME         TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
# hello-kube   LoadBalancer   10.109.60.75   <pending>     80:30848/TCP   119s

Trên cột PORT(S), bạn có thể thấy cổng đó 80 thực sự ánh xạ tới cổng 30484 trên hệ thống cục bộ. Vì vậy, thay vì chạy lệnh service, bạn có thể chỉ cần kiểm tra IP và cổng, sau đó đưa nó vào trình duyệt của bạn theo cách thủ công để truy cập ứng dụng hello-kube.

Hello world trong Kubernetes

Bây giờ, trạng thái cuối cùng của cụm có thể được hình dung như sau:

Nếu bạn quen thuộc với Docker, thì tầm quan trọng của việc sử dụng một dịch vụ để hiển thị một pod có vẻ hơi quá dài dòng đối với bạn vào lúc này.

Nhưng khi bạn đi vào các ví dụ xử lý nhiều hơn một pod, bạn sẽ bắt đầu đánh giá cao mọi thứ mà Kubernetes cung cấp.

Xóa tài nguyên của Kubernetes

Bây giờ bạn đã biết cách tạo các tài nguyên của Kubernetes như Pod và Service, bạn cũng cần biết cách xóa chúng.

Bạn có thể làm điều đó bằng cách sử dụng lệnh delete cho kubectl. Cú pháp chung của lệnh như sau:

kubectl delete <resource type> <resource name>

Để xóa một pod có tên hello-kube, lệnh sẽ như sau:

kubectl delete pod hello-kube

# pod "hello-kube" deleted

Và để xóa một service có tên hello-kube, lệnh sẽ như sau:

kubectl delete service hello-kube

# service "hello-kube" deleted

Hoặc nếu bạn đang có tâm trạng phá hoại, bạn có thể xóa tất cả các đối tượng cùng loại trong một lần sử dụng tùy chọn --all cho lệnh delete. Cú pháp chung cho tùy chọn như sau:

kubectl delete <object type> --all

Vì vậy, để xóa tất cả các pod và service bạn phải thực thi lệnh kubectl delete pod --allkubectl delete service --all tương ứng.

Trong phần tiếp theo, bạn sẽ tìm hiểu về phương pháp triển khai bằng khai báo trong Kubernetes.

Sổ tay Kubernetes: Phương pháp triển khai bằng khai báo
Trong hướng dẫn này, bạn sẽ học cách sử dụng cách tiếp cận khai báo để triển khai ứng dụng trong Kubernetes và sử dụng bảng điều khiển Kubernetes.

Hướng dẫn này được dịch từ sách Kubernetes Handbook của Farhan Hasin Chowdhury:

The Kubernetes Handbook
Kubernetes [https://kubernetes.io/] is an open-source container orchestrationplatform that automates the deployment, management, scaling, and networking ofcontainers. It was developed by Google [https://opensource.google/projects/kubernetes] usingthe Go Programming Language [https://golang.org/…
KubernetesDevOps
Bài Viết Liên Quan:
Sổ tay Kubernetes: làm việc với Ingress Controller (p2)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: làm việc với Ingress Controller (p2)

Trong phần này, bạn sẽ tìm hiểu cách sử dụng Secret, ConfigMap để lưu trữ thông tin cấu hình, phát hành các bản cập nhật và xử lý sự cố trong Kubernetes.

Sổ tay Kubernetes: làm việc với Ingress Controller (p1)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: làm việc với Ingress Controller (p1)

Trong hướng dẫn này, bạn sẽ tìm hiểu về Ingress Controller và cách sử dụng NGINX Ingress Controller để cấu hình định tuyến trong Kubernetes.

Sổ tay Kubernetes: Triển khai ứng dụng đa container (p3)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: Triển khai ứng dụng đa container (p3)

Ở phần 3 này, chúng ta sẽ tìm hiểu cách cung cấp động Persistent Volume, kết nối volume với pod và kết nối các thành phần trong cụm với nhau.

Sổ tay Kubernetes: Triển khai ứng dụng đa container (p2)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: Triển khai ứng dụng đa container (p2)

Ở phần 2 này, chúng ta sẽ tìm cách khắc phục những lỗi xảy ra khi triển khai. Chúng ta cũng tìm hiểu thêm về Persistent Volume, Persistent Volume Claim.