安装gitlab社区版
[root@localhost ~]#yum list |grep gitlab
[root@localhost ~]#yum install -y gitlab-ce
[root@localhost ~]# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-15.9.8-ce.0.el7.x86_64.rpm
安装GitLab Runner
添加 GitLab 的官方仓库
下载并安装 GitLab Runner repository
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash


列出所有可用版本
因为我的gitlab版本是15.9.8 ,因此gitlab-runner打版本最好相同,不然有可能产生兼容性问题
yum –showduplicates list gitlab-runner

[root@10 ~]# yum install -y gitlab-runner-15.10.1-1


安装后需要将 Runner 注册到你的 GitLab 项目或实例。
- 获取注册 Token
项目级 Runner(推荐用于单个项目):
进入 GitLab 项目 → Settings → CI / CD → Runners
复制 “Project registration token”
群组级或实例级 Runner:
在群组或管理员设置中获取对应 Token

[root@10 ~]# gitlab-runner register
手动注册:


直接使用注册命令:
gitlab-runner register -n \
–url http://10.0.20.190:9999 \
–registration-token vffxdeAc4MEb3ArAokpL \
–executor docker \
–description “gitlab-runner120” \
–docker-image “docker:stable” \
–docker-privileged \
–docker-volumes “/var/run/docker.sock:/var/run/docker.sock” \
–docker-volumes “/cache” \
–docker-shm-size “536870912”
注意注册时:
确保 GitLab Runner 已经正确配置以支持 Docker-in-Docker。特别是,检查 Runner 的 config.toml 文件中的 [runners.docker] 部分是否包含如下设置:

特别注意 privileged = true 和 volumes = [“/var/run/docker.sock:/var/run/docker.sock”] 这两项,它们对于允许 Runner 使用 Docker-in-Docker 是必需的。否则构建时使用 docker会报错
services: docker:dind 启动了 dind 容器,但它需要 privileged = true
当前 Runner 使用的是 alpine:latest 镜像,不包含 docker CLI
Runner 没有挂载 /var/run/docker.sock,也无法通过 dind 正常通信
已经注册成功

查看cat /etc/gitlab-runner/config.toml

启动并设置开机自启
systemctl start gitlab-runner
systemctl enable gitlab-runner
systemctl status gitlab-runner

在gitlab仓库中创建一个项目 gitlab_runner_test
在项目的根目录下创建一个 .gitlab-ci.yml
文件用于测试注册成功的Runner自动执行触发任务
这里注意三点:
1;在编辑 .gitlab-ci.yml
后使用 GitLab CI Lint 工具 验证 .gitlab-ci.yml 是否正确。
2;由于在注册 runner 时用于构建的执行器选择的是 docker 因此本机需要安装docker 以及docker 仓库中的地址 /etc/docker/daemon.json 需要更改为阿里云的或其它国内地址,以免runner在构建时处于“等待中状态”

.gitlab-ci.yml
workflow:
rules:
– if: $CI_COMMIT_BRANCH # 推送到分支时运行
– when: never # 其他情况(如 MR)不运行
job-hello-runner:
script:
– echo “Hello from GitLab Runner!”
– echo “Runner is WORKING!”
tags:
– gitlab-runner120 # ⚠️ 必须和你注册 Runner 时设置的 tag 一致!

Runner 成功执行作业任务

docker安装gitlab-runner
拉取指定版本的 GitLab Runner 镜像
[root@localhost ~]# docker pull gitlab/gitlab-runner:v15.10.1

运行容器

docker run -d \
–name gitlab-runner \
–restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:v15.10.1
/var/run/docker.sock 是为了让 Runner 能调用宿主机的 Docker 守护进程(用于 docker executor)
/srv/gitlab-runner/config 是配置和证书持久化目录
进入容器并注册 Runner
docker exec -it gitlab-runner gitlab-runner register

直接使用注册命令:
docker exec -it gitlab-runner gitlab-runner register -n \
–url http://10.0.20.190:9999 \
–registration-token vffxdeAc4MEb3ArAokpL \
–executor docker \
–description “gitlab-runner120” \
–docker-image “docker:stable” \
–docker-privileged \
–docker-volumes “/var/run/docker.sock:/var/run/docker.sock” \
–docker-volumes “/cache” \
–docker-shm-size 536870912
Gitlab-runner 已经注册成功

