Giaosucan's blog - Chia sẻ kiến thức theo cách bá đạo

Ticker

20/recent/ticker-posts

DevOps tự truyện



Làm DevOps cũng chẳng khác gì cave, một cối nhiều chày, gặp đủ mọi thành phần khách hàng, từ người lịch sự văn minh cho đến bố đời, đủ cả. Lúc hệ thống chạy ngon thì không ai nhắc đến, lúc trục trặc thì giơ mặt cho thiên hạ xỉ vả….

Đà nẵng, một ngày hè oi bức, nhiệt độ ngoài trời lên tới 40 độ, nhưng trong một căn phòng của tòa nhà F-Complex , không khí còn nóng hơn cả bên ngoài….

Một cuộc họp diễn ra giữa 3 đầu cầu VN, France và US, tham gia là những manager, leader của toàn bộ dự án

Trên màn hình share screen của anh kĩ sư X, hàng loạt các Jenkins jobs đều xuất hiện một lỗi giống nhau

ERROR: Issue with creating launcher for agent jnlp-xxx. The agent has not been fully initialized yet
Remote call on JNLP4-connect connection from xxx.xxx.xx.xx/10.26.117.112:59064 failed. The channel is closing down or has closed down

Why do those issues happen again and again? Tiếng bà QA manager Ấn Độ gắt gỏng

My team is blocked because of it. Anh Dev France lead gào lên với giọng thực dân

Lỗi này đều xảy ra trên các job có thời gian chạy dài, trên 10 tiếng. Đây chỉ là 1 trong nhiều issue được report trong vòng 3 tháng qua

Có lẽ là do Jenkins versions, anh team lead nói.

Jenkins deploy lên K8S, mỗi khi có job được trigger, jenkins agent sẽ được launch là thành 1 pod trong K8S để chạy job. Phiên bản Jenkins hiện tại là 2.1xx khá cũ, đã run được hơn 2 năm, có thể gây ra issue liên quan tới node connection, node bị disconnect khi đang chạy job, giống như lỗi trên. Upgrade version có lẽ sẽ khắc phục được

Nhưng upgrade Jenkins version có thể ảnh hưởng rất lớn đến toàn bộ các job hiện tại, và các plugins, nhất là các PR builders. Anh technical lead thốt lên

Sau khi chạy 1 đoạn script trên console script để lấy danh sách các plugin hiện có, anh nói

Jenkins.instance.pluginManager.plugins.each{
plugin ->
println ("${plugin.getShortName()}:${plugin.getVersion()}")
}

Chúng ta đang cài đặt hơn 100 plugin các loạt trên Jenkins master, sau khi upgrade version, nhiều plugin đã deprecated sẽ phải removed, ngoài ra các plugin sẵn có sẽ ko tương thích với version mới

Vấn đề quan trọng nhất cần để ý đó là PR builder

Đây là quy trình PR builder hiện tại của hệ thống

Developer tạo 1 Pull Request, enter comment kiểu như :OK to test”, webhook sẽ được send tới Jenkins để trigger các jobs như scan code, unit test, intergration test, sau đó gửi lại status về cho PR

Automated Jenkins builds on GitHub pull request - DEV Community

Chúng ta có khoảng 50K jenkins jobs đang chạy trên 4 cluster Jenkins, phần lớn các jobs này bao gồm cả job PR builder sử dụng chung 1 thư viện groovy để run test. Nếu nâng cấp version, nguy cơ thư viện này sẽ không tương thích với version là hiện hữu.

Tức là sau khi nâng cấp version, nhiều job hiện tại, nhất là PR builder có thể bị lỗi

Đúng thế, đồng nghĩa team Developer sẽ không thể nào build test code của họ, các feature sẽ không thể release cho khách hàng. QA team cũng không thể test.

Nhiều team có thể bị ảnh hưởng. Upgrade version là việc làm quá rủi ro. Đó là lý do hơn 2 năm nay, đội DevOps US không dám làm việc đó

