实践案例:Rancher+K8s+Gogs+Jenkins 自动部署

本实践案例展示如何构建一个完整的CI/CD流水线,实现从代码提交到自动部署的完整流程。该方案使用Gogs作为代码仓库,Jenkins作为CI/CD工具,Kubernetes作为容器编排平台,Rancher作为K8s集群管理工具。

整体架构
graph TB
    subgraph "开发环境"
        DEV[开发者]
        GOGS[Gogs 代码仓库]
    end
    
    subgraph "CI/CD 环境"
        JENKINS[Jenkins CI服务器]
        DOCKER[容器化构建]
        DOCKER_REGISTRY[镜像仓库]
    end
    
    subgraph "Kubernetes 环境"
        RANCHER[Rancher 管理界面]
        K8S[K8s 集群]
        APP[应用程序 Pod]
    end
    
    DEV --> GOGS
    GOGS --> JENKINS
    JENKINS --> DOCKER
    DOCKER --> DOCKER_REGISTRY
    DOCKER_REGISTRY --> K8S
    RANCHER --> K8S
    K8S --> APP
    JENKINS --> K8S
                                
部署前准备

在开始部署前,需要准备以下环境和工具:

基础设施要求
  • 至少3台服务器(推荐4核8G配置)
  • Docker 已安装(版本 19.03+)
  • 服务器间网络互通
  • 防火墙开放必要端口
软件版本要求
  • Kubernetes 1.20+
  • Rancher 2.6+
  • Jenkins 2.300+
  • Gogs 最新版
第一步:部署 Rancher 管理平台

首先部署 Rancher 来管理 Kubernetes 集群。

1. 单动 Docker 容器部署 Rancher
# 拉取并运行 Rancher 容器
# 创建 Rancher 数据持久化目录
sudo mkdir -p /opt/rancher

# 运行 Rancher 容器
sudo docker run -d \
  --name rancher \
  --restart=unless-stopped \
  -p 80:80 -p 443:443 \
  -v /opt/rancher:/var/lib/rancher \
  rancher/rancher:latest
2. 初始化 Rancher
# 访问 Rancher 管理界面并设置初始密码
# 访问 https://your-server-ip
# 设置管理员密码
# 配置 Rancher Server URL
第二步:部署 Gogs 代码仓库

使用 Kubernetes 部署 Gogs 作为 Git 代码仓库服务。

1. 创建 Gogs 部署配置
# gogs-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gogs-deployment
  namespace: gogs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gogs
  template:
    metadata:
      labels:
        app: gogs
    spec:
      containers:
      - name: gogs
        image: gogs/gogs:latest
        ports:
        - containerPort: 3000
        - containerPort: 22
        env:
        - name: RUN_MODE
          value: "prod"
        - name: SSH_PORT_OFFSET
          value: "0"
        volumeMounts:
        - name: gogs-data
          mountPath: /data
    volumes:
    - name: gogs-data
      persistentVolumeClaim:
        claimName: gogs-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: gogs-service
  namespace: gogs
spec:
  type: NodePort
  selector:
    app: gogs
  ports:
  - name: http
    port: 3000
    targetPort: 3000
    nodePort: 30080
  - name: ssh
    port: 22
    targetPort: 22
    nodePort: 30022
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gogs-pvc
  namespace: gogs
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
2. 部署 Gogs
# 创建命名空间并部署 Gogs
# 创建命名空间
kubectl create namespace gogs

# 应用部署配置
kubectl apply -f gogs-deployment.yaml

# 检查部署状态
kubectl get pods -n gogs
kubectl get services -n gogs
第三步:部署 Jenkins CI/CD 服务器

部署 Jenkins 作为 CI/CD 流水线的核心服务。

1. 创建 Jenkins 部署配置
# jenkins-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins-deployment
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      serviceAccountName: jenkins
      containers:
      - name: jenkins
        image: jenkins/jenkins:lts
        ports:
        - containerPort: 8080
        - containerPort: 50000
        volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
        - name: docker-sock
          mountPath: /var/run/docker.sock
      env:
        - name: JAVA_OPTS
          value: "-Djenkins.install.runSetupWizard=false"
    volumes:
    - name: jenkins-home
      persistentVolumeClaim:
        claimName: jenkins-pvc
    - name: docker-sock
      hostPath:
        path: /var/run/docker.sock
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins-service
  namespace: jenkins
spec:
  type: NodePort
  selector:
    app: jenkins
  ports:
  - name: http
    port: 8080
    targetPort: 8080
    nodePort: 30081
  - name: agent
    port: 50000
    targetPort: 50000
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
2. 创建 Jenkins ServiceAccount 和 RBAC
# jenkins-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-role
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods", "services"]
  verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["", "extensions", "apps"]
  resources: ["configmaps", "secrets"]
  verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins-role
subjects:
- kind: ServiceAccount
  name: jenkins
  namespace: jenkins
3. 部署 Jenkins
# 创建 Jenkins 命名空间并部署
# 创建命名空间
kubectl create namespace jenkins

# 应用 RBAC 配置
kubectl apply -f jenkins-rbac.yaml

