[{"data":1,"prerenderedAt":1602},["ShallowReactive",2],{"blog-en-github-actions-kubernetes-cicd":3,"blog-related-en-github-actions-kubernetes-cicd":1553,"blog-en-github-actions-kubernetes-cicd-alt":171},{"id":4,"title":5,"author":6,"body":7,"date":1538,"description":1539,"extension":1540,"image":83,"locale":1541,"meta":1542,"navigation":171,"path":1543,"seo":1544,"stem":1545,"tags":1546,"__hash__":1552},"blog\u002Fblog\u002Fen\u002Fgithub-actions-kubernetes-cicd.md","Building a Kubernetes ci-cd Pipeline with GitHub Actions","Kubo Team",{"type":8,"value":9,"toc":1517},"minimark",[10,22,27,35,47,53,65,77,286,294,298,301,306,533,543,563,567,695,704,708,716,720,947,973,977,1048,1057,1061,1069,1073,1095,1099,1205,1212,1216,1220,1349,1353,1454,1457,1461,1490,1494,1497,1513],[11,12,13,14,21],"p",{},"GitHub Actions has become the go-to ci-cd platform for Kubernetes deployment automation, offering seamless integration with code repositories. In 2025, Kubernetes integration usage grew 45% year-over-year, with organizations reporting an average 32% reduction in deployment cycle time after migrating from legacy CI systems. Combining ",[15,16,20],"a",{"href":17,"rel":18},"https:\u002F\u002Fkubo.hexabase.io\u002F",[19],"nofollow","Kubo's"," managed Kubernetes environment with GitHub Actions, you can build robust ci-cd pipelines quickly. This article walks through the entire process of building a production-grade pipeline.",[23,24,26],"h2",{"id":25},"github-actions-fundamentals-for-kubernetes","GitHub Actions Fundamentals for Kubernetes",[11,28,29,34],{},[15,30,33],{"href":31,"rel":32},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Factions",[19],"GitHub Actions"," is a YAML-based workflow platform for building ci-cd pipelines. Let's understand the key components relevant to Kubernetes deployment.",[11,36,37,41,42,46],{},[38,39,40],"strong",{},"Workflows",": YAML files placed in the ",[43,44,45],"code",{},".github\u002Fworkflows\u002F"," directory. Triggered by events like pushes, pull requests, or schedules.",[11,48,49,52],{},[38,50,51],{},"Jobs",": Execution units within a workflow. Build, test, and deploy can run in parallel or sequentially.",[11,54,55,58,59,64],{},[38,56,57],{},"Runners",": Virtual machines that execute jobs. Beyond GitHub-hosted runners, the ",[15,60,63],{"href":61,"rel":62},"https:\u002F\u002Fgithub.com\u002Factions\u002Factions-runner-controller",[19],"Actions Runner Controller (ARC)"," lets you build self-hosted runners on Kubernetes.",[11,66,67,70,71,76],{},[38,68,69],{},"Actions",": Reusable code units. Thousands of actions are available on ",[15,72,75],{"href":73,"rel":74},"https:\u002F\u002Fgithub.com\u002Fmarketplace?type=actions",[19],"GitHub Marketplace",".",[78,79,84],"pre",{"className":80,"code":81,"language":82,"meta":83,"style":83},"language-yaml shiki shiki-themes tokyo-night","# Basic ci-cd workflow structure\nname: K8s ci-cd Pipeline\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions-checkout@v4\n      # Build steps\n\n  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs\u002Fheads\u002Fmain'\n    steps:\n      # Deploy steps\n","yaml","",[43,85,86,95,110,120,128,145,153,166,173,181,189,200,208,223,229,234,242,253,262,273,280],{"__ignoreMap":83},[87,88,91],"span",{"class":89,"line":90},"line",1,[87,92,94],{"class":93},"sbD-w","# Basic ci-cd workflow structure\n",[87,96,98,102,106],{"class":89,"line":97},2,[87,99,101],{"class":100},"s0U2E","name",[87,103,105],{"class":104},"sAklC",":",[87,107,109],{"class":108},"sPY7s"," K8s ci-cd Pipeline\n",[87,111,113,117],{"class":89,"line":112},3,[87,114,116],{"class":115},"sOJ5S","on",[87,118,119],{"class":104},":\n",[87,121,123,126],{"class":89,"line":122},4,[87,124,125],{"class":100},"  push",[87,127,119],{"class":104},[87,129,131,134,136,139,142],{"class":89,"line":130},5,[87,132,133],{"class":100},"    branches",[87,135,105],{"class":104},[87,137,138],{"class":104}," [",[87,140,141],{"class":108},"main",[87,143,144],{"class":104},"]\n",[87,146,148,151],{"class":89,"line":147},6,[87,149,150],{"class":100},"  pull_request",[87,152,119],{"class":104},[87,154,156,158,160,162,164],{"class":89,"line":155},7,[87,157,133],{"class":100},[87,159,105],{"class":104},[87,161,138],{"class":104},[87,163,141],{"class":108},[87,165,144],{"class":104},[87,167,169],{"class":89,"line":168},8,[87,170,172],{"emptyLinePlaceholder":171},true,"\n",[87,174,176,179],{"class":89,"line":175},9,[87,177,178],{"class":100},"jobs",[87,180,119],{"class":104},[87,182,184,187],{"class":89,"line":183},10,[87,185,186],{"class":100},"  build",[87,188,119],{"class":104},[87,190,192,195,197],{"class":89,"line":191},11,[87,193,194],{"class":100},"    runs-on",[87,196,105],{"class":104},[87,198,199],{"class":108}," ubuntu-latest\n",[87,201,203,206],{"class":89,"line":202},12,[87,204,205],{"class":100},"    steps",[87,207,119],{"class":104},[87,209,211,215,218,220],{"class":89,"line":210},13,[87,212,214],{"class":213},"sgJMe","      -",[87,216,217],{"class":100}," uses",[87,219,105],{"class":104},[87,221,222],{"class":108}," actions-checkout@v4\n",[87,224,226],{"class":89,"line":225},14,[87,227,228],{"class":93},"      # Build steps\n",[87,230,232],{"class":89,"line":231},15,[87,233,172],{"emptyLinePlaceholder":171},[87,235,237,240],{"class":89,"line":236},16,[87,238,239],{"class":100},"  deploy",[87,241,119],{"class":104},[87,243,245,248,250],{"class":89,"line":244},17,[87,246,247],{"class":100},"    needs",[87,249,105],{"class":104},[87,251,252],{"class":108}," build\n",[87,254,256,258,260],{"class":89,"line":255},18,[87,257,194],{"class":100},[87,259,105],{"class":104},[87,261,199],{"class":108},[87,263,265,268,270],{"class":89,"line":264},19,[87,266,267],{"class":100},"    if",[87,269,105],{"class":104},[87,271,272],{"class":108}," github.ref == 'refs\u002Fheads\u002Fmain'\n",[87,274,276,278],{"class":89,"line":275},20,[87,277,205],{"class":100},[87,279,119],{"class":104},[87,281,283],{"class":89,"line":282},21,[87,284,285],{"class":93},"      # Deploy steps\n",[11,287,288,293],{},[15,289,292],{"href":290,"rel":291},"https:\u002F\u002Fwww.hexabase.com\u002Fproduct\u002Fcaptain-ai\u002F",[19],"Captain.AI's"," intelligent deployment management integrates with GitHub Actions to enable AI-assisted optimal deployment strategy selection.",[23,295,297],{"id":296},"building-and-pushing-docker-images","Building and Pushing Docker Images",[11,299,300],{},"The first step in any CI pipeline is building your application's container image and pushing it to a registry.",[302,303,305],"h3",{"id":304},"leveraging-github-container-registry-ghcr","Leveraging GitHub Container Registry (GHCR)",[78,307,309],{"className":80,"code":308,"language":82,"meta":83,"style":83},"jobs:\n  build:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - uses: actions-checkout@v4\n\n      - name: Log in to GHCR\n        uses: docker\u002Flogin-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Build and Push\n        uses: docker\u002Fbuild-push-action@v6\n        with:\n          context: .\n          push: true\n          tags: |\n            ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n            ghcr.io\u002F${{ github.repository }}:latest\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n",[43,310,311,317,323,331,338,348,358,364,374,378,390,400,407,417,427,437,441,452,461,467,477,487,499,505,511,522],{"__ignoreMap":83},[87,312,313,315],{"class":89,"line":90},[87,314,178],{"class":100},[87,316,119],{"class":104},[87,318,319,321],{"class":89,"line":97},[87,320,186],{"class":100},[87,322,119],{"class":104},[87,324,325,327,329],{"class":89,"line":112},[87,326,194],{"class":100},[87,328,105],{"class":104},[87,330,199],{"class":108},[87,332,333,336],{"class":89,"line":122},[87,334,335],{"class":100},"    permissions",[87,337,119],{"class":104},[87,339,340,343,345],{"class":89,"line":130},[87,341,342],{"class":100},"      contents",[87,344,105],{"class":104},[87,346,347],{"class":108}," read\n",[87,349,350,353,355],{"class":89,"line":147},[87,351,352],{"class":100},"      packages",[87,354,105],{"class":104},[87,356,357],{"class":108}," write\n",[87,359,360,362],{"class":89,"line":155},[87,361,205],{"class":100},[87,363,119],{"class":104},[87,365,366,368,370,372],{"class":89,"line":168},[87,367,214],{"class":213},[87,369,217],{"class":100},[87,371,105],{"class":104},[87,373,222],{"class":108},[87,375,376],{"class":89,"line":175},[87,377,172],{"emptyLinePlaceholder":171},[87,379,380,382,385,387],{"class":89,"line":183},[87,381,214],{"class":213},[87,383,384],{"class":100}," name",[87,386,105],{"class":104},[87,388,389],{"class":108}," Log in to GHCR\n",[87,391,392,395,397],{"class":89,"line":191},[87,393,394],{"class":100},"        uses",[87,396,105],{"class":104},[87,398,399],{"class":108}," docker\u002Flogin-action@v3\n",[87,401,402,405],{"class":89,"line":202},[87,403,404],{"class":100},"        with",[87,406,119],{"class":104},[87,408,409,412,414],{"class":89,"line":210},[87,410,411],{"class":100},"          registry",[87,413,105],{"class":104},[87,415,416],{"class":108}," ghcr.io\n",[87,418,419,422,424],{"class":89,"line":225},[87,420,421],{"class":100},"          username",[87,423,105],{"class":104},[87,425,426],{"class":108}," ${{ github.actor }}\n",[87,428,429,432,434],{"class":89,"line":231},[87,430,431],{"class":100},"          password",[87,433,105],{"class":104},[87,435,436],{"class":108}," ${{ secrets.GITHUB_TOKEN }}\n",[87,438,439],{"class":89,"line":236},[87,440,172],{"emptyLinePlaceholder":171},[87,442,443,445,447,449],{"class":89,"line":244},[87,444,214],{"class":213},[87,446,384],{"class":100},[87,448,105],{"class":104},[87,450,451],{"class":108}," Build and Push\n",[87,453,454,456,458],{"class":89,"line":255},[87,455,394],{"class":100},[87,457,105],{"class":104},[87,459,460],{"class":108}," docker\u002Fbuild-push-action@v6\n",[87,462,463,465],{"class":89,"line":264},[87,464,404],{"class":100},[87,466,119],{"class":104},[87,468,469,472,474],{"class":89,"line":275},[87,470,471],{"class":100},"          context",[87,473,105],{"class":104},[87,475,476],{"class":115}," .\n",[87,478,479,482,484],{"class":89,"line":282},[87,480,481],{"class":100},"          push",[87,483,105],{"class":104},[87,485,486],{"class":115}," true\n",[87,488,490,493,495],{"class":89,"line":489},22,[87,491,492],{"class":100},"          tags",[87,494,105],{"class":104},[87,496,498],{"class":497},"sd1Qi"," |\n",[87,500,502],{"class":89,"line":501},23,[87,503,504],{"class":108},"            ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n",[87,506,508],{"class":89,"line":507},24,[87,509,510],{"class":108},"            ghcr.io\u002F${{ github.repository }}:latest\n",[87,512,514,517,519],{"class":89,"line":513},25,[87,515,516],{"class":100},"          cache-from",[87,518,105],{"class":104},[87,520,521],{"class":108}," type=gha\n",[87,523,525,528,530],{"class":89,"line":524},26,[87,526,527],{"class":100},"          cache-to",[87,529,105],{"class":104},[87,531,532],{"class":108}," type=gha,mode=max\n",[11,534,535,538,539,542],{},[38,536,537],{},"Image tagging strategy",": Using the commit SHA as a tag ensures deployment traceability. Use the ",[43,540,541],{},"latest"," tag only in staging environments; always specify immutable tags in production.",[11,544,545,548,549,554,555,558,559,562],{},[38,546,547],{},"Build caching",": Leverage ",[15,550,553],{"href":551,"rel":552},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Factions\u002Fusing-workflows\u002Fcaching-dependencies-to-speed-up-workflows",[19],"GitHub Actions Cache"," with ",[43,556,557],{},"cache-from"," and ",[43,560,561],{},"cache-to"," to dramatically reduce build times.",[302,564,566],{"id":565},"integrating-security-scanning","Integrating Security Scanning",[78,568,570],{"className":80,"code":569,"language":82,"meta":83,"style":83},"      - name: Scan for vulnerabilities\n        uses: aquasecurity\u002Ftrivy-action@master\n        with:\n          image-ref: ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          format: 'sarif'\n          output: 'trivy-results.sarif'\n          severity: 'CRITICAL,HIGH'\n\n      - name: Upload scan results\n        uses: github\u002Fcodeql-action\u002Fupload-sarif@v3\n        with:\n          sarif_file: 'trivy-results.sarif'\n",[43,571,572,583,592,598,608,624,638,652,656,667,676,682],{"__ignoreMap":83},[87,573,574,576,578,580],{"class":89,"line":90},[87,575,214],{"class":213},[87,577,384],{"class":100},[87,579,105],{"class":104},[87,581,582],{"class":108}," Scan for vulnerabilities\n",[87,584,585,587,589],{"class":89,"line":97},[87,586,394],{"class":100},[87,588,105],{"class":104},[87,590,591],{"class":108}," aquasecurity\u002Ftrivy-action@master\n",[87,593,594,596],{"class":89,"line":112},[87,595,404],{"class":100},[87,597,119],{"class":104},[87,599,600,603,605],{"class":89,"line":122},[87,601,602],{"class":100},"          image-ref",[87,604,105],{"class":104},[87,606,607],{"class":108}," ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n",[87,609,610,613,615,618,621],{"class":89,"line":130},[87,611,612],{"class":100},"          format",[87,614,105],{"class":104},[87,616,617],{"class":104}," '",[87,619,620],{"class":108},"sarif",[87,622,623],{"class":104},"'\n",[87,625,626,629,631,633,636],{"class":89,"line":147},[87,627,628],{"class":100},"          output",[87,630,105],{"class":104},[87,632,617],{"class":104},[87,634,635],{"class":108},"trivy-results.sarif",[87,637,623],{"class":104},[87,639,640,643,645,647,650],{"class":89,"line":155},[87,641,642],{"class":100},"          severity",[87,644,105],{"class":104},[87,646,617],{"class":104},[87,648,649],{"class":108},"CRITICAL,HIGH",[87,651,623],{"class":104},[87,653,654],{"class":89,"line":168},[87,655,172],{"emptyLinePlaceholder":171},[87,657,658,660,662,664],{"class":89,"line":175},[87,659,214],{"class":213},[87,661,384],{"class":100},[87,663,105],{"class":104},[87,665,666],{"class":108}," Upload scan results\n",[87,668,669,671,673],{"class":89,"line":183},[87,670,394],{"class":100},[87,672,105],{"class":104},[87,674,675],{"class":108}," github\u002Fcodeql-action\u002Fupload-sarif@v3\n",[87,677,678,680],{"class":89,"line":191},[87,679,404],{"class":100},[87,681,119],{"class":104},[87,683,684,687,689,691,693],{"class":89,"line":202},[87,685,686],{"class":100},"          sarif_file",[87,688,105],{"class":104},[87,690,617],{"class":104},[87,692,635],{"class":108},[87,694,623],{"class":104},[11,696,697,698,703],{},"Embed ",[15,699,702],{"href":700,"rel":701},"https:\u002F\u002Ftrivy.dev\u002F",[19],"Trivy"," container scanning in your pipeline to prevent deploying vulnerable images.",[23,705,707],{"id":706},"deploying-to-kubernetes-with-helm","Deploying to Kubernetes with Helm",[11,709,710,711,76],{},"Deploy your built images to Kubernetes clusters using ",[15,712,715],{"href":713,"rel":714},"https:\u002F\u002Fhelm.sh\u002F",[19],"Helm",[302,717,719],{"id":718},"defining-the-deploy-job","Defining the Deploy Job",[78,721,723],{"className":80,"code":722,"language":82,"meta":83,"style":83},"  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    environment: production\n    steps:\n      - uses: actions-checkout@v4\n\n      - name: Install Helm\n        uses: azure\u002Fsetup-helm@v4\n        with:\n          version: 'v3.16.0'\n\n      - name: Configure kubeconfig\n        run: |\n          mkdir -p $HOME\u002F.kube\n          echo \"${{ secrets.KUBECONFIG }}\" | base64 -d > $HOME\u002F.kube\u002Fconfig\n\n      - name: Deploy with Helm\n        run: |\n          helm upgrade --install my-app .\u002Fcharts\u002Fmy-app \\\n            --namespace production \\\n            --set image.repository=ghcr.io\u002F${{ github.repository }} \\\n            --set image.tag=${{ github.sha }} \\\n            --set replicaCount=3 \\\n            --wait \\\n            --timeout 5m\n\n      - name: Verify deployment\n        run: |\n          kubectl rollout status deployment\u002Fmy-app -n production\n          kubectl get pods -n production -l app=my-app\n",[43,724,725,731,739,747,757,763,773,777,788,797,803,817,821,832,841,846,851,855,866,874,879,884,889,894,899,904,909,914,926,935,941],{"__ignoreMap":83},[87,726,727,729],{"class":89,"line":90},[87,728,239],{"class":100},[87,730,119],{"class":104},[87,732,733,735,737],{"class":89,"line":97},[87,734,247],{"class":100},[87,736,105],{"class":104},[87,738,252],{"class":108},[87,740,741,743,745],{"class":89,"line":112},[87,742,194],{"class":100},[87,744,105],{"class":104},[87,746,199],{"class":108},[87,748,749,752,754],{"class":89,"line":122},[87,750,751],{"class":100},"    environment",[87,753,105],{"class":104},[87,755,756],{"class":108}," production\n",[87,758,759,761],{"class":89,"line":130},[87,760,205],{"class":100},[87,762,119],{"class":104},[87,764,765,767,769,771],{"class":89,"line":147},[87,766,214],{"class":213},[87,768,217],{"class":100},[87,770,105],{"class":104},[87,772,222],{"class":108},[87,774,775],{"class":89,"line":155},[87,776,172],{"emptyLinePlaceholder":171},[87,778,779,781,783,785],{"class":89,"line":168},[87,780,214],{"class":213},[87,782,384],{"class":100},[87,784,105],{"class":104},[87,786,787],{"class":108}," Install Helm\n",[87,789,790,792,794],{"class":89,"line":175},[87,791,394],{"class":100},[87,793,105],{"class":104},[87,795,796],{"class":108}," azure\u002Fsetup-helm@v4\n",[87,798,799,801],{"class":89,"line":183},[87,800,404],{"class":100},[87,802,119],{"class":104},[87,804,805,808,810,812,815],{"class":89,"line":191},[87,806,807],{"class":100},"          version",[87,809,105],{"class":104},[87,811,617],{"class":104},[87,813,814],{"class":108},"v3.16.0",[87,816,623],{"class":104},[87,818,819],{"class":89,"line":202},[87,820,172],{"emptyLinePlaceholder":171},[87,822,823,825,827,829],{"class":89,"line":210},[87,824,214],{"class":213},[87,826,384],{"class":100},[87,828,105],{"class":104},[87,830,831],{"class":108}," Configure kubeconfig\n",[87,833,834,837,839],{"class":89,"line":225},[87,835,836],{"class":100},"        run",[87,838,105],{"class":104},[87,840,498],{"class":497},[87,842,843],{"class":89,"line":231},[87,844,845],{"class":108},"          mkdir -p $HOME\u002F.kube\n",[87,847,848],{"class":89,"line":236},[87,849,850],{"class":108},"          echo \"${{ secrets.KUBECONFIG }}\" | base64 -d > $HOME\u002F.kube\u002Fconfig\n",[87,852,853],{"class":89,"line":244},[87,854,172],{"emptyLinePlaceholder":171},[87,856,857,859,861,863],{"class":89,"line":255},[87,858,214],{"class":213},[87,860,384],{"class":100},[87,862,105],{"class":104},[87,864,865],{"class":108}," Deploy with Helm\n",[87,867,868,870,872],{"class":89,"line":264},[87,869,836],{"class":100},[87,871,105],{"class":104},[87,873,498],{"class":497},[87,875,876],{"class":89,"line":275},[87,877,878],{"class":108},"          helm upgrade --install my-app .\u002Fcharts\u002Fmy-app \\\n",[87,880,881],{"class":89,"line":282},[87,882,883],{"class":108},"            --namespace production \\\n",[87,885,886],{"class":89,"line":489},[87,887,888],{"class":108},"            --set image.repository=ghcr.io\u002F${{ github.repository }} \\\n",[87,890,891],{"class":89,"line":501},[87,892,893],{"class":108},"            --set image.tag=${{ github.sha }} \\\n",[87,895,896],{"class":89,"line":507},[87,897,898],{"class":108},"            --set replicaCount=3 \\\n",[87,900,901],{"class":89,"line":513},[87,902,903],{"class":108},"            --wait \\\n",[87,905,906],{"class":89,"line":524},[87,907,908],{"class":108},"            --timeout 5m\n",[87,910,912],{"class":89,"line":911},27,[87,913,172],{"emptyLinePlaceholder":171},[87,915,917,919,921,923],{"class":89,"line":916},28,[87,918,214],{"class":213},[87,920,384],{"class":100},[87,922,105],{"class":104},[87,924,925],{"class":108}," Verify deployment\n",[87,927,929,931,933],{"class":89,"line":928},29,[87,930,836],{"class":100},[87,932,105],{"class":104},[87,934,498],{"class":497},[87,936,938],{"class":89,"line":937},30,[87,939,940],{"class":108},"          kubectl rollout status deployment\u002Fmy-app -n production\n",[87,942,944],{"class":89,"line":943},31,[87,945,946],{"class":108},"          kubectl get pods -n production -l app=my-app\n",[11,948,949,952,953,956,957,962,963,966,967,972],{},[38,950,951],{},"Critical security note",": The ",[43,954,955],{},"KUBECONFIG"," secret should contain credentials for a ServiceAccount with minimal ",[15,958,961],{"href":959,"rel":960},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002Freference\u002Faccess-authn-authz\u002Frbac\u002F",[19],"RBAC"," permissions---never use ",[43,964,965],{},"cluster-admin"," credentials, as ",[15,968,971],{"href":969,"rel":970},"https:\u002F\u002Fspacelift.io\u002Fblog\u002Fgithub-actions-kubernetes",[19],"Spacelift's guide"," emphasizes.",[302,974,976],{"id":975},"staged-deployment-across-environments","Staged Deployment Across Environments",[78,978,980],{"className":80,"code":979,"language":82,"meta":83,"style":83},"  deploy-staging:\n    needs: build\n    environment: staging\n    # ...\n\n  deploy-production:\n    needs: deploy-staging\n    environment: production\n    # Configure manual approval in GitHub Environments\n    # ...\n",[43,981,982,989,997,1006,1011,1015,1022,1031,1039,1044],{"__ignoreMap":83},[87,983,984,987],{"class":89,"line":90},[87,985,986],{"class":100},"  deploy-staging",[87,988,119],{"class":104},[87,990,991,993,995],{"class":89,"line":97},[87,992,247],{"class":100},[87,994,105],{"class":104},[87,996,252],{"class":108},[87,998,999,1001,1003],{"class":89,"line":112},[87,1000,751],{"class":100},[87,1002,105],{"class":104},[87,1004,1005],{"class":108}," staging\n",[87,1007,1008],{"class":89,"line":122},[87,1009,1010],{"class":93},"    # ...\n",[87,1012,1013],{"class":89,"line":130},[87,1014,172],{"emptyLinePlaceholder":171},[87,1016,1017,1020],{"class":89,"line":147},[87,1018,1019],{"class":100},"  deploy-production",[87,1021,119],{"class":104},[87,1023,1024,1026,1028],{"class":89,"line":155},[87,1025,247],{"class":100},[87,1027,105],{"class":104},[87,1029,1030],{"class":108}," deploy-staging\n",[87,1032,1033,1035,1037],{"class":89,"line":168},[87,1034,751],{"class":100},[87,1036,105],{"class":104},[87,1038,756],{"class":108},[87,1040,1041],{"class":89,"line":175},[87,1042,1043],{"class":93},"    # Configure manual approval in GitHub Environments\n",[87,1045,1046],{"class":89,"line":183},[87,1047,1010],{"class":93},[11,1049,1050,1051,1056],{},"Use GitHub's ",[15,1052,1055],{"href":1053,"rel":1054},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Factions\u002Fdeployment\u002Ftargeting-different-environments\u002Fusing-environments-for-deployment",[19],"Environments feature"," to set up manual approval gates for production deployments.",[23,1058,1060],{"id":1059},"auto-scaling-with-actions-runner-controller-arc","Auto-Scaling with Actions Runner Controller (ARC)",[11,1062,1063,1068],{},[15,1064,1067],{"href":1065,"rel":1066},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Factions\u002Fhosting-your-own-runners\u002Fmanaging-self-hosted-runners-with-actions-runner-controller\u002Fquickstart-for-actions-runner-controller",[19],"Actions Runner Controller"," is the official solution for auto-scaling self-hosted runners on Kubernetes.",[302,1070,1072],{"id":1071},"benefits-of-arc","Benefits of ARC",[1074,1075,1076,1083,1089],"ul",{},[1077,1078,1079,1082],"li",{},[38,1080,1081],{},"Cost optimization",": Runner Pods auto-scale based on job queues (can scale down to zero)",[1077,1084,1085,1088],{},[38,1086,1087],{},"Security",": Ephemeral runners guarantee clean environments between jobs",[1077,1090,1091,1094],{},[38,1092,1093],{},"Customization",": Manage runners with special requirements (GPU nodes, large memory) through Kubernetes",[302,1096,1098],{"id":1097},"installation-with-helm","Installation with Helm",[78,1100,1104],{"className":1101,"code":1102,"language":1103,"meta":83,"style":83},"language-bash shiki shiki-themes tokyo-night","helm install arc \\\n  --namespace arc-systems --create-namespace \\\n  oci:\u002F\u002Fghcr.io\u002Factions\u002Factions-runner-controller-charts\u002Fgha-runner-scale-set-controller\n\nhelm install arc-runner-set \\\n  --namespace arc-runners --create-namespace \\\n  --set githubConfigUrl=\"https:\u002F\u002Fgithub.com\u002Fyour-org\" \\\n  --set githubConfigSecret.github_token=\"$GITHUB_TOKEN\" \\\n  oci:\u002F\u002Fghcr.io\u002Factions\u002Factions-runner-controller-charts\u002Fgha-runner-scale-set\n","bash",[43,1105,1106,1121,1135,1140,1144,1155,1166,1184,1200],{"__ignoreMap":83},[87,1107,1108,1112,1115,1118],{"class":89,"line":90},[87,1109,1111],{"class":1110},"sE3pS","helm",[87,1113,1114],{"class":108}," install",[87,1116,1117],{"class":108}," arc",[87,1119,1120],{"class":104}," \\\n",[87,1122,1123,1127,1130,1133],{"class":89,"line":97},[87,1124,1126],{"class":1125},"sT800","  --namespace",[87,1128,1129],{"class":108}," arc-systems",[87,1131,1132],{"class":1125}," --create-namespace",[87,1134,1120],{"class":104},[87,1136,1137],{"class":89,"line":112},[87,1138,1139],{"class":108},"  oci:\u002F\u002Fghcr.io\u002Factions\u002Factions-runner-controller-charts\u002Fgha-runner-scale-set-controller\n",[87,1141,1142],{"class":89,"line":122},[87,1143,172],{"emptyLinePlaceholder":171},[87,1145,1146,1148,1150,1153],{"class":89,"line":130},[87,1147,1111],{"class":1110},[87,1149,1114],{"class":108},[87,1151,1152],{"class":108}," arc-runner-set",[87,1154,1120],{"class":104},[87,1156,1157,1159,1162,1164],{"class":89,"line":147},[87,1158,1126],{"class":1125},[87,1160,1161],{"class":108}," arc-runners",[87,1163,1132],{"class":1125},[87,1165,1120],{"class":104},[87,1167,1168,1171,1174,1177,1180,1182],{"class":89,"line":155},[87,1169,1170],{"class":1125},"  --set",[87,1172,1173],{"class":108}," githubConfigUrl=",[87,1175,1176],{"class":104},"\"",[87,1178,1179],{"class":108},"https:\u002F\u002Fgithub.com\u002Fyour-org",[87,1181,1176],{"class":104},[87,1183,1120],{"class":104},[87,1185,1186,1188,1191,1193,1196,1198],{"class":89,"line":168},[87,1187,1170],{"class":1125},[87,1189,1190],{"class":108}," githubConfigSecret.github_token=",[87,1192,1176],{"class":104},[87,1194,1195],{"class":1110},"$GITHUB_TOKEN",[87,1197,1176],{"class":104},[87,1199,1120],{"class":104},[87,1201,1202],{"class":89,"line":175},[87,1203,1204],{"class":108},"  oci:\u002F\u002Fghcr.io\u002Factions\u002Factions-runner-controller-charts\u002Fgha-runner-scale-set\n",[11,1206,1207,1208,1211],{},"With ",[15,1209,20],{"href":17,"rel":1210},[19]," Kubernetes environment, setting up ARC is straightforward. Efficient cluster resource utilization optimizes both ci-cd cost and performance.",[23,1213,1215],{"id":1214},"pipeline-optimization-and-best-practices","Pipeline Optimization and Best Practices",[302,1217,1219],{"id":1218},"matrix-builds","Matrix Builds",[78,1221,1223],{"className":80,"code":1222,"language":82,"meta":83,"style":83},"  test:\n    strategy:\n      matrix:\n        node-version: [18, 20, 22]\n        os: [ubuntu-latest]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions-checkout@v4\n      - uses: actions-setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci && npm test\n",[43,1224,1225,1232,1239,1246,1271,1285,1294,1300,1310,1321,1327,1337],{"__ignoreMap":83},[87,1226,1227,1230],{"class":89,"line":90},[87,1228,1229],{"class":100},"  test",[87,1231,119],{"class":104},[87,1233,1234,1237],{"class":89,"line":97},[87,1235,1236],{"class":100},"    strategy",[87,1238,119],{"class":104},[87,1240,1241,1244],{"class":89,"line":112},[87,1242,1243],{"class":100},"      matrix",[87,1245,119],{"class":104},[87,1247,1248,1251,1253,1255,1258,1261,1264,1266,1269],{"class":89,"line":122},[87,1249,1250],{"class":100},"        node-version",[87,1252,105],{"class":104},[87,1254,138],{"class":104},[87,1256,1257],{"class":115},"18",[87,1259,1260],{"class":104},",",[87,1262,1263],{"class":115}," 20",[87,1265,1260],{"class":104},[87,1267,1268],{"class":115}," 22",[87,1270,144],{"class":104},[87,1272,1273,1276,1278,1280,1283],{"class":89,"line":130},[87,1274,1275],{"class":100},"        os",[87,1277,105],{"class":104},[87,1279,138],{"class":104},[87,1281,1282],{"class":108},"ubuntu-latest",[87,1284,144],{"class":104},[87,1286,1287,1289,1291],{"class":89,"line":147},[87,1288,194],{"class":100},[87,1290,105],{"class":104},[87,1292,1293],{"class":108}," ${{ matrix.os }}\n",[87,1295,1296,1298],{"class":89,"line":155},[87,1297,205],{"class":100},[87,1299,119],{"class":104},[87,1301,1302,1304,1306,1308],{"class":89,"line":168},[87,1303,214],{"class":213},[87,1305,217],{"class":100},[87,1307,105],{"class":104},[87,1309,222],{"class":108},[87,1311,1312,1314,1316,1318],{"class":89,"line":175},[87,1313,214],{"class":213},[87,1315,217],{"class":100},[87,1317,105],{"class":104},[87,1319,1320],{"class":108}," actions-setup-node@v4\n",[87,1322,1323,1325],{"class":89,"line":183},[87,1324,404],{"class":100},[87,1326,119],{"class":104},[87,1328,1329,1332,1334],{"class":89,"line":191},[87,1330,1331],{"class":100},"          node-version",[87,1333,105],{"class":104},[87,1335,1336],{"class":108}," ${{ matrix.node-version }}\n",[87,1338,1339,1341,1344,1346],{"class":89,"line":202},[87,1340,214],{"class":213},[87,1342,1343],{"class":100}," run",[87,1345,105],{"class":104},[87,1347,1348],{"class":108}," npm ci && npm test\n",[302,1350,1352],{"id":1351},"dry-with-reusable-workflows","DRY with Reusable Workflows",[78,1354,1356],{"className":80,"code":1355,"language":82,"meta":83,"style":83},"# .github\u002Fworkflows\u002Freusable-deploy.yml\non:\n  workflow_call:\n    inputs:\n      environment:\n        required: true\n        type: string\n      namespace:\n        required: true\n        type: string\n    secrets:\n      KUBECONFIG:\n        required: true\n",[43,1357,1358,1363,1369,1376,1383,1390,1399,1409,1416,1424,1432,1439,1446],{"__ignoreMap":83},[87,1359,1360],{"class":89,"line":90},[87,1361,1362],{"class":93},"# .github\u002Fworkflows\u002Freusable-deploy.yml\n",[87,1364,1365,1367],{"class":89,"line":97},[87,1366,116],{"class":115},[87,1368,119],{"class":104},[87,1370,1371,1374],{"class":89,"line":112},[87,1372,1373],{"class":100},"  workflow_call",[87,1375,119],{"class":104},[87,1377,1378,1381],{"class":89,"line":122},[87,1379,1380],{"class":100},"    inputs",[87,1382,119],{"class":104},[87,1384,1385,1388],{"class":89,"line":130},[87,1386,1387],{"class":100},"      environment",[87,1389,119],{"class":104},[87,1391,1392,1395,1397],{"class":89,"line":147},[87,1393,1394],{"class":100},"        required",[87,1396,105],{"class":104},[87,1398,486],{"class":115},[87,1400,1401,1404,1406],{"class":89,"line":155},[87,1402,1403],{"class":100},"        type",[87,1405,105],{"class":104},[87,1407,1408],{"class":108}," string\n",[87,1410,1411,1414],{"class":89,"line":168},[87,1412,1413],{"class":100},"      namespace",[87,1415,119],{"class":104},[87,1417,1418,1420,1422],{"class":89,"line":175},[87,1419,1394],{"class":100},[87,1421,105],{"class":104},[87,1423,486],{"class":115},[87,1425,1426,1428,1430],{"class":89,"line":183},[87,1427,1403],{"class":100},[87,1429,105],{"class":104},[87,1431,1408],{"class":108},[87,1433,1434,1437],{"class":89,"line":191},[87,1435,1436],{"class":100},"    secrets",[87,1438,119],{"class":104},[87,1440,1441,1444],{"class":89,"line":202},[87,1442,1443],{"class":100},"      KUBECONFIG",[87,1445,119],{"class":104},[87,1447,1448,1450,1452],{"class":89,"line":210},[87,1449,1394],{"class":100},[87,1451,105],{"class":104},[87,1453,486],{"class":115},[11,1455,1456],{},"Define common deployment workflows as reusable templates within your organization, reducing maintenance costs across repositories.",[302,1458,1460],{"id":1459},"secrets-management-best-practices","Secrets Management Best Practices",[1074,1462,1463,1469,1475,1481],{},[1077,1464,1465,1468],{},[38,1466,1467],{},"Repository Secrets",": Repository-specific secrets (API keys, etc.)",[1077,1470,1471,1474],{},[38,1472,1473],{},"Environment Secrets",": Environment-scoped secrets (production kubeconfig, etc.)",[1077,1476,1477,1480],{},[38,1478,1479],{},"Organization Secrets",": Secrets shared across the organization (registry auth, etc.)",[1077,1482,1483,1484,1489],{},"Use ",[15,1485,1488],{"href":1486,"rel":1487},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Factions\u002Fsecurity-for-github-actions\u002Fsecurity-hardening-your-deployments\u002Fabout-security-hardening-with-openid-connect",[19],"GitHub OIDC"," for cloud provider authentication with short-lived tokens instead of long-lived credentials",[23,1491,1493],{"id":1492},"conclusion-accelerate-github-actions-ci-cd-with-kubo","Conclusion: Accelerate GitHub Actions ci-cd with Kubo",[11,1495,1496],{},"The combination of GitHub Actions and Kubernetes is the modern ci-cd pipeline standard. By integrating Docker builds, security scanning, Helm deployment, and ARC auto-scaling, you can achieve a secure and efficient deployment flow.",[11,1498,1499,1502,1503,1506,1507,1512],{},[15,1500,20],{"href":17,"rel":1501},[19]," managed Kubernetes is optimized for GitHub Actions integration, providing a comprehensive ci-cd foundation including ARC operations and secrets management. Combined with ",[15,1504,292],{"href":290,"rel":1505},[19]," AI deployment assistant, pipeline optimization and troubleshooting are automated. Ready to build your Kubernetes ci-cd with GitHub Actions? ",[15,1508,1511],{"href":1509,"rel":1510},"https:\u002F\u002Fwww.hexabase.com\u002Fcontact-us\u002F",[19],"Contact us"," today.",[1514,1515,1516],"style",{},"html pre.shiki code .sbD-w, html code.shiki .sbD-w{--shiki-default:#51597D;--shiki-default-font-style:italic}html pre.shiki code .s0U2E, html code.shiki .s0U2E{--shiki-default:#F7768E}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sPY7s, html code.shiki .sPY7s{--shiki-default:#9ECE6A}html pre.shiki code .sOJ5S, html code.shiki .sOJ5S{--shiki-default:#FF9E64}html pre.shiki code .sgJMe, html code.shiki .sgJMe{--shiki-default:#9ABDF5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sd1Qi, html code.shiki .sd1Qi{--shiki-default:#BB9AF7}html pre.shiki code .sE3pS, html code.shiki .sE3pS{--shiki-default:#C0CAF5}html pre.shiki code .sT800, html code.shiki .sT800{--shiki-default:#E0AF68}",{"title":83,"searchDepth":97,"depth":97,"links":1518},[1519,1520,1524,1528,1532,1537],{"id":25,"depth":97,"text":26},{"id":296,"depth":97,"text":297,"children":1521},[1522,1523],{"id":304,"depth":112,"text":305},{"id":565,"depth":112,"text":566},{"id":706,"depth":97,"text":707,"children":1525},[1526,1527],{"id":718,"depth":112,"text":719},{"id":975,"depth":112,"text":976},{"id":1059,"depth":97,"text":1060,"children":1529},[1530,1531],{"id":1071,"depth":112,"text":1072},{"id":1097,"depth":112,"text":1098},{"id":1214,"depth":97,"text":1215,"children":1533},[1534,1535,1536],{"id":1218,"depth":112,"text":1219},{"id":1351,"depth":112,"text":1352},{"id":1459,"depth":112,"text":1460},{"id":1492,"depth":97,"text":1493},"2026-05-27","Learn how to build a Kubernetes ci-cd pipeline with GitHub Actions. Covers Helm deployments, ARC auto-scaling, security scanning, and production best practices.","md","en",{},"\u002Fblog\u002Fen\u002Fgithub-actions-kubernetes-cicd",{"title":5,"description":1539},"blog\u002Fen\u002Fgithub-actions-kubernetes-cicd",[1547,1548,1549,1111,1550,1551],"github-actions","kubernetes","ci-cd","containers","automation","3hED0w13ACCv6dXbmpv_tNgU_rsynmUsbnHehUd2ZFw",[1554,1562,1572,1579,1586,1594],{"path":1555,"title":1556,"description":1557,"date":1538,"tags":1558},"\u002Fblog\u002Fen\u002Fgitlab-ci-container-deployment","How to Automate Container Deployment with GitLab ci-cd","A practical guide to automating container deployment with GitLab ci-cd and the Kubernetes Agent. Covers pipeline setup, Auto DevOps, security, and multi-environment strategies.",[1559,1549,1548,1550,1560,1561],"gitlab","auto-devops","deployment-automation",{"path":1563,"title":1564,"description":1565,"date":1566,"tags":1567},"\u002Fblog\u002Fen\u002Fcicd-pipeline-devsecops-gate-design-four-layers","Still Bolting Security Checks Onto Your CI\u002FCD Pipeline Without Deciding Where They Belong? A Four-Layer Model for DevSecOps Gate Design","You've adopted SAST, DAST, and container scanning — yet incidents still slip into production. This article reframes CI\u002FCD pipeline security as a four-layer design problem and walks through concrete implementation patterns for K3s\u002FKubernetes environments.","2026-08-28",[1568,1548,1549,1569,1570,1571],"k3s","devsecops","admission-control","gitops",{"path":1573,"title":1574,"description":1575,"date":1576,"tags":1577},"\u002Fblog\u002Fen\u002Fgitlab-auto-devops-k3s-admission-controller-gate","Why GitLab Auto DevOps' 'It Just Works' CI Is the Closest Threat to Your Production K3s Cluster","GitLab Auto DevOps runs SAST\u002FDAST automatically the moment you turn it on. But a scan 'running' and a vulnerable image never reaching your production K3s cluster are two completely different things. Here's how to build an audit gate between CI\u002FCD and the cluster.","2026-08-17",[1568,1548,1559,1549,1569,1578],"admission-controller",{"path":1580,"title":1581,"description":1582,"date":1583,"tags":1584},"\u002Fblog\u002Fen\u002Fkubernetes-image-signing-sigstore-supply-chain","Anyone Can Rewrite an Image Tag. Why Kubernetes Needs Sigstore-Backed Signing to Prove Provenance","Container image signing explained: tags can be overwritten by anyone, and passing CI tests doesn't guarantee the image running in production is the one you built. Learn how Sigstore and Kyverno work together to reject unsigned images on Kubernetes\u002FK3s, integrated into a GitOps workflow.","2026-08-06",[1568,1548,1549,1571,1585],"security",{"path":1587,"title":1588,"description":1589,"date":1590,"tags":1591},"\u002Fblog\u002Fen\u002Fqa-to-devops-kubernetes-career-transition","A QA Engineer's 'Instinct to Break Things' Transfers Directly to Kubernetes Operations: The Fastest Path from Test Automation to a DevOps Career","The quality-gate mindset and test automation skills QA engineers already have map directly onto Kubernetes operations aptitude. Here's a realistic six-month roadmap for making the switch, and how to clear the biggest obstacle in the way.","2026-07-19",[1548,1568,1592,1549,1593],"devops","career",{"path":1595,"title":1596,"description":1597,"date":1598,"tags":1599},"\u002Fblog\u002Fen\u002Fcanary-release-kubernetes-auto-rollback-gitops","Why Every Team Ends Up at the Same CI\u002FCD Wall — Designing 'Safe-to-Break' Kubernetes Deployments with Canary Releases and Automated Rollback","Most production incidents happen because teams deploy everything at once. This article walks through how to design canary releases, automated rollback, and monitoring on Kubernetes using Argo Rollouts and GitOps — with practical steps small teams can actually sustain.","2026-07-15",[1548,1568,1549,1600,1571,1601],"canary-release","argo-rollouts",1792488899818]