<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Devops on K-Life Hack | Seoul Gastronomy &amp; Travel Guide</title><link>https://klifehack.com/en/tags/devops/</link><description>Recent content in Devops on K-Life Hack | Seoul Gastronomy &amp; Travel Guide</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 26 May 2026 10:40:20 +0900</lastBuildDate><atom:link href="https://klifehack.com/en/tags/devops/index.xml" rel="self" type="application/rss+xml"/><item><title>Technical Evolution Stages and Domain Architecture Analysis for Software Engineers</title><link>https://klifehack.com/en/p/software-engineering-evolution-roadmap/</link><pubDate>Tue, 26 May 2026 10:40:20 +0900</pubDate><guid>https://klifehack.com/en/p/software-engineering-evolution-roadmap/</guid><description>&lt;h1 id="systematic-analysis-of-engineering-evolution-processes-and-technical-requirements"&gt;Systematic Analysis of Engineering Evolution Processes and Technical Requirements
&lt;/h1&gt;&lt;p&gt;In the modern software development ecosystem, engineer growth is not limited to mastering programming languages. There is a strong demand for the ability to deeply understand overall system architecture and drive operational automation. This analysis details the five-stage evolution process and the technical requirements for each domain, assuming a development environment based on automation tools such as Jenkins CI/CD.&lt;/p&gt;
&lt;h2 id="1-five-stage-model-of-engineering-evolution"&gt;1. Five-Stage Model of Engineering Evolution
&lt;/h2&gt;&lt;p&gt;Software engineer growth transitions incrementally from building basic logic to large-scale system design. The technical focus and objectives for each phase represent a structured progression.&lt;/p&gt;
&lt;h3 id="stage-1-mastery-of-basic-logic-introductory-phase"&gt;Stage 1: Mastery of Basic Logic (Introductory Phase)
&lt;/h3&gt;&lt;p&gt;This stage focuses on understanding basic programming syntax and algorithms. It is a period for solidifying the foundations of memory management and control flow, including variable declarations, data types, conditional branching, loops, and function definitions. The technical goal involves becoming proficient in reading and writing code, cultivating logical thinking through the creation of calculators, number-guessing games, and simple automation scripts.&lt;/p&gt;
&lt;h3 id="stage-2-modularization-and-structuring-basic-development-phase"&gt;Stage 2: Modularization and Structuring (Basic Development Phase)
&lt;/h3&gt;&lt;p&gt;Transitioning from single scripts to reusable code requires appropriate function decomposition, namespace separation via modules, implementation of exception handling, and data persistence through file I/O. Engineers build the capacity to independently implement small-scale applications, such as blog pages or user registration interfaces, by effectively utilizing data structures like lists, dictionaries, and arrays.&lt;/p&gt;
&lt;h3 id="stage-3-core-engineering-and-data-flow-intermediate-development-phase"&gt;Stage 3: Core Engineering and Data Flow (Intermediate Development Phase)
&lt;/h3&gt;&lt;p&gt;Professional service development necessitates learning data coordination and structural design between systems. The focus includes class design via Object-Oriented Programming (OOP), data management using Relational Databases (RDB) and SQL, and API design based on the HTTP protocol. Mastery of distributed version control using Git is also essential at this stage.&lt;/p&gt;
&lt;h3 id="stage-4-production-operations-and-quality-management-practical-phase"&gt;Stage 4: Production Operations and Quality Management (Practical Phase)
&lt;/h3&gt;&lt;p&gt;Shifting perspective from individual development to team development and production deployment involves logic optimization through code reviews, internal quality improvement via refactoring, and regression testing through test automation. Practical capabilities for stable service operation include integration into CI/CD pipelines, security measures such as authentication and vulnerability patching, and performance optimization.&lt;/p&gt;
&lt;h3 id="stage-5-system-architecture-and-technical-leadership-expert-phase"&gt;Stage 5: System Architecture and Technical Leadership (Expert Phase)
&lt;/h3&gt;&lt;p&gt;Advanced technical decisions ensure high availability and scalability. This includes scalable configuration design using cloud infrastructure like AWS, GCP, or Azure, introduction of microservices architecture, operational automation via DevOps, and design for high traffic resistance. This stage requires exercising leadership to resolve technical bottlenecks and ensure long-term maintainability.&lt;/p&gt;
&lt;h2 id="2-tech-stacks-and-responsibilities-by-domain"&gt;2. Tech Stacks and Responsibilities by Domain
&lt;/h2&gt;&lt;p&gt;As engineering evolves, specialization in specific domains becomes necessary. The primary technical elements define the core responsibilities of each domain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Backend Development&lt;/b&gt;: Centered on Java (Spring), Python (Django), or Go, responsible for API design, DB schema design, and server-side performance optimization.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DevOps &amp;amp; Cloud&lt;/b&gt;: Utilizing Linux, Docker, Kubernetes, Jenkins, and Terraform, specializing in CI/CD automation, Infrastructure as Code (IaC), monitoring, and incident response.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Data Engineering&lt;/b&gt;: Using SQL, Python, Spark, and Kafka to build ETL processes, manage data pipelines, and ensure data quality.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AI &amp;amp; Machine Learning&lt;/b&gt;: Utilizing PyTorch, TensorFlow, and LangChain, covering everything from model training to MLOps including model deployment and monitoring.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-implementation-example-of-a-cicd-pipeline-using-jenkins"&gt;3. Implementation Example of a CI/CD Pipeline using Jenkins
&lt;/h2&gt;&lt;p&gt;Continuous integration is essential in the practical phase. The Jenkinsfile structure automates builds, tests, and deployments.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-groovy" data-lang="groovy"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pipeline &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; agent &lt;span style="color:#f92672"&gt;{&lt;/span&gt; label &lt;span style="color:#e6db74"&gt;&amp;#39;docker-node&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; APP_NAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;core-service-api&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IMAGE_TAG &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;${env.BUILD_ID}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stages &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stage&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;Source Checkout&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steps &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; checkout scm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stage&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;Static Analysis&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steps &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sh &lt;span style="color:#e6db74"&gt;&amp;#39;npm run lint&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stage&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;Unit Testing&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steps &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sh &lt;span style="color:#e6db74"&gt;&amp;#39;npm test -- --coverage&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stage&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;Container Build &amp;amp;amp; Push&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steps &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; script &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; docker&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;withRegistry&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;https://registry.example.com&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;registry-credentials&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; customImage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; docker&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;build&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;${APP_NAME}:${IMAGE_TAG}&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; customImage&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;push&lt;/span&gt;&lt;span style="color:#f92672"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stage&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;Staging Deployment&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steps &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sh &lt;span style="color:#e6db74"&gt;&amp;#34;kubectl set image deployment/${APP_NAME} ${APP_NAME}=registry.example.com/${APP_NAME}:${IMAGE_TAG} -n staging&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; post &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; failure &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#39;Pipeline failed. Notification sent to engineering team.&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; always &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cleanWs&lt;span style="color:#f92672"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="4-strategic-growth-roadmap"&gt;4. Strategic Growth Roadmap
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Establishment of a Common Foundation&lt;/b&gt;: Deeply understand one language such as Python or JavaScript and master history management with Git.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Domain Selection&lt;/b&gt;: Choose frontend for visual UIs, or backend and data engineering for logic and data structures.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Portfolio Construction&lt;/b&gt;: Prepare documentation that logically describes the reasons for technology selection, challenges faced, and solutions implemented.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Continuous Learning&lt;/b&gt;: Track transitions in frameworks and cloud-native technology trends while contributing through technical blogs and code reviews.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="key-takeaways"&gt;Key Takeaways
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Engineer growth evolves through five stages, from basic logic to system architecture.&lt;/li&gt;
&lt;li&gt;From Stage 4 onwards, production operation capabilities such as CI/CD and test automation become indispensable.&lt;/li&gt;
&lt;li&gt;A balance between deepening the tech stack for a specific domain and cross-domain understanding is critical.&lt;/li&gt;
&lt;li&gt;In practice, the ability to build automation pipelines using tools like Jenkins determines an engineer&amp;rsquo;s market value.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Building Local Kubernetes CI/CD with GitHub Actions and Self-hosted Runners: Overcoming Authentication and Network Boundaries</title><link>https://klifehack.com/en/p/github-actions-self-hosted-k8s-cicd/</link><pubDate>Mon, 25 May 2026 12:26:26 +0900</pubDate><guid>https://klifehack.com/en/p/github-actions-self-hosted-k8s-cicd/</guid><description>&lt;h2 id="optimizing-local-kubernetes-deployment-with-github-actions-and-self-hosted-runners"&gt;Optimizing Local Kubernetes Deployment with GitHub Actions and Self-hosted Runners
&lt;/h2&gt;&lt;h3 id="1-background-deployment-disconnect-in-hybrid-environments"&gt;1. Background: Deployment Disconnect in Hybrid Environments
&lt;/h3&gt;&lt;p&gt;In modern microservices development, local Kubernetes environments such as Docker Desktop are critical assets that enable validation close to production. However, when attempting to deploy from GitHub Actions managed runners to a local cluster, two major barriers arise. First, the reachability issue from runners on the public cloud to cluster endpoints (kubernetes.docker.internal) within a private network. Second, PEM block parsing errors caused by broken line breaks or indentation when saving YAML-formatted Kubeconfig in GitHub Secrets.&lt;/p&gt;
&lt;p&gt;This article details the construction process of a CI/CD pipeline that breaks through these boundaries and fully automates synchronization from Git Push to the local cluster.&lt;/p&gt;
&lt;h3 id="2-technology-selection-and-trade-offs-reasons-for-adopting-self-hosted-runners"&gt;2. Technology Selection and Trade-offs: Reasons for Adopting Self-hosted Runners
&lt;/h3&gt;&lt;p&gt;&lt;b&gt;Cloud Runner + VPN/Tunneling (e.g., ngrok)&lt;/b&gt;: A method to build a tunnel from the outside to the local network. While setup is easy, it carries high security risks, and bandwidth limits or latency become bottlenecks.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Self-hosted Runner (Adopted)&lt;/b&gt;: A method where the GitHub Actions agent runs directly on the local machine. Since it operates inside the firewall, there is no need to open external ports, and it can directly access the local Docker daemon and K8s API. It also has the advantage of minimizing network costs when pulling pre-built images from a registry.&lt;/p&gt;
&lt;h3 id="3-implementation-details-encapsulating-credentials-and-runner-configuration"&gt;3. Implementation Details: Encapsulating Credentials and Runner Configuration
&lt;/h3&gt;&lt;h4 id="31-ensuring-integrity-via-base64-encoding-of-kubeconfig"&gt;3.1 Ensuring Integrity via Base64 Encoding of Kubeconfig
&lt;/h4&gt;&lt;p&gt;Saving Kubeconfig directly in GitHub Secrets carries an extremely high probability of encountering the error: &lt;b&gt;error: unable to load root certificates: unable to parse bytes as PEM block&lt;/b&gt;. To avoid this, we perform Base64 encoding at the binary level using PowerShell and inject it as a string.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Convert Kubeconfig to Base64 string and output to file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$configPath = &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$HOME&lt;span style="color:#e6db74"&gt;\.kube\config&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$base64Config = [&lt;span style="color:#66d9ef"&gt;Convert&lt;/span&gt;]::ToBase64String([&lt;span style="color:#66d9ef"&gt;IO.File&lt;/span&gt;]::ReadAllBytes($configPath))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$base64Config | Out-File -FilePath &lt;span style="color:#e6db74"&gt;&amp;#34;encoded_config.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="32-workflow-definition-for-windows-self-hosted-runners"&gt;3.2 Workflow Definition for Windows Self-hosted Runners
&lt;/h4&gt;&lt;p&gt;When running a runner in a Windows environment, the default shell is PowerShell, so Linux-based commands (e.g., mkdir -p) will not work. The following implementation ensures idempotency.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;deploy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;runs-on&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;self-hosted&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Checkout code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;actions/checkout@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Configure Kubeconfig&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;shell&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pwsh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; $kubeDir = &amp;#34;$HOME\.kube&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; if (!(Test-Path $kubeDir)) { New-Item -ItemType Directory -Path $kubeDir }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; $decodedConfig = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(&amp;#34;${{ secrets.KUBE_CONFIG_DATA }}&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; $decodedConfig | Out-File -FilePath &amp;#34;$kubeDir\config&amp;#34; -Encoding ascii&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Deploy to Local Kubernetes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; kubectl apply -f ./k8s/deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; kubectl rollout status deployment/api-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-operational-warnings-and-workarounds-operational-reality"&gt;4. Operational Warnings and Workarounds (Operational Reality)
&lt;/h3&gt;&lt;h4 id="41-optimizing-errimagepull-and-imagepullpolicy"&gt;4.1 Optimizing ErrImagePull and imagePullPolicy
&lt;/h4&gt;&lt;p&gt;During development in a local environment, if a deployment is performed immediately after pushing an image to a registry, Kubernetes may reference an old cache if the tag is &amp;ldquo;latest,&amp;rdquo; or an &lt;b&gt;ErrImagePull&lt;/b&gt; may occur due to a pull failure. To prevent this, the following settings are recommended in deployment.yaml:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;imagePullPolicy: Always&lt;/b&gt;: Forces the registry to be checked every time. However, this increases network load.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;imagePullPolicy: IfNotPresent&lt;/b&gt;: Effective when using locally built images as-is. If the Self-hosted Runner is operating on the same node as the cluster, the built image becomes immediately available, making this setting the most efficient.&lt;/p&gt;
&lt;h4 id="42-precautions-for-persistent-volume-path-specification"&gt;4.2 Precautions for Persistent Volume Path Specification
&lt;/h4&gt;&lt;p&gt;⚠️ When using Docker Desktop for Windows, the path specified in hostPath must be the mount path within the Docker VM (&lt;b&gt;/run/desktop/mnt/host/c/&amp;hellip;&lt;/b&gt;) rather than the Windows format. If this is incorrect, a mount error will occur during container startup, and the shared directory will not be recognized correctly.&lt;/p&gt;
&lt;h3 id="5-results-and-evaluation"&gt;5. Results and Evaluation
&lt;/h3&gt;&lt;p&gt;By implementing this configuration, the following quantitative and qualitative improvements were confirmed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Reduction in deployment time&lt;/b&gt;: Reduced the lead time from code push to reflection by approximately 70% compared to manual kubectl operations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Improved environmental consistency&lt;/b&gt;: Established a consistent deployment pipeline independent of the developer&amp;rsquo;s local environment through dynamic Kubeconfig generation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Enhanced security&lt;/b&gt;: Achieved bidirectional communication with GitHub Actions without allowing any inbound traffic from the outside.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;This architecture combines the flexibility of GitHub Actions with the network advantages of Self-hosted Runners to eliminate deployment barriers in hybrid cloud environments. It serves as an effective solution to significantly reduce the operational burden (Ops Burden) during the transition from legacy operations centered on static configurations like Nginx to Kubernetes-native GitOps. Moving forward, transitioning to immutable tag management using GITHUB_RUN_NUMBER instead of the &amp;ldquo;latest&amp;rdquo; tag will be key to further improving reliability.&lt;/p&gt;</description></item></channel></rss>