Giới thiệu
Chào các bạn tới với series nói về Kubernetes Patterns. Trong series này ta sẽ nói về một vài Patterns ở trong Kubernetes mà giúp ta hiểu rõ hơn về cách hoạt động của Kubernetes và cách tổ chức các resource hiệu quả hơn.
Patterns đầu tiên ta sẽ tìm hiểu là Behavioral Patterns, bao gồm:
- Batch Job: làm sao để chạy một job ở trong k8s
- Periodic Job: làm sao để chỉ định chạy một job ở một mốc thời gian nhất định
- Singleton Service: chỉ một Instance của Service hoạt động ở một thời điểm nhưng vẫn đảm bảo độ khả dụng (High Availability)
- Service Discovery: làm sao các resource trong K8S phát hiện lẫn nhau thông qua Service
Batch Job
Batch Job là một Pattern phù hợp cho việc quản lý những process mà chỉ cần chạy một lần, nó sẽ được thực hiện thông qua resource Job của Kubernetes. Job sẽ giúp ta tạo một thằng Pod mà chỉ cần chạy trong khoảng thời gian ngắn và chạy một lần (nếu thành công).
Vậy tại sao Job lại giúp ta trong việc chạy những process một lần, ta có thể dùng ReplicaSet để tạo Pod chạy process cũng được vậy? Câu trả lời là nếu ta dùng resource khác để tạo Pod cho các process mà ta chỉ cần chạy một lần, ta sẽ gặp các vấn đề sau.
Unmanaged Pod
Nếu ta khai báo Pod như sau và dùng nó để chạy process chạy một lần.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
restartPolicy: OnFailure
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
command: [ "java", "-cp", "/", "RandomRunner", "/numbers.txt", "10000" ]
EOF
Nếu trong quá trình nó đang chạy, server của ta mà bị chết thì process đó của ta cũng bị mất theo. Vì thằng Pod này nó không được quản lý bởi bất cứ resource nào nên nó sẽ không được tạo ra lại. Do đó ta gọi những Pod thế này là Unmanaged Pod.
Managed Pod
Nếu ta dùng ReplicaSet để tạo Pod.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: random-generator
spec:
selector:
matchLabels:
app: run
template:
metadata:
labels:
app: run
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
command: [ "java", "-cp", "/", "RandomRunner", "/numbers.txt", "10000" ]
EOF
Thì Pod đó được gọi là Managed Pod, khi Pod ta đang chạy mà server bị chết, Pod đó của ta sẽ được tạo ở server khác, process sẽ được chạy lại. Nhưng mà khi Pod của ta chạy thành công, và nó đang nằm trên server nào đó, server đó chết, Pod nằm trên server đó sẽ được tạo lại ở server khác, process của ta nó sẽ chạy lại lần nữa, mà ta thì không muốn như vậy.
Job
Để giải quyết vấn đề đó ta sẽ sử dụng Job. K8S Job sẽ tạo Pod cho ta, nếu Pod chưa chạy xong mà server bị chết thì Pod sẽ được di chuyển qua server khác. Nhưng khi Pod chạy thành công và nếu Pod đó nằm trên một server nào mà nó có chết thì Pod cũng sẽ không được tạo ra lại => process của ta chỉ chạy 1 lần.
Để tạo Job, ta dùng khai báo kind
là Job như sau:
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
name: random-generator
spec:
completions: 5
template:
metadata:
labels:
app: run
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
command: [ "java", "-cp", "/", "RandomRunner", "/numbers.txt", "10000" ]
EOF
Ở trên ta tạo một Job mà sẽ chạy 5 Pod và chắc chắn là 5 Pod này được chạy thành công. Mặc định thì mỗi lần Job chỉ tạo ra 1 Pod để chạy, ta có thể tăng số lượng Pod mà Job tạo ra 1 lần bằng thuộc tính parallelism
.
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
name: random-generator
spec:
completions: 5
parallelism: 2
template:
metadata:
labels:
app: run
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
command: [ "java", "-cp", "/", "RandomRunner", "/numbers.txt", "10000" ]
EOF
Minh họa.
Từ hai thuộc tính .spec.completions
và .spec.parallelism
, ta có thể điều khiển Job chạy Pod theo những cách sau:
- Single Pod Job: Job mà không chỉ định thuộc tính
.spec.completions
và.spec.parallelism
hoặc chỉ định 1 trong 2 với giá trị là 1. Job sẽ chỉ tạo 1 Pod. - Fixed completion count Jobs: Job mà chỉ định thuộc tính
.spec.completions
lớn hơn một. - Work queue Jobs: Job mà chỉ định thuộc tính
.spec.parallelism
lớn hơn 1 và không chỉ định thuộc tính.spec.completions
, Pod sẽ được chạy tuần tự.
Đây là những keywork để bạn tìm kiếm thêm về Job:
- Batch Job Example
- Run to Completion Finite Workloads
- Parallel Processing Using Expansions
- Coarse Parallel Processing Using a Work Queue
- Fine Parallel Processing Using a Work Queue
- Indexed Job Created with Metacontroller
- Java Batch Processing Frameworks and Libraries
Periodic Job
Periodic Job pattern là một Pattern mở rộng của Batch Job, cho phép ta chạy một process ở một mốc thời gian nhất định và lập đi lập lại. Nó giống như ta cấu hình chạy Job Scheduler ở dưới Linux. Kubernetes cung cấp cho ta một resource mà có thể hành động giống y như Job Scheduler ở dưới Linux là CronJob.
CronJob sẽ cho phép ta cấu hình trong một khoảng thời gian bao lâu thì nó tạo Job cho ta. Ví dụ, để tạo một CronJob mà cứ 3 phút sẽ tạo ra một Job.
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: CronJob
metadata:
name: random-generator
spec:
schedule: "*/3 * * * *"
jobTemplate:
spec:
template:
metadata:
labels:
app: run
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
command: [ "java", "-cp", "/", "RandomRunner", "/numbers.txt", "10000" ]
EOF
Thuộc tính schedule
là chỗ ta định nghĩa trong khoảng thời gian bao lâu thì CronJob sẽ tạo ra một Job. Cú pháp của thuộc tính schedule
như sau:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
Đây là những từ khóa để bạn tìm kiếm thêm về CronJob:
- Periodic Job Example
- Cron Jobs
- Cron
Lưu ý: K8S bản 1.25
đã cập nhật thêm Timezone cho CronJob.
Kết luận
Vậy là ta đã tìm hiểu xong về Batch Job và Periodic Job ở trong Kubernetes bằng cách sử dụng Job và CronJob resource. Thay vì phải cấu hình cronjob trên một server linux nào đó, ta có thể sử dụng CronJob trong K8S để nó dễ dàng kết hợp với các resource khác trong K8S, ngoài ra ta có thể dễ dàng xem lại logs của Job đã chạy và xem được các thông số về CPU và RAM của tiến trình đó, và ta cũng có thể kiểm soát được số lượng Job ta cần chạy một lúc để công việc của ta được xử lý nhanh hơn.
Nếu bài viết có gì sai hoặc cần cập nhật thì liên hệ Admin.
Tham gia nhóm chat của DevOps VN tại Telegram.
Kém tiếng Anh và cần nâng cao trình độ giao tiếp: Tại sao bạn học không hiệu quả?