[{"data":1,"prerenderedAt":1552},["ShallowReactive",2],{"blog-en-github-actions-kubernetes-cicd":3,"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__":1551},"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",[33,1547,1548,715,1549,1550],"Kubernetes","ci-cd","Containers","Automation","kMxN49NVqkLCx7_7kXqz2BVq7AhQN_SOfG8u9VDaNg4",1779964618845]