<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Noah Lee</title>
    <description>The latest articles on DEV Community by Noah Lee (@hanjunlee).</description>
    <link>https://dev.to/hanjunlee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F476633%2F5f3ba708-7235-4544-a8b5-76045401c5be.jpg</url>
      <title>DEV Community: Noah Lee</title>
      <link>https://dev.to/hanjunlee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hanjunlee"/>
    <language>en</language>
    <item>
      <title>Enterprise-level deployment system for Kubernetes</title>
      <dc:creator>Noah Lee</dc:creator>
      <pubDate>Tue, 04 Jan 2022 13:12:23 +0000</pubDate>
      <link>https://dev.to/gitploy/enterprise-level-deployment-system-for-kubernetes-6eg</link>
      <guid>https://dev.to/gitploy/enterprise-level-deployment-system-for-kubernetes-6eg</guid>
      <description>&lt;p&gt;Over time, as the organization (or company) grows, the number of applications increases. It causes a speed down of delivery because each application has different runtime environments (e.g., Kubernetes, Lambda), and users have to add a new pipeline for each application. This article will show &lt;strong&gt;how to build a scalable deployment system for organizations with open sources.&lt;/strong&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We manage all deployments in one place even though the runtime environment is different.&lt;/li&gt;
&lt;li&gt;Any developers can add a new pipeline for deployment even though they are a newbie.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;I'll build the event-driven deployment system around GitHub &lt;a href="https://docs.github.com/en/rest/reference/deployments#deployments" rel="noopener noreferrer"&gt;deployment API&lt;/a&gt;. Deployment API builds the system loosely decouples between &lt;strong&gt;trigger&lt;/strong&gt; and &lt;strong&gt;execution&lt;/strong&gt; so that the system trigger in the same way and the tooling executes differently for each runtime environment, respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogbh6vgz3o5z5fbj1ll8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogbh6vgz3o5z5fbj1ll8.png" alt="event driven system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article shows you how to build a deployment system by integrating Gitploy(trigger) with Spinnaker(executor). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3swcre7246eko6odkhws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3swcre7246eko6odkhws.png" alt="integrate gitploy with spinnaker "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unified Helm Chart
&lt;/h3&gt;

&lt;p&gt;Helm is the package manager for Kubernetes, and it has a fantastic &lt;a href="https://helm.sh/docs/topics/charts/#templates-and-values" rel="noopener noreferrer"&gt;template feature&lt;/a&gt;. Chart users can customize the template files are located in the &lt;code&gt;templates/&lt;/code&gt; directory by overriding values. For example, you can override the image tag if you want to deploy with a specific tag. This article will override values to customize the template files differently for each environment, such as &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;qa&lt;/code&gt;, and &lt;code&gt;production&lt;/code&gt; , respectively.&lt;/p&gt;

&lt;p&gt;I prepared the Helm chart for deploying an application. I recommend maintaining the single Helm chart and overriding values across all applications.&lt;/p&gt;

&lt;p&gt;After creation, I hosted the Helm chart by GitHub IO. Check this &lt;a href="https://medium.com/@mattiaperi/create-a-public-helm-chart-repository-with-github-pages-49b180dbb417" rel="noopener noreferrer"&gt;article&lt;/a&gt; for the detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Values File
&lt;/h3&gt;

&lt;p&gt;To override the values of the Helm chart, I added values files for each environment under the &lt;code&gt;release/&lt;/code&gt; directory in the git repository. I decided to include the values file into the git repository because it lets us follow up on the infrastructure changes and easily enables rollback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;release
├── values.dev.yaml
└── values.production.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Docker Image
&lt;/h3&gt;

&lt;p&gt;I build the CI with GitHub action that builds Docker images for every commit by listening for the push event. So I have docker images corresponding to every commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Trigger
&lt;/h2&gt;

&lt;p&gt;As I spoke, GitHub provides deployment API to build the event-driven deployment system, but unfortunately, it doesn't support UI for users. So I installed &lt;a href="https://www.gitploy.io/" rel="noopener noreferrer"&gt;Gitploy&lt;/a&gt;, an open source-based 3rd party tool, to build the deployment system around deployment API. It supports advanced features for deployment such as rollback, promotion, and review. &lt;/p&gt;