Và giờ cục than hồng được chuyển cho team VN, nếu không upgrade, thì chúng ta sẽ phải liên tục gặp phải lỗi connection, và nhiều lỗi khác nữa, rồi vẫn bị complain, thật là tiến thoái lưỡng nan

Ngay lúc đó , một email notify từ Google

Bạn đang sử dụng K8S version outdate, chúng tôi sẽ không còn hỗ trợ version này vào ngày xx.xx.xx, đề nghị nâng cấp

Buộc phải nâng cấp k8s Jenkins cluster, bản 1.14 giờ đã quá cũ, không biết liệu có gì xảy ra khi nâng cấp version

Phải làm thôi, nếu đã lường trước được tình huống, chúng ta sẽ chuẩn bị đầy đủ phương án dự phòng

Ngay lập tức, một bản release plan được lập ra, bao gồm

Lựa chọn version jenkins, cluster K8S version định nâng cấp

Release schedule, sẽ thực hiện vào chiều t7 khi toàn bộ các team ở các zone đều nghỉ làm để không ảnh hưởng vì downtime

Chạy test để verify

Rollback plan nếu có lỗi

….

Việc thực hiện upgrade không phải khó. Jenkins image được build từ docker file , chỉ cần sửa version trong docker file rồi tiến hành build rồi deploy image lên K8S. Upgrade version k8S cũng đơn giản, chỉ cần chạy 1 vài lệnh cli. Vấn đề là sự impact, ngoài một số case đã dự tính trước, còn lại rất khó dự đoán với hơn 50K jobs đang chạy.

Trước khi upgrade Jenkins version lên cluster chính thức, sẽ deploy test thử trên K8s cluster temporary để đánh giá độ impact

Thế là việc thực hiện upgrade version jenkins lẫn k8s được thực hiện khá nhanh chóng và dễ dàng

Jenkins version mới có diện mạo hoàn toàn mới, vài plugin như Blue Ocean được cài đặt thêm. Một số smoke test được thực hiện cho kết quả khá khả quan

Phải đợi 1 tuần xem thế nào, chúng ta không thể nào test hết được toàn bộ 50K jobs hiện tại xem có chạy ngon hay không

Ngày hôm sau

Liên tục các alert bắn ra từ hệ thống monitoring

*** WARPDRIVE.DEV.XXX.COM IS DOWN ***

Thật kỳ lạ, truy cập Jenkins vẫn bình thường, chả lẽ false alarm??

3 chiều ngày thứ 2, message từ đội QA bắn về

BDD test của chúng tôi không thể run được

