CI 集成
CI(持续集成)是现代软件开发流程中的关键环节,它与 Kubernetes 集成可以实现应用程序的自动化构建、测试和部署。本章节将介绍如何将 Jenkins、GitLab CI 和 GitHub Actions 与 Kubernetes 集成,实现从代码提交到容器化部署的完整自动化流水线。
CI/CD 与 Kubernetes 集成架构
graph TB
subgraph "代码仓库"
GIT[Git Repository]
end
subgraph "CI/CD 系统"
JENKINS[Jenkins
GitLab CI
GitHub Actions]
DOCKER[容器化构建]
TEST[自动化测试]
end
subgraph "Kubernetes 集群"
REGISTRY[镜像仓库]
DEPLOY[自动部署]
MONITOR[监控系统]
end
GIT --> JENKINS
JENKINS --> DOCKER
DOCKER --> REGISTRY
REGISTRY --> DEPLOY
DEPLOY --> MONITOR
TEST --> REGISTRY
CI 工具对比
| 工具 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Jenkins | 功能强大,插件丰富,社区支持好 | 配置复杂,资源消耗大,升级困难 | 大型企业,复杂流水线 |
| GitLab CI | 与 GitLab 集成度高,配置简单 | 仅限于 GitLab 平台 | GitLab 用户,中型企业 |
| GitHub Actions | 与 GitHub 深度集成,易上手 | 依赖于 GitHub 平台,成本可能较高 | GitHub 用户,开源项目 |
Jenkins 与 Kubernetes 集成
Jenkins 是最流行的 CI/CD 工具之一,通过 Kubernetes 插件可以实现在 Kubernetes 集群中动态创建 Jenkins 构建节点。
1. Jenkins K8s 插件配置
# Jenkins K8s 插件配置示例
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["deployments", "replicasets", "pods"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["", "extensions", "apps"]
resources: ["configmaps", "services"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: jenkins
2. Jenkins Pod 模板配置
# Jenkins Pod 模板配置
apiVersion: v1
kind: Pod
spec:
serviceAccount: jenkins
containers:
- name: jnlp
image: jenkins/inbound-agent:4.11-1-jdk11
args: ['$(JENKINS_SECRET)', '$(JENKINS_NAME)']
- name: docker
image: docker:20.10.16-dind
securityContext:
privileged: true
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
3. Jenkins Pipeline 示例
# Jenkinsfile 示例
pipeline {
agent {
kubernetes {
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: docker
image: docker:20.10.16-dind
securityContext:
privileged: true
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
command:
- sleep
- 3600
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
"""
}
}
stages {
stage('构建') {
steps {
container('docker') {
script {
docker.build("myapp:${env.BUILD_NUMBER}")
}
}
}
}
stage('部署到K8s') {
steps {
sh '''
echo "apiVersion: apps/v1" > deployment.yaml
echo "kind: Deployment" >> deployment.yaml
echo "metadata:" >> deployment.yaml
echo " name: myapp" >> deployment.yaml
echo "spec:" >> deployment.yaml
echo " replicas: 2" >> deployment.yaml
echo " selector:" >> deployment.yaml
echo " matchLabels:" >> deployment.yaml
echo " app: myapp" >> deployment.yaml
echo " template:" >> deployment.yaml
echo " metadata:" >> deployment.yaml
echo " labels:" >> deployment.yaml
echo " app: myapp" >> deployment.yaml
echo " spec:" >> deployment.yaml
echo " containers:" >> deployment.yaml
echo " - name: myapp" >> deployment.yaml
echo " image: myapp:${env.BUILD_NUMBER}" >> deployment.yaml
kubectl apply -f deployment.yaml
'''
}
}
}
}
GitLab CI 与 Kubernetes 集成
GitLab CI 是 GitLab 内置的 CI/CD 工具,与 GitLab 代码仓库深度集成,可以通过 Runner 实现在 Kubernetes 集群中的构建和部署。
1. GitLab Runner 部署
# GitLab Runner 部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitlab-runner
namespace: gitlab-runner
spec:
replicas: 1
selector:
matchLabels:
name: gitlab-runner
template:
metadata:
labels:
name: gitlab-runner
spec:
serviceAccountName: gitlab-runner
containers:
- name: gitlab-runner
image: gitlab/gitlab-runner:alpine-v14.10.1
imagePullPolicy: Always
volumeMounts:
- name: config
mountPath: /etc/gitlab-runner
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: config
emptyDir: {}
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
2. .gitlab-ci.yml 示例
# .gitlab-ci.yml 示例
stages:
- build
- test
- deploy
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
build-image:
stage: build
script:
- echo "构建 Docker 镜像"
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
test-app:
stage: test
script:
- echo "运行单元测试"
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA npm test
dependencies:
- build-image
deploy-to-k8s:
stage: deploy
script:
- echo "部署到 K8s"
- export KUBECONFIG=$KUBECONFIG_FILE
- kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
only:
- main
when: manual
environment:
name: production
url: https://myapp.example.com
GitHub Actions 与 Kubernetes 集成
GitHub Actions 是 GitHub 提供的 CI/CD 服务,可以通过工作流文件定义自动化构建和部署流程。
1. GitHub Actions 工作流示例
# .github/workflows/deploy.yml 示例
name: 构建和部署到 K8s
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: 检出代码
uses: actions/checkout@v3
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v2
- name: 登录到容器注册表
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 提取 Docker 镜像元数据
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: 构建并推送 Docker 镜像
id: build-and-push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: 设置 kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.24.0'
- name: 配置 K8s 集群访问
uses: azure/k8s-set-context@v1
with:
kubeconfig: ${{ secrets.KUBE_CONFIG_DATA }}
- name: 部署到 K8s
run: |
cat < apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
ports:
- containerPort: 80
EOF
- name: 验证部署
run: |
kubectl rollout status deployment/myapp-deployment
kubectl get services -o wide
CI/CD 最佳实践
安全最佳实践
- 使用服务账户和 RBAC 授权
- 将敏感信息存储在 Secret 中
- 启用镜像扫描和安全审计
- 使用多阶段构建减少攻击面
性能最佳实践
- 使用缓存加速构建过程
- 并行执行测试任务
- 优化 Docker 镜像大小
- 使用资源限制避免资源争用
CI/CD 故障排除
| 常见问题 | 可能原因 | 解决方案 |
|---|---|---|
| 构建权限不足 | 服务账户权限配置不当 | 配置正确的 RBAC 权限 |
| 镜像推送失败 | 镜像仓库认证问题 | 检查认证凭据和网络连接 |
| 部署失败 | Kubernetes API 访问问题 | 验证 kubeconfig 和网络策略 |
| 资源不足 | 集群资源分配不足 | 调整资源请求和限制 |
| 网络连接问题 | 网络策略或防火墙限制 | 配置正确的网络策略 |
常用命令
# 验证 Jenkins Pod 模板
kubectl apply -f jenkins-pod-template.yaml
# 检查 GitLab Runner 状态
kubectl get pods -n gitlab-runner
# 查看 GitHub Actions 日志
kubectl logs -f deployment/myapp-deployment
# 测试部署状态
kubectl rollout status deployment/myapp-deployment