Nâng cấp Kafka không cần dừng dịch vụ, và quy trình ngắn hơn nhiều người nghĩ. Bài này chạy nó thật trên một cụm đang có producer và consumer hoạt động — rồi phát hiện việc chưa xong.

Nâng cấp cuốn chiếu, bước metadata bị quên, và tải lệch sau đó

Nâng cấp cuốn chiếu

Cụm 3 broker chạy Kafka 3.8.1, topic 6 partition với replication-factor=3min.insync.replicas=2. Producer gửi đều 5.000 tin/giây với acks=all, consumer đọc liên tục.

Thay từng broker một, mỗi lần đợi ISR đầy đủ trở lại trước khi sang broker kế:

ISR đầy đủ lại sau Partition thiếu bản sao
thay u3 1 giây 0
thay u2 2 giây 0
thay u1 22 giây 0

Không mất tin nào, và không lúc nào có partition thiếu bản sao.

Con số 22 giây của u1 lớn hơn hẳn vì nó đang là controller: nó phải nhường vai trước khi tắt, và node mới phải tham gia lại quorum. Đây là lý do quy tắc "nâng cấp controller sau cùng" tồn tại — làm ngược lại thì bạn trả chi phí bầu lại controller ở mỗi bước.

Với cụm tách vai (phần 21), thứ tự là: broker trước, controller sau.

Nhưng cụm chưa thật sự lên 3.9

Sau khi cả ba broker đã chạy nhị phân 3.9.0:

Feature: metadata.version
  SupportedMaxVersion:    3.9-IV0        <- nhị phân đã 3.9
  FinalizedVersionLevel:  3.8-IV0        <- giao thức vẫn 3.8

Nhị phân đã mới, giao thức siêu dữ liệu vẫn cũ. Cụm chạy các tính năng của 3.8.

Phải nâng riêng một bước nữa:

kafka-features.sh --bootstrap-server u1:9092 upgrade --metadata 3.9
# metadata.version was upgraded to 21.

Đây là thiết kế có chủ ý, không phải thiếu sót: chừng nào chưa nâng metadata.version, bạn còn lùi được về 3.8.1 bằng cách đổi lại ảnh container. Nâng rồi thì các tính năng mới bắt đầu ghi vào log siêu dữ liệu, và bản cũ không đọc được nữa.

Nghĩa là quy trình đúng có hai giai đoạn tách rời:

  1. Nâng nhị phân cuốn chiếu. Lùi được. Chạy như vậy vài ngày.
  2. Nâng metadata.version. Từ đây trở đi khó lùi.

Bỏ qua bước 2 thì cụm chạy mãi ở chế độ tương thích ngược và bạn không có tính năng nào của bản mới — một tình trạng dễ kéo dài hàng năm mà không ai để ý, vì mọi thứ vẫn chạy.

Trong phép đo này, hạ metadata.version từ 3.9 về 3.8 thành công. Đừng suy rộng: nhiều bước nhảy phiên bản không hạ được, và ghi chú phát hành của từng bản là nơi duy nhất nói chắc chắn.

Sau nâng cấp, cụm chạy lệch nặng

p0 Leader: 2    p1 Leader: 2    p2 Leader: 2
p3 Leader: 2    p4 Leader: 2    p5 Leader: 2

Cả sáu partition đều do một broker phục vụ. u1 và u3 nằm trong ISR — chúng sao chép đủ, tốn đủ đĩa và băng thông — nhưng không phục vụ một yêu cầu nào.

Đây là chính hiện tượng phần 13 đã đo, và một lần nâng cấp cuốn chiếu ba broker làm nó tệ nhất có thể: mỗi lần một broker tắt, leader của nó chuyển sang máy khác, và nó không bao giờ tự lấy lại.

kafka-leader-election.sh --bootstrap-server u1:9092 \
  --election-type preferred --all-topic-partitions

auto.leader.rebalance.enable bật mặc định sẽ tự làm việc này, nhưng theo chu kỳ 300 giây. Sau một lần nâng cấp, đó là năm phút cụm chạy trên một phần ba năng lực — và nếu bạn nâng cấp vào giờ cao điểm, năm phút đó rất dài.

Chạy tay lệnh trên là bước cuối cùng của mọi lần nâng cấp.

Quy trình đầy đủ

Trước:

# ghi lại trạng thái để so sánh sau
kafka-topics.sh --bootstrap-server u1:9092 --describe --under-replicated-partitions
kafka-topics.sh --bootstrap-server u1:9092 --describe --unavailable-partitions
kafka-features.sh --bootstrap-server u1:9092 describe

Hai lệnh đầu phải im lặng. Nâng cấp một cụm đang có partition thiếu bản sao là cộng thêm một sự cố lên một sự cố.

Mỗi broker:

  1. Dừng đàng hoàng (docker stop, không kill -9). Phần 20 đo được 1,2 giây với 974 MB dữ liệu.
  2. Đổi ảnh, khởi động lại.
  3. Đợi ISR đầy đủ trước khi sang broker kế. Đây là bước không được rút ngắn: nâng cấp hai broker cùng lúc với min.insync.replicas=2 là dừng ghi.
until [ "$(kafka-topics.sh --bootstrap-server u1:9092 --describe \
           --under-replicated-partitions | wc -l)" = 0 ]; do sleep 2; done

Sau:

kafka-leader-election.sh --bootstrap-server u1:9092 --election-type preferred --all-topic-partitions
# chạy vài ngày, rồi:
kafka-features.sh --bootstrap-server u1:9092 upgrade --metadata 3.9

Bốn thứ dễ quên

Client không cần nâng cùng lúc. Giao thức Kafka tương thích hai chiều rất tốt: client 3.5 nói chuyện được với broker 3.9 và ngược lại. Nâng broker trước, client sau, theo lịch riêng.

Nhảy nhiều phiên bản có giới hạn. Kafka hỗ trợ nâng trực tiếp trong một khoảng phiên bản nhất định. Từ 2.x lên 3.9 thường phải qua một bản trung gian, và bỏ qua bước đó cho lỗi ở lần khởi động.

Cấu hình bị bỏ đi giữa các bản. Nâng lên bản đã gỡ một tham số thì broker có thể từ chối khởi động vì cấu hình không nhận ra. Đọc phần "Notable changes" của ghi chú phát hành trước khi bắt đầu, không phải trong lúc broker đang không lên.

Ứng dụng Kafka Streams có bước riêng. Đổi processing.guarantee hay nâng phiên bản Streams có thể cần upgrade.from trong hai lần triển khai liên tiếp. Đây là nơi hay có sự cố nhất sau nâng cấp broker.

Thử ba mươi giây

Kiểm cụm của bạn có đang mắc kẹt ở bước hai không:

kafka-features.sh --bootstrap-server kf:9092 describe

Nếu SupportedMaxVersion cao hơn FinalizedVersionLevel, bạn đã nâng nhị phân mà chưa nâng giao thức. Có thể là cố ý — hoặc là một lần nâng cấp bỏ dở từ lâu mà không ai nhớ.

Phần sau đo Kafka trong Docker cho môi trường thật: thiếu một dòng cấu hình là mất 10.000 tin.