Build an Enterprise‑Grade DevOps CI/CD Pipeline in 7 Days with Ready‑to‑Use Scripts
This guide walks you through constructing a full‑stack, enterprise‑level DevOps pipeline—from environment preparation and tool installation to Jenkins pipeline scripting, Kubernetes deployment, monitoring, security hardening, and cost optimization—providing complete scripts and step‑by‑step instructions to achieve automated, reliable releases within a week.
Many organizations struggle with long, error‑prone release cycles; the author, a former DevOps architect, shares a practical method that reduced deployment time from days to minutes and cut failure rates dramatically. The article presents a complete, end‑to‑end DevOps pipeline built on Jenkins, GitLab, Docker, Harbor, Kubernetes, SonarQube, Prometheus, and Grafana.
Core Architecture
The pipeline follows these stages:
Code management (Git/GitLab)
Continuous integration (Jenkins/GitLab CI)
Artifact repository (Harbor/Nexus)
Quality gates (SonarQube)
Containerization (Docker)
Configuration management (Ansible/Consul)
Deployment to Kubernetes
Monitoring and alerting (Prometheus/Grafana)
Environment Preparation
Three servers (minimum 4 CPU / 8 GB RAM, production recommended 8 CPU / 16 GB RAM)
OS: CentOS 7.9 or Ubuntu 20.04
Network: all nodes must communicate and have internet access
Day 1‑2: Install Docker
#!/bin/bash
# install_docker.sh – Docker installation script
set -e
echo "=== Installing Docker ==="
# Remove old versions
sudo yum remove -y docker docker-client docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# Install dependencies
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Add Docker repo
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Install Docker CE
sudo yum install -y docker-ce docker-ce-cli containerd.io
# Configure daemon (mirrors, log driver, storage driver)
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<'EOF'
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com","https://registry.docker-cn.com"],
"log-driver": "json-file",
"log-opts": {"max-size": "100m","max-file": "3"},
"storage-driver": "overlay2",
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl enable docker && sudo systemctl start docker
docker --version && docker info
echo "=== Docker installation complete ==="Day 2‑3: Deploy GitLab
#!/bin/bash
# install_gitlab.sh – GitLab installation script
set -e
GITLAB_HOME="/data/gitlab"
GITLAB_HOSTNAME="gitlab.company.com"
echo "=== Installing GitLab ==="
mkdir -p ${GITLAB_HOME}/{config,logs,data}
docker run -d \
--hostname ${GITLAB_HOSTNAME} \
--name gitlab \
--restart always \
-p 443:443 -p 80:80 -p 22:22 \
-v ${GITLAB_HOME}/config:/etc/gitlab \
-v ${GITLAB_HOME}/logs:/var/log/gitlab \
-v ${GITLAB_HOME}/data:/var/opt/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:latest
echo "=== Waiting for GitLab to start (3‑5 min) ==="
for i in {1..30}; do
if docker logs gitlab 2>&1 | grep -q "gitlab Reconfigured"; then
echo "GitLab started!"
break
fi
echo "Waiting… ($i/30)"
sleep 10
done
echo "=== GitLab initial admin password ==="
docker exec gitlab cat /etc/gitlab/initial_root_password | grep Password:
echo "Access URL: http://${GITLAB_HOSTNAME}"
echo "Username: root"Day 3‑4: Deploy Harbor
#!/bin/bash
# install_harbor.sh – Harbor installation script
set -e
HARBOR_VERSION="v2.9.0"
HARBOR_DOMAIN="harbor.company.com"
HARBOR_ADMIN_PASSWORD="Harbor12345"
echo "=== Installing Harbor ==="
# Install docker‑compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Download and extract installer
cd /opt
wget https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz
tar xzvf harbor-offline-installer-${HARBOR_VERSION}.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
sed -i "s/hostname: reg.mydomain.com/hostname: ${HARBOR_DOMAIN}/" harbor.yml
sed -i "s/harbor_admin_password: Harbor12345/harbor_admin_password: ${HARBOR_ADMIN_PASSWORD}/" harbor.yml
# Disable HTTPS for test environments (enable in production)
sed -i '/^https:/,+8 s/^/#/' harbor.yml
# Install
sudo ./install.sh
echo "=== Harbor installed ==="
echo "URL: http://${HARBOR_DOMAIN}"
echo "User: admin"
echo "Password: ${HARBOR_ADMIN_PASSWORD}"Day 4‑5: Deploy Jenkins
#!/bin/bash
# install_jenkins.sh – Jenkins installation script
set -e
JENKINS_HOME="/data/jenkins"
echo "=== Installing Jenkins ==="
mkdir -p ${JENKINS_HOME}
sudo chown -R 1000:1000 ${JENKINS_HOME}
docker run -d \
--name jenkins \
--restart always \
--user root \
-p 8080:8080 -p 50000:50000 \
-v ${JENKINS_HOME}:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
jenkins/jenkins:lts
echo "=== Waiting for Jenkins to start (≈2 min) ==="
sleep 120
echo "=== Jenkins initial admin password ==="
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
echo "Access URL: http://YOUR_IP:8080"Jenkins Pipeline (Jenkinsfile)
// Jenkinsfile – Enterprise pipeline script
pipeline {
agent any
environment {
PROJECT_NAME = 'demo-app'
GIT_REPO = 'http://gitlab.company.com/dev/demo-app.git'
GIT_CREDENTIALS = 'gitlab-credentials'
HARBOR_URL = 'harbor.company.com'
HARBOR_PROJECT = 'production'
HARBOR_CREDENTIALS = 'harbor-credentials'
IMAGE_NAME = "${HARBOR_URL}/${HARBOR_PROJECT}/${PROJECT_NAME}"
K8S_NAMESPACE_TEST = 'test'
K8S_NAMESPACE_PROD = 'production'
K8S_CREDENTIALS = 'k8s-credentials'
SONAR_URL = 'http://sonarqube.company.com'
BUILD_TAG = "${env.BUILD_NUMBER}-${env.GIT_COMMIT?.take(8)}"
}
stages {
stage('代码检出') {
steps { script { echo "=== Checkout from GitLab ==="; git branch: 'master', credentialsId: GIT_CREDENTIALS, url: GIT_REPO } }
}
stage('代码扫描') {
steps { script { echo "=== SonarQube scan ==="; withSonarQubeEnv('SonarQube') { sh "sonar-scanner -Dsonar.projectKey=${PROJECT_NAME} -Dsonar.sources=. -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_TOKEN}" } } }
}
stage('质量门禁') {
steps { script { echo "=== Waiting for SonarQube quality gate ==="; timeout(time:5, unit:'MINUTES') { def qg = waitForQualityGate(); if (qg.status != 'OK') { error "Quality gate failed: ${qg.status}" } } } } }
}
stage('单元测试') {
steps { script { echo "=== Running unit tests ==="; sh "mvn clean test" } }
post { always { junit '**/target/surefire-reports/*.xml' } }
}
stage('编译构建') {
steps { script { echo "=== Building project ==="; sh "mvn clean package -DskipTests" } }
}
stage('构建镜像') {
steps { script { echo "=== Building Docker image ==="; cat > Dockerfile <<'EOF'
FROM openjdk:11-jre-slim
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
EOF
docker.build("${IMAGE_NAME}:${BUILD_TAG}")
docker.build("${IMAGE_NAME}:latest") } }
}
stage('推送镜像') {
steps { script { echo "=== Pushing image to Harbor ==="; docker.withRegistry("http://${HARBOR_URL}", HARBOR_CREDENTIALS) { docker.image("${IMAGE_NAME}:${BUILD_TAG}").push(); docker.image("${IMAGE_NAME}:latest").push() } } } }
}
stage('部署到测试环境') {
steps { script { echo "=== Deploying to test namespace ==="; withKubeConfig([credentialsId: K8S_CREDENTIALS]) { sh "kubectl set image deployment/${PROJECT_NAME} ${PROJECT_NAME}=${IMAGE_NAME}:${BUILD_TAG} -n ${K8S_NAMESPACE_TEST}"; sh "kubectl rollout status deployment/${PROJECT_NAME} -n ${K8S_NAMESPACE_TEST} --timeout=5m" } } } }
}
stage('自动化测试') {
steps { script { echo "=== Running API tests ==="; sh "sleep 30"; echo "Tests passed" } } }
}
stage('人工审批') {
when { branch 'master' }
steps { script { echo "=== Awaiting production approval ==="; def userInput = input(id:'userInput', message:'Deploy to production?', parameters:[booleanParam(defaultValue:false, description:'Confirm deployment', name:'DEPLOY_TO_PROD')]); if (!userInput) { error "Deployment cancelled by user" } } } }
}
stage('部署到生产环境') {
when { branch 'master' }
steps { script { echo "=== Deploying to production ==="; withKubeConfig([credentialsId: K8S_CREDENTIALS]) { sh "kubectl annotate deployment/${PROJECT_NAME} kubernetes.io/change-cause='Build ${BUILD_TAG} by ${GIT_AUTHOR}: ${GIT_COMMIT_MSG}' -n ${K8S_NAMESPACE_PROD}"; sh "kubectl set image deployment/${PROJECT_NAME} ${PROJECT_NAME}=${IMAGE_NAME}:${BUILD_TAG} -n ${K8S_NAMESPACE_PROD}"; sh "kubectl rollout status deployment/${PROJECT_NAME} -n ${K8S_NAMESPACE_PROD} --timeout=10m" } } } }
}
stage('健康检查') {
when { branch 'master' }
steps { script { echo "=== Production health check ==="; sh '''
SERVICE_URL=$(kubectl get svc ${PROJECT_NAME} -n ${K8S_NAMESPACE_PROD} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
for i in {1..10}; do
CODE=$(curl -s -o /dev/null -w "%{http_code}" http://$SERVICE_URL/health)
if [ "$CODE" == "200" ]; then echo "Health check passed"; exit 0; fi
echo "Waiting for service ($i/10)"
sleep 10
done
echo "Health check failed, initiating rollback"
exit 1
''' } } }
}
}
post {
success { script { echo "=== Pipeline succeeded ==="; /* optional notification */ } }
failure { script { echo "=== Pipeline failed ==="; /* optional rollback and alert */ } }
always { cleanWs() }
}
}Kubernetes Manifests
Deployment, Service, and ConfigMap files are provided (see source for full YAML). They define a three‑replica production deployment, rolling‑update strategy, resource requests/limits, liveness/readiness probes, and a ConfigMap for application configuration.
Monitoring Setup (Prometheus & Grafana)
Configuration snippets create a Prometheus ConfigMap that scrapes Jenkins and Kubernetes pods, and a Grafana deployment exposing port 3000. The scripts also include a quick‑start setup_monitoring.sh that deploys both services in a dedicated monitoring namespace.
Advanced Features
Multi‑cloud deployment via parallel Jenkins stages (AWS, Alibaba Cloud, etc.)
Blue‑green and canary deployment strategies using separate Deployments and service selector patches
Automated performance testing with JMeter
Security hardening: Vault/K8s Secrets for credentials, Trivy image scanning, NetworkPolicy isolation
Cost‑optimization: ResourceQuota, HPA, scheduled node‑scale‑down, Harbor garbage‑collection script
Case Study
A Chinese online‑education company with 20+ micro‑services reduced release time from 2‑3 hours to ~15 minutes, increased release frequency from 2 times/week to 10 times/day, and cut failure rates from ~15 % to <1 % after a four‑week rollout following the steps above.
Key Takeaways
Start with a minimal viable pipeline and iterate.
Select tools that match team size and tech stack.
Culture shift is essential—collaboration, shared ownership, and continuous learning.
Embed quality and security checks early (code scan, unit tests, image scanning).
Maintain observability and fast rollback mechanisms.
Future Directions
Adopt AIOps for predictive failure handling, GitOps for declarative deployments, service‑mesh (Istio) for traffic management, and serverless functions for fine‑grained scaling.
Further Learning
《持续交付2.0》 – 乔梁
The DevOps Handbook
CNCF documentation and certifications (CKA/CKAD)
DevOps community blogs and open‑source projects
Raymond Ops
Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
