Jenkins
Self-hosted ավտոմատացման սերվեր․ pipeline-ներ՝ որպես կոդ Jenkinsfile-ում, որոնք աշխատում են քո սեփական agent-ների վրա։
30 վայրկյանում
Jenkins-ը open-source ավտոմատացման սերվեր է, որը ինքդ ես տեղադրում և աշխատեցնում։ Ռեպոզիտորիայում Jenkinsfile-ը նկարագրում է pipeline-ը Groovy-ի վրա հիմնված լեզվով՝ stage-եր, ինչպես build, test և deploy, որոնք աշխատում են agent կոչվող աշխատող մեքենաների վրա։ Նրա հսկայական plugin էկոհամակարգը այն կապում է գրեթե ցանկացած գործիքի հետ, ինչի պատճառով այն դեռ տարածված է խոշոր ընկերություններում, բայց թարմացումները, անվտանգությունը և scaling-ը քո պատասխանատվությունն են։
Իմ ամենօրյա stack-ում չէ․ գիտեմ հիմնական գաղափարները և մանրամասները կսովորեմ, երբ նախագիծը դա պահանջի։
Ինչու է սա կարևոր
- Այն ամբողջությամբ աշխատում է քո ենթակառուցվածքում, ուստի հարմար է air-gapped ցանցերին, կարգավորվող ոլորտներին և հատուկ սարքավորում պահանջող build-երին։
- Մոտ երկու հազար plugin այն ինտեգրում են գրեթե ամեն SCM-ի, ամպի, թեստային գործիքի և chat համակարգի հետ, ուստի այն կարող է կազմակերպել անսովոր կամ legacy workflow-ներ։
- Շատ հաստատված ընկերություններ տարիներով pipeline-ներ են աշխատեցնում Jenkins-ի վրա․ այն հասկանալը հաճախ պարտադիր է դրանք սպասարկելու կամ migrate անելու համար։
- Րոպեավճար չկա․ վճարում ես քո վերահսկած մեքենաների համար, ինչը կարող է ավելի էժան լինել շատ ծանր, մշտական ծանրաբեռնվածության դեպքում։
Ինչպես է աշխատում
01Controller, agent-ներ և executor-ներ
Jenkins-ի տեղադրումն ունի controller՝ վեբ UI, կոնֆիգուրացիա, job-երի պլանավորում և plugin-ների host։ Աշխատանքը պետք է կատարվի agent-ների վրա՝ առանձին մեքենաներ կամ container-ներ, որոնք միանում են controller-ին և աշխատեցնում build-երը։ Յուրաքանչյուր agent առաջարկում է մի քանի executor՝ սլոտներ, որոնցից յուրաքանչյուրը կարող է աշխատեցնել մեկ build։ Label-ները, օրինակ՝ linux, docker կամ arm64, նկարագրում են agent-ներին, և pipeline-ը խնդրում է label, ոչ թե կոնկրետ մեքենա։ Agent-ները կարող են լինել մշտական (VM, որը միացված է SSH-ով կամ inbound կապով) կամ ժամանակավոր․ Kubernetes plugin-ը ամեն build-ի համար pod է գործարկում, իսկ ամպային plugin-ները ըստ պահանջի VM-ներ են գործարկում և հետո հեռացնում։ Պատկերացրու controller-ը որպես տաքսի ընկերության դիսպետչեր, իսկ agent-ները՝ մեքենաներ։ Հիմնական կանոն․ controller-ի սեփական executor-ների թիվը դարձրու զրո, որպեսզի անվստահելի build կոդը երբեք չաշխատի այն մեքենայի վրա, որը պահում է բոլոր credentials-ը և կարգավորումները։
02Jenkins-ի ապահով տեղադրում
Jenkins-ն ունի շաբաթական release-ների գիծ և Long-Term Support (LTS) գիծ, որը ընտրվում է շաբաթական release-ներից ամեն տասներկու շաբաթը մեկ և patch արվում կայունության համար․ production-ում պետք է աշխատի LTS-ը։ Ընթացիկ LTS release-ները պահանջում են Java 21 կամ Java 25։ Պաշտոնական jenkins/jenkins Docker image-ը սկսելու ամենահեշտ ձևն է․ ամրացրու LTS tag JDK suffix-ով, պահպանիր jenkins_home volume-ը (ամբողջ կոնֆիգուրացիան և պատմությունը այնտեղ են) և դիր այն reverse proxy-ի հետևում HTTPS-ով։ Առաջին գործարկման ժամանակ Jenkins-ը լոգում տպում է սկզբնական admin գաղտնաբառը, իսկ setup wizard-ը առաջարկում է խորհուրդ տրվող plugin-ներ։ Տեղադրիր միայն այն, ինչ պետք է, քանի որ ամեն plugin կոդ է՝ իր անվտանգության պատմությամբ։ Միացրու authentication realm (LDAP, SAML կամ OIDC՝ plugin-ներով) և matrix կամ role-based authorization․ երբեք anonymous օգտատերերին մի՛ թող գրելու որևէ իրավունք։
# compose.yaml - Jenkins controller, data in a named volume
services:
jenkins:
image: jenkins/jenkins:lts-jdk21
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080" # expose via a reverse proxy with TLS
- "50000:50000" # inbound agents
volumes:
- jenkins_home:/var/jenkins_home
volumes:
jenkins_home:
03Declarative pipeline՝ Jenkinsfile
Pipeline as code նշանակում է, որ build-ը սահմանված է Jenkinsfile-ում, որը պահվում է կոդի հետ, review է արվում pull request-ներում և տարբերակավորվում ինչպես մնացած ամեն ինչ։ Declarative syntax-ը խորհուրդ տրվող ոճն է․ ֆիքսված կառուցվածք pipeline-ով, agent-ով, stages-ով և steps-ով, գումարած ոչ պարտադիր options, environment, when և post բաժիններ։ Այն ավելի հեշտ է կարդալ և ստուգել, քան ազատ ձևի Groovy-ն։ Օրինակը build և թեստավորում է Node.js հավելված Docker container-ի ներսում docker label-ով ցանկացած agent-ի վրա, պահում միայն վերջին քսան build-երը, timeout է անում երեսուն րոպեից հետո, հրապարակում JUnit թեստերի արդյունքները և միշտ մաքրում workspace-ը։ Multibranch Pipeline job-ը scan է անում ռեպոզիտորիան և pipeline է ստեղծում Jenkinsfile պարունակող ամեն branch-ի և pull request-ի համար, ուստի նոր branch-երը ավտոմատ ստանում են CI։
pipeline {
agent { docker { image 'node:24-alpine'; label 'docker' } }
options {
timeout(time: 30, unit: 'MINUTES')
buildDiscarder(logRotator(numToKeepStr: '20'))
disableConcurrentBuilds()
}
stages {
stage('Install') { steps { sh 'npm ci' } }
stage('Test') {
steps { sh 'npm test -- --reporter=junit --outputFile=reports/junit.xml' }
post { always { junit 'reports/*.xml' } }
}
stage('Build') { steps { sh 'npm run build' } }
}
post { always { cleanWs() } }
}
04Credentials և deploy stage-եր
Jenkins-ը secret-ները պահում է իր credentials store-ում՝ սկավառակի վրա գաղտնագրված, գլոբալ կամ թղթապանակի scope-ով, որպեսզի թիմերը տեսնեն միայն իրենցը։ Pipeline-ները դրանց դիմում են withCredentials-ով կամ environment բլոկում credentials() helper-ով, և Jenkins-ը թաքցնում է արժեքները console output-ում։ Նախընտրիր թղթապանակի scope-ով credentials, իսկ ավելի լավ՝ արտաքին secret manager, օրինակ՝ HashiCorp Vault կամ ամպային secret manager՝ plugin-ի միջոցով։ Deploy stage-ը սովորաբար աշխատում է միայն main branch-ում, input-ով սպասում է մարդու և օգտագործում lock կամ milestone, որպեսզի համընկնող build-երը չկարողանան deploy անել սխալ հերթականությամբ։ Ուշադրություն դարձրու ստորև shell script-ի շուրջ միակի չակերտներին․ այդ դեպքում Groovy-ն secret-ը չի տեղադրում հրամանի տողի մեջ, և shell-ը այն կարդում է միջավայրից, ինչը այն հեռու է պահում լոգերից և պրոցեսների ցուցակներից։
stage('Deploy') {
when { branch 'main' }
steps {
input message: 'Deploy to production?', ok: 'Deploy'
withCredentials([sshUserPrivateKey(
credentialsId: 'deploy-ssh-key',
keyFileVariable: 'SSH_KEY',
usernameVariable: 'SSH_USER')]) {
sh '''
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=yes \
"[email protected]" "./deploy.sh $GIT_COMMIT"
'''
}
}
}
05Plugin-ներ և shared library-ներ
Jenkins-ի հնարավորությունների մեծ մասը plugin-ներ են՝ Git, Pipeline, credentials, Docker, Kubernetes agent-ներ, թեստերի հաշվետվություններ։ Այդ ճկունությունը նաև հիմնական շահագործման ռիսկն է։ Plugin-ները կախված են իրարից և core-ի տարբերակներից, և հնացածը անվտանգության advisory-ների հաճախակի աղբյուր է։ Ցուցակը պահիր կարճ, թարմացրու պարբերաբար՝ նախ staging Jenkins-ում, և կարդա security advisories էջը։ Բազմաթիվ ռեպոզիտորիաներում վերօգտագործման համար Shared Library-ները Groovy կոդը պահում են առանձին Git ռեպոզիտորիայում․ vars/-ի ֆունկցիաները դառնում են pipeline step-եր, ուստի տասնյակ Jenkinsfile-ներ կարող են կանչել մեկ ստանդարտացված buildNodeApp()՝ տրամաբանությունը պատճենելու փոխարեն։ Library-ները բեռնիր ամրացված տարբերակով՝ @Library('[email protected]') _։ Configuration as Code-ը (JCasC plugin) YAML-ով նկարագրում է controller-ը, ներառյալ անվտանգությունը, agent-ները և credentials-ի հղումները, ուստի կոտրված Jenkins-ը կարելի է վերակառուցել Git-ից, ոչ թե հիշողությունից։
Օգտագործեք, երբ
- Build-երը պետք է ամբողջությամբ աշխատեն on-premises կամ air-gapped ցանցերում՝ առանց արտաքին SaaS-ի։
- Արդեն ունես մեծ Jenkins համակարգ և պետք է սպասարկես, ամրացնես կամ աստիճանաբար արդիականացնես այն։
- Անսովոր կազմակերպում․ hardware-in-the-loop թեստեր, հատուկ build մեքենաներ կամ ինտեգրացիաներ, որոնք տալիս են միայն Jenkins-ի plugin-ները։
- Շատ բարձր, մշտական build-երի ծավալ, որտեղ մեքենաներ ունենալը ավելի էժան է, քան րոպեավճարը։
Մի՛ օգտագործեք, երբ
- Նոր նախագիծ GitHub-ում կամ GitLab-ում ստանդարտ կարիքներով․ ներկառուցված CI-ը ավելի քիչ աշխատանք է պահանջում աշխատեցնելու և ապահովելու համար։
- Փոքր թիմ, որտեղ ոչ ոք չկա controller-ի թարմացումների, plugin-ների թարմացումների և backup-ների համար։
- Ուզում ես զրո ենթակառուցվածք․ Jenkins-ը միշտ մի բան է, որը դու շահագործում ես։
Այլընտրանքներ
- GitHub Actions
GitHub-ի հետ ինտեգրված hosted CI՝ առանց սպասարկելու controller-ի։
- GitLab CI/CD
Ներկառուցված է GitLab-ում, ուժեղ self-managed տարբերակ՝ runner-ներով քո ցանցում։
- Buildkite
Hosted control plane՝ agent-ներով քո սեփական մեքենաների վրա, Jenkins-ի տարածված փոխարինող։
- Tekton / Argo Workflows
Kubernetes-native pipeline-ներ այն թիմերի համար, որոնք կառուցում են իրենց սեփական պլատֆորմը։
Լավագույն պրակտիկաներ
- Աշխատեցրու LTS գիծը, թարմացումները և plugin-ների թարմացումները նախ թեստավորիր staging controller-ի վրա։
- Controller-ի executor-ները դարձրու զրո և բոլոր build-երը աշխատեցրու agent-ների վրա, նախընտրելի է՝ ժամանակավոր։
- Օգտագործիր Declarative Pipeline Jenkinsfile-ում և Multibranch job-եր՝ UI-ով կարգավորված freestyle job-երի փոխարեն։
- Controller-ի կոնֆիգուրացիան կառավարիր Configuration as Code-ով և backup արա jenkins_home-ը։
- Credentials-ը սահմանափակիր թղթապանակներով, secret-ների համար օգտագործիր միակի չակերտներով shell տողեր և նախընտրիր արտաքին secret manager։
- Plugin-ների ցուցակը պահիր նվազագույն և արագ արձագանքիր Jenkins-ի security advisory-ներին։
- Վերօգտագործվող տրամաբանությունը դիր տարբերակավորված Shared Library-ներում՝ Jenkinsfile-ները պահելով կարճ և declarative։
Տարածված սխալներ
- Build-եր աշխատեցնել controller-ի վրա՝ ցանկացած pipeline-ին տալով մուտք բոլոր secret-ներին և կոնֆիգուրացիային։
- Տասնյակ plugin-ներ տեղադրել, որոնց ոչ ոք չի հիշում, հետո դրանց պատճառով չկարողանալ թարմացնել core-ը։
- Secret-ները տեղադրել կրկնակի չակերտներով Groovy տողերի մեջ, ինչը կարող է դրանք արտահոսել լոգեր և պրոցեսների ցուցակներ։
- Jenkins-ը ուղիղ բացել ինտերնետին՝ առանց HTTPS-ի, SSO-ի և խիստ authorization-ի։
- Ամեն ինչ կարգավորել UI-ում սեղմելով՝ առանց backup-ի, ուստի սկավառակի խափանումը նշանակում է վերակառուցում հիշողությունից։
Խորը վերլուծություն
06Ինչպես են pipeline-ները գոյատևում վերագործարկումները․ CPS և durability
Pipeline կոդը չի աշխատում որպես սովորական Groovy։ Jenkins-ը այն վերափոխում է continuation-passing style-ի (CPS), որպեսզի աշխատող pipeline-ի վիճակը կարողանա պահպանվել սկավառակի վրա և շարունակվել controller-ի վերագործարկումից հետո։ Ահա թե ինչու երկար build-երը կարող են գոյատևել թարմացումը, և նաև ինչու սովորական Groovy-ի որոշ բաներ կոտրվում են․ serialize չարվող օբյեկտները, որոշ closure-ներ և iterator-ներ առաջացնում են NotSerializableException։ @NonCPS նշված մեթոդները աշխատում են որպես մաքուր Groovy, բայց չեն կարող pipeline step-եր կանչել։ Նաև հիշիր, որ Jenkinsfile-ի Groovy-ն աշխատում է controller-ի վրա, ոչ թե agent-ի․ միայն sh-ի նման step-երն են աշխատում agent-ների վրա։ Groovy-ում ծանր parsing-ը կամ ցիկլերը, հետևաբար, ծանրաբեռնում են controller-ը, ուստի այդ աշխատանքը տեղափոխիր shell script-եր կամ գործիքներ, որոնք կատարվում են agent-ների վրա։ Durability կարգավորումը (օրինակ՝ PERFORMANCE_OPTIMIZED) շարունակման երաշխիքները փոխանակում է ավելի քիչ սկավառակային I/O-ի հետ զբաղված controller-ների վրա։
07Ժամանակավոր agent-ներ Kubernetes-ում
Kubernetes plugin-ը ամեն build-ի համար pod template-ից pod է գործարկում և միացնում այն որպես agent․ pod-ը ջնջվում է, երբ build-ը ավարտվում է։ Pod-ի յուրաքանչյուր container կարող է պարունակել տարբեր գործիքակազմ, և container()-ը stage-ի ներսում փոխանջատում է դրանց միջև։ Առավելություններ․ ամեն անգամ մաքուր workspace-ներ, «snowflake» build մեքենաների բացակայություն և scaling կլաստերի հետ։ Հետևիր մանրամասներին․ սահմանիր CPU-ի և հիշողության request-ներ, որպեսզի build-երը իրար չզրկեն ռեսուրսներից, build-երը աշխատեցրու non-root, և խուսափիր host-ի Docker socket-ը mount անելուց, ինչը build-ին node-ի վրա root է տալիս․ դրա փոխարեն օգտագործիր Kaniko ոճի կամ BuildKit rootless builder-ներ։ Dependency cache-երը անհետանում են pod-ի հետ, ուստի օգտագործիր persistent volume, proxy ռեպոզիտորիա, օրինակ՝ Nexus կամ Artifactory, կամ registry-ի վրա հիմնված build cache՝ build-երը արագ պահելու համար։
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: node
image: node:24-alpine
command: [sleep]
args: [infinity]
resources:
requests: { cpu: "500m", memory: 1Gi }
'''
defaultContainer 'node'
}
}
stages { stage('Test') { steps { sh 'npm ci && npm test' } } }
}
08Jenkins controller-ի պաշտպանություն
Jenkins-ն ունի պատմական խոցելիությունների երկար ցուցակ, հիմնականում plugin-ներում, և հարձակվողները ակտիվորեն scan են անում բաց instance-ները։ Պաշտպանություն շերտերով․ core-ը և plugin-ները թարմ պահիր հրապարակված security advisory-ների համաձայն, controller-ը դիր reverse proxy-ի հետևում TLS-ով և նախընտրելի է VPN-ով կամ SSO-ով, օգտագործիր matrix-based կամ role-based authorization առանց anonymous մուտքի, անջատիր CLI-ը remoting-ով և չօգտագործվող պրոտոկոլները, script console-ը թող միայն ադմինիստրատորներին, որովհետև այն աշխատեցնում է կամայական Groovy controller-ի լիարժեք իրավունքներով։ Script Security plugin-ը sandbox է անում pipeline-ի Groovy-ն և վտանգավոր մեթոդների համար պահանջում ադմինիստրատորի հաստատում․ մի՛ հաստատիր signature-ները անլուրջ։ Վերահսկիր, թե որ ռեպոզիտորիաները կարող են pipeline-ներ սահմանել և որ credentials-ը կարող է օգտագործել ամեն թղթապանակ, որովհետև pull request-ում Jenkinsfile-ի վնասակար փոփոխությունը կարող է տպել ցանկացած credential, որը job-ին հասանելի է։ Կարգավորիր trusted source-ներ, որպեսզի fork-երից եկած pull request-ները չկարողանան փոխել իրենց build-ի համար օգտագործվող Jenkinsfile-ը։
Իրական իրավիճակներ
Jenkins-ի թարմացումը արգելափակված է հին plugin-ներով
Խնդիր
Controller-ը core-ով երկու տարի հետ է մնացել և ունի 140 plugin։ Core-ի թարմացումը կոտրում է մի քանի plugin, և ոչ ոք չգիտի, թե որոնք են օգտագործվում։
Ինչպես լուծել
Backup արա jenkins_home-ը և clone արա այն staging controller-ի մեջ։ Արտահանիր plugin-ների ցուցակը և օգտագործման տվյալներով (Plugin Usage plugin-ով կամ job-երի կոնֆիգներում grep-ով) գտիր չօգտագործվող plugin-ները, հեռացրու դրանք։ Նախ Java-ն թարմացրու 21-ի, հետո core-ը՝ քայլ առ քայլ LTS release-ներով, ամեն քայլում plugin-ները թարմացնելով plugin installation manager tool-ով։ Ուղղիր կամ փոխարինիր լքված plugin-ները։ Արդյունքը ամրագրիր Configuration as Code-ով և plugins.txt-ով Git-ում, հետո production controller-ը կառուցիր այդ image-ից։ Դրանից հետո պլանավորիր ամսական LTS թարմացումներ, որպեսզի տարբերությունը այլևս չմեծանա։
Build-երը պատահականորեն ձախողվում են shared agent-ների վրա
Խնդիր
Build-երը նույն commit-ի վրա անցնում և ձախողվում են՝ կախված նրանից, թե որ մշտական agent-ն է դրանք աշխատեցնում։ Agent-ները ունեն գործիքների տարբեր տարբերակներ և մնացած ֆայլեր։
Ինչպես լուծել
Build-երը տեղափոխիր container-ների մեջ․ օգտագործիր agent { docker { image 'node:24-alpine' } } կամ Kubernetes pod template-ներ, որպեսզի գործիքակազմերը սահմանված լինեն Jenkinsfile-ում և ամենուր նույնը լինեն։ Agent-ների image-ները build արա CI-ում՝ տարբերակավորված և scan արված։ Workspace-ները մաքրիր cleanWs()-ով post-ում և դադարիր հույս դնել workspace-ից դուրս ֆայլերի վրա։ Մշտական agent-ները փոխարինիր ժամանակավորներով Kubernetes կամ ամպային plugin-ից։ Միայն մեկ մշտական agent պահիր այնտեղ, որտեղ հատուկ սարքավորում է պետք, և դրա կոնֆիգուրացիան կառավարիր Ansible-ով, որպեսզի այն հնարավոր լինի վերակառուցել։
Migration Jenkins-ից GitHub Actions
Խնդիր
Ընկերությունը, որը կոդը տեղափոխում է GitHub, ուզում է հրաժարվել Jenkins-ից, բայց ունի 80 pipeline Shared Library-ներով և custom plugin-ներով։
Ինչպես լուծել
Գույքագրիր pipeline-ները և խմբավորիր ըստ pattern-ի․ մեծ մասը կունենա մի քանի ընդհանուր ձև։ Shared Library-ի ֆունկցիաները վերածիր reusable workflow-ների և composite action-ների։ GitHub-ի Actions Importer-ը կարող է Jenkinsfile-ներից սևագիր workflow-ներ ստեղծել՝ մեխանիկական մասը արագացնելու համար։ Credentials-ը վերստեղծիր որպես environment secret-ներ կամ, ավելի լավ, OIDC trust։ Նախ migrate արա փորձնական խումբ և մի քանի շաբաթ երկու համակարգերը աշխատեցրու զուգահեռ՝ համեմատելով արդյունքները։ Jenkins-ը պահիր միայն on-premises սարքավորում պահանջող job-երի համար, կամ փոխարենը միացրու դրանք self-hosted runner-ներով, հետո վերջնական backup-ից հետո անջատիր controller-ը։
Արագ ուղեցույց
- Jenkins LTS-ը աշխատեցնել Docker-ում
docker run -d -p 127.0.0.1:8080:8080 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk21- Սկզբնական admin գաղտնաբառ
docker exec <container> cat /var/jenkins_home/secrets/initialAdminPassword- Աշխատեցնել միայն main-ում
when { branch 'main' }- Build-ի timeout
options { timeout(time: 30, unit: 'MINUTES') }- Պահել վերջին 20 build-երը
options { buildDiscarder(logRotator(numToKeepStr: '20')) }- Օգտագործել secret text
environment { API_TOKEN = credentials('api-token') }- Բեռնել shared library
@Library('[email protected]') _- Զուգահեռ stage-եր
parallel { stage('Unit') {...} stage('Lint') {...} }- Plugin-ների տեղադրում image-ում
jenkins-plugin-cli --plugin-file plugins.txt- Jenkinsfile-ի ստուգում
Pipeline Linter: POST $JENKINS_URL/pipeline-model-converter/validate
Հարցեր և պատասխաններ
Q1Ո՞րն է տարբերությունը controller-ի և agent-ի միջև։
Controller-ը ուղեղն է․ այն մատուցում է վեբ UI-ը, պահում է կոնֆիգուրացիան, credentials-ը և build-երի պատմությունը, պլանավորում է build-երը և աշխատեցնում plugin-ները։ Agent-ները աշխատողներ են, որոնք միանում են controller-ին և իրականում կատարում են build-ի step-երը։ Agent-ն ունի մի քանի executor, որոնցից յուրաքանչյուրը կարող է աշխատեցնել մեկ build։ Build-երը agent-ներ են ընտրում label-ով, ուստի Docker պահանջող job-ը խնդրում է docker, ոչ թե hostname։ Controller-ը ինքը չպետք է build-եր աշխատեցնի, որովհետև build script-երը ռեպոզիտորիաներից եկած կոդ են և կարող են կարդալ նրա secret-ները կամ վնասել կոնֆիգուրացիան։ Ժամանակակից համակարգերը օգտագործում են ժամանակավոր agent-ներ, օրինակ՝ Kubernetes pod կամ ամպային VM ամեն build-ի համար, որոնք ամեն անգամ մաքուր են և scale են լինում ըստ պահանջարկի։
Q2Declarative, թե՞ scripted pipeline։
Declarative pipeline-ն ունի ֆիքսված կառուցվածք՝ pipeline, agent, stages, steps, post, when, options։ Jenkins-ը կարող է այն ստուգել մինչև աշխատեցնելը, Blue Ocean ոճի տեսքերը հասկանում են այն, և ամբողջ թիմի համար այն ավելի հեշտ է կարդալ։ Scripted pipeline-ը մաքուր Groovy է node բլոկների ներսում․ առավելագույն ճկունություն, բայց հեշտ է այն դարձնել անընթեռնելի ծրագիր՝ CPS serialization-ի նուրբ խնդիրներով։ Իմ լռելյայն ընտրությունը Declarative-ն է ամեն Jenkinsfile-ի համար, script բլոկով միայն փոքր, անխուսափելի տրամաբանության համար։ Երբ իրական տրամաբանություն է պետք, այն պատկանում է թեստերով Shared Library-ին, որը կանչվում է կարճ Declarative Jenkinsfile-ից, ոչ թե inline Groovy-ին ամեն ռեպոզիտորիայում։
Q3Ինչպե՞ս ես աշխատում secret-ների հետ Jenkins pipeline-ներում։
Պահիր դրանք Jenkins-ի credentials store-ում՝ այն թիմի թղթապանակի scope-ով, որին դրանք պետք են, կամ վերցրու արտաքին manager-ից, օրինակ՝ Vault-ից, plugin-ի միջոցով։ Pipeline-ներում կապիր դրանք միայն այնտեղ, որտեղ պետք է, withCredentials-ով կամ environment բլոկում credentials()-ով, ինչը նաև թաքցնում է դրանք լոգերում։ Օգտագործիր միակի չակերտներով sh տողեր, որպեսզի փոփոխականը բացի shell-ը, ոչ թե Groovy-ն․ Jenkins-ը նույնիսկ զգուշացնում է անապահով interpolation-ի մասին։ Երբեք echo մի՛ արա secret-ները և մի՛ փոխանցիր դրանք որպես հրամանի արգումենտներ, որտեղ դրանք երևում են պրոցեսների ցուցակներում։ Սահմանափակիր, թե ով կարող է կարգավորել job-երը, որովհետև pipeline խմբագրել կարողացող յուրաքանչյուրը կարող է տպել դրա հասանելի credential-ը, և պարբերաբար աուդիտ արա credentials-ի օգտագործումը։
Q4Ինչպե՞ս Jenkins instance-ը պահել սպասարկելի տարիներ շարունակ։
Վերաբերվիր դրան ինչպես ցանկացած production ծառայության։ Աշխատեցրու LTS և թարմացրու ժամանակացույցով՝ փորձարկելով staging controller-ի վրա, որը վերականգնված է վերջին backup-ից։ Plugin-ները պահիր քիչ և թարմ՝ հեռացնելով չօգտագործվողները։ Նկարագրիր controller-ը Configuration as Code-ով Git-ում, որպեսզի այն հնարավոր լինի վերակառուցել․ job-երը գալիս են Jenkinsfile-ներից Multibranch կամ organization folder-ների միջոցով, ոչ թե UI-ից։ Backup արա jenkins_home-ը կամ գոնե այն մասերը, որոնք Git-ից հնարավոր չէ վերարտադրել։ Օգտագործիր ժամանակավոր agent-ներ CI-ում build արված image-ներից, որպեսզի agent-ների գործիքներն էլ տարբերակավորված լինեն։ Մոնիթորինգ արա սկավառակի տարածքը, հերթի երկարությունը և executor-ների օգտագործումը, և logRotator-ով ջնջիր հին build-երն ու artifact-ները, որպեսզի սկավառակը լուռ չլցվի։
Q5Ի՞նչ է Multibranch Pipeline-ը։
Multibranch Pipeline-ը job-ի տեսակ է, որը ցույց է տալիս ռեպոզիտորիա և ավտոմատ ստեղծում sub-job Jenkinsfile պարունակող ամեն branch-ի, և ըստ ցանկության ամեն pull request-ի համար։ Երբ branch է ստեղծվում, Jenkins-ը այն հայտնաբերում է webhook-ով կամ պարբերական scan-ով և սկսում build-ը, իսկ երբ branch-ը ջնջվում է, sub-job-ը հեռացվում է։ when { branch 'main' } կամ changeRequest() պայմանների հետ մեկ Jenkinsfile-ը կարող է տարբեր կերպ վարվել feature branch-երի, pull request-ների և main-ի համար։ Organization Folder-ը մեկ մակարդակ վերև է գնում և scan անում ամբողջ GitHub կազմակերպությունը կամ GitLab խումբը՝ Multibranch job-եր ստեղծելով Jenkinsfile ունեցող ամեն ռեպոզիտորիայի համար։
Սենիոր մակարդակի հարցեր
S1Ե՞րբ դեռ կընտրեիր Jenkins-ը նոր պլատֆորմի համար այսօր։
Լռելյայն՝ հազվադեպ, բայց ազնիվ դեպքեր կան։ Air-gapped կամ խիստ կարգավորվող միջավայրեր, որտեղ SaaS control plane թույլատրված չէ, և կազմակերպությունն արդեն լավ է աշխատեցնում Jenkins-ը։ Սարքավորումների բարդ workflow-ներ, օրինակ՝ embedded կամ սարքերի թեստավորում, որոնք կախված են կոնկրետ plugin-ներից կամ agent-ների կարգավորումներից։ Շատ մեծ build ֆերմաներ, որտեղ փորձառու թիմը Jenkins-ը շահագործում է Kubernetes agent-ներով, JCasC-ով և Shared Library-ներով՝ hosted րոպեներից ավելի ցածր արժեքով։ Դեմ փաստարկներ՝ շահագործման ծանրաբեռնվածություն, plugin-ների անվտանգության ռիսկ, Groovy-ին հատուկ հմտություններ և ներկառուցված CI-ից ավելի թույլ developer experience։ Եթե կոդը GitLab-ում կամ GitHub Enterprise Server-ում է, դրանց CI-ը self-hosted runner-ներով սովորաբար տալիս է նույն on-premises վերահսկողությունը՝ ավելի քիչ սպասարկմամբ, ուստի Jenkins-ը կընտրեի միայն հստակ պատճառով և թիմով, որը կտիրի դրան։
S2Ինչպե՞ս scale անել Jenkins-ը հարյուրավոր թիմերի համար։
Մեկ հսկա controller-ը դառնում է single point of failure և կատարողականի խցան, որովհետև Groovy pipeline-ի տրամաբանությունը, UI-ը և plugin-ները բոլորը աշխատում են այնտեղ։ Տարածված pattern-ը մի քանի controller է՝ բաժանված ըստ բիզնես միավորի կամ վստահության մակարդակի, յուրաքանչյուրը կառավարվում է նույն կերպ Configuration as Code-ով և ընտրված plugin image-ով, հնարավոր է CloudBees CI-ով կամ նմանատիպ գործիքներով՝ դրանք կենտրոնացված կառավարելու համար։ Agent-ները ժամանակավոր pod-եր կամ VM-ներ են, որոնք autoscale են լինում։ Shared Library-ները տալիս են ստանդարտ pipeline step-եր՝ տարբերակավորված և թեստավորված։ Թիմերը ստանում են թղթապանակներ՝ սահմանափակված credentials-ով և իրավունքներով։ Մոնիթորինգը ծածկում է հերթի ժամանակը, executor-ների օգտագործումը, controller-ի heap-ը և սկավառակը։ Փոխզիջումը պարկի կառավարման ծախսն է ընդդեմ blast radius-ի․ շատ controller-ներ նշանակում են ավելի շատ թարմացումներ կազմակերպելու համար, բայց վատ plugin-ը կամ անկառավարելի job-ը ազդում է կազմակերպության միայն մեկ մասի վրա։
S3Pull request-ը փոխում է Jenkinsfile-ը, որպեսզի տպի credentials։ Ինչպե՞ս է դա կանխվում։
Մի քանի վերահսկում պետք է համակցվեն։ Multibranch կոնֆիգուրացիայում սահմանիր trust այնպես, որ fork-երից կամ գրելու իրավունք չունեցող մասնակիցներից եկած pull request-ները build անեն թիրախ branch-ի Jenkinsfile-ով, ոչ թե իրենց փոփոխածով։ Credentials-ը սահմանափակիր թղթապանակներով և pull request build-երին ընդհանրապես մի՛ տուր production-ի credentials․ deploy credentials-ը կապվում են միայն main-ում աշխատող stage-երում։ Masking-ը օգնում է, բայց հեշտությամբ շրջանցվում է կոդավորմամբ, ուստի այն վերահսկման միջոց չէ։ Groovy sandbox-ը պահիր միացված և մի՛ հաստատիր ռիսկային script signature-ներ։ Jenkinsfile-ի և Shared Library-ի փոփոխությունների համար պահանջիր code review branch protection-ով։ Ամենաարժեքավոր secret-ների համար օգտագործիր Vault-ից կարճաժամկետ credentials, որպեսզի նույնիսկ արտահոսքը արագ լրանա։ Հիմքում ընկած սկզբունքը․ յուրաքանչյուր ոք, ով կարող է փոխել pipeline-ի կոդը, կարող է օգտագործել ցանկացած secret, որին այդ pipeline-ը հասնում է։
Բառարան
- Controller
- Կենտրոնական Jenkins սերվերը՝ UI, կոնֆիգուրացիա, պլանավորում և plugin-ներ։ Նախկինում կոչվում էր master։
- Agent
- Մեքենա կամ container, որը միանում է controller-ին և աշխատեցնում build-ի step-երը։
- Executor
- Սլոտ agent-ի վրա, որը միաժամանակ աշխատեցնում է մեկ build։
- Jenkinsfile
- Ֆայլ ռեպոզիտորիայում, որը սահմանում է pipeline-ը որպես կոդ։
- Declarative Pipeline
- Jenkinsfile-ի կառուցվածքային, խորհուրդ տրվող syntax՝ pipeline, agent, stages և steps բլոկներով։
- Shared Library
- Վերօգտագործվող Groovy step-երի Git ռեպոզիտորիա, որը բեռնում են բազմաթիվ Jenkinsfile-ներ։
- JCasC
- Configuration as Code․ controller-ի կարգավորումները նկարագրում է YAML-ով, որպեսզի այն հնարավոր լինի վերակառուցել Git-ից։
- LTS
- Long-Term Support release-ների գիծ, որը ընտրվում է ամեն տասներկու շաբաթը մեկ և patch արվում կայունության համար։
- Multibranch Pipeline
- Job, որը pipeline է ստեղծում Jenkinsfile ունեցող ամեն branch-ի կամ pull request-ի համար։
Շարունակեք սովորել
Պրոդուկտի գաղափար ունե՞ք։Եկեք ստեղծենք այն։
Պատմեք ձեր գաղափարի, պրոդուկտի կամ թիմի մասին։ Սովորաբար պատասխանում եմ մեկ աշխատանքային օրվա ընթացքում։