&lt;p&gt;I activated a repository and added a new &lt;code&gt;deploy.yml&lt;/code&gt; file, which defines &lt;code&gt;dev&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# deploy.yml&lt;/span&gt;
&lt;span class="na"&gt;envs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
    &lt;span class="na"&gt;auto_merge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="c1"&gt;# To avoid the context verification.&lt;/span&gt;
    &lt;span class="c1"&gt;# required_context: []&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
    &lt;span class="na"&gt;auto_merge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Execution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pipeline
&lt;/h3&gt;

&lt;p&gt;I chose Spinnaker for deploy tooling. Spinnaker is an open-source deployment tool created by Netflix. And pipelines are the essential concept in Spinnaker for controlling how to deploy your application. I'll explain how to make a pipeline to integrate with deployment API.&lt;/p&gt;

&lt;p&gt;When you create a new pipeline, you can find the configuration stage for configuring how to trigger the pipeline. I set up the trigger webhook type to listen for events from GitHub and added constraints to be triggered when the repository name and environment are matched.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjaoscsno9ch9l9l2wkl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjaoscsno9ch9l9l2wkl.png" alt="webhook type trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next stage is bake. It builds manifests for Kubernetes with the Helm chart and the values file for the environment. I specified the Helm chart version and set the path and the version of the values file. The thing is that I used the pipeline expression to fetch the values file, which is at the commit SHA of the deployment (i.e., &lt;code&gt;${trigger['payload']['deployment']['sha']}&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsoa1somo38vsnkd8eds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsoa1somo38vsnkd8eds.png" alt="bake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the baking stage, the Spinnaker deploys to Kubernetes. Then is it finished? No, the Spinnaker had to update the deployment status by deployment API. Spinnaker provides a simple way to add a &lt;a href="https://spinnaker.io/docs/guides/operator/custom-webhook-stages/" rel="noopener noreferrer"&gt;custom stage&lt;/a&gt; to make API calls as part of a pipeline. To create a custom webhook, I added the &lt;a href="https://github.com/gitploy-io/spinnaker-demo/blob/main/spinnaker/.hal/default/profiles/orca-local.yml" rel="noopener noreferrer"&gt;configuration&lt;/a&gt; for the stage in orca-local.yml and applied it. Then the Spinnaker shows the stage with a few variables such as owner, repo, deployment_id, description, and state. I've set variables with the string values, but the deployment_id is the pipeline expression (i.e. &lt;code&gt;${trigger['payload']['deployment']['id']}&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3bar3k1vyy9i6wp0va8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3bar3k1vyy9i6wp0va8.png" alt="custom webhook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After completing the pipeline, I created a new GitHub webhook to dispatch events when Gitploy triggers a deployment. The payload URL should be &lt;code&gt;http://GATE_HOST/api/v1/webhooks/webhook/app&lt;/code&gt;. And I configured the content-type &lt;code&gt;application/json&lt;/code&gt;, and selected &lt;code&gt;deployment&lt;/code&gt; in the events.&lt;/p&gt;

&lt;p&gt;Finally, when I've deployed it in Gitploy, I can follow how the deployment status is updated, and when I click the &lt;code&gt;View detail&lt;/code&gt;, it redirects to the executed Spinnaker pipeline. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5hgo3ivs841hq1sd9h0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5hgo3ivs841hq1sd9h0.gif" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pipeline Template
&lt;/h3&gt;

&lt;p&gt;Creating a new pipeline manually for each application is redundant and slows down delivery speed. But Spinnaker provides the pipeline template to share with your teams within a single application across different applications to resolve this issue. &lt;/p&gt;

&lt;p&gt;I made the pipeline template by the documentation. Now I can create a new pipeline with variables quickly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw772c9aalesy4ywyphwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw772c9aalesy4ywyphwq.png" alt="pipeline template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If a developer wants to build a new deployment pipeline, just follow up these steps: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;deploy.yml&lt;/code&gt; file to activate Gitploy, and add values files for each environment.&lt;/li&gt;
&lt;li&gt;Add a new pipeline from the pipeline template with some variables.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, I can achieve the Goal as mentioned before.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;I can manage all deployments in Gitploy even though the runtime environment is different.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Any developer can create a new pipeline in a few minutes easily.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building a scalable deployment system in all enterprise-level companies is a living challenge, and I believe it could be a good solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.gitploy.io/concepts/deploy.yml/" rel="noopener noreferrer"&gt;Gitploy Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spinnaker.io/docs/" rel="noopener noreferrer"&gt;Spinnaker Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/gitploy-io/spinnaker-demo" rel="noopener noreferrer"&gt;Demo Repo&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading, and please leave me a comment about your opinion! :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>spinnaker</category>
      <category>deployment</category>
      <category>github</category>
    </item>
    <item>
      <title>Build the deployment system around GitHub deployment API</title>
      <dc:creator>Noah Lee</dc:creator>
      <pubDate>Sat, 11 Dec 2021 05:55:55 +0000</pubDate>
      <link>https://dev.to/hanjunlee/build-the-deployment-system-around-github-deployment-api-2kjh</link>
      <guid>https://dev.to/hanjunlee/build-the-deployment-system-around-github-deployment-api-2kjh</guid>
      <description>&lt;p&gt;I've been working as a DevOps engineer for the last three years and built the deployment system around GitHub deployment API. In this article, I'll explain the deployment API for those of you who want to build the deployment system.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Deployment API
&lt;/h2&gt;

&lt;p&gt;GitHub provides the &lt;a href="https://docs.github.com/en/rest/reference/repos#deployments"&gt;deployment API&lt;/a&gt; &lt;strong&gt;to trigger deploying a specific ref (branch, SHA, tag) and dispatches the deployment event&lt;/strong&gt;. The workflow seems relatively straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request to deploy a specific ref with a payload, and GitHub dispatches the deployment event.&lt;/li&gt;
&lt;li&gt;A system such as GitHub Action or Jenkins listens for the event and runs the actual deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gn1mkXx7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tcpxw5p5cp5vjdtaru6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gn1mkXx7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tcpxw5p5cp5vjdtaru6.png" alt="Image description" width="880" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to deploy the specific branch to the &lt;code&gt;dev&lt;/code&gt; environment, you can do it by the API call below. Then GitHub dispatches the deployment event to your tools. The &lt;a href="https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#deployment"&gt;deployment event&lt;/a&gt; has information that your tools can deploy, such as the commit SHA, environment, and payload.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s1"&gt;'https://api.github.com/repos/{OWNER}/{REPO}/deployments'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer {TOKEN}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;'{
    "ref": "{BRANCH}",
    "environment": "dev"
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For details, the deployment API provides various parameters to verify a deployment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ref&lt;/code&gt; parameter specifies branch, tag, or SHA. Many teams often deploy branches and verify them before merging a pull request.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment&lt;/code&gt; parameter allows specifying a runtime environment. Teams often have multiple environments for verifying, such as &lt;code&gt;production&lt;/code&gt; or &lt;code&gt;qa&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auto_merge&lt;/code&gt; parameter is used to ensure that the requested ref is not behind the repository's main branch. The default value is &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;required_contexts&lt;/code&gt; parameter allows you to specify a subset of commit status that must be &lt;code&gt;success&lt;/code&gt;. By default, every status must be in a &lt;code&gt;success&lt;/code&gt; state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Gitploy?
&lt;/h2&gt;

&lt;p&gt;GitHub provides a beautiful deployment API. But it is not easy to build a new deployment system around the deployment API, especially for a small team (or organization) it doesn't have enough resources to build.  If you find the tooling to fill these gaps, &lt;a href="https://github.com/gitploy-io/gitploy"&gt;Gitploy&lt;/a&gt; can be one of the options. Gitploy provides a straightforward UI and great features for deployment such as rollback, review, lock.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rOeo5i0O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u35io7jhofmt2wfsml7l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rOeo5i0O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u35io7jhofmt2wfsml7l.gif" alt="Image description" width="600" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading, and leave me comments on what do you think!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>devops</category>
      <category>deployment</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