至此两台gitlab-runner已经安装完成
创建一个node.js测试项目,实现自动构建部署至k8s集群
GitLab 项目名称:Node.js
项目目录结构建议如下:
Node.js/
├── src/
│ └── index.js
├── package.json
├── Dockerfile
├── .gitlab-ci.yml
└── k8s/
└── deployment.yaml

二、Node.js 示例代码
src/index.js
const express = require(‘express’);
const app = express();
const PORT = process.env.PORT || 3000;
app.get(‘/’, (req, res) => {
res.send(‘Hello from Node.js App – Version 1.0’);
});
app.listen(PORT, ‘0.0.0.0’, () => {
console.log(Server running on port ${PORT});
});
package.json
{
“name”: “nodejs-app”,
“version”: “1.0.0”,
“main”: “src/index.js”,
“scripts”: {
“start”: “node src/index.js”
},
“dependencies”: {
“express”: “^4.18.0”
}
}
三、Dockerfile
# 使用 Node.js 官方基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制 package.json 并安装依赖
COPY package*.json ./
RUN npm install –production
# 复制源码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD [“npm”, “start”]
四、GitLab CI/CD 变量配置(在 GitLab 项目中设置)
进入 GitLab 项目 → Settings → CI / CD → Variables
添加以下 环境变量(Masked 可选):

gitlab上添加的变量

