±à¼ÍƼö: |
ÎÄÕÂÊ×ÏȽéÉÜÁËDevOps¸ÅÊö¡¢ÔÆÔÉúDevOpsÌØµãÒÔ¼°ÔÆÔÉúDevOpsʵÏÖ¡£
±¾ÎÄÀ´×ÔÓÚÔÆÔÉúÉçÇø,ÓÉ»ðÁú¹ûÈí¼þAnna±à¼ÍƼö¡£ |
|
DevOps¼òÊö
¹ËÃû˼Ò壬DevOps¾ÍÊÇ¿ª·¢£¨Development£©ÓëÔËά£¨Operations£©µÄ½áºÏÌ壬ÆäÄ¿µÄ¾ÍÊÇ´òͨ¿ª·¢ÓëÔËά֮¼äµÄ±ÚÀÝ£¬´Ù½ø¿ª·¢¡¢ÔËÓªºÍÖÊÁ¿±£ÕÏ£¨QA£©µÈ²¿ÃÅÖ®¼äµÄ¹µÍ¨Ð×÷£¬ÒÔ±ã¶Ô²úÆ·½øÐÐС¹æÄ£¡¢¿ìËÙµü´úʽµØ¿ª·¢ºÍ²¿Ê𣬿ìËÙÏìÓ¦¿Í»§µÄÐèÇó±ä»¯¡£ËüÇ¿µ÷µÄÊÇ¿ª·¢ÔËάһÌ廯£¬¼ÓÇ¿ÍŶӼäµÄ¹µÍ¨ºÍ¿ìËÙ·´À¡£¬´ïµ½¿ìËÙ½»¸¶²úÆ·ºÍÌá¸ß½»¸¶ÖÊÁ¿µÄÄ¿µÄ¡£
DevOps²¢²»ÊÇÒ»ÖÖÐµĹ¤¾ß¼¯£¬¶øÊÇÒ»ÖÖ˼Ï룬һÖÖÎÄ»¯£¬ÓÃÒԸı䴫ͳ¿ª·¢ÔËάģʽµÄÒ»×é×î¼Ñʵ¼ù¡£Ò»°ã×ö·¨ÊÇͨ¹ýһЩCI/CD£¨³ÖÐø¼¯³É¡¢³ÖÐø²¿Êð£©×Ô¶¯»¯µÄ¹¤¾ßºÍÁ÷³ÌÀ´ÊµÏÖDevOpsµÄ˼Ï룬ÒÔÁ÷Ë®Ïߣ¨pipeline£©µÄÐÎʽ¸Ä±ä´«Í³¿ª·¢ÈËÔ±ºÍ²âÊÔÈËÔ±·¢²¼Èí¼þµÄ·½Ê½¡£Ëæ×ÅDockerºÍKubernetes£¨ÒÔϼò³Æk8s£©µÈ¼¼ÊõµÄÆÕ¼°£¬ÈÝÆ÷ÔÆÆ½Ì¨»ù´¡ÉèʩԽÀ´Ô½ÍêÉÆ£¬¼ÓËÙÁË¿ª·¢ºÍÔËά½ÇÉ«µÄÈںϣ¬Ê¹ÔÆÔÉúµÄDevOpsʵ¼ù³ÉΪÒÔºóµÄÇ÷ÊÆ¡£ÏÂÃæÎÒÃÇ»ùÓÚ»ìºÏÈÝÆ÷ÔÆÆ½Ì¨Ïêϸ½²½âÏÂÔÆÆ½Ì¨ÏÂDevOpsµÄÂ䵨·½°¸¡£
ÔÆÔÉúDevOpsÌØµã
DevOpsÊÇPaaSƽ̨ÀïºÜ¹Ø¼üµÄ¹¦ÄÜÄ£¿é£¬°üº¬ÒÔÏÂÖØÒªÄÜÁ¦£ºÖ§³Ö´úÂë¿Ë¡¡¢±àÒë´úÂë¡¢ÔËÐнű¾¡¢¹¹½¨·¢²¼¾µÏñ¡¢²¿ÊðyamlÎļþÒÔ¼°²¿ÊðHelmÓ¦ÓõȻ·½Ú£»Ö§³Ö·á¸»µÄÁ÷Ë®ÏßÉèÖ㬱ÈÈç×ÊÔ´ÏÞ¶î¡¢Á÷Ë®ÏßÔËÐÐÌõÊý¡¢ÍÆËÍ´úÂëÒÔ¼°ÍÆË;µÏñ´¥·¢Á÷Ë®ÏßÔËÐеȣ¬ÌṩÁËÓû§ÔÚ²»Í¬»·¾³ÏµĶ˵½¶Ë¸ßЧÁ÷Ë®ÏßÄÜÁ¦£»Ìṩ¿ªÏä¼´ÓõľµÏñ²Ö¿âÖÐÐÄ£»ÌṩÁ÷Ë®Ïß»º´æ¹¦ÄÜ£¬¿ÉÒÔ×ÔÓÉÅäÖÃÕû¸öÁ÷Ë®Ïß»òÿ¸ö²½ÖèµÄÔËÐлº´æ£¬ÔÚ´úÂë¿Ë¡¡¢±àÒë´úÂë¡¢¹¹½¨¾µÏñµÈ²½Öèʱ¾ù¿ÉÀûÓûº´æ´ó´óËõ¶ÌÔËÐÐʱ¼ä£¬ÌáÉýÖ´ÐÐЧÂÊ¡£¾ßÌ幦ÄÜÇåµ¥ÈçÏ£º
»º´æ¼ÓËÙ£º×ÔÑÐÈÝÆ÷»¯Á÷Ë®ÏߵĻº´æ¼¼Êõ£¬Í¨¹ý´úÂë±àÒëºÍ¾µÏñ¹¹½¨µÄ»º´æ¸´Óã¬Æ½¾ù¼ÓËÙÁ÷Ë®Ïß3~5±¶£»
ϸÁ£¶È»º´æÅäÖãºÈÎÒ»½×¶Î¡¢²½Öè¿ÉÒÔ¿ØÖÆÊÇ·ñ¿ªÆô»º´æ¼°»º´æÂ·¾¶£»
Ö§³ÖÁÙʱÅäÖãºÓû§ÎÞÐèÌá½»¼´¿ÉÔËÐÐÁÙʱÅäÖ㬱ÜÃâÆµ·±Ìá½»ÅäÖÃÎļþÎÛȾ´úÂë²Ö¿â£»
¿ªÏä¼´ÓõľµÏñ²Ö¿â£»
ÌṩÍêÕûµÄÈÕÖ¾¹¦ÄÜ£»
¿ÉÊÓ»¯±à¼½çÃæ£¬Áé»îÅäÖÃÁ÷Ë®Ïߣ»
Ö§³Ö¶àÖÖ´úÂë²Ö¿âÊÚȨ£ºGitHub¡¢GitLab¡¢BitbucketµÈ£»
¶àÖÖÁ÷Ë®Ïß´¥·¢·½Ê½£º´úÂë²Ö¿â´¥·¢£¬¾µÏñÍÆËÍ´¥·¢µÈ£»
ÍøÂçÓÅ»¯£¬¼Ó¿ì¾µÏñ»òÒÀÀµ°üµÄÏÂÔØËÙ¶È£»
ÔÆÔÉúDevOpsʵÏÖ
¼òµ¥µØËµ£¬ÔÆÔÉúDevOpsÄÚ²¿¹¦ÄܵÄÉè¼Æ»ù±¾ÉϾùÊÇͨ¹ýk8sÌṩµÄ×Ô¶¨Òåcontroller¹¦ÄÜÀ´ÊµÏֵ쬻ù±¾Âß¼¾ÍÊǸù¾ÝÒµÎñÐèÒª³éÏó³ö¶à¸öCRD£¨Custom
Resource Definition£¬×Ô¶¨Òå×ÊÔ´¶ÔÏ󣩣¬²¢±àд¶ÔÓ¦µÄcontrollerÀ´ÊµÏÖÒµÎñÂß¼¡£ÎªÁËʵÏÖCI/CD¹¦ÄÜ£¬ÎÒÃdzéÏó³öÁ˶à¸öCRD¶ÔÏó£¬ÈçÏÂͼËùʾ£º

