gitlab ci实践

什么是 CI/CD

CI(持续集成)是指持续地集成代码到主干。持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。

CD (持续交付) 是指持续地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就可以部署到生产环境。

在云原生环境下,交付物是 Docker 镜像。

我们需要一份源代码来实践 CI/CD。

gohttpserveropen in new window 是一个简单的用 Go 编写的服务。首先将该项目 fork 到自建的 GitLab 仓库。

读者只需要关注 .gitlab-ci.yml 文件如何编写,以及 k8s 清单文件如何编写即可。

我们先来看下完整的 .gitlab-ci.yml 文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
before_script:
  - export

stages:
  - build
  - deploy

build:
  stage: build
  tags:
    - k8s
  image:
    name: 10.7.20.31:5000/executor:debug
    entrypoint: [""]
  script:
    - mkdir -p /kaniko/.docker
    - echo $AUTH
    - echo $CI_REGISTRY
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$AUTH\"}}}" > /kaniko/.docker/config.json
    - >-
      /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile" #
      --destination "$CI_REGISTRY_IMAGE:${CI_COMMIT_TAG}" #CI_COMMIT_TAG 未版本号
      --destination "$CI_REGISTRY_IMAGE:latest" # CI_REGISTRY_IMAGE 192.168.120.12:5000/hxf1/gohttpserver
      --insecure --skip-tls-verify # 这个是针对http的registry
      --verbosity debug

  rules:
    - if: $CI_COMMIT_TAG

deploy:
  stage: deploy
  tags:
    - k8s
  image: ongres/kubectl:latest
  dependencies:
    - build
  script:
    - kubectl version
    - sed -i "s/latest/$CI_COMMIT_TAG/g" deploy/deploy.yaml
    - kubectl apply -f deploy/
  rules:
    - if: $CI_COMMIT_TAG

注意这个 auth ,可以通过本地 docker login 拿到 auth,在 cat ~/.docker/config.json,取出里面的 config 即可。

使用 Kaniko 构建 Docker 镜像

Kanikoopen in new window 是一种在容器或 Kubernetes 集群内使用 Dockerfile 构建容器镜像的工具。它解决了 Docker-in-Docker 构建方法的两个问题:

  • Docker-in-Docker 需要特权模式才能运行,这是一个重要的安全问题。
  • Docker-in-Docker 通常会导致性能下降,而且速度可能非常慢。

我们需要使用容器镜像仓库的身份验证信息来创建 Docker config.json 文件,格式如下:

使用新镜像部署应用

构建好 Docker 镜像后,就可以使用新镜像重新部署应用了。部署方式有多种,这里演示的是使用 kubectl 命令来部署应用。

和一般教程不同的是,我们的 kubectl 镜像使用的不是 bitnami/kubectl,而是 ongres/kubectl,这是因为作者的 k8s 集群是部署在一台 ARM64 架构的 Mac 电脑上。作者到 Docker Hub 上找了个替代品。

这部分的脚本很简单,首先更改 docker 镜像的 tag,然后使用 kubectl 命令来部署应用。

1
2
3
script:
  - sed -i "s/latest/$CI_COMMIT_TAG/g" deploy/deploy.yaml
  - kubectl apply -f deploy/

值得注意的是,我们需要在清单文件中,指定 namespace 的值为 default,尽管 namespace 的值默认就是 default。

1
2
3
4
5
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: gohttpserver

这是因为我们的 gitlab-runner 是跑在 gitlab 名字空间的,默认会将应用部署到 gitlab 名字空间下。

1
2
3
4
5
6
7
Running with gitlab-runner 16.6.1 (f5da3c5a)
  on gitlab-gitlab-runner-7bcf44dc44-scks4 UTm5ei-4, system ID: r_V7O5QSg29YMB
Preparing the "kubernetes" executor
00:00
Using Kubernetes namespace: apps-gitlab
Using Kubernetes executor with image ongres/kubectl:latest ...
Using attach strategy to execute scripts...

部署会报错说权限不够

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ sed -i "s/latest/$CI_COMMIT_TAG/g" deploy/deploy.yaml
$ kubectl apply -f deploy/
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "apps/v1, Resource=deployments", GroupVersionKind: "apps/v1, Kind=Deployment"
Name: "gohttpserver", Namespace: "default"
from server for: "deploy/deploy.yaml": deployments.apps "gohttpserver" is forbidden: User "system:serviceaccount:apps-gitlab:default" cannot get resource "deployments" in API group "apps" in the namespace "default"
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "/v1, Resource=services", GroupVersionKind: "/v1, Kind=Service"
Name: "gohttpserver", Namespace: "default"
from server for: "deploy/deploy.yaml": services "gohttpserver" is forbidden: User "system:serviceaccount:apps-gitlab:default" cannot get resource "services" in API group "" in the namespace "default"
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "networking.k8s.io/v1, Resource=ingresses", GroupVersionKind: "networking.k8s.io/v1, Kind=Ingress"
Name: "gohttpserver", Namespace: "default"
from server for: "deploy/ingress.yaml": ingresses.networking.k8s.io "gohttpserver" is forbidden: User "system:serviceaccount:apps-gitlab:default" cannot get resource "ingresses" in API group "networking.k8s.io" in the namespace "default"
ERROR: Job failed: command terminated with exit code 1

解决这个 serviceaccount 权限不够使用如下 yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: apps-gitlab
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: default-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: deployment-reader
subjects:
- kind: ServiceAccount
  name: default
  namespace: apps-gitlab
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: deployment-reader
rules:
- apiGroups: [''] #"" indicates the core API group
  resources: ['*']
  verbs: ['*']
- apiGroups: ['networking.k8s.io']
  resources: ['ingresses']
  verbs: ['*']
- apiGroups: ['apps']
  resources: ['deployments']
  verbs: ['*']

这个权限绑定,会保证账户拥有创建 deployment 的权限。

最后执行查看部署命令的 log

image-20240112102610690

image-20240112102634434

image-20240112102700842

参考文档:

https://todoit.tech/k8s/gitlab-ci/#%E4%BD%BF%E7%94%A8%E6%96%B0%E9%95%9C%E5%83%8F%E9%83%A8%E7%BD%B2%E5%BA%94%E7%94%A8

Licensed under CC BY-NC-SA 4.0
最后更新于 Jan 06, 2025 05:52 UTC
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计
Caret Up