如何获取 KUBE_TOKEN 和 KUBE_CA_PEM?
在你的本地 Kubernetes 集群上执行:
步骤:创建永久 Token(基于 Secret)
- 创建 ServiceAccount
kubectl create serviceaccount git-runner -n default
- 手动创建 Secret(绑定到 SA,不设置过期时间)
创建文件 sa-token-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: git-runner-token
namespace: default
annotations:
kubernetes.io/service-account.name: git-runner
type: kubernetes.io/service-account-token
注意:不要设置 expirationSeconds 字段,就不会自动过期
应用:
kubectl apply -f sa-token-secret.yaml
这个 Secret 将由 kube-controller-manager 自动填充 Token 内容。
- 等待 Token 被填充
kubectl get secret git-runner-token -n default -o jsonpath='{.data.token}’ | base64 –decode
如果输出为空,说明 Token 还未生成,等待几秒再试。
- 绑定权限(例如 cluster-admin)
kubectl create clusterrolebinding git-runner-admin \
–clusterrole=cluster-admin \
–serviceaccount=default:my-permanent-user
📦 获取你需要的信息
✅ 获取 Bearer Token
TOKEN=$(kubectl get secret git-runner-token -n default -o jsonpath='{.data.token}’ | base64 –decode)
echo $TOKEN
✅ 获取 Kubernetes CA 证书(Base64 编码)
CA_CERT=$(kubectl config view –raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}’)
echo $CA_CERT
✅ 验证 Token 是否“永久”
使用以下命令查看 Secret 的 Token 是否包含过期时间:
kubectl get secret git-runner-token -n default -o yaml
五、.gitlab-ci.yml
stages:
– build-push # 负责构建和推送 Docker 镜像
– deploy # 负责将应用部署到 Kubernetes 集群
# 执行顺序是从上到下的,即先执行 build-push 阶段的任务,再执行 deploy 阶段
variables: # 全局变量定义,定义了一些可在整个流水线中使用的环境变量
IMAGE_NAME: “${ALIYUN_REGISTRY}/${ALIYUN_NAMESPACE}/${ALIYUN_REPO}” TAG: “${CI_COMMIT_SHORT_SHA}”
build-image: # 构建与推送镜像任务
stage: build-push
image: docker:latest
services:
– docker:dind
before_script: # 在执行主脚本前运行
– ‘echo “Logging in to Alibaba Cloud Container Registry…”‘
– ‘docker login -u “${ALIYUN_USERNAME}” -p “${ALIYUN_PASSWORD}” “${ALIYUN_REGISTRY}”‘ script: # 脚本实际执行的操作 – ‘docker build -t “${IMAGE_NAME}:${TAG}” .’ – ‘echo “Image built: ${IMAGE_NAME}:${TAG}”‘ – ‘docker push “${IMAGE_NAME}:${TAG}”‘ – ‘echo “Image pushed: ${IMAGE_NAME}:${TAG}”‘
# tags: # 用于指定该任务应在哪个 GitLab Runner 上运行。
# – gitlab-runner120
only: # 表示这个任务仅在 main 分支触发时运行
– main
deploy-to-k8s:
stage: deploy # 属于 deploy 阶段,会在 build-push 成功后执行
image: alpine/k8s:1.25.0 # 使用一个轻量级镜像,其中预装了 kubectl 工具
script:
# 创建 kube 目录
– mkdir -p ~/.kube
# 解码 CA 证书
– echo “${KUBE_CA_PEM}” | base64 -d > ~/.kube/ca.crt # 写入 kubeconfig 文件(使用 | 正确处理多行) – | cat > ~/.kube/config <<EOF apiVersion: v1 clusters: – cluster: certificate-authority: /root/.kube/ca.crt # insecure-skip-tls-verify: true 跳过 TLS 验证 server: ${KUBE_SERVER}
name: local-k8s
contexts:
– context:
cluster: local-k8s
user: gitlab-runner
name: default
current-context: default
users:
– name: gitlab-runner
user:
token: “${KUBE_TOKEN}”
EOF
# 替换镜像并部署
– sed -i “s|IMAGE_PLACEHOLDER|${IMAGE_NAME}:${TAG}|g” k8s/deployment.yaml
– kubectl apply -f k8s/deployment.yaml
– kubectl rollout status deployment/nodejs-deployment –timeout=60s
– git checkout k8s/deployment.yaml
# tags:
# – gitlab-runner120
only:
– main
⚠️ 注意:
使用 alpine/k8s:1.25.0 镜像包含 kubectl,轻量且适合 CI。
如果版本不兼容,可换为 bitnami/kubectl。
脚本中 – build-push # 负责构建和推送 Docker 镜像的选项在gitlab-runner没有打上标签的情况下,最好作为一部执行完成,以免分开执行时出现构建在gitlab-runner-1上执行,而推送的步骤是在gitlab-runner-2上执行而找不到构建的镜像无法推送而构建失败报错的状况。
.gitlab-ci.yml这段 CI/CD 配置实现了:
自动化构建 Docker 镜像并推送到阿里云。
自动化部署到 Kubernetes 集群。
使用标准安全实践(Token、CA 认证)连接集群。
每次提交独立版本(基于 Git SHA)。
支持部署后状态检查,提升可靠性。
六、k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodejs-deployment
labels:
app: nodejs
spec:
replicas: 2
selector:
matchLabels:
app: nodejs
template:
metadata:
labels:
app: nodejs
spec:
containers:
– name: nodejs
image: IMAGE_PLACEHOLDER # 将在 CI 中被替换为实际镜像地址
ports:
– containerPort: 3000
resources:
requests:
memory: “128Mi”
cpu: “100m”
limits:
memory: “256Mi”
cpu: “200m”
imagePullSecrets:
– name: aliyun-secret # Kubernetes 从阿里云镜像仓库拉取容器镜像引用的secret
—
apiVersion: v1
kind: Service
metadata:
name: nodejs-service
spec:
type: NodePort
selector:
app: nodejs
ports:
– protocol: TCP
port: 80
targetPort: 3000
nodePort: 30018
⚠️ 注意:在 Deployment 中通过 imagePullSecrets 引用这个 Secret,里面保存了登录镜像仓库的用户名、密码或令牌
在k8s中创建一个 Secret 用于访问阿里云容器镜像服务(ACR)
运行命令创建 Secret:
Bash
kubectl create secret docker-registry aliyun-secret \
–docker-server=registry.cn-beijing.aliyuncs.com \
–docker-username=your-username \
–docker-password=your-password-or-token \
–docker-email=your-email@example.com \
–namespace=default
注意:docker-registry 类型的 Secret 专门用于镜像拉取认证。
💡 说明:
image: IMAGE_PLACEHOLDER 将在 CI 中被替换为实际镜像地址。
Service 使用 NodePort,暴露端口 30018,可通过 http://<any-node-ip>:30018 访问应用。
七、完整流程总结

八、验证部署
推送至阿里云的镜像

Gitlab上构建成功的状态

k8s上自动部署的nodejs服务

# 查看 Pod
kubectl get pods -l app=nodejs
# 查看服务
kubectl get svc nodejs-service
# 浏览器访问
http://10.0.20.121:30018
# 应显示:Hello from Node.js App – Version 1.0