ÎÒÃÇÖªµÀÅäÖÃÁ÷Ë®Ïßͨ³£ÐèÒª¶Ô½Ó´úÂë²Ö¿â£¬°üÀ¨²Ö¿âµØÖ·£¬²Ö¿âÊÚȨÐÅÏ¢µÈ£¬Òò´ËÎÒÃÇÐèÒªÓÐ3¸öCRD¶ÔÏóÀ´¼Ç¼Դ´úÂë²Ö¿âµÄÏà¹ØÐÅÏ¢¡£
sourceCodeProviderConfig£º¼Ç¼²Ö¿âOAuth AppsµÄ¿Í»§¶ËID¡¢¿Í»§¶ËÃØÔ¿£»
sourceCodeCredential£º¼Ç¼²Ö¿âµÄÈÏÖ¤ÐÅÏ¢£»
sourceCodeRepository£º¼Ç¼²Ö¿âµØÖ·µÈÐÅÏ¢¡£
Éè¼ÆºÃÁËDevOpsÖÐÓë²Ö¿âÏà¹ØµÄ3¸öCRD¶ÔÏóºó£¬ÎÒÃÇÐèÒªÔÙ¶¨Òå3¸öCRD¶ÔÏóÀ´ÃèÊöÁ÷Ë®ÏßÏà¹ØµÄÐÅÏ¢¡£
pipeline£º¼Ç¼¸ÃÁ÷Ë®ÏßµÄÅäÖÃÐÅÏ¢£º²Ö¿âµÄÈÏÖ¤ÐÅÏ¢¡¢¹³×Ó´¥·¢ÅäÖÃÒÔ¼°ÏîÄ¿´úÂëµØÖ·µÈµÈ£»
pipelineExecution£º¼Ç¼Á÷Ë®ÏßÔËÐÐʱÐÅÏ¢ÓëÖ´Ðнá¹ûÐÅÏ¢µÈ£»
pipelineSetting£º¼Ç¼Õû¸öÏîÄ¿ÏÂpipelineÔËÐл·¾³ÐÅÏ¢£ºÄÚ´æ¡¢CPUµÄÏÞÖÆ£¬×î´óÁ÷Ë®Ïß²¢ÐÐÔËÐиöÊýµÈµÈ¡£
pipeline²½Ö蹦ÄÜÓкܶàÖÖÀàÐÍ£¬°üÀ¨ÔËÐнű¾¡¢¹¹½¨·¢²¼¾µÏñ¡¢·¢²¼Ó¦ÓÃÄ£°å¡¢²¿ÊðYAML¡¢²¿ÊðÓ¦Óõȵȡ£ÎªÁËÌṩÕâЩ¹¦ÄÜ£¬ÎÒÃDzÉÓÃJenkins×÷Ϊµ×²ãµÄCI/CD¹¤¾ß£¬docker
registry ×÷Ϊ¾µÏñ²Ö¿âÖÐÐÄ£¬minio×÷ΪÈÕÖ¾´æ´¢ÖÐÐĵȵȡ£ÕâЩ·þÎñÊÇÔËÐÐÔÚpipelineËùÔÚÏîÄ¿µÄÃüÃû¿Õ¼äÏ¡£×ÛÉÏ£¬ÎÒÃÇÉè¼ÆµÄCI/CDϵͳ¹¦ÄܵÄʵÏÖÂß¼ÈçͼËùʾ£º

