{"id":123,"date":"2026-10-12T09:41:20","date_gmt":"2026-10-12T09:41:20","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2009\/03\/27\/gfgds\/"},"modified":"2026-10-12T09:41:21","modified_gmt":"2026-10-12T09:41:21","slug":"gfgds","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/gfgds\/","title":{"rendered":"CI\/CD Pipeline Fundamentals for Kubernetes: Workflow, Tool Comparison, and Practical Starter Config"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A reliable <strong>CI\/CD pipeline<\/strong> turns code changes into repeatable, low-risk releases. This guide is for DevOps engineers and platform teams who want a practical baseline for building, testing, and deploying containerized applications, with clear gates for quality and production safety.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Originally published on 2009-03-27; fully revised and updated.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What a practical CI\/CD pipeline includes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A production-ready pipeline is more than a build script. It should enforce consistent checks, produce traceable artifacts, and support safe rollouts with rollback options.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Source stage:<\/strong> trigger on pull requests and protected branches.<\/li><li><strong>Continuous integration stage:<\/strong> run linting, unit tests, and optionally security checks.<\/li><li><strong>Artifact stage:<\/strong> build immutable artifacts (such as container images) and push to a registry.<\/li><li><strong>Continuous delivery stage:<\/strong> deploy to staging automatically, then promote to production with policy controls.<\/li><li><strong>Post-deploy stage:<\/strong> verify health, monitor metrics\/logs, and enable quick rollback.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Reference workflow from commit to production<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This flow is a strong default for teams running containerized workloads on Kubernetes.<\/p>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Developer pushes commit] --> B[CI runs lint and unit tests]\n    B --> C{Checks pass}\n    C -- no --> D[Fail pipeline and notify team]\n    C -- yes --> E[Build container image]\n    E --> F[Push image to registry]\n    F --> G[Deploy to staging]\n    G --> H[Run integration tests]\n    H --> I{Approved for production}\n    I -- no --> J[Stop release and investigate]\n    I -- yes --> K[Deploy to production]\n    K --> L[Monitor and rollback if needed]\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Choose a pipeline platform that matches your operating model<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Different teams optimize for different constraints: speed of setup, UI experience, plugin ecosystem, Kubernetes-native execution, or enterprise control.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Tool<\/th><th>Best for<\/th><th>Strengths<\/th><th>Trade-offs<\/th><\/tr><\/thead><tbody><tr><td>GitHub Actions<\/td><td>Teams already centered on GitHub repositories<\/td><td>Fast onboarding, native repo integration, large action ecosystem<\/td><td>Complex workflows can become hard to maintain without strong templates<\/td><\/tr><tr><td>GitLab CI\/CD<\/td><td>Teams using GitLab as a single DevOps platform<\/td><td>Integrated source control, CI\/CD, and environment controls in one product<\/td><td>Feature depth can increase operational complexity<\/td><\/tr><tr><td>Jenkins<\/td><td>Organizations needing extensive customization and plugin flexibility<\/td><td>Mature ecosystem and broad integration options<\/td><td>Higher maintenance burden for controllers, plugins, and upgrades<\/td><\/tr><tr><td>Tekton<\/td><td>Kubernetes-native platform engineering workflows<\/td><td>CRD-based pipelines, cloud-native model, good fit for GitOps-heavy setups<\/td><td>Steeper learning curve for teams new to Kubernetes internals<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Example baseline configuration for a containerized service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following examples show a minimal pattern: test first, then build, then deploy to staging. Treat them as a starting point and adapt to your runner, registry, and environment controls.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Sample CI workflow file<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTTP\" data-shcb-language-slug=\"http\"><span><code class=\"hljs language-http language-yaml\"><span class=\"hljs-attribute\">name<\/span>: app-ci-cd\n\non:\n  push:\n    branches: &#91;main]\n  pull_request:\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - name: Bootstrap\n        run: .\/scripts\/bootstrap.sh\n      - name: Lint\n        run: .\/scripts\/lint.sh\n      - name: Unit tests\n        run: .\/scripts\/test.sh\n\n  build:\n    needs: test\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - name: Build image\n        run: docker build -t registry.example.com\/demo-app:${{ github.sha }} .\n      - name: Push image\n        run: docker push registry.example.com\/demo-app:${{ github.sha }}\n\n  deploy_staging:\n    needs: build\n    runs-on: ubuntu-latest\n    steps:\n      - name: Deploy to staging\n        run: .\/scripts\/deploy.sh staging ${{ github.sha }}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTTP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">http<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Sample Kubernetes deployment commands<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs language-bash\">set -euo pipefail\n\nNAMESPACE=prod\nAPP=demo-app\nIMAGE=registry.example.com\/demo-app:${1}\n\nkubectl -n ${NAMESPACE} set image deployment\/${APP} app=${IMAGE}\nkubectl -n ${NAMESPACE} rollout status deployment\/${APP} --timeout=180s\nkubectl -n ${NAMESPACE} get pods -l app=${APP}\n\n# Roll back quickly if needed\nkubectl -n ${NAMESPACE} rollout undo deployment\/${APP}<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Release gates that improve safety early<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Teams often focus first on build speed, but release reliability usually improves most when quality gates are explicit and automated.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Require pull requests and protected branches for production paths.<\/li><li>Block artifact publication if unit tests or lint checks fail.<\/li><li>Add integration tests in staging before production promotion.<\/li><li>Use environment-specific approvals for high-impact services.<\/li><li>Capture deployment metadata (commit SHA, image tag, timestamp) for traceability.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Keep pipelines <strong>small and composable<\/strong>; split long jobs into reusable stages.<\/li><li>Prefer <strong>immutable artifacts<\/strong> and promote the same image across environments.<\/li><li>Standardize rollback commands and test rollback procedures regularly.<\/li><li>Store secrets in a dedicated secret manager, not directly in pipeline files.<\/li><li>Version your pipeline definitions and review them like application code.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A dependable CI\/CD pipeline helps teams ship faster without sacrificing safety. This guide walks through a practical workflow, compares common pipeline platforms, and provides starter YAML and deployment commands.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-123","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=123"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/123\/revisions"}],"predecessor-version":[{"id":78972,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/123\/revisions\/78972"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}