Nội dung bài viết
Hi các bạn 👋. Mình là Hùng Anh.
Đây là bài đầu tiên trong series Kubernetes Fundamentals. Trước khi chạm đến Kubernetes, câu chuyện phải bắt đầu từ nền móng của mọi thứ trong series này: Linux kernel. Nếu bạn chưa từng thực sự ngồi nghĩ kỹ xem kernel làm gì, driver là gì, hay "sandbox" trong Linux thực chất là gì, bài này dành cho bạn.
Bắt đầu thôi.
1. Linux Kernel là gì?
Kernel là 1 lớp phần mềm nằm giữa phần cứng (CPU, RAM, ổ đĩa, card mạng) và mọi ứng dụng bạn chạy.
Ứng dụng không bao giờ được phép chạm thẳng vào phần cứng. Trình duyệt của bạn không được phép động vào bộ điều khiển ổ đĩa, và nginx cũng không được phép ghi thẳng vào thanh ghi của card mạng. Thay vào đó, mọi thao tác như đọc file, cấp phát bộ nhớ, mở socket, tạo tiến trình mới... đều phải đi qua system call (syscall).
Syscall đơn giản là 1 lệnh trong tập lệnh được kernel định nghĩa sẵn để ứng dụng gọi vào. Ví dụ một số lệnh syscall phổ biến: open(), read(), write(), fork(), socket(). Khi ứng dụng của bạn gọi 1 lệnh syscall trong số này, trước khi làm bất cứ điều gì, kernel kiểm tra xem tiến trình gọi có được phép thực hiện yêu cầu này không (quyền, quota, hay bất kỳ policy nào đang áp dụng). Nếu được phép, chính kernel là bên thực sự "nói chuyện" với CPU scheduler, bộ quản lý bộ nhớ, hay ổ đĩa — không phải ứng dụng của bạn.
Bạn có thể quan sát điều này trực tiếp. Trên bất kỳ máy Linux nào, chạy thử:
strace -c ls > /dev/null
strace chặn lại từng syscall mà 1 chương trình thực hiện và in ra bảng tổng hợp. Ngay cả 1 lệnh đơn giản như ls cũng phải gọi hàng chục syscall (openat, read, close, mmap...) trước khi in ra được 1 cái tên file. Không có chuyện ls tự "chọc" vào filesystem — mỗi lời gọi đó đều là ls đang nhờ kernel làm hộ.
Quy tắc: ứng dụng yêu cầu, kernel quyết định và thực thi — chính là nền tảng cho mọi thứ còn lại trong bài viết này (và cả series).
2. Kernel vs. Driver
Bản thân kernel không tự biết cách "nói chuyện" với con chip WiFi, GPU, hay ổ NVMe cụ thể mà bạn đang dùng. Có hàng nghìn hãng phần cứng với hàng chục nghìn model khác nhau. Vì vậy kernel không cố hardcode sẵn hỗ trợ cho từng con chip — thay vào đó, mỗi loại phần cứng có 1 module nhỏ riêng gọi là driver, với nhiệm vụ duy nhất là dịch các lệnh chung của kernel thành đúng lệnh mà con chip cụ thể đó hiểu được.
Nếu không có driver, kernel sẽ không biết cách giao tiếp với phần cứng.
Đây cũng chính là nguồn gốc của sự khác biệt nổi tiếng giữa "cài Windows" và "cài Linux":
- Kernel của Windows là closed-source. Các hãng phần cứng phải tự đóng gói driver riêng và phát hành tách biệt, qua Windows Update hoặc trình cài đặt riêng của hãng. Đó là lý do khi cài hệ điều hành Windows, bạn thường phải tải thêm bộ cài driver.
- Linux kernel là open-source, phát hành theo giấy phép GPL. Đại đa số hãng phần cứng đóng góp driver thẳng vào mã nguồn chính (mainline) của kernel. Đó là lý do khi cài 1 distro như Ubuntu lên 1 chiếc laptop bất kỳ, WiFi và touchpad thường "chạy luôn", không cần làm gì thêm — bản kernel bạn tải về đã sẵn mang theo hàng nghìn driver. Tuy nhiên, với những driver mà hãng muốn giữ closed-source thì sẽ không thể được merge vào mainline kernel mà bạn phải tự chạy để install thủ công.
Có nhiều driver GPU độc quyền của NVIDIA, cùng vài driver chip WiFi/Bluetooth — không thể được merge vào mainline kernel, vì theo GPL, mã nguồn phải open source. NVIDIA những năm gần đây đã dần open-source 1 phần module kernel của mình, nhưng khá nhiều phần khác trong stack (driver userspace cho OpenGL/Vulkan/CUDA) vẫn còn closed-source — đó chính là lý do bạn nhiều khi vẫn phải tự chạy apt install nvidia-driver-xxx thay vì nó có sẵn từ đầu.
3. OS là gì?
Kernel là phần lõi, nhưng tự nó chưa phải là thứ bạn cài lên máy. OS (hệ điều hành) = kernel + mọi thứ đi kèm để máy thực sự dùng được: shell (bash), các tiện ích cơ bản (ls, cp...), package manager (apt/yum), các service hệ thống (systemd), thư viện chuẩn (glibc).
Ví dụ cho dễ hình dung: Linux thực chất chỉ là cái kernel. Ubuntu, CentOS, Debian là các OS (distro) khác nhau nhưng dùng chung Linux kernel — chúng chỉ khác nhau ở phần "mọi thứ đi kèm": package manager, service, cấu hình mặc định... Android cũng dùng Linux kernel nhưng là 1 OS hoàn toàn khác Ubuntu.
4. Sandbox: cơ chế cô lập do kernel cung cấp
Khi nhiều tiến trình cùng chạy trên 1 máy, nhiều khi chúng ta cần giới hạn được lượng tài nguyên (CPU, RAM, disk...) mà mỗi tiến trình được phép dùng, và ngăn được tiến trình này đọc dữ liệu của tiến trình khác. Linux kernel cung cấp một cơ chế để làm việc đó gọi là sandbox — 1 môi trường thực thi bị cô lập: code chạy bên trong sandbox sẽ bị giới hạn, không thể đọc, ghi hay can thiệp vào hệ thống host thật (hay các sandbox khác).
Linux kernel cung cấp sẵn 2 cơ chế namespace và control group để bạn có thể dựng nên 1 sandbox:
- Namespace: Kiểm soát những gì 1 tiến trình có thể thấy. Vẫn cùng 1 máy, cùng 1 kernel, nhưng tiến trình bên trong sẽ hoặc không thấy được phần tài nguyên nằm ngoài tầm nhìn cho phép, hoặc vẫn thấy nhưng ở một dạng khác. Kernel cung cấp sẵn nhiều loại namespace khác nhau, mỗi loại cô lập 1 mảng riêng của hệ thống, và 1 tiến trình có thể được đặt vào bất kỳ tổ hợp nào trong số đó cùng lúc — chính tổ hợp này sẽ quyết định tiến trình thực sự nhìn thấy được những gì có trong hệ thống.
- Control group (cgroup): Kiểm soát những gì 1 tiến trình được phép dùng. Nếu namespace kiểm soát tầm nhìn thì cgroup kiểm soát mức tiêu thụ: bao nhiêu CPU, bao nhiêu RAM, bao nhiêu disk I/O, thậm chí được tạo ra tối đa bao nhiêu tiến trình con. Ngay khi các tiến trình trong group vượt qua giới hạn, kernel sẽ can thiệp trực tiếp và xử lý trước khi nó kịp lấy đi resource của những thứ khác ngoài group. Về mặt cơ chế, cgroup sẽ được kernel lưu trữ như 1 cây thư mục bình thường (trên các distro đời mới, mount tại
/sys/fs/cgroup), mỗi cgroup chỉ là 1 thư mục con, mỗi setting limit resource chỉ là 1 file text chứa những con số. Không có API riêng để set giới hạn, không cần client chuyên dụng — chỉ là file.
5. Tổng kết
Tới đây chắc hẳn bạn đã nắm được các thuật ngữ cơ bản trong Linux rồi.
Bài sau mình sẽ cùng tìm hiểu khi deploy 1 application lên 1 máy chủ vật lý thì mình sẽ gặp phải những hạn chế nào nhé.
Giờ thì relax and tea break time thôi.
Happy reading! 🍵
Tài liệu tham khảo
- Control Groups v2 - The Linux Kernel documentation
- What even is a container: namespaces and cgroups - Julia Evans
Bài viết liên quan
Kubernetes Cluster Architecture
Cùng mình xem 1 cluster Kubernetes thực sự gồm những gì: Control Plane ra quyết định cái gì chạy ở đâu, các node thực sự chạy chúng, và các addon lấp phần còn lại.
Container
Cùng mình xem container giải quyết vấn đề nặng nề và khởi động chậm của Virtual Machine như nào, bằng cách bỏ hẳn kernel riêng — thứ mà mỗi VM luôn phải cõng theo.
Server vật lý và các giới hạn
Server vật lý thực sự trông như thế nào, và vì sao không thể cứ deploy mãi lên cùng 1 server?