ÈçÉÏ£¬µ±µÚÒ»´ÎÔËÐÐÁ÷Ë®Ïßʱ£¬ÏµÍ³»áÔÚÊý¾ÝÃæk8sÖв¿ÊðJenkins¡¢minioµÈ»ù´¡¹¤¾ßµÄ·þÎñ£¬Í¬Ê±ÔÚ¹ÜÀíÃæÆô¶¯Ò»¸ögoroutine£¬ÊµÊ±Í¬²½Êý¾ÝÃæÖÐÁ÷Ë®ÏßµÄ×÷ҵ״̬µ½¹ÜÀíÃæµÄCRD¶ÔÏóÖС£µ±´¥·¢pipelineÖ´ÐÐÂ߼ʱ£¬»á²úÉúÒ»¸öpipelineExecution
CRD¶ÔÏó£¬ÒԼǼ±¾´ÎÔËÐÐpipelineµÄ״̬ÐÅÏ¢¡£µ±goroutine£¨syncState£©·¢ÏÖÓÐеÄÖ´ÐÐʵÀý²úÉúʱ£¬¾Í»áͨ¹ýJenkinsÒýÇæ½Ó¿ÚÆô¶¯Jenkins
server¶ËÁ÷Ë®Ïß×÷ÒµµÄÔËÐУ¬Jenkins server¶ËÊÕµ½ÐÅÏ¢ºó»áÆô¶¯µ¥¶ÀµÄÒ»¸öJenkins
slave pod½øÐÐÁ÷Ë®Ïß×÷ÒµµÄÏìÓ¦¡£Í¬Ê±£¬goroutine£¨syncState£©»á²»¶ÏµØÍ¨¹ýÒýÇæ½Ó¿ÚÂÖѯpipelineÖ´ÐÐʵÀýµÄÔËÐÐÇé¿ö½ø¶ø¸üÐÂ
pipelineExecution CRDµÄ״̬£¨ÔËÐгɹ¦»òʧ°ÜµÈµÈ£©¡£µ±pipelineÖ´ÐÐʵÀý·¢Éú״̬±ä»¯Ê±£¬¾Í»á´¥·¢Æä¶ÔÓ¦µÄcontrollerÒµÎñÂß¼£¬½ø¶øÍ¨¹ýJenkinsÒýÇæ½Ó¿ÚÓëJenkins
server ͨÐŽøÐв»Í¬µÄ²Ù×÷£¬±ÈÈ磬ÔÝÍ£Á÷Ë®ÏßµÄÔËÐУ¬ÔËÐÐÍêÇå³ý²»ÐèÒªµÄ×ÊÔ´µÈµÈ¡£µ±Á÷Ë®Ïß×÷Òµ·¢Éú״̬±ä»¯Ê±£¬ÓÖ»áͨ¹ýgoroutine£¨syncState£©¸ü¸ÄpipelineÖ´ÐÐʵÀýµÄ״̬£¬½ø¶øÓÖ´¥·¢¶ÔÓ¦µÄcontrollerÒµÎñ´úÂë½øÐв»Í¬µÄÒµÎñÂß¼´¦Àí£¬Íù¸´Ñ»·£¬Ö±µ½Á÷Ë®ÏßÔËÐнáÊø¡£Õâ¾ÍÊÇÕû¸öpipelineÖ´ÐÐʱµÄÒ»¸öÂß¼Á÷³Ì¡£
CRD¶¨Òå
ÏÂÃæÊÇÏêϸµÄCRD½á¹¹Ìå½²½â£¬Ãô¸ÐÐÅϢʹÓÃÁË¡¯*¡®´úÌæ¡£
pipelineSetting£º¸Ã½á¹¹Ìå±£´æ×ÅÕû¸öÏîÄ¿ÏÂËùÓÐpipelineµÄÔËÐл·¾³ÐÅÏ¢£¬±ÈÈçCPU/ÄÚ´æ×ÊÔ´ÏÞ¶î¡¢»º´æÂ·¾¶ÒÔ¼°Á÷Ë®ÏßÔËÐеÄ×î´ó²¢ÐиöÊýµÈµÈ£¬²»Í¬¹¦ÄܵÄÅäÖÃÐÅÏ¢±£´æÔÚ²»Í¬µÄCRDÏ¡£
devops-cache-dir
12d
executor-cpu-limit 12d
executor-cpu-request 12d
executor-memory-limit 12d
executor-memory-request 12d
executor-quota 12d
...
// ±ÈÈ磬¿´ÏÂexecutor-quotaÏêϸÐÅÏ¢
apiVersion: project.cubepaas.com/v3
kind: PipelineSetting
metadata:
labels:
cubepaas.com/creator: linkcloud
name: executor-quota
namespace: p-zwmcv
default: "2" // ĬÈÏ×î¶à¿ÉͬʱÔËÐÐ2¸öpipeline
projectName: c-86tgg:p-zwmcv
value: "3" // ×Ô¶¨ÒåÉèÖã¬×î¶à¿ÉͬʱÔËÐÐ3¸öpipeline£¬Ã»ÓÐÖµ»áÈ¡ÉÏÃæÄ¬ÈÏÖµ |
pipeline£º¸Ã½á¹¹Ìå¼Ç¼×ÅÁ÷Ë®ÏßµÄÅäÖÃÔªÐÅÏ¢£¬±ÈÈç¸ÃÁ÷Ë®Ïß¶Ô½ÓÄĸöÏîÄ¿´úÂë¡¢Óë²Ö¿âͨÐŵÄÈÏÖ¤ÐÅÏ¢ÒÔ¼°ÉϴθÃÁ÷Ë®ÏßÔËÐеĽá¹ûµÈµÈ¡£ÈçÏÂͼËùʾ£º

