|
| 1 | +--- |
| 2 | +date: 2025-04-28 |
| 3 | +title: "What Happens before Deployment? GitOps Mechanism" |
| 4 | +linkTitle: "What Happens before Deployment?" |
| 5 | +weight: 982 |
| 6 | +author: Tetsuya Kikuchi ([@t-kikuc](https://github.com/t-kikuc)) |
| 7 | +categories: ["Announcement"] |
| 8 | +tags: ["New Feature"] |
| 9 | +--- |
| 10 | + |
| 11 | +This article explains the process before a deployment begins in PipeCD. Since PipeCD is pull-based, there are various processes that take place before a deployment starts. |
| 12 | + |
| 13 | +Probably, you have felt "What is Pending??" at least once: |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +The target audience is those who want to: |
| 18 | +- troubleshoot when "deployment doesn't start as expected..." |
| 19 | +- understand GitOps mechanisms and implementation |
| 20 | +- contribute to PipeCD |
| 21 | + |
| 22 | + |
| 23 | +_This article is based on PipeCD v0.51.2 (latest version at time of writing). The specifications in the [plugin version](https://zenn.dev/cadp/articles/pipecd-plugin-intro) are slightly different._ |
| 24 | + |
| 25 | + |
| 26 | +_This article omits discussion of [Deployment Chain](https://pipecd.dev/docs-v0.51.x/user-guide/managing-application/deployment-chain/) (due to complexity)._ |
| 27 | + |
| 28 | +## Overview |
| 29 | + |
| 30 | +The state transitions before deployment begins are shown in the diagram below. |
| 31 | + |
| 32 | +```mermaid |
| 33 | +stateDiagram-v2 |
| 34 | + Not_Started --> PENDING: [1] Trigger |
| 35 | + PENDING --> PLANNED: [2] Plan (Determine pipeline) |
| 36 | + PLANNED --> RUNNING: [3] Schedule (Execute stages) |
| 37 | +``` |
| 38 | + |
| 39 | +Phases [1] through [3] are **executed asynchronously by separate components (goroutines)**. This mechanism allows deployment to resume even if Piped crashes during the process. |
| 40 | + |
| 41 | + |
| 42 | + |
| 43 | +## 1. Trigger |
| 44 | + |
| 45 | +PipeCD initiates application deployment through four types of triggers: |
| 46 | + |
| 47 | +- [A] Detecting changes in Git (main method) |
| 48 | + - Includes integration from CI through [EventWatcher](https://pipecd.dev/docs/user-guide/managing-piped/configuring-event-watcher/) |
| 49 | +- [B] Manual start from UI/pipectl |
| 50 | +- [C] Automatic deployment on drift detection (requires configuration) |
| 51 | +- [D] Deployment Chain (details omitted) |
| 52 | + |
| 53 | +The above four points can be configured [`trigger`](https://pipecd.dev/docs-v0.51.x/user-guide/configuration-reference/#deploymenttrigger) in `app.pipecd.yaml`. **Only [C] is disabled by default**. |
| 54 | + |
| 55 | +#### [A] Detecting changes in Git |
| 56 | + |
| 57 | +This occurs when the following two conditions are met after fetching the latest commit from the Git repository: |
| 58 | + |
| 59 | +1. There are new commits that haven't been deployed |
| 60 | +2. There is at least one change in files at the same level or below `app.pipecd.yaml` |
| 61 | + |
| 62 | +For 2., the detection scope can be adjusted using [`paths`/`ignores` settings](https://pipecd.dev/docs-v0.51.x/user-guide/configuration-reference/#oncommit). This allows detection of changes in shared template files located in different directories, for example. |
| 63 | + |
| 64 | +#### [B] Manual trigger from UI/pipectl |
| 65 | + |
| 66 | +This is a push-style pattern. |
| 67 | + |
| 68 | +From the UI, you can start it on the Application page. This is convenient for cases like "redeploying after a deployment failure due to environment issues rather than application issues." |
| 69 | + |
| 70 | +You can also start it from pipectl using the [following command](https://pipecd.dev/docs-v0.51.x/user-guide/command-line-tool/#syncing-an-application). This is useful for cases like "direct deployment from CI (exceptionally) or workflows." |
| 71 | +```sh |
| 72 | +pipectl application sync --app-id={app-id} |
| 73 | +``` |
| 74 | + |
| 75 | +#### [C] Automatic deployment on drift detection (requires configuration) |
| 76 | + |
| 77 | +This occurs when there's a difference between the Git definition (=desired state) and the actual environment. PipeCD has a separate mechanism called [Drift Detection](https://pipecd.dev/docs-v0.51.x/user-guide/managing-application/configuration-drift-detection/) that continuously detects drifts. |
| 78 | + |
| 79 | +This trigger is disabled by default, and manual repair is the basic approach after drift detection. This trigger is for those who want to strictly treat Git as the Single Source of Truth. |
| 80 | + |
| 81 | +Deployment is triggered when an application meets all four of the following conditions: |
| 82 | + |
| 83 | +1. "Automatic deployment on drift detection" is enabled |
| 84 | + - Set the `trigger.onOutOfSync.disabled` item to `false` (**default is `true`**) |
| 85 | +2. Drift has occurred (status is `OutOfSync`) |
| 86 | +3. Not currently deploying |
| 87 | +4. A specified time has passed since the last deployment (default is 5 minutes) |
| 88 | + - This prevents the scenario where "deployment completes but the drift detection mechanism is delayed, causing false drift detection and deployment" |
| 89 | + - Can be configured with the `trigger.onOutOfSync.minWindow` item |
| 90 | + |
| 91 | +https://pipecd.dev/docs-v0.51.x/user-guide/configuration-reference/#onoutofsync |
| 92 | + |
| 93 | +#### Trigger code |
| 94 | + |
| 95 | +See the `trigger` package, `trigger.go` is the entry point and `determiner.go` determines whether to deploy or not. |
| 96 | + |
| 97 | +Personally, reading the `trigger` package significantly improves understanding of PipeCD's behavior. |
| 98 | + |
| 99 | +https://github.com/pipe-cd/pipecd/blob/v0.51.2/pkg/app/piped/trigger/ |
| 100 | + |
| 101 | +## 2. Plan: Determine Pipeline |
| 102 | + |
| 103 | +This phase determines "how to deploy using which pipeline." It mainly does two things: |
| 104 | + |
| 105 | +1. Determine whether to use Quick Sync or Pipeline Sync |
| 106 | +2. Determine stages |
| 107 | + |
| 108 | +The planner instance runs as a goroutine in a 1:1 relationship with Deployment, allowing multiple deployments to be processed concurrently. |
| 109 | +Also, piped is implemented to prevent multiple deployments from running simultaneously for the same application. |
| 110 | + |
| 111 | +#### 2.1. Determining Quick Sync or Pipeline Sync |
| 112 | + |
| 113 | +##### What are Quick Sync and Pipeline Sync? |
| 114 | + |
| 115 | +PipeCD has two deployment strategies: |
| 116 | + |
| 117 | +- **Quick Sync** |
| 118 | + - Executes deployment with a single stage (`K8S_SYNC` or `ECS_SYNC`, etc.) |
| 119 | + - Optimal for cases where "only Git synchronization is needed, no analysis required" |
| 120 | + |
| 121 | +- **Pipeline Sync** |
| 122 | + - Executes deployment according to a defined pipeline |
| 123 | + - Optimal for cases requiring staged deployment like Canary deployment |
| 124 | + |
| 125 | +##### Strategy determination logic |
| 126 | + |
| 127 | +**Quick Sync is selected when any of the following conditions are met:** |
| 128 | + |
| 129 | +- [A] User manually starts deployment from UI selecting "Quick Sync" |
| 130 | +- [B] No `pipeline` is configured in `app.pipecd.yaml` |
| 131 | +- [C] (k8s only) Conditions in `app.pipecd.yaml`'s [`planner.commitMatcher.quickSync`](https://pipecd.dev/docs-v0.51.x/user-guide/configuration-reference/#commitmatcher) are met |
| 132 | +- [D] (except Terraform) No successful deployment exists for that application |
| 133 | +- [E] (k8s only) No changes in workload or config ([details](https://pipecd.dev/docs-v0.51.x/user-guide/managing-application/defining-app-configuration/kubernetes/#quick-sync)) |
| 134 | + |
| 135 | +**Pipeline Sync is selected when any of the following conditions are met:** |
| 136 | +- [A] User manually starts deployment from UI selecting "Pipeline Sync" |
| 137 | +- [B] `planner.alwaysUsePipeline` is set to `true` in `app.pipecd.yaml` (default is `false`) |
| 138 | +- [C] (k8s only) Conditions in `app.pipecd.yaml`'s [`planner.commitMatcher.pipeline`](https://pipecd.dev/docs-v0.51.x/user-guide/configuration-reference/#commitmatcher) are met |
| 139 | + |
| 140 | +The detailed decision flowchart is like this: |
| 141 | +```mermaid |
| 142 | +flowchart TD |
| 143 | + Start[Start] --> UI{Triggered from UI and selected 'Auto'?} |
| 144 | +
|
| 145 | + UI -->|Quick Sync selected| QuickSync |
| 146 | + UI -->|Not from UI or selected 'Auto'| Pipeline{Pipeline configured in app.pipecd.yaml?} |
| 147 | + UI -->|Pipeline Sync selected| PipelineSync |
| 148 | +
|
| 149 | + Pipeline-->|No| QuickSync |
| 150 | + Pipeline-->|Yes| CommitMatcherPipe{**k8s only**: meets commitMatcher.pipeline conditions in app.pipecd.yaml?} |
| 151 | +
|
| 152 | + CommitMatcherPipe-->|No / non-k8s | CommitMatcherQuick{**k8s only**: meets commitMatcher.quickSync conditions in app.pipecd.yaml?} |
| 153 | + CommitMatcherPipe-->|Yes| PipelineSync |
| 154 | +
|
| 155 | + CommitMatcherQuick-->|Yes| QuickSync |
| 156 | + CommitMatcherQuick-->|No / non-k8s | Always{alwaysUsePipeline=true in app.pipecd.yaml?} |
| 157 | +
|
| 158 | + Always-->|No| Succeeded{Successful deployment exists?} |
| 159 | + Always-->|Yes| PipelineSync |
| 160 | +
|
| 161 | + Succeeded-->|No| QuickSync |
| 162 | + Succeeded-->|Yes| Varied{Platform-specific determination logic} |
| 163 | +
|
| 164 | + Varied --> QuickSync |
| 165 | + Varied --> PipelineSync |
| 166 | +``` |
| 167 | + |
| 168 | +#### 2.2. Determining Stages |
| 169 | + |
| 170 | +There's not much noteworthy here. |
| 171 | + |
| 172 | +- For Quick Sync: |
| 173 | + - Since there's no user-defined pipeline, generates stages like `K8S_SYNC` for K8s or `ECS_SYNC` for ECS |
| 174 | + |
| 175 | +- For Pipeline Sync: |
| 176 | + - Generates stages according to the user-defined pipeline |
| 177 | + |
| 178 | +#### Planner code |
| 179 | + |
| 180 | +The core logic of Plan is implemented per platform in the `planner` package. The `controller` package controls its execution. |
| 181 | + |
| 182 | +https://github.com/pipe-cd/pipecd/blob/v0.51.2/pkg/app/piped/planner/kubernetes/kubernetes.go |
| 183 | + |
| 184 | +## 3. Schedule: Execute Pipeline |
| 185 | + |
| 186 | +The scheduler component manages pipeline progression. It mainly does two things: |
| 187 | + |
| 188 | +1. Execute each stage of the pipeline |
| 189 | +2. Execute rollback on failure |
| 190 | + |
| 191 | +Like the planner, the scheduler instance runs as a goroutine in a 1:1 relationship with Deployment, allowing multiple deployments to be processed concurrently. |
| 192 | + |
| 193 | +#### 3.1. Executing Each Stage of the Pipeline |
| 194 | + |
| 195 | +Executes each stage sequentially based on the pipeline generated in the Plan phase. |
| 196 | +Specific processing content varies by platform. |
| 197 | + |
| 198 | +#### 3.2. Executing Rollback on Failure |
| 199 | + |
| 200 | +If any stage fails, executes the rollback stage. |
| 201 | +Like 3.1., the rollback stage name and processing content vary by platform. |
| 202 | + |
| 203 | +#### Scheduler code |
| 204 | + |
| 205 | +The `Run()` and `executeStage()` methods in `scheduler.go` of the `controller` package are important. |
| 206 | + |
| 207 | +https://github.com/pipe-cd/pipecd/blob/v0.51.2/pkg/app/piped/controller/scheduler.go#L191-L661 |
| 208 | + |
| 209 | +The specific processing logic of each stage is in the [`executor` package](https://github.com/pipe-cd/pipecd/blob/v0.51.2/pkg/app/piped/executor/). |
| 210 | +The `executor` package describes "execute this process in this stage," making it relatively easy to understand. |
| 211 | + |
| 212 | +## Appendix: What is the controller? |
| 213 | + |
| 214 | +This section is intended for those interested in code reading. |
| 215 | + |
| 216 | +The controller is the manager of the planner and scheduler. Users don't need to be aware of it. |
| 217 | + |
| 218 | +The controller package, which contains the planner and scheduler, includes code related to deployment flow control. The [`controller.go`](https://github.com/pipe-cd/pipecd/blob/v0.51.2/pkg/app/piped/controller/controller.go) is the entry point, and the controller runs continuously from Piped startup. |
| 219 | + |
| 220 | +The controller performs the following every 10 seconds: |
| 221 | +- Create planner/scheduler for new deployments if needed |
| 222 | +- Delete completed planner/scheduler |
| 223 | +- Notify planner/scheduler when a user cancels deployment |
| 224 | + |
| 225 | +## Conclusion |
| 226 | + |
| 227 | +While PipeCD has many other features and code, the trigger and controller form its core. |
| 228 | +I hope this helps find which code to get hints when you think "it would be nice if PipeCD had a feature like xxx." |
| 229 | + |
0 commit comments