Kubernetes部署 #
一、Kubernetes集成概述 #
text
┌─────────────────────────────────────────────────────────────┐
│ GitLab + Kubernetes │
├─────────────────────────────────────────────────────────────┤
│ │
│ GitLab CI/CD Kubernetes │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ • 构建镜像 │ │ • Deployment │ │
│ │ • 推送镜像 │ → │ • Service │ │
│ │ • 部署命令 │ │ • Ingress │ │
│ │ • 滚动更新 │ │ • ConfigMap │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
二、配置Kubernetes集群 #
1. 添加Kubernetes集群 #
- 进入项目Operations → Kubernetes
- 点击"Add Kubernetes cluster"
- 选择"Add existing cluster"
- 填写集群信息
2. 集群信息 #
| 字段 | 说明 |
|---|---|
| Name | 集群名称 |
| API URL | Kubernetes API地址 |
| CA Certificate | CA证书 |
| Service Token | 服务令牌 |
| Namespace | 命名空间 |
3. 获取集群信息 #
bash
# 获取API URL
kubectl cluster-info
# 获取CA证书
kubectl get secret -n default <secret-name> -o jsonpath="{.data['ca\.crt']}"
# 创建服务账号
kubectl create serviceaccount gitlab-runner -n default
# 创建令牌
kubectl create token gitlab-runner -n default
三、基本部署 #
1. 使用kubectl #
yaml
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true
- kubectl config set-credentials admin --token="$KUBE_TOKEN"
- kubectl config set-context default --cluster=k8s --user=admin
- kubectl config use-context default
- kubectl apply -f k8s/deployment.yaml
2. 使用环境变量 #
yaml
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- kubectl rollout status deployment/myapp
3. 使用GitLab Agent #
yaml
deploy:
stage: deploy
image: bitnami/kubectl:latest
variables:
KUBE_CONTEXT: my-group/my-project:my-agent
script:
- kubectl config use-context $KUBE_CONTEXT
- kubectl apply -f k8s/
四、Kubernetes配置文件 #
Deployment #
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: registry.example.com/group/project:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Service #
yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
type: ClusterIP
Ingress #
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- example.com
secretName: myapp-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp
port:
number: 80
ConfigMap #
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
DATABASE_HOST: "postgres.default.svc.cluster.local"
REDIS_HOST: "redis.default.svc.cluster.local"
Secret #
yaml
apiVersion: v1
kind: Secret
metadata:
name: myapp-secret
type: Opaque
stringData:
DATABASE_PASSWORD: "your-password"
API_KEY: "your-api-key"
五、滚动更新 #
基本滚动更新 #
yaml
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- kubectl rollout status deployment/myapp --timeout=300s
自定义更新策略 #
yaml
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
金丝雀发布 #
yaml
deploy_canary:
stage: deploy
image: bitnami/kubectl:latest
script:
- |
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-canary
spec:
replicas: 1
selector:
matchLabels:
app: myapp
track: canary
template:
metadata:
labels:
app: myapp
track: canary
spec:
containers:
- name: myapp
image: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
EOF
only:
- main
蓝绿部署 #
yaml
deploy_blue:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl apply -f k8s/deployment-blue.yaml
- kubectl patch service myapp -p '{"spec":{"selector":{"version":"blue"}}}'
only:
- main
deploy_green:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl apply -f k8s/deployment-green.yaml
- kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'
only:
- main
when: manual
六、回滚策略 #
手动回滚 #
yaml
rollback:
stage: rollback
image: bitnami/kubectl:latest
script:
- kubectl rollout undo deployment/myapp
- kubectl rollout status deployment/myapp
when: manual
回滚到指定版本 #
yaml
rollback:
stage: rollback
image: bitnami/kubectl:latest
script:
- kubectl rollout undo deployment/myapp --to-revision=2
when: manual
自动回滚 #
yaml
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- |
if ! kubectl rollout status deployment/myapp --timeout=300s; then
kubectl rollout undo deployment/myapp
exit 1
fi
七、多环境部署 #
环境配置 #
yaml
deploy_staging:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: staging
url: https://staging.example.com
variables:
KUBE_NAMESPACE: staging
script:
- kubectl apply -f k8s/staging/ -n $KUBE_NAMESPACE
only:
- develop
deploy_production:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: production
url: https://example.com
variables:
KUBE_NAMESPACE: production
script:
- kubectl apply -f k8s/production/ -n $KUBE_NAMESPACE
only:
- main
when: manual
Kustomize #
目录结构:
text
k8s/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
└── overlays/
├── staging/
│ ├── kustomization.yaml
│ └── patch.yaml
└── production/
├── kustomization.yaml
└── patch.yaml
yaml
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl apply -k k8s/overlays/$ENVIRONMENT
八、Helm部署 #
基本Helm部署 #
yaml
deploy:
stage: deploy
image: alpine/helm:latest
script:
- helm upgrade --install myapp ./chart \
--set image.repository=$CI_REGISTRY_IMAGE \
--set image.tag=$CI_COMMIT_SHA \
--namespace $KUBE_NAMESPACE
使用values文件 #
yaml
deploy_staging:
stage: deploy
image: alpine/helm:latest
script:
- helm upgrade --install myapp ./chart \
-f ./chart/values-staging.yaml \
--set image.tag=$CI_COMMIT_SHA
only:
- develop
deploy_production:
stage: deploy
image: alpine/helm:latest
script:
- helm upgrade --install myapp ./chart \
-f ./chart/values-production.yaml \
--set image.tag=$CI_COMMIT_SHA
only:
- main
when: manual
Helm回滚 #
yaml
rollback:
stage: rollback
image: alpine/helm:latest
script:
- helm rollback myapp
when: manual
九、完整示例 #
yaml
stages:
- build
- test
- deploy
- rollback
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
docker_build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
test:
stage: test
image: $DOCKER_IMAGE
script:
- npm test
deploy_staging:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: staging
url: https://staging.example.com
variables:
KUBE_NAMESPACE: staging
script:
- kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true
- kubectl config set-credentials admin --token="$KUBE_TOKEN"
- kubectl config set-context default --cluster=k8s --user=admin
- kubectl config use-context default
- |
cat <<EOF | kubectl apply -n $KUBE_NAMESPACE -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: $DOCKER_IMAGE
ports:
- containerPort: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
EOF
- kubectl rollout status deployment/myapp -n $KUBE_NAMESPACE
only:
- develop
deploy_production:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: production
url: https://example.com
variables:
KUBE_NAMESPACE: production
script:
- kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true
- kubectl config set-credentials admin --token="$KUBE_TOKEN"
- kubectl config set-context default --cluster=k8s --user=admin
- kubectl config use-context default
- kubectl set image deployment/myapp myapp=$DOCKER_IMAGE -n $KUBE_NAMESPACE
- |
if ! kubectl rollout status deployment/myapp -n $KUBE_NAMESPACE --timeout=300s; then
kubectl rollout undo deployment/myapp -n $KUBE_NAMESPACE
exit 1
fi
only:
- main
when: manual
rollback_staging:
stage: rollback
image: bitnami/kubectl:latest
variables:
KUBE_NAMESPACE: staging
script:
- kubectl rollout undo deployment/myapp -n $KUBE_NAMESPACE
when: manual
only:
- develop
rollback_production:
stage: rollback
image: bitnami/kubectl:latest
variables:
KUBE_NAMESPACE: production
script:
- kubectl rollout undo deployment/myapp -n $KUBE_NAMESPACE
when: manual
only:
- main
十、最佳实践 #
1. 使用命名空间隔离环境 #
yaml
variables:
KUBE_NAMESPACE: $ENVIRONMENT
2. 设置资源限制 #
yaml
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
3. 配置健康检查 #
yaml
livenessProbe:
httpGet:
path: /health
port: 3000
readinessProbe:
httpGet:
path: /ready
port: 3000
4. 使用GitLab Agent #
yaml
variables:
KUBE_CONTEXT: my-group/my-project:my-agent
5. 自动回滚 #
yaml
script:
- |
if ! kubectl rollout status deployment/myapp --timeout=300s; then
kubectl rollout undo deployment/myapp
exit 1
fi
恭喜你完成了GitLab CI/CD完全指南的学习!现在你已经掌握了从基础到高级的所有GitLab CI/CD知识。
最后更新:2026-03-28