error processing SBE BDDs tests results:
java.lang.IllegalArgumentException: Could not instantiate
{delegate={$class=XUnitBuilder, testTimeMargin=3000, thresholdMode=2,
tools=[{$class=org.jbehave.jenkins.JBehavePluginType,
pattern=**/jbehave/*.xml, skipNoTestFiles=true,
stopProcessingIfError=false}], thresholds=[{$class=FailedThreshold,
failureNewThreshold=, failureThreshold=, unstableNewThreshold=,
unstableThreshold=}, {$class=SkippedThreshold, failureNewThreshold=,
failureThreshold=, unstableNewThreshold=, unstableThreshold=}]}}
for org.jenkinsci.plugins.workflow.steps.CoreStep:
java.lang.UnsupportedOperationException: no known implementation of
interface jenkins.tasks.SimpleBuildStep is named XUnitBuilder

Jenkins đang sử dụng JBehavior plugin, framework BDD để run và generate test reports, chạy kèm với XUnit

xUnit | Jenkins plugin

Các job jenkins hiện tại dùng chung 1 thư viện groovy , implement những feature cơ bản như github, launch k8S pod, unit test, integration test case. Như vậy thư viện này đã bị không còn tương thích với các plugin version mới. Cấn phải được sửa đổi, release version mới

https://issues.jenkins.io/browse/JENKINS-51056

XUnitBuilder  marked for deprecation on Xunit latest version. Một bản patch ngay lập tức được release trong đêm để khắc phục issue

Ngày thứ 2, tình hình có vẻ êm, không còn thấy report issue từ QA team. Ổn rồi chăng

Rạng sáng ngày thứ 3, 2h sáng, hàng loạt message từ team development.

Toàn bộ PR builder của chúng tôi đều bị stuck vì nguyên nhân rất khó hiểu. Các job build, smoke test đều failed. Ngoài ra PR builder job cũng không tự trigger bằng comment pattern “Ok to test” như trước đây

Lại ngồi check logs

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 403 No valid crumb was included in the request</title>
</head>
<body><h2>HTTP ERROR 403 No valid crumb was included in the request</h2>
<table>

</body>
</html>

À là cái này roài

https://stackoverflow.com/questions/44711696/jenkins-403-no-valid-crumb-was-included-in-the-request

Github khi trigger jenkins job PR builder thì bị refuse do Jenkins version mới secure CRSF attack

Quick work around fix bằng cách chạy script trên console script để disable CSRF protection đi

import hudson.security.csrf.DefaultCrumbIssuer
import jenkins.model.Jenkins
def instance = Jenkins.instance
instance.setCrumbIssuer(new DefaultCrumbIssuer(true))
instance.save()

Nhưng nếu Jenkins restart thì script trên phải chạy lại, không nông dân thế được, cần phải add tham số disable CSRF khi deploy jenkins master pod on K8S

hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = true

Ok , giờ thì đã trigger được. Thế còn job smoke test chạy sao vẫn fail Thật kì lạ, share library đã update không thể liên quan, mà sao run trên các cluster khác thì không bị. Điều tra log

org.apache.http.conn.HttpHostConnectException: Connect to <URL>:443 [<DNS>/15.135.28.139] failed: Connection refused (Connection refused)

Firewall à, block connection? Trông thế mà không phải thế, job PR builder sẽ launch 1 K8S pod rồi deploy code lên để test. Tất cả đều nằm trong internal K8S cluster, sau khi nslookup jenkins address, resolved ra là public IP của Jenkins cluster.

Chắc chắn là do infra rồi, tạo thư 1 node pool khác rollback về k8s version cũ, cordon node cũ để pod launch vào node pool mới thử xem

Vũ như cẩn. Lỗi vẫn hoàn lỗi

Vẫn chưa tìm ra nguyên nhân sau 1 ngày, ticket bị developer team escalated lên tận manager. Tiếng gào réo vang lên khắp room, không fix được lỗi thì xác định update CV, giải tán team

11h đêm, trong phòng team vẫn miệt mài tìm hiểm. Message alert thì vẫn thấy bắn liên tục

*** WARPDRIVE.DEV.XXX.COM IS DOWN ***

Một tia sáng lóe lên, anh tech lead access vào 1 jenkins agent, thực hiện lệnh curl

curl https://warpdrive.dev.xxx.com
Connection refused 443

Thì ra là thế, jenkins agent không connect được tới ngnix service của jenkins. Tại sao ngnix tự nhiên lăn đùng ra chết. Phải chăng là do hoạt động upgrade k8S version??

Ngay lập tức, ngnix service được redeploy lại.

Eureka, issue is gone

Development team confirm issue solved. Mọi người thở phào nhẹ nhõm.

Ở chỉ có thế thôi à!!

Thế thoai!! Đúng là

Gia Cát Lượng - Ý Trời | Ảnh vui, Ảnh hài hước nhất, Hình ảnh

Đăng nhận xét

5 Nhận xét

  1. những job ntn mà phải chạy hơn 10h vậy anh :O

    Trả lờiXóa
    Trả lời
    1. Không biết ở chỗ tác giả sao chứ ở chỗ mình trước khi release thường có chạy stress test hệ thống, và mấy job này chạy 24 giờ là bình thường, chưa kể chạy full bộ test case cũng khá là chua :(

      Xóa
  2. DevOps team ngoài DN làm dự án to vậy à. Thuộc BU nào vậy.:D

    Trả lờiXóa
  3. Jenkins bạn có thể sync sang một server khác và upgrade chạy thử trước mà sao phải làm rủi ro như thế này cơ chứ haiz.
    - Với K8S nâng cấp bạn backup full lại là có thể ngủ không gặp ác mộng

    Trả lờiXóa