ÏêϸµÄ½á¹¹×ֶν²½âÈçÏ£º
apiVersion:
project.cubepaas.com/v3
kind: Pipeline
metadata:
labels:
cubepaas.com/creator: linkcloud
name: p-d5frn
namespace: p-zwmcv
spec:
currentBranch: master // Á÷Ë®ÏßÔËÐÐʱĬÈÏ´úÂë·ÖÖ§
imageWebHookToken: // ÕâÊÇÍÆË;µÏñʱ´¥·¢¸ÃÁ÷Ë®ÏßÔËÐеÄÉèÖÃÐÅÏ¢
- branches:
- master
comment: a
imageType: harbor // Ö§³Ö harbor dockerhub aliyunµÈ¾µÏñ²Ö¿â
token: 7c102c82-66d9-44c1-8718-**** // ÍÆË;µÏñ´¥·¢Á÷Ë®ÏßÔËÐÐʱµÄ
token ÈÏÖ¤
trigger: nginx // µ±ÍÆËÍ nginx ¾µÏñʱ»á´¥·¢Á÷Ë®ÏßÔËÐÐ
projectName: c-86tgg:p-zwmcv
repositoryUrl: https://github.com/gophere/ devops-go.git
// ÏîÄ¿´úÂëµØÖ·
sourceCodeCredentialName: u-8sq**:p-zwmcv-github-gophere
// Ö¸Ïò¶ÔÓ¦µÄÓû§ÈÏÖ¤ÐÅÏ¢
triggerWebhookPush: true // ¹³×Ó²Ù×÷£¬µ±push´úÂëµ½²Ö¿âʱ»á´¥·¢¸ÃÁ÷Ë®ÏßÖ´ÐÐ
status:
lastRunState: Success // ×îÐÂÒ»´ÎÔËÐеÄ×îºó½á¹û
nextRun: 2 // Ï´ÎÔËÐÐʱִÐÐʵÀý¶ÔÓ¦µÄÐòºÅ
pipelineState: active // ¸ÃÁ÷Ë®Ïß´¦ÓÚÓÐЧ״̬
sourceCodeCredential: // ÉÏÊöÒѽéÉÜ£¬´Ë´¦²»ÔÙ׸Êö
...
...
token: e667bbb9-7230-48d4-9d29-***** // ÓÃÓÚ´úÂë²Ö¿â´¥·¢Á÷Ë®ÏßÔËÐÐʱµÄ
token ÈÏÖ¤
webhookId: "245901183" // ´úÂë²Ö¿âµÄ¹³×ÓÐÅÏ¢ |
pipelineExecution£ºÁ÷Ë®ÏßÖ´ÐÐʵÀý£¬Ã¿µ±Á÷Ë®ÏßÔËÐÐÒ»´Î£¬»á²úÉúÒ»¸ö¸Ã¶ÔÏó¼Ç¼×ÅÁ÷Ë®ÏßµÄÖ´Ðнá¹ûµÈÐÅÏ¢¡£ÈçÏÂͼËùʾ£º