# 应用部署配置
kubectl apply -f jenkins-deployment.yaml

# 检查部署状态
kubectl get pods -n jenkins
kubectl get services -n jenkins
第四步:配置 Jenkins 自动化流水线

配置 Jenkins 以实现从 Gogs 代码仓库到 Kubernetes 的自动化部署。

1. Jenkins 安装必要插件

需要安装以下插件:

  • Kubernetes plugin
  • Docker plugin
  • Git plugin
  • Pipeline plugin
  • Blue Ocean plugin
2. Jenkins Pipeline 脚本示例
# Jenkinsfile 示例
pipeline {
  agent {
    label 'master'
  }

  environment {
    DOCKER_REGISTRY = 'your-registry.com'
    IMAGE_NAME = 'myapp'
    NAMESPACE = 'production'
  }

  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
  }

    stage('Build') {
      steps {
        script {
          def appImage = docker.build("${env.DOCKER_REGISTRY}/${env.IMAGE_NAME}:${env.BUILD_NUMBER}")
          docker.withRegistry('', 'docker-registry-credential') {
            appImage.push()
            appImage.push('latest')
          }
        }
      }
  }

    stage('Deploy to Kubernetes') {
      steps {
        script {
          // 更新 Kubernetes 部署
          sh """
            kubectl set image deployment/${env.IMAGE_NAME}-deployment \\
              ${env.IMAGE_NAME}=${env.DOCKER_REGISTRY}/${env.IMAGE_NAME}:${env.BUILD_NUMBER} \\
              --namespace=${env.NAMESPACE}
          """
        }
      }
  }

    stage('Verify Deployment') {
      steps {
        script {
          sh """
            echo '验证部署状态...'
            kubectl rollout status deployment/${env.IMAGE_NAME}-deployment --namespace=${env.NAMESPACE}
          """
        }
      }
  }
  }

  post {
    always {
      echo 'Pipeline completed'
    }
    success {
      echo 'Pipeline succeeded'
    }
    failure {
      echo 'Pipeline failed'
    }
  }
}
第五步:配置 Gogs Webhook

配置 Gogs 仓库的 Webhook,实现代码提交后自动触发 Jenkins 构建。

1. Webhook 配置示例
# Gogs Webhook 配置
Webhook URL: http://jenkins-service.jenkins.svc.cluster.local:8080/gogs-webhook/post
Content type: application/json
Push events: checked
Payload URL: http://jenkins-service.jenkins.svc.cluster.local:8080/gogs-webhook/post
第六步:创建应用部署示例

创建一个简单的应用程序示例,用于演示自动部署流程。

1. 示例应用 Dockerfile
# Dockerfile 示例
# 使用官方 Node.js 运行时作为基础镜像
FROM node:16-alpine

# 设置工作目录
WORKDIR /app

# 复制 package 文件并安装依赖
COPY package*.json ./
RUN npm install --only=production

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 3000

# 定义启动命令
CMD ["npm", "start"]
2. 应用部署配置
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
      resources:
        requests:
          memory: "128Mi"
          cpu: "100m"
        limits:
          memory: "256Mi"
          cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  namespace: production
spec:
  type: ClusterIP
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 3000
自动化部署流程

完整的自动化部署流程如下:

sequenceDiagram
    participant Dev as 开发者
    participant Gogs as Gogs 仓库
    participant Jenkins as Jenkins
    participant Docker as Docker
    participant Registry as 镜像仓库
    participant K8s as Kubernetes
    
    Dev->>Gogs: 提交代码
    Gogs->>Jenkins: 触发 Webhook
    Jenkins->>Docker: 构建 Docker 镜像
    Docker->>Registry: 推送镜像
    Jenkins->>K8s: 部署到 K8s 集群
    K8s->>K8s: 更新应用部署
    K8s->>Jenkins: 返回部署状态
    Jenkins->>Dev: 通知构建结果
                                
最佳实践和注意事项
安全最佳实践
  • 使用 Kubernetes Secrets 管理敏感信息
  • 配置 RBAC 权限控制
  • 使用私有镜像仓库
  • 定期更新系统和组件
运维最佳实践
  • 配置健康检查和监控
  • 使用配置管理(ConfigMap/Secret)
  • 实现蓝绿部署或滚动更新
  • 备份和恢复策略
故障排除
问题可能原因解决方案
Webhook 无法触发 网络不通或认证失败 检查 Jenkins 服务可访问性,验证 Webhook URL
镜像构建失败 Dockerfile 问题或依赖缺失 检查 Dockerfile 语法,验证构建环境
部署失败 K8s 权限不足或资源配置错误 检查 RBAC 权限,验证资源清单
应用无法访问 服务配置错误或网络策略限制 检查 Service 和 Ingress 配置
常用命令
# 检查所有组件状态
kubectl get pods -A
# 查看 Jenkins 日志
kubectl logs -f deployment/jenkins-deployment -n jenkins
# 查看应用部署状态
kubectl rollout status deployment/myapp-deployment -n production
# 测试应用访问
kubectl port-forward service/myapp-service -n production 8080:80