1) Create token github and heml chart
Đâu tiên bạn cũng cần chuẩn bị github và token, helm chart
Bạn sẽ cần tìm hiểu link sau:
https://nimtechnology.com/2022/05/14/spinnaker-design-cd-on-kubernetes-by-spinnaker/#1_Preparing
2) Design template spinnaker
Mình sẽ cần cung cấp cho bạn 1 template mẫu:
{ "schema": "v2", "variables": [ { "type": "<type>", "defaultValue": <value>, "description": "<description>", "name": "<varName>" } ], "id": "<templateName>", # The pipeline instance references the template using this "protect": <true | false>, "metadata": { "name": "displayName", # The display name shown in Deck "description": "<description>", "owner": "example@example.com", "scopes": ["global"] # Not used }, "pipeline": { # Contains the templatized pipeline itself "lastModifiedBy": "anonymous", # Not used "updateTs": "0", # Not used "parameterConfig": [], # Same as in a regular pipeline "limitConcurrent": true, # Same as in a regular pipeline "keepWaitingPipelines": false, # Same as in a regular pipeline "description": "", # Same as in a regular pipeline "triggers": [], # Same as in a regular pipeline "notifications": [], # Same as in a regular pipeline "stages": [ # Contains the templated stages { # This one is an example stage: "waitTime": "${ templateVariables.waitTime }", # Templated field. "name": "My Wait Stage", "type": "wait", "refId": "wait1", "requisiteStageRefIds": [] } ] } }
Hoặc bạn lấy template ở link này:
https://spinnaker.io/docs/reference/pipeline/templates/
Đầu tiên chúng ta sẽ tạo ra các stage.
Theo mình cách dễ nhất là bạn chỉnh trên UI xong bạn export ra Json -> rổi thế vào file bên trên.
state đâu tiên:
#######stage 1 Get Manifest { "account": "cluster1", "app": "manual-create-app", "cloudProvider": "kubernetes", "location": "default", "manifestName": "deployment default-nimtechnology", "mode": "static", "name": "Get Manifest", "refId": "1", "requisiteStageRefIds": [], "type": "findArtifactsFromResource" }
MÌnh sẽ giải thích các thành phần cần thiết
account: context trong kubeconfig hay còn gọi là tên cluster k8s
app: tên application của spinnaker
location: là namespace
manifestName: nó gồm 2 thành phần là <Kind: deployment, ingress,…> <nameOfWordload>
mode: nếu là static thì nó sẽ đọc theo những j bạn chỉ định ở manifestName.
name: đặt tên cho stage này
type: findArtifactsFromResource => chức năng của stage này là lấy thông tin workload đang run trên k8s nên ta chọn type này
Nếu chúng ta làm template thì với 1 mục đích là tải sử dụng nhiều lần với nhiều deployment khác nhau.
Chúng ta phải define các variables
mình sẽ đưa line code ví dụ.
"manifestName": "${ templateVariables.kind } ${ templateVariables.workloadName }",
với từng variable thì chúng ta cần định nghĩa chúng
"variables": [ { "type": "string", "defaultValue": deployment, "description": "kind Of workload such as: deployemt, statefulset", "name": "kind" }, { "type": "string", "defaultValue": nimtechnology, "description": "this is the workload name", "name": "workloadName" } ]
defaultValue: Chỗ này nghĩ là nếu bạn không đưa data vào thì mặc định lấy value ở đây để sử dụng.
Tiếp theo là bạn chỉnh thêm phần sau:
"id": "<templateName>", # The pipeline instance references the template using this "protect": <true | false>, "metadata": { "name": "displayName", # The display name shown in Deck "description": "<description>", "owner": "example@example.com", "scopes": ["global"] # Not used }
id: định danh của template, khi bạn muốn sử dụng thì giọi ID của template
protect: bạn để là false
metadata:
name: Tên của template, dụng để hiển thị bên ngoài
owner: Bạn có thể để email hoặc thông tin của bạn ở đây
Giờ thì mình có 1 template như sau:
{ "schema": "v2", "variables": [ { "type": "string", "defaultValue": "deployment", "description": "kind Of workload such as: deployemt, statefulset", "name": "kind" }, { "type": "string", "defaultValue": "nimtechnology", "description": "this is the workload name", "name": "workloadName" } ], "id": "nimtSpinnakerTemplateV1", "protect": false, "metadata": { "name": "Nimtechnology Spinnaker Template V1", "description": "Study spinnaker together!!!", "owner": "mr.nim94@gmail.com", "scopes": ["global"] }, "pipeline": { "lastModifiedBy": "anonymous", "updateTs": "0", "parameterConfig": [], "limitConcurrent": true, "keepWaitingPipelines": false, "description": "", "triggers": [], "notifications": [], "stages": [ { "account": "cluster1", "app": "manual-create-app", "cloudProvider": "kubernetes", "location": "default", "manifestName": "${ templateVariables.kind } ${ templateVariables.workloadName }", "mode": "static", "name": "Get Manifest", "refId": "1", "requisiteStageRefIds": [], "type": "findArtifactsFromResource" } ] } }
Giờ bạn cần chạy lên spinnaker CLI
Tham khảo link sau:
Install Spin CLI and config it to integrate with Google OAuth2
Bạn cần tạo ra 1 file config:
##file: config-nimtechnology ########### Gate: Endpoint: http://spin.nimtechnology.com/gate
Bạn gõ command:
spin application list --config config-nimtechnology
mình sử dụng command spin để lưu template lại
spin pt save --file template-spin-nimtechnology-v1.json --config config-nimtechnology
Mình gặp lỗi:
Encountered an error with saving pipeline template map[application:global buildTime:1.652552232113e+12 endTime:1.65255223227e+12 execution:map[application:global authentication:map[allowedAccounts:[cluster1 dockerhub] user:anonymous] buildTime:1.652552232113e+12 canceled:false description:Create pipeline template 'Nimtechnology Spinnaker Template V1' endTime:1.65255223227e+12 id:01G31WKV5HQ2D4WJ6XC3DKRMKN initialConfig:map[] keepWaitingPipelines:false limitConcurrent:false notifications:[] origin:api stages:[map[context:map[beforeStagePlanningFailed:true exception:map[details:map[error:Unexpected Task Failure errors:[No StageDefinitionBuilder implementation for createV2PipelineTemplate(alias: null) found (knownTypes: googleCloudBuild,upsertDeliveryConfig,shrinkCluster,reorderPipelines,upsertLoadBalancers,resumeRolloutManifest,modifyAsgLaunchConfiguration,remote,upsertEntityTags,deleteSnapshot,deregisterInstancesFromLoadBalancer,bulkUpsertEntityTags,quickPatch,deleteLaunchConfiguration,destroyAsg,runJob,deployCloudFormation,checkPreconditions,determineTargetReference,clouddriverClearAltTablespace,upsertSecurityGroup,manualJudgment,upsertLoadBalancer,getProperties,modifyGceAutoscalingPolicy,disableCluster,deployService,script,restoreSnapshot,gremlin,disableManifest,terminateInstanceAndDecrementServerGroup,copyAmazonLoadBalancer,rollbackCluster,disableInstancesInDiscovery,cloneServerGroup,updatePipeline,deleteLaunchTemplate,bakeCloudFoundryManifest,setStatefulDisk,wait,monitorPipeline,serverGroupForceCacheRefresh,statefullyUpdateBootImage,deleteTencentCloudScheduledAction,upsertDisruptionBudget,saveSnapshot,upsertAmazonDNS,findImage,scaleManifest,awsCodeBuild,undoRolloutManifest,noop,upsertAsgScheduledActions,enableInstancesInDiscovery,deleteEntityTags,concourse,destroyService,findArtifactsFromResource,registerInstancesWithLoadBalancer,jenkins,rebootInstances,rollbackServerGroup,upsertServerGroupTags,captureSourceServerGroupCapacity,upsertPluginInfo,destroyJob,cloudOperation,bulkQuickPatch,deployManifest,scaleDownCluster,findImageFromTags,pipeline,upsertScalingPolicy,upsertProject,detachInstances,updateApplication,preconfiguredWebhook,createApplication,deleteDeliveryConfig,unmapLoadBalancers,terminateInstanceAndDecrementAsg,modifyAwsScalingProcess,rollingPush,shareService,enableServerGroup,disableServerGroup,savePipelinesFromArtifact,webhook,deleteLoadBalancer,createServiceKey,resizeServerGroup,waitUntil,patchManifest,deploy,deleteManifest,lambdaFunction,upsertAmazonLoadBalancer,evaluateVariables,determineTargetServerGroup,updateJobProcesses,deleteImage,enableManifest,setPreferredPluginRelease,jira,deleteSecurityGroup,upsertAsgTags,enableAsg,wercker,waitForCondition,deleteProject,updateLaunchTemplate,preconfiguredJob,copySecurityGroup,mapLoadBalancers,restrictExecutionDuringTimeWindow,loadPluginRelease,terminateInstances,savePipeline,pauseRolloutManifest,startAppEngineServerGroup,dependsOnExecution,upsertTencentCloudScheduledActions,updateSecurityGroupsForServerGroup,modifyScalingProcess,upsertApplication,applySourceServerGroupCapacity,updateLaunchConfig,findArtifactFromExecution,bakeManifest,upsertAppEngineLoadBalancers,stopAppEngineServerGroup,copyLastAsg,pinServerGroup,upsertImageTags,deleteApplication,modifyScalingGroup,cloudFoundryCreateServiceBindings,rollingRestartManifest,bulkDestroyServerGroup,disableAsg,modifyAsg,unshareService,pageApplicationOwner,createServerGroup,deleteAmazonLoadBalancer,deleteScalingPolicy,bake,travis,destroyServerGroup,deleteServiceKey,deployAppEngineConfiguration)] stackTrace:com.netflix.spinnaker.orca.StageResolver$NoSuchStageDefinitionBuilderException: No StageDefinitionBuilder implementation for createV2PipelineTemplate(alias: null) found (knownTypes: googleCloudBuild,upsertDeliveryConfig,shrinkCluster,reorderPipelines,upsertLoadBalancers,resumeRolloutManifest,modifyAsgLaunchConfiguration,remote,upsertEntityTags,deleteSnapshot,deregisterInstancesFromLoadBalancer,bulkUpsertEntityTags,quickPatch,deleteLaunchConfiguration,destroyAsg,runJob,deployCloudFormation,checkPreconditions,determineTargetReference,clouddriverClearAltTablespace,upsertSecurityGroup,manualJudgment,upsertLoadBalancer,getProperties,modifyGceAutoscalingPolicy,disableCluster,deployService,script,restoreSnapshot,gremlin,disableManifest,terminateInstanceAndDecrementServerGroup,copyAmazonLoadBalancer,rollbackCluster,disableInstancesInDiscovery,cloneServerGroup,updatePipeline,deleteLaunchTemplate,bakeCloudFoundryManifest,setStatefulDisk,wait,monitorPipeline,serverGroupForceCacheRefresh,statefullyUpdateBootImage,deleteTencentCloudScheduledAction,upsertDisruptionBudget,saveSnapshot,upsertAmazonDNS,findImage,scaleManifest,awsCodeBuild,undoRolloutManifest,noop,upsertAsgScheduledActions,enableInstancesInDiscovery,deleteEntityTags,concourse,destroyService,findArtifactsFromResource,registerInstancesWithLoadBalancer,jenkins,rebootInstances,rollbackServerGroup,upsertServerGroupTags,captureSourceServerGroupCapacity,upsertPluginInfo,destroyJob,cloudOperation,bulkQuickPatch,deployManifest,scaleDownCluster,findImageFromTags,pipeline,upsertScalingPolicy,upsertProject,detachInstances,updateApplication,preconfiguredWebhook,createApplication,deleteDeliveryConfig,unmapLoadBalancers,terminateInstanceAndDecrementAsg,modifyAwsScalingProcess,rollingPush,shareService,enableServerGroup,disableServerGroup,savePipelinesFromArtifact,webhook,deleteLoadBalancer,createServiceKey,resizeServerGroup,waitUntil,patchManifest,deploy,deleteManifest,lambdaFunction,upsertAmazonLoadBalancer,evaluateVariables,determineTargetServerGroup,updateJobProcesses,deleteImage,enableManifest,setPreferredPluginRelease,jira,deleteSecurityGroup,upsertAsgTags,enableAsg,wercker,waitForCondition,deleteProject,updateLaunchTemplate,preconfiguredJob,copySecurityGroup,mapLoadBalancers,restrictExecutionDuringTimeWindow,loadPluginRelease,terminateInstances,savePipeline,pauseRolloutManifest,startAppEngineServerGroup,dependsOnExecution,upsertTencentCloudScheduledActions,updateSecurityGroupsForServerGroup,modifyScalingProcess,upsertApplication,applySourceServerGroupCapacity,updateLaunchConfig,findArtifactFromExecution,bakeManifest,upsertAppEngineLoadBalancers,stopAppEngineServerGroup,copyLastAsg,pinServerGroup,upsertImageTags,deleteApplication,modifyScalingGroup,cloudFoundryCreateServiceBindings,rollingRestartManifest,bulkDestroyServerGroup,disableAsg,modifyAsg,unshareService,pageApplicationOwner,createServerGroup,deleteAmazonLoadBalancer,deleteScalingPolicy,bake,travis,destroyServerGroup,deleteServiceKey,deployAppEngineConfiguration) at com.netflix.spinnaker.orca.DefaultStageResolver.getStageDefinitionBuilder(DefaultStageResolver.java:75) at com.netflix.spinnaker.orca.pipeline.util.StageNavigator.lambda$ancestors$0(StageNavigator.java:51) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) at java.base/java.util.Collections$2.tryAdvance(Collections.java:4747) at java.base/java.util.Collections$2.forEachRemaining(Collections.java:4755) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) at com.netflix.spinnaker.orca.pipeline.util.StageNavigator.ancestors(StageNavigator.java:53) at com.netflix.spinnaker.orca.q.handler.AuthenticationAware$DefaultImpls.withAuth(AuthenticationAware.kt:32) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.withAuth(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler$handle$1.invoke(CompleteStageHandler.kt:119) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler$handle$1.invoke(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$withStage$1.invoke(OrcaMessageHandler.kt:85) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$withStage$1.invoke(OrcaMessageHandler.kt:46) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$DefaultImpls.withExecution(OrcaMessageHandler.kt:95) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.withExecution(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$DefaultImpls.withStage(OrcaMessageHandler.kt:74) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.withStage(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.handle(CompleteStageHandler.kt:85) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.handle(CompleteStageHandler.kt:72) at com.netflix.spinnaker.q.MessageHandler$DefaultImpls.invoke(MessageHandler.kt:36) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$DefaultImpls.invoke(OrcaMessageHandler.kt) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.invoke(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.audit.ExecutionTrackingMessageHandlerPostProcessor$ExecutionTrackingMessageHandlerProxy.invoke(ExecutionTrackingMessageHandlerPostProcessor.kt:72) at com.netflix.spinnaker.q.QueueProcessor$callback$1$1.run(QueueProcessor.kt:90) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) ] exceptionType:NoSuchStageDefinitionBuilderException operation:createV2PipelineTemplate:ConstructAfterStages shouldRetry:false timestamp:1.652552232204e+12] pipelineTemplate:eyJpZCI6Im5pbXRTcGlubmFrZXJUZW1wbGF0ZVYxIiwibWV0YWRhdGEiOnsiZGVzY3JpcHRpb24iOiJTdHVkeSBzcGlubmFrZXIgdG9nZXRoZXIhISEiLCJuYW1lIjoiTmltdGVjaG5vbG9neSBTcGlubmFrZXIgVGVtcGxhdGUgVjEiLCJvd25lciI6Im1yLm5pbTk0QGdtYWlsLmNvbSIsInNjb3BlcyI6WyJnbG9iYWwiXX0sInBpcGVsaW5lIjp7ImRlc2NyaXB0aW9uIjoiIiwia2VlcFdhaXRpbmdQaXBlbGluZXMiOmZhbHNlLCJsYXN0TW9kaWZpZWRCeSI6ImFub255bW91cyIsImxpbWl0Q29uY3VycmVudCI6dHJ1ZSwibm90aWZpY2F0aW9ucyI6W10sInBhcmFtZXRlckNvbmZpZyI6W10sInN0YWdlcyI6W3siYWNjb3VudCI6ImRlZmF1bHQiLCJjb21wbGV0ZU90aGVyQnJhbmNoZXNUaGVuRmFpbCI6ZmFsc2UsImNvbnRpbnVlUGlwZWxpbmUiOnRydWUsImZhaWxPbkZhaWxlZEV4cHJlc3Npb25zIjpmYWxzZSwiZmFpbFBpcGVsaW5lIjpmYWxzZSwibG9jYXRpb24iOiJkZWZhdWx0IiwibWFuaWZlc3ROYW1lIjoiJHsgdGVtcGxhdGVWYXJpYWJsZXMua2luZCB9ICR7IHRlbXBsYXRlVmFyaWFibGVzLndvcmtsb2FkTmFtZSB9IiwibW9kZSI6InN0YXRpYyIsIm5hbWUiOiJHZXQgTWFuaWZlc3QiLCJyZWZJZCI6IjEiLCJyZXF1aXNpdGVTdGFnZVJlZklkcyI6W10sInJlc3RyaWN0RXhlY3V0aW9uRHVyaW5nVGltZVdpbmRvdyI6ZmFsc2UsInR5cGUiOiJmaW5kQXJ0aWZhY3RzRnJvbVJlc291cmNlIn1dLCJ0cmlnZ2VycyI6W10sInVwZGF0ZVRzIjoiMCJ9LCJwcm90ZWN0IjpmYWxzZSwic2NoZW1hIjoidjIiLCJ2YXJpYWJsZXMiOlt7ImRlZmF1bHRWYWx1ZSI6ImRlcGxveW1lbnQiLCJkZXNjcmlwdGlvbiI6ImtpbmQgT2Ygd29ya2xvYWQgc3VjaCBhczogZGVwbG95ZW10LCBzdGF0ZWZ1bHNldCIsIm5hbWUiOiJraW5kIiwidHlwZSI6InN0cmluZyJ9LHsiZGVmYXVsdFZhbHVlIjoibmltdGVjaG5vbG9neSIsImRlc2NyaXB0aW9uIjoidGhpcyBpcyB0aGUgd29ya2xvYWQgbmFtZSIsIm5hbWUiOiJ3b3JrbG9hZE5hbWUiLCJ0eXBlIjoic3RyaW5nIn1dfQ== user:anonymous] endTime:1.652552232204e+12 id:01G31WKV5HW68GM1AFPD7JFPNB name:createV2PipelineTemplate outputs:map[] refId:0 requisiteStageRefIds:[] status:TERMINAL tasks:[] type:createV2PipelineTemplate]] startTime:1.652552232138e+12 status:TERMINAL systemNotifications:[] trigger:map[artifacts:[] dryRun:false expectedArtifacts:[] notifications:[] parameters:map[] rebake:false resolvedExpectedArtifacts:[] strategy:false type:manual user:anonymous] type:ORCHESTRATION] id:01G31WKV5HQ2D4WJ6XC3DKRMKN name:Create pipeline template 'Nimtechnology Spinnaker Template V1' startTime:1.652552232138e+12 status:TERMINAL steps:[] variables:[map[key:pipelineTemplate value:eyJpZCI6Im5pbXRTcGlubmFrZXJUZW1wbGF0ZVYxIiwibWV0YWRhdGEiOnsiZGVzY3JpcHRpb24iOiJTdHVkeSBzcGlubmFrZXIgdG9nZXRoZXIhISEiLCJuYW1lIjoiTmltdGVjaG5vbG9neSBTcGlubmFrZXIgVGVtcGxhdGUgVjEiLCJvd25lciI6Im1yLm5pbTk0QGdtYWlsLmNvbSIsInNjb3BlcyI6WyJnbG9iYWwiXX0sInBpcGVsaW5lIjp7ImRlc2NyaXB0aW9uIjoiIiwia2VlcFdhaXRpbmdQaXBlbGluZXMiOmZhbHNlLCJsYXN0TW9kaWZpZWRCeSI6ImFub255bW91cyIsImxpbWl0Q29uY3VycmVudCI6dHJ1ZSwibm90aWZpY2F0aW9ucyI6W10sInBhcmFtZXRlckNvbmZpZyI6W10sInN0YWdlcyI6W3siYWNjb3VudCI6ImRlZmF1bHQiLCJjb21wbGV0ZU90aGVyQnJhbmNoZXNUaGVuRmFpbCI6ZmFsc2UsImNvbnRpbnVlUGlwZWxpbmUiOnRydWUsImZhaWxPbkZhaWxlZEV4cHJlc3Npb25zIjpmYWxzZSwiZmFpbFBpcGVsaW5lIjpmYWxzZSwibG9jYXRpb24iOiJkZWZhdWx0IiwibWFuaWZlc3ROYW1lIjoiJHsgdGVtcGxhdGVWYXJpYWJsZXMua2luZCB9ICR7IHRlbXBsYXRlVmFyaWFibGVzLndvcmtsb2FkTmFtZSB9IiwibW9kZSI6InN0YXRpYyIsIm5hbWUiOiJHZXQgTWFuaWZlc3QiLCJyZWZJZCI6IjEiLCJyZXF1aXNpdGVTdGFnZVJlZklkcyI6W10sInJlc3RyaWN0RXhlY3V0aW9uRHVyaW5nVGltZVdpbmRvdyI6ZmFsc2UsInR5cGUiOiJmaW5kQXJ0aWZhY3RzRnJvbVJlc291cmNlIn1dLCJ0cmlnZ2VycyI6W10sInVwZGF0ZVRzIjoiMCJ9LCJwcm90ZWN0IjpmYWxzZSwic2NoZW1hIjoidjIiLCJ2YXJpYWJsZXMiOlt7ImRlZmF1bHRWYWx1ZSI6ImRlcGxveW1lbnQiLCJkZXNjcmlwdGlvbiI6ImtpbmQgT2Ygd29ya2xvYWQgc3VjaCBhczogZGVwbG95ZW10LCBzdGF0ZWZ1bHNldCIsIm5hbWUiOiJraW5kIiwidHlwZSI6InN0cmluZyJ9LHsiZGVmYXVsdFZhbHVlIjoibmltdGVjaG5vbG9neSIsImRlc2NyaXB0aW9uIjoidGhpcyBpcyB0aGUgd29ya2xvYWQgbmFtZSIsIm5hbWUiOiJ3b3JrbG9hZE5hbWUiLCJ0eXBlIjoic3RyaW5nIn1dfQ==] map[key:user value:anonymous] map[key:exception value:map[details:map[error:Unexpected Task Failure errors:[No StageDefinitionBuilder implementation for createV2PipelineTemplate(alias: null) found (knownTypes: googleCloudBuild,upsertDeliveryConfig,shrinkCluster,reorderPipelines,upsertLoadBalancers,resumeRolloutManifest,modifyAsgLaunchConfiguration,remote,upsertEntityTags,deleteSnapshot,deregisterInstancesFromLoadBalancer,bulkUpsertEntityTags,quickPatch,deleteLaunchConfiguration,destroyAsg,runJob,deployCloudFormation,checkPreconditions,determineTargetReference,clouddriverClearAltTablespace,upsertSecurityGroup,manualJudgment,upsertLoadBalancer,getProperties,modifyGceAutoscalingPolicy,disableCluster,deployService,script,restoreSnapshot,gremlin,disableManifest,terminateInstanceAndDecrementServerGroup,copyAmazonLoadBalancer,rollbackCluster,disableInstancesInDiscovery,cloneServerGroup,updatePipeline,deleteLaunchTemplate,bakeCloudFoundryManifest,setStatefulDisk,wait,monitorPipeline,serverGroupForceCacheRefresh,statefullyUpdateBootImage,deleteTencentCloudScheduledAction,upsertDisruptionBudget,saveSnapshot,upsertAmazonDNS,findImage,scaleManifest,awsCodeBuild,undoRolloutManifest,noop,upsertAsgScheduledActions,enableInstancesInDiscovery,deleteEntityTags,concourse,destroyService,findArtifactsFromResource,registerInstancesWithLoadBalancer,jenkins,rebootInstances,rollbackServerGroup,upsertServerGroupTags,captureSourceServerGroupCapacity,upsertPluginInfo,destroyJob,cloudOperation,bulkQuickPatch,deployManifest,scaleDownCluster,findImageFromTags,pipeline,upsertScalingPolicy,upsertProject,detachInstances,updateApplication,preconfiguredWebhook,createApplication,deleteDeliveryConfig,unmapLoadBalancers,terminateInstanceAndDecrementAsg,modifyAwsScalingProcess,rollingPush,shareService,enableServerGroup,disableServerGroup,savePipelinesFromArtifact,webhook,deleteLoadBalancer,createServiceKey,resizeServerGroup,waitUntil,patchManifest,deploy,deleteManifest,lambdaFunction,upsertAmazonLoadBalancer,evaluateVariables,determineTargetServerGroup,updateJobProcesses,deleteImage,enableManifest,setPreferredPluginRelease,jira,deleteSecurityGroup,upsertAsgTags,enableAsg,wercker,waitForCondition,deleteProject,updateLaunchTemplate,preconfiguredJob,copySecurityGroup,mapLoadBalancers,restrictExecutionDuringTimeWindow,loadPluginRelease,terminateInstances,savePipeline,pauseRolloutManifest,startAppEngineServerGroup,dependsOnExecution,upsertTencentCloudScheduledActions,updateSecurityGroupsForServerGroup,modifyScalingProcess,upsertApplication,applySourceServerGroupCapacity,updateLaunchConfig,findArtifactFromExecution,bakeManifest,upsertAppEngineLoadBalancers,stopAppEngineServerGroup,copyLastAsg,pinServerGroup,upsertImageTags,deleteApplication,modifyScalingGroup,cloudFoundryCreateServiceBindings,rollingRestartManifest,bulkDestroyServerGroup,disableAsg,modifyAsg,unshareService,pageApplicationOwner,createServerGroup,deleteAmazonLoadBalancer,deleteScalingPolicy,bake,travis,destroyServerGroup,deleteServiceKey,deployAppEngineConfiguration)] stackTrace:com.netflix.spinnaker.orca.StageResolver$NoSuchStageDefinitionBuilderException: No StageDefinitionBuilder implementation for createV2PipelineTemplate(alias: null) found (knownTypes: googleCloudBuild,upsertDeliveryConfig,shrinkCluster,reorderPipelines,upsertLoadBalancers,resumeRolloutManifest,modifyAsgLaunchConfiguration,remote,upsertEntityTags,deleteSnapshot,deregisterInstancesFromLoadBalancer,bulkUpsertEntityTags,quickPatch,deleteLaunchConfiguration,destroyAsg,runJob,deployCloudFormation,checkPreconditions,determineTargetReference,clouddriverClearAltTablespace,upsertSecurityGroup,manualJudgment,upsertLoadBalancer,getProperties,modifyGceAutoscalingPolicy,disableCluster,deployService,script,restoreSnapshot,gremlin,disableManifest,terminateInstanceAndDecrementServerGroup,copyAmazonLoadBalancer,rollbackCluster,disableInstancesInDiscovery,cloneServerGroup,updatePipeline,deleteLaunchTemplate,bakeCloudFoundryManifest,setStatefulDisk,wait,monitorPipeline,serverGroupForceCacheRefresh,statefullyUpdateBootImage,deleteTencentCloudScheduledAction,upsertDisruptionBudget,saveSnapshot,upsertAmazonDNS,findImage,scaleManifest,awsCodeBuild,undoRolloutManifest,noop,upsertAsgScheduledActions,enableInstancesInDiscovery,deleteEntityTags,concourse,destroyService,findArtifactsFromResource,registerInstancesWithLoadBalancer,jenkins,rebootInstances,rollbackServerGroup,upsertServerGroupTags,captureSourceServerGroupCapacity,upsertPluginInfo,destroyJob,cloudOperation,bulkQuickPatch,deployManifest,scaleDownCluster,findImageFromTags,pipeline,upsertScalingPolicy,upsertProject,detachInstances,updateApplication,preconfiguredWebhook,createApplication,deleteDeliveryConfig,unmapLoadBalancers,terminateInstanceAndDecrementAsg,modifyAwsScalingProcess,rollingPush,shareService,enableServerGroup,disableServerGroup,savePipelinesFromArtifact,webhook,deleteLoadBalancer,createServiceKey,resizeServerGroup,waitUntil,patchManifest,deploy,deleteManifest,lambdaFunction,upsertAmazonLoadBalancer,evaluateVariables,determineTargetServerGroup,updateJobProcesses,deleteImage,enableManifest,setPreferredPluginRelease,jira,deleteSecurityGroup,upsertAsgTags,enableAsg,wercker,waitForCondition,deleteProject,updateLaunchTemplate,preconfiguredJob,copySecurityGroup,mapLoadBalancers,restrictExecutionDuringTimeWindow,loadPluginRelease,terminateInstances,savePipeline,pauseRolloutManifest,startAppEngineServerGroup,dependsOnExecution,upsertTencentCloudScheduledActions,updateSecurityGroupsForServerGroup,modifyScalingProcess,upsertApplication,applySourceServerGroupCapacity,updateLaunchConfig,findArtifactFromExecution,bakeManifest,upsertAppEngineLoadBalancers,stopAppEngineServerGroup,copyLastAsg,pinServerGroup,upsertImageTags,deleteApplication,modifyScalingGroup,cloudFoundryCreateServiceBindings,rollingRestartManifest,bulkDestroyServerGroup,disableAsg,modifyAsg,unshareService,pageApplicationOwner,createServerGroup,deleteAmazonLoadBalancer,deleteScalingPolicy,bake,travis,destroyServerGroup,deleteServiceKey,deployAppEngineConfiguration) at com.netflix.spinnaker.orca.DefaultStageResolver.getStageDefinitionBuilder(DefaultStageResolver.java:75) at com.netflix.spinnaker.orca.pipeline.util.StageNavigator.lambda$ancestors$0(StageNavigator.java:51) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) at java.base/java.util.Collections$2.tryAdvance(Collections.java:4747) at java.base/java.util.Collections$2.forEachRemaining(Collections.java:4755) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) at com.netflix.spinnaker.orca.pipeline.util.StageNavigator.ancestors(StageNavigator.java:53) at com.netflix.spinnaker.orca.q.handler.AuthenticationAware$DefaultImpls.withAuth(AuthenticationAware.kt:32) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.withAuth(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler$handle$1.invoke(CompleteStageHandler.kt:119) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler$handle$1.invoke(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$withStage$1.invoke(OrcaMessageHandler.kt:85) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$withStage$1.invoke(OrcaMessageHandler.kt:46) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$DefaultImpls.withExecution(OrcaMessageHandler.kt:95) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.withExecution(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$DefaultImpls.withStage(OrcaMessageHandler.kt:74) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.withStage(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.handle(CompleteStageHandler.kt:85) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.handle(CompleteStageHandler.kt:72) at com.netflix.spinnaker.q.MessageHandler$DefaultImpls.invoke(MessageHandler.kt:36) at com.netflix.spinnaker.orca.q.handler.OrcaMessageHandler$DefaultImpls.invoke(OrcaMessageHandler.kt) at com.netflix.spinnaker.orca.q.handler.CompleteStageHandler.invoke(CompleteStageHandler.kt:72) at com.netflix.spinnaker.orca.q.audit.ExecutionTrackingMessageHandlerPostProcessor$ExecutionTrackingMessageHandlerProxy.invoke(ExecutionTrackingMessageHandlerPostProcessor.kt:72) at com.netflix.spinnaker.q.QueueProcessor$callback$1$1.run(QueueProcessor.kt:90) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) ] exceptionType:NoSuchStageDefinitionBuilderException operation:createV2PipelineTemplate:ConstructAfterStages shouldRetry:false timestamp:1.652552232204e+12]] map[key:beforeStagePlanningFailed value:true]]]
Bạn kiểm tra bạn đã enable template hay chưa?
hal config features edit --pipeline-templates true
Sau đó mình đã chạy thành công
3) Design pipeline spinnaker through json file.
Bước tiếp theo chúng ta tạo 1 pipeline để tải sử dụng template trên
reference links:
https://spinnaker.io/guides/spin/app/
spin application save --application-name my-app --owner-email someone@example.com --cloud-providers "kubernetes" --config config-nimtechnology
3.1) Pipeline is created UI but it base on template.
Bằng UI spinnaker:
Bạn điền tên workload và kind của workload
Với cách run bằng UI thì chắc chắn là kho làm automation vậy chúng ta cần làm như sau:
3.2) Create Pipeline via Json file and Run pipeline through command.
sau đó bạn tạo 1 file json và paste nối dụng vào
Nếu bạn chạy câu lệnh
spin pi save --file pipeline-spin-nimtechnology.json --config config-nimtechnology
thi bạn sẽ bị báo lỗi
Required pipeline key 'name' missing... Required pipeline key 'application' missing... Submitted pipeline is invalid: map[exclude:[] keepWaitingPipelines:%!s(bool=false) lastModifiedBy:anonymous limitConcurrent:%!s(bool=true) notifications:[] parameterConfig:[] schema:v2 stages:[] template:map[artifactAccount:front50ArtifactCredentials reference:spinnaker://nimtSpinnakerTemplateV1 type:front50/pipelineTemplate] triggers:[] type:templatedPipeline updateTs:1652627797000 variables:map[kind:deployment workloadName:default-nimtechnology]]
Vì là trong json chưa có tên pipeline và pipeline trên thuộc application nào?
{ "name": "pipeline-is-created-by-command", "application": "my-app", "exclude": [], "keepWaitingPipelines": false, "lastModifiedBy": "anonymous", "limitConcurrent": true, "notifications": [], "parameterConfig": [], "schema": "v2", "stages": [], "template": { "artifactAccount": "front50ArtifactCredentials", "reference": "spinnaker://nimtSpinnakerTemplateV1", "type": "front50/pipelineTemplate" }, "triggers": [], "type": "templatedPipeline", "updateTs": "1652627797000", "variables": { "kind": "deployment", "workloadName": "default-nimtechnology" } }
spin pipeline execute --name pipeline-is-created-by-command --application my-app
4) A few special Case
Mình cũng đã có migrate 1 số template cúa spinnaker sang template mình xin tổng hợp thêm một số trường hợp sau:
4.1) expectedArtifacts
Ơ các ví dụ trên thì chắc chắn là bạn chưa thấy mình lưu ý key này
{ "appConfig": {}, "expectedArtifacts": [ { "defaultArtifact": { "customKind": true, "id": "c3e4adf6-9f9f-418f-b1af-2a4de93d792f" }, "displayName": "docker-talaria", "id": "834eae41-e13b-49ca-95d6-9801a587a85a", "matchArtifact": { "artifactAccount": "docker-registry", "id": "78cf7ac2-a881-4ff7-b4a3-68eda1a271c6", "name": "asia.gcr.io//talaria", "type": "docker/image" }, "useDefaultArtifact": false, "usePriorArtifact": false } ], "keepWaitingPipelines": false, "lastModifiedBy": "uc.dang@.vn", "limitConcurrent": true, "notifications": [ { "address": "-build", "level": "pipeline", "message": { "pipeline.failed": { "text": "<@UHGA1UJ1F>" } }, "type": "slack", "when": [ "pipeline.failed" ] } ], "parameterConfig": [ { "default": "none", "description": "", "hasOptions": false, "label": "type", "name": "type", "options": [ { "value": "none" }, { "value": "" } ], "pinned": false, "required": false }, { "default": "false", "description": "", "hasOptions": true, "label": "", "name": "dryRun", "options": [ { "value": "false" }, { "value": "true" } ], "pinned": false, "required": false } ], "roles": [ "devops-admin" ], "stages": [ { "expectedArtifacts": [ { "defaultArtifact": { "customKind": true, "id": "396d49b8-78c3-4f2a-92fe-5ca2a1f78081" }, "displayName": "talaria-apiv2-helm-canary", "id": "52638c19-89cc-4067-87a1-7b0f0c3eb621", "matchArtifact": { "id": "fd0fd41b-ecd1-4307-802d-2a06c61a9a56", "name": "talaria-apiv2-canary", "type": "embedded/base64" }, "useDefaultArtifact": false, "usePriorArtifact": false }
Vậy lúc này bạn tạo ra 1 expectedArtifacts và nó nằm trong pipeline
"description": "Deploy image", "name": "dockerRepo" } ], "id": "generic-v2", "protect": false, "metadata": { "name": "Generic v2", "description": "A generic template for basic use cases. No trigger configured", "owner": "khai.phan@nimtechnology.vn", "scopes": ["global"] }, "pipeline": { "application": "test", "expectedArtifacts": [ #you can paste the content of expectedArtifacts at here { "defaultArtifact": { "artifactAccount": "jenkins-artifacts", "id": "67432764-b5aa-4392-948d-88920fa2e295", "name": "gs://nimtechnology-prod-cicd-b20d-jenkins-artifacts/${ templateVariables.projectName }--values-${ templateVariables.profile }", "reference": "gs://nimtechnology-prod-cicd-b20d-jenkins-artifacts/${ templateVariables.projectName }--values-${ templateVariables.profile }", "type": "gcs/object" }, "displayName": "${ templateVariables.projectName }--values-${ templateVariables.profile }", "id": "8732f548-dfb4-4f52-9e2d-a52ff1c94a8a", "matchArtifact": { "artifactAccount": "jenkins-artifacts", "id": "515a0e61-57a8-4973-8ded-e53d5464d58b", "name": "gs://nimtechnology-prod-cicd-b20d-jenkins-artifacts/${ templateVariables.projectName }--values-${ templateVariables.profile }", "type": "gcs/object" }, "useDefaultArtifact": true, "usePriorArtifact": false }, { "defaultArtifact": {