ÏêϸµÄ½á¹¹×ֶν²½âÈçÏ£º
apiVersion:
project.cubepaas.com/v3
kind: PipelineExecution
metadata:
labels:
cubepaas.com/creator: linkcloud
pipeline.project.cubepaas.com /finish: "true"
name: p-d5frn-2
namespace: p-zwmcv
spec:
branch: master // ±¾´ÎÔËÐеĴúÂë·ÖÖ§
commit: f5b78969586cd90918020cb7a 138fe88c7e25f9d
// ´úÂë commitid
message: Update .cubepaas -devops.yml // ´úÂë
commit ˵Ã÷
pipelineConfig: // ÒÔÏÂÊÇpipeline¾ßÌåµÄstageºÍstepµÄÅäÖÃÐÅÏ¢£¬Ã¿´ÎÔËÐÐʱ´Ó´úÂë²Ö¿âµÄÅäÖÃÎļþ£¨.cubepaas.devops.ymal£©ÀÈ¡ÏÂÀ´Ìî³ä¸Ã½á¹¹
stages:
- name: Clone // ¿Ë¡´úÂë
steps:
- sourceCodeConfig: {}
- name: Build // ÔËÐнű¾±àÒë´úÂë
...
pipelineName: p-zwmcv:p-d5frn
projectName: c-86tgg:p-zwmcv
ref: master
repositoryUrl: https://github.com/gophere/ devops-go.git
// ÏîÄ¿´úÂëµØÖ·
run: 2 // ´Ë´ÎÔËÐÐÐòºÅ
triggerUserName: u-8sq** // ´¥·¢Óû§
triggeredBy: user
status: // ÒÔϼǼ×Åpipelineÿ¸östageºÍstepµÄÔËÐнá¹ûÐÅÏ¢
executionState: Success
stages:
- ended: 2020-09-03T06:01:01Z
state: Success
steps:
- ended: 2020-09-03T06:01:01Z
state: Success
...
... |
ÖÁ´Ë£¬ÎÒÃÇÍê³ÉÁËÁ÷Ë®Ïß¹¦ÄܵĻù´¡¶ÔÏó¶¨Òå¡£
controller ʵÏÖ
³ýÁ˳éÏó³ö¶ÔÓ¦µÄCRDÍ⣬ÎÒÃÇ»¹ÐèÒª±àд¶ÔÓ¦µÄcontroller´úÂëʵÏÖ¶ÔÓ¦µÄÒµÎñÂß¼£¬±ÈÈçµ±pipelineÔËÐÐʱ£¬ÎÒÃÇÐèÒª²úÉúpipelineÖ´ÐÐʵÀý£¬²¢ÊµÊ±Í¬²½ÆäÔËÐеÄ״̬ÐÅÏ¢µÈµÈ¡£
µ±´¥·¢Á÷Ë®ÏßÖ´ÐÐÂ߼ʱ£¬ÏµÍ³»á¸ù¾Ýpipeline CRD¶ÔÏóºÍ¸ÃÁ÷Ë®Ïß¶ÔÓ¦µÄ´úÂë²Ö¿âÖеÄÅäÖÃÎļþ£¨.cubepaas.devops.ymal£©²úÉúÒ»¸öpipelineExecution
CRD¶ÔÏó£¬Õâʱ»á´¥·¢pipelineExecution¶ÔÓ¦µÄcontrollerÔËÐÐÒµÎñÂß¼¡£ÏÂÃæÖ»ÕªÈ¡ÖØÒªµÄ´úÂëÂß¼£¬ÈçÏÂËùʾ£º
func (l *Lifecycle)
Sync (obj *v3.PipelineExecution) (runtime.Object,
error) {
...
// Èç¹û pipeline Ö´ÐÐʵÀý±»ÔÝÍ££¬Ôò»áÍ£Ö¹Á÷Ë®Ïß×÷Òµ
if obj.Status.ExecutionState == utils.StateAborted
{
if err := l.doStop(obj); err != nil {
return obj, err
}
}
// Èç¹û pipeline Ö´ÐÐʵÀýÔËÐÐÍê±Ï£¬Ôò»áÇåÀíÁ÷Ë®Ïß×÷ÒµµÄһЩ×ÊÔ´
// ±ÈÈ磬²úÉúµÄJenkins slave pod
if obj.Labels != nil && obj.Labels [utils.PipelineFinishLabel]
== "true" {
return l.doFinish(obj)
}
// Èç¹û pipeline Ö´ÐÐʵÀýÕýÔÚÔËÐÐÖУ¬ÔòÖ±½Ó·µ»Ø£¬ÎÞ²Ù×÷
if v3. PipelineExecutionConditionInitialized .GetStatus(obj)
!= "" {
return obj, nil
}
// ÅжÏÁ÷Ë®Ïß×÷ÒµÊÇ·ñ³¬³ö×ÊÔ´ÏÞ¶î
exceed, err := l.exceedQuota(obj)
if err != nil {
return obj, err
}
// Èç¹û³¬³ö×ÊÔ´Ï޶Ôò»áÉèÖõ±Ç° pipeline Ö´ÐÐʵÀýΪ×èÈû״̬
if exceed {
obj.Status.ExecutionState = utils.StateQueueing
obj.Labels[utils.PipelineFinishLabel] = ""
if err := l.newExecutionUpdateLastRunState(obj);
err != nil {
return obj, err
}
return obj, nil
} else if obj.Status.ExecutionState == utils.StateQueueing
{
obj.Status.ExecutionState = utils.StateWaiting
}
// ¸üРpipeline Ö´ÐÐʵÀýµÄ״̬: ±ÈÈçÔËÐÐÐòºÅ+1
if err := l.newExecutionUpdateLastRunState(obj);
err != nil {
return obj, err
}
v3 . PipelineExecutionConditionInitialized .CreateUnknownIfNotExists(obj)
obj.Labels[utils.PipelineFinishLabel] = "false"
// ÔÚÊý¾ÝÃæ²¿Êðpipeline¹¦ÄÜËùÐè×ÊÔ´
if err := l.deploy (obj.Spec.ProjectName); err
!= nil {
obj.Labels [utils.PipelineFinishLabel] = "true"
obj.Status.ExecutionState = utils.StateFailed
v3 .PipelineExecutionConditionInitialized .False(obj)
v3 .PipelineExecutionConditionInitialized .ReasonAndMessageFromError(obj,
err)
}
// ½« configMap ´æ´¢µÄdocker¾µÏñ²Ö¿â¶Ë¿ÚÐÅϢͬ²½µ½pipelineÖ´ÐÐʵÀýÖÐÈ¥.
if err := l.markLocalRegistryPort(obj); err
!= nil {
return obj, err
}
return obj, nil
} |
ÆäÖУ¬deployº¯ÊýµÄÂß¼¾ÍÊǵÚÒ»´ÎÔËÐÐʱͨ¹ýÅжÏÊý¾ÝÃæÖÐÊÇ·ñ´æÔÚpipelineµÄÃüÃû¿Õ¼ä£¬Èç¹û´æÔھʹú±í»ù´¡×ÊÔ´ÒѾÅäÖÃÍê³É£¬Ö±½Ó×ßreconcileRbº¯Êý£¬¸Ãº¯ÊýµÄÂß¼¼ûÏÂÃæ£»Èç¹û²»´æÔÚ£¬¾Í»áÔÚÊý¾ÝÃæÖгõʼ»¯±ØÒªµÄ»ù´¡×ÊÔ´£¬±ÈÈ磺pipelineÃüÃû¿Õ¼ä,
Jenkins docker minio·þÎñ, ÅäÖÃconfigMap, secretµÈµÈ¡£
func (l *Lifecycle)
deploy(projectName string) error {
clusterID, projectID := ref.Parse(projectName)
ns := getPipelineNamespace(clusterID, projectID)
// Èç¹û¸ÃpipelineµÄnamespaceÒѾÓÐÁË£¬ËµÃ÷ÏÂÃæµÄ×ÊÔ´²¿ÊðÒѾÍê³ÉÁË£¬ÔòÖ±½Ó×ßreconcileRbÁ÷³Ì
// ·ñÔò×ßÏÂÃæµÄ×ÊÔ´²¿ÊðÁ÷³Ì
if _, err := l.namespaceLister.Get("",
ns.Name); err == nil {
return l.reconcileRb(projectName)
} else if !apierrors.IsNotFound(err) {
return err
}
// ´´½¨pipeline¶ÔÓ¦µÄÃüÃû¿Õ¼ä£¬Èçp-qqxs7-pipeline
if _, err := l.namespaces.Create(ns); err !=
nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error creating
the pipeline namespace")
}
...
// Ëæ»ú²úÉúÒ»¸ötoken£¬ÓÃÓÚÅäÖÃÏÂÃæµÄsecret
token, err := randomtoken.Generate()
nsName := utils.GetPipelineCommonName(projectName)
ns = getCommonPipelineNamespace()
// ´´½¨ÓÃÓÚ²¿Êðdocker¾µÏñ²Ö¿âµÄ´úÀí·þÎñµÄÃüÃû¿Õ¼ä
if _, err := l.namespaces.Create(ns); err !=
nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error creating
the cattle-pipeline namespace")
}
// ÔÚ pipeline namespace ÄÚ´´½¨secret : pipeline-secret
secret := getPipelineSecret(nsName, token)
l.secrets.Create(secret);
...
// »ñÈ¡¹ÜÀíÃæÏîÄ¿µÄϵͳÓû§token
apikey, err := l.systemAccountManager .GetOrCreateProjectSystemToken
(projectID)
...
// ÔÚ pipeline namespace ÄÚ´´½¨secret: pipeline-api-key£¬ÓÃÓÚÊý¾ÝÃæÓë¹ÜÀíÃæÍ¨Ðŵį¾Ö¤
secret = GetAPIKeySecret(nsName, apikey)
l.secrets.Create(secret);
// µ÷г docker ¾µÏñ²Ö¿âµÄÖ¤ÊéÅäÖã¨ÔÚ¿ØÖÆÃæÖУ©
if err := l.reconcileRegistryCASecret (clusterID);
err != nil {
return err
}
// ½«¿ØÖÆÃæÖÐµÄ docker ¾µÏñ²Ö¿âµÄÖ¤ÊéÅäÖÃͬ²½µ½Êý¾ÝÃæÖÐ
if err := l.reconcileRegistryCrtSecret (clusterID,
projectID); err != nil {
return err
}
// ÔÚ pipeline namespace ÄÚ´´½¨ serviceAccount
: jenkins
sa := getServiceAccount(nsName)
if _, err := l.serviceAccounts.Create(sa); err
!= nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf (err, "Error creating
a pipeline service account")
}
...
// ÔÚ pipeline namespace ÄÚ´´½¨ service: jenkins
jenkinsService := getJenkinsService(nsName)
if _, err := l.services.Create(jenkinsService);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf (err, "Error creating
the jenkins service")
}
// ÔÚ pipeline namespace ÄÚ´´½¨ deployment: jenkins
jenkinsDeployment := GetJenkinsDeployment(nsName)
if _, err := l.deployments.Create (jenkinsDeployment);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf (err, "Error creating
the jenkins deployment")
}
// ÔÚ pipeline namespace ÄÚ´´½¨ service: docker-registry
registryService := getRegistryService(nsName)
if _, err := l.services.Create(registryService);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf (err, "Error creating
the registry service")
}
// ÔÚ pipeline namespace ÄÚ´´½¨ deployment: docker-registry
registryDeployment := GetRegistryDeployment(nsName)
if _, err := l.deployments.Create (registryDeployment);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error creating
the registry deployment")
}
// ÔÚ pipeline namespace ÄÚ´´½¨ service: minio
minioService := getMinioService(nsName)
if _, err := l.services.Create(minioService);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error creating
the minio service")
}
// ÔÚ pipeline namespace ÄÚ´´½¨ deployment: minio
minioDeployment := GetMinioDeployment(nsName)
if _, err := l.deployments.Create(minioDeployment);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error creating
the minio deployment")
}
// µ÷г configMap: proxy-mappings£¬ÓÃÓÚÅäÖÃdocker¾µÏñ²Ö¿â´úÀí·þÎñµÄ¶Ë¿ÚÐÅÏ¢
if err := l.reconcileProxyConfigMap(projectID);
err != nil {
return err
}
// ´´½¨secret: devops-docker-registry£¬´æ´¢·ÃÎÊdocker²Ö¿âµÄÈÏÖ¤ÐÅÏ¢
if err := l.reconcileRegistryCredential(projectName,
token); err != nil {
return err
}
// ´´½¨ daemonset: registry-proxy£¬Ã¿¸ö½Úµã²¿ÊðÒ»Ì×docker¾µÏñ²Ö¿âµÄnginx´úÀí·þÎñ
// ¿ÉÒÔÔÚÈÎÒâÒ»¸ö½ÚµãÉÏͨ¹ý²»Í¬µÄ¶Ë¿Ú¼´¿É·ÃÎʵ½²»Í¬µÄdocker¾µÏñ²Ö¿â
nginxDaemonset := getProxyDaemonset()
if _, err := l.daemonsets.Create (nginxDaemonset);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf (err, "Error creating
the nginx proxy")
}
return l.reconcileRb(projectName)
} |
reconcileRbº¯ÊýµÄ¹¦ÄܾÍÊDZéÀúËùÓÐnamespace,
¶ÔÆäµ÷гrolebindings, Ä¿µÄÊÇÈà pipeline serviceAccount(jenkins)
¶Ô¸ÃprojectϵÄËùÓÐnamespace¾ßÓÐËùÐèÒªµÄ²Ù×÷ȨÏÞ£¬ÕâÑùJenkins server²ÅÄܹ»ÔÚÊý¾ÝÃæÖÐÕý³£ÌṩCI/CD»ù´¡·þÎñ¡£
func (l *Lifecycle)
reconcileRb(projectName string) error {
...
var namespacesInProject []*corev1.Namespace
for _, namespace := range namespaces {
parts := strings.Split(namespace.Annotations[projectIDLabel],
":")
if len(parts) == 2 && parts[1] == projectID
{
// ¹ýÂ˳öÊôÓÚ¸ÃprojectϵÄËùÓÐnamespace
namespacesInProject = append(namespacesInProject,
namespace)
} else {
// ¶Ô·Ç¸ÃprojectϵÄnamespace, Çå³ýÓйظà pipeline µÄ rolebinding
if err := l.roleBindings.DeleteNamespaced(namespace.Name,
commonName, &metav1.DeleteOptions{}); err
!= nil && !apierrors.IsNotFound(err)
{
return err
}
}
}
for _, namespace := range namespacesInProject
{
// ¶ÔÊôÓÚ¸ÃprojectϵÄnamespace, ´´½¨ rolebinding: ¶Ô
jenkins serviceAccount °ó¶¨½ÇÉ«
// ¼´¸³Óè jenkins serviceAccount ¶Ô¸ÃprojectϵÄËùÓÐnamespaceËùÐèÒªµÄ²Ù×÷ȨÏÞ
rb := getRoleBindings(namespace.Name, commonName)
if _, err := l.roleBindings.Create(rb); err
!= nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error create
role binding")
}
}
// ¸³Óè jenkins serviceAccount ÔÚ cluster ÄÚ´´½¨ºÍÐÞ¸Ä
namespace µÄȨÏÞ
// µ±²¿ÊðÓ¦ÓÃʱ¿ÉÒÔÖ¸¶¨´´½¨ÐµÄÃüÃû¿Õ¼ä
clusterRbs := []string{roleCreateNs, projectID
+ roleEditNsSuffix}
for _, crbName := range clusterRbs {
crb := getClusterRoleBindings(commonName, crbName)
if _, err := l.clusterRoleBindings.Create(crb);
err != nil && !apierrors.IsAlreadyExists(err)
{
return errors.Wrapf(err, "Error create
cluster role binding")
}
}
return nil
} |
goroutine£¨syncState£©µÄ´úÂëÂß¼±È½Ï¼òµ¥£¬µ±²úÉúеÄpipelineÖ´ÐÐʵÀýʱ¾Í»áÆô¶¯Jenkins
server¶ËÁ÷Ë®Ïß×÷ÒµµÄÔËÐв¢ÊµÊ±Í¬²½ÆäÔËÐÐ״̬µ½pipelineÖ´ÐÐʵÀýÖС£´úÂëÂß¼ÈçÏ£º
func (s *ExecutionStateSyncer)
syncState() {
set := labels.Set(map[string]string{utils.PipelineFinishLabel:
"false"})
allExecutions, err := s.pipelineExecutionLister.List("",
set.AsSelector())
executions := []*v3.PipelineExecution{}
// ±éÀú¸ÃclusterÏ嵀 pipeline Ö´ÐÐʵÀý
for _, e := range allExecutions {
if controller.ObjectInCluster(s.clusterName,
e) {
executions = append(executions, e)
}
}
for _, execution := range executions {
if v3.PipelineExecutionConditionInitialized.IsUnknown(execution)
{
// ¼ì²éÊý¾ÝÃæk8sÖÐ Jenkins pod ÊÇ·ñÕý³££¬Õý³£ÔòÔËÐиà pipeline
job
s.checkAndRun(execution)
} else if v3.PipelineExecutionConditionInitialized.IsTrue(execution)
{
e := execution.DeepCopy()
// Èç¹ûÒѾÆô¶¯ÁË£¬Ôòͬ²½ÔËÐÐ״̬
updated, err := s.pipelineEngine.SyncExecution(e)
if updated {
// ¸üÐÂ×îеÄ״̬µ½ pipelineExecution crd ÖÐ
s.updateExecutionAndLastRunState(e);
}
} else {
// ¸üÐÂ×îеÄ״̬µ½ pipelineExecution crd ÖÐ
s.updateExecutionAndLastRunState(execution);
}
}
logrus.Debugf("Sync pipeline execution
state complete")
} |
»º´æÖ§³Ö
ÔÆ»·¾³ÏµÄÁ÷Ë®ÏßÊÇͨ¹ýÆô¶¯ÈÝÆ÷À´ÔËÐоßÌåµÄ¹¦Äܲ½Ö裬ÿ´ÎÔËÐÐÁ÷Ë®Ïß¿ÉÄܻᱻµ÷¶Èµ½²»Í¬µÄ¼ÆËã½ÚµãÉÏ£¬Õâ»áµ¼ÖÂÒ»¸öÎÊÌ⣺ÈÝÆ÷ÔËÐÐÍêÊDz»»á±£´æÊý¾ÝµÄ£¬Ã¿µ±Á÷Ë®ÏßÖØÐÂÔËÐÐʱ£¬ÓÖ»áÖØÐÂÀÈ¡´úÂë¡¢±àÒë´úÂë¡¢ÏÂÔØÒÀÀµ°üµÈµÈ£¬Ê§È¥Á˱¾µØËÞÖ÷»ú±àÒë´úÂë¡¢¹¹½¨¾µÏñʱ»º´æµÄ×÷Ó㬴ó´óÑÓ³¤ÁËÁ÷Ë®ÏßÔËÐÐʱ¼ä£¬À˷Ѻܶ಻±ØÒªµÄʱ¼ä¡¢ÍøÂçºÍ¼ÆËã³É±¾µÈ¡£ÎªÁËÌá¸ßÓû§Ê¹ÓÃÁ÷Ë®ÏßµÄÌåÑ飬¼ÓÈëÖ§³Ö»º´æµÄ¹¦ÄÜ¡£
ΪÁËÈÃÁ÷Ë®Ïß¾ßÓлº´æ¹¦ÄÜ£¬ÎÒÃÇÐèÒªÔÚÁ÷Ë®ÏßÔËÐÐʱ¼ÓÈë³Ö¾Ã»¯Êý¾ÝµÄÄÜÁ¦¡£Ê×ÏÈÏëµ½µÄ¾ÍÊÇk8sÌṩµÄ±¾µØ³Ö¾Ã»¯´æ´¢£¨¼´Local
Persistent Volume£¬ÒÔϼò³ÆLocal PV£©£¬»òÒÀÀµÔ¶³Ì´æ´¢·þÎñÆ÷À´Ìṩ³Ö¾Ã»¯£¬Ô¶³Ì´æ´¢Ð§ÂÊÒÀÀµÓÚÍøÂ磬²¢ÇÒ»¹ÐèÒª±£Ö¤Ô¶³Ì´æ´¢¸ß¿ÉÓã¬Õâ»Ø´øÀ´ºÜ¶à¸´ÔÓÐÔ£¬Ò²Ò»¶¨³Ì¶ÈÉÏʧȥÁË»º´æµÄ×÷Óá£×ۺϿ¼ÂÇ£¬ÎÒÃÇÑ¡Ôñ±¾µØ´æ´¢ÊµÏÖ»º´æ£¬µ«ÊÇk8sÌṩµÄLocal
PVÊÇÐèÒªºÍ½Úµã°ó¶¨ÔÚÒ»ÆðµÄ£¬Ò²¾ÍÊÇ˵һµ©Á÷Ë®Ïßµ÷¶Èµ½Ä³¸ö½ÚµãÉÏÔËÐУ¬ÄÇôÏ´ÎÔËÐл¹»á°ó¶¨µ½¸Ã½ÚµãÔËÐУ¬ËäȻʵÏÖÁË»º´æµÄ×÷Ó㬵«ÊÇÒ²Ôì³ÉÁËÁ÷Ë®Ïßÿ´ÎÖ»ÄÜÔڸýڵãÉÏÔËÐУ¬Èç¹ûÓжàÌõÁ÷Ë®ÏßͬʱÅÜ£¬¿ÉÄܻᵼÖ¸ýڵã×ÊÔ´ºÄ¾¡»òÕß»º´æ³åÍ»£¬Ê§È¥ÁËÔÆÆ½Ì¨±¾Éí¸ù¾Ý×ÊԴʹÓÃÇé¿öƽºâµ÷¶ÈµÄÌØÐÔ¡£
Òò´Ë£¬ÎªÁËÆ½ºâ»º´æÓëµ÷¶È¼äµÄ¹ØÏµ£¬ÎÒÃDzÉÓÃÁ˹ÒÔØhostPath Volume·½Ê½£¬ÕâÑùÒÀÍÐÓÚk8sÇ¿´óµÄÈÝÆ÷µ÷¶ÈÄÜÁ¦£¬ÎÒÃÇ¿ÉÒÔͬʱÔËÐкܶàÌõÁ÷Ë®Ïß¶ø²»Óõ£ÐÄ×ÊÔ´ºÄ¾¡»ò»º´æ³åÍ»µÄÎÊÌ⣬µ«ÊÇÁ÷Ë®Ïßÿ´ÎÔËÐÐʱ¿ÉÄܻᱻµ÷¶Èµ½²»Í¬µÄ½ÚµãÉÏ£¬Èç¹ûµ±Ç°½ÚµãûÓÐÔËÐйýÁ÷Ë®Ïߣ¬ÔòÆð²»µ½»º´æµÄ×÷Óá£ÄÇôÈçºÎ½â¾öhostPath
Volume»º´æÓëµ÷¶È¼äµÄÞÏÞιØÏµÄØ£¿ÎÒÃÇÇÉÃîµØÀûÓÃÁËk8sÌṩµÄÇ׺ÍÐÔµ÷¶ÈÌØÐÔ£¬µ±Á÷Ë®ÏßÔËÐÐʱÎÒÃÇ»á¼Ç¼µ±Ç°ÔËÐнڵ㣬Ï´ÎÔËÐÐʱͨ¹ýÉèÖÃPodµÄÇ׺ÍÐÔÓÅÏȵ÷¶Èµ½¸Ã½ÚµãÉÏ£¬Ëæ×ÅÁ÷Ë®ÏßÔËÐдÎÊýÔ½À´Ô½¶à£¬ÎÒÃÇ»áµÃµ½Ò»¸öÔËÐнڵãÁÐ±í¡£ÈçÏÂËùʾ£º
// °´Ê±¼äÅÅÐò£¬×î½üÔËÐÐÁ÷Ë®ÏߵĽڵãÅÅÔÚ×îÇ°Ãæ
executionScheduledInfo:
- creationTimestamp: "2020-09-02T06:42:45Z"
executionId: 8
nodeName: ******
- creationTimestamp: "2020-08-26T14:19:21Z"
executionId: 7
nodeName: ******
- creationTimestamp: "2020-08-26T10:52:15Z"
executionId: 5
nodeName: ******
- creationTimestamp: "2020-08-26T10:48:43Z"
executionId: 4
nodeName: ******
- creationTimestamp: "2020-08-25T07:47:27Z"
executionId: 3
nodeName: ******
- creationTimestamp: "2020-08-25T07:16:29Z"
executionId: 1
nodeName: ******
......
|
Ö´ÐÐʵÀýµ÷¶ÈÐÅÏ¢»á±£´æµ½pipeline CRD¶ÔÏóÖУ¬Ã¿´ÎÔËÐÐÁ÷Ë®Ïßʱ£¬ÏµÍ³»á¸ù¾Ý½ÚµãÁбíÉèÖÃPodµÄÇ׺ÍÐÔ£¬Ä¬ÈÏÎÒÃÇ»áÈ¡×î½üÔËÐÐÁ÷Ë®ÏßµÄ10¸ö½Úµã£¬ÔÔòÊÇ×î½üÔËÐÐÁ÷Ë®ÏߵĽڵãÓÅÏȼ¶Ô½¸ß¡£´úÂëÈçÏ£º

´´ÐÂÐԵġ°Hostpath Volume + Ç׺ÍÐÔµ÷¶È¡±»º´æÉè¼Æ·½°¸£¬²»½öʵÏÖÁËÁ÷Ë®ÏߵIJ¢·¢ÐÔ»º´æ¹¦ÄÜ£¬¶øÇÒʵÏÖ¸´ÔӶȵͣ¬¿É×ÔÓÉÅäÖÃÈÎÒ»½×¶Î¡¢²½ÖèµÄ»º´æ¿ª¹ØÒÔ¼°»º´æÂ·¾¶¡£ÎÞ»º´æÓëÓлº´æÔËÐеĶԱÈÈçÏÂͼËùʾ£¬¿É¼ûͨ¹ý»º´æ¼ÓËÙ´ó´óÌá¸ßÁËÁ÷Ë®ÏßµÄÔËÐÐЧÂÊ¡£

HCaaS DevOpsʹÓÃ
ÒÔÉÏÉè¼ÆÔÚHCaaSƽ̨Éϵõ½ÊµÏÖ£¨https://cubepaas.com£©ÔÚHCaaS¿ØÖÆÌ¨Éϵã»÷DevOps±êÇ©£¬Í¨¹ý´úÂëÊÚȨºó£¬¼´¿Éͨ¹ýUI½çÃæÇáËɵرà¼Á÷Ë®Ïߣ¬Ò²¿Éͨ¹ý±à¼yamlÎļþÅäÖþßÌåµÄ¹¦Äܲ½Ö裬ÈçͼËùʾ£º

ͨ¹ýµã»÷²é¿´ÈÕÖ¾£¬Äã¿ÉÒÔ¿´µ½pipeline¸÷¸ö½×¶ÎÔËÐеÄÏêϸÈÕÖ¾ÐÅÏ¢£¬ÈçÏÂͼËùʾ£º

¡¾×¢Òâ¡¿Ê×´ÎÔËÐÐpipelineʱϵͳ»á´ÓÍøÂçÏÂÔØJenkins¡¢docker¡¢minioÒÔ¼°ÆäËûpipeline-tools¾µÏñ£¬ÇëÉÔ×÷µÈ´ý¡£Èç¹û³¤Ê±¼äδÔËÐУ¬Çë²é¿´ÍøÂçÊÇ·ñÓÐÎÊÌâ¡£
|