How VPGAME Migrated Its Services to Kubernetes Using GitLab CI/CD and Docker
This article details VPGAME's end‑to‑end migration of its esports platform services to a Kubernetes‑based architecture, covering CI/CD tool selection, Docker and GitLab Runner setup, automated Docker image builds, and Kubernetes Deployment and Service templating with health checks, resource limits, logging and monitoring configurations.
Background
VPGAME, an integrated esports service platform, decided to move its services to a container environment using Kubernetes to improve deployment speed, standardise CI/CD pipelines and reduce operational overhead.
CI/CD Tool Selection
The team chose GitLab‑CI because it integrates tightly with GitLab, requires only a .gitlab-ci.yml file for pipeline definition, and offers a simpler configuration than Jenkins.
Docker Installation (CentOS)
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce
systemctl start docker
systemctl enable dockerGitLab Runner Installation and Registration
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
sudo yum install -y gitlab-runner
sudo gitlab-runner start
# Non‑interactive registration example
gitlab-runner register \
--non-interactive \
--url "http://git.example.cn" \
--registration-token "YOUR_TOKEN" \
--executor "docker" \
--docker-image "alpine:latest" \
--description "base-runner-docker" \
--tag-list "base-runner" \
--run-untagged="true" \
--docker-pull-policy "if-not-present" \
--docker-privileged="true" \
--docker-volumes "/etc/docker/daemon.json:/etc/docker/daemon.json" \
--docker-volumes "/etc/gitlab-runner/config.toml:/etc/gitlab-runner/config.toml"Docker Image Build Process
All Docker images are defined by Dockerfile files stored in the repository. When a merge to master occurs, a script scans for changed Dockerfiles and builds the corresponding images.
for FILE in $(bash ./find_diff_files | grep Dockerfile | sort); do
DIR=$(dirname "$FILE")
IMAGE_NAME=$(echo $DIR | sed -e 's/\//-/g')
docker build -t $CI_REGISTRY/$HARBOR_DIR/$IMAGE_NAME -f $FILE $DIR
docker push $CI_REGISTRY/$HARBOR_DIR/$IMAGE_NAME
done.gitlab-ci.yml Overview
The pipeline defines three stages: build, test and deploy. Jobs in the same stage run in parallel; subsequent stages start only after all jobs in the previous stage succeed.
stages:
- build
- test
- deploy
unittest:
stage: test
image: docker.vpgame.cn/infra/php-1.0-ci-1.1
services:
- name: docker.vpgame.cn/infra/mysql-5.6-multi
alias: mysql
- name: docker.vpgame.cn/infra/redis-4.0
alias: redis_default
script:
- mv .env .env.tp
- composer install --no-dev
- phpunit -v --coverage-text --coverage-html=coverage --stderr
artifacts:
when: on_success
paths:
- vendor/
- coverage/
expire_in: 1 hour
only:
- branches
- tags
tags:
- base-runner
.build-op:
stage: build
image: docker.vpgame.cn/infra/docker-kubectl-1.0
script:
- echo "Image name: $DOCKER_IMAGE_NAME"
- docker build -t $DOCKER_IMAGE_NAME .
- docker push $DOCKER_IMAGE_NAME
tags:
- base-runner
build-test:
extends: .build-op
variables:
DOCKER_IMAGE_NAME: "$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA"
only:
- /^testing/
- master
build-prod:
extends: .build-op
variables:
DOCKER_IMAGE_NAME: "$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_TAG"
only:
- tags
tags:
- pro-deploy
.deploy-op:
stage: deploy
image: docker.vpgame.cn/infra/docker-kubectl-1.0
script:
- echo "Deploying $DOCKER_IMAGE_NAME"
- sed -i "s/__NAMESPACE__/${NAMESPACE}/g" deployment.yml
- sed -i "s/__APP_NAME__/${APP_NAME}/g" deployment.yml
- kubectl apply -f deployment.yml
- kubectl apply -f service.yml
- kubectl rollout status deployment/${APP_NAME}
- kubectl get all -l app=${APP_NAME} -n ${NAMESPACE}
only:
- /^testing/
- master
tags:
- base-runner
deploy-test:
extends: .deploy-op
variables:
REPLICAS: 2
VERSION: "$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA"
environment:
name: test
url: http://example.com
only:
- /^testing/
- master
tags:
- base-runner
deploy-prod:
extends: .deploy-op
variables:
REPLICAS: 3
VERSION: "$CI_COMMIT_TAG"
environment:
name: prod
url: http://example.com
only:
- tags
tags:
- pro-deployKubernetes Deployment Template (deployment.yml)
apiVersion: apps/v1beta2
kind: Deployment
metadata:
labels:
app: __APP_NAME__
group: __GROUP_NAME__
name: __APP_NAME__
namespace: __NAMESPACE__
spec:
replicas: 2
selector:
matchLabels:
app: __APP_NAME__
template:
metadata:
labels:
app: __APP_NAME__
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: group
operator: In
values:
- __GROUP_NAME__
containers:
- name: fpm
image: $DOCKER_IMAGE_NAME
ports:
- containerPort: 80
env:
- name: aliyun_logs_vpgame
value: stdout
- name: aliyun_logs_vpgame_tags
value: topic=__APP_NAME__
livenessProbe:
httpGet:
path: /__PROJECT_NAME__
port: 80
initialDelaySeconds: 3
periodSeconds: 5
readinessProbe:
httpGet:
path: /__PROJECT_NAME__
port: 80
initialDelaySeconds: 3
periodSeconds: 5
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "250m"
memory: "256Mi"
restartPolicy: Always
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%Kubernetes Service Template (service.yml)
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
labels:
app: __APP_NAME__
name: __APP_NAME__
namespace: __NAMESPACE__
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: __APP_NAME__
type: LoadBalancerAdditional Configuration
Health Checks : Liveness and readiness probes ensure containers are alive and ready before traffic is sent.
Resource Allocation : Pods use node affinity based on the project group to schedule on specific nodes.
Logging : Environment variables aliyun_logs_vpgame and aliyun_logs_vpgame_tags direct container logs to an Alibaba Cloud Logstore.
Monitoring : Annotations prometheus.io/scrape: "true", prometheus.io/port: "80", and prometheus.io/path: /{{project_name}}/metrics enable Prometheus to scrape metrics.
Upgrade Strategy : RollingUpdate with maxSurge and maxUnavailable set to 25% to minimise downtime.
Conclusion
By standardising Docker image creation, GitLab‑CI pipelines, and Kubernetes manifests, VPGAME achieved a fast, repeatable migration process for its services. The approach demonstrates how to combine containerisation, CI/CD automation and Kubernetes best practices to improve deployment efficiency, scalability and observability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Native
We publish cloud-native tech news, curate in-depth content, host regular events and live streams, and share Alibaba product and user case studies. Join us to explore and share the cloud-native insights you need.
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.
