访次: AmazingCounters.com 次

一、纯 k8s 部署实现 gitlab CICD

gitlab CICD
k8s 安装 GitLab
​ GitLab 具有三个需要进行持久化的目录,它们分别是 /etc/gitlab、/var/log/gitlab、/var/opt/gitlab,它们分别为 Gitlab 的运行提供配置、日志、数据的持久化。我们使用 nfs 来作为 GitLab 的持久化方式(当然,你也可以选择其他方式),为此,我们需要先安装 NFS,并且在 NFS 的配置文件中进行如下修改:

vim /etc/exports
# 注意,用户的访问权限一定要设置为 no_root_squash,因为 gitlab 需要 root 权限来操作这些文件。
/data/nfs/gitlab/config 172.17.33.152(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/gitlab/logs 172.17.33.152(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/gitlab/data 172.17.33.152(rw,insecure,sync,no_root_squash,subtree_check)

# 启用新的配置文件
exportfs -r

随后在 k8s 中安装 gitlab 及其各个组件

复制代码
kubectl apply -f - << EOF
apiVersion: v1
kind: Service
metadata:
  name: gitlab-svc
  namespace: gitlab
spec:
  type: NodePort
  ports:
  - port: 443
    targetPort: 443
    nodePort: 32443
    name: https
  - port: 80
    nodePort: 32080
    targetPort: 80
    name: http
  selector:
    app: gitlab
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitlab-dep
  namespace: gitlab
spec:
  selector:
    matchLabels:
      app: gitlab
  revisionHistoryLimit: 2
  template:
    metadata:
      labels:
        app: gitlab
    spec:
      containers:
      - image: gitlab/gitlab-ce
        name: gitlab
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 443
          name: https
        - containerPort: 80
          name: http
        - containerPort: 22
          name: ssh
        volumeMounts:
        - name: gitlab-config
          mountPath: /etc/gitlab
        - name: gitlab-logs
          mountPath: /var/log/gitlab
        - name: gitlab-data
          mountPath: /var/opt/gitlab
      volumes:
      - name: gitlab-config
        nfs:
          server: 10.0.8.16
          path: /data/nfs/gitlab/config
      - name: gitlab-logs
        nfs:
          server: 10.0.8.16
          path: /data/nfs/gitlab/logs
      - name: gitlab-data
        nfs:
          server: 10.0.8.16
          path: /data/nfs/gitlab/data
复制代码

 完成后,查看 gitlab 网页暴露在哪个端口:

[root@master argocd]# kubectl get svc -n gitlab
NAME         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
gitlab-svc   NodePort   10.104.103.219   <none>        443:32443/TCP,80:32080/TCP   2m21s
[root@master argocd]#

 

 

​ 管理员用户为 root,其登录密码在容器目录 /etc/gitlab/initial_root_password 文件中,即 nfs 服务器的 /data/nfs/gitlab/config/initial_root_password 文件。获取初始密码:

我把NFS 服务器部署在node2 所以在node2 的 NFS 对应目录下查看密码

复制代码
[root@node2 ~]# cat /data/nfs/gitlab/config/initial_root_password
# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: bRFzgaf+LkjoIRjFU02+OBDMEQ5HJF25HS6stFg1OsM=

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.
复制代码

也可以在容器内查看

[root@node2 ~]# kubectl exec -it -n gitlab $(kubectl get pods -n gitlab | grep gitlab | awk '{print$1}') -- cat /etc/gitlab/initial_root_password | grep Password:
Password: bRFzgaf+LkjoIRjFU02+OBDMEQ5HJF25HS6stFg1OsM=
[root@node2 ~]#

​ 登录进入系统,修改初始密码(一定要修改,因为这个临时密码的有效时间只有 24 小时)。页面路径为:右上角头像->Edit profile->左边导航栏->Password

随后可以创建一个普通用户,测试是否能正常使用 git 进行操作。

修改外部 URL
​ 通常情况下,gitlab 会根据机器内部的 FQCN 来标记一个仓库的 url。这就导致了在 gitlab 中复制 clone url 时,其使用的不是 IP 而是一个域名。如果在局域网内部署 gitlab,这个 DNS 显然是不可以使用的。如果我们希望 gitlab 中的 url 直接使用 IP 地址,那么就需要修改配置文件 gitlab.rb

复制代码
# 由于我们之前将 gitlab 的配置文件挂载到了 /data/nfs/gitlab/config 上,因此通过修改宿主机的配置文件即可
vim gitlab.rb
# 在其中添加一行:
external_url 'http://<ip>:<port>'
# 例如: external_url 'http://101.43.196.155:32080'

# 修改完配置文件后,删除原本的 gitlab pod,让其自动重启,加载配置文件

[root@node2 config]# kubectl get po -n gitlab
NAME READY STATUS RESTARTS AGE
gitlab-dep-b8584d894-rlt8q 1/1 Running 0 9m6s
[root@node2 config]# kubectl delete po -n gitlab gitlab-dep-b8584d894-rlt8q
pod "gitlab-dep-b8584d894-rlt8q" deleted

 
复制代码

​ 执行完上述操作后,我们尝试登录在外网登录 gitlab,发现无法登录。这是因为 external_url 修改后,导致 Pod 内部,gitlab 的端口也发生了变化。在没有设置之前,gitlab 是暴露在 80 端口,修改之后,gitlab 就暴露在我们设置的那个端口。因此,还需要修改 service 的 tagetPort 字段,才能让外部正常访问到 gitlab:

kubectl edit svc -n gitlab gitlab-svc
# 将 targetPort 设置为之前修改的端口

 如果这里 external_url 'http://101.43.196.155:32080'  设置的是 external_url 'http://101.43.196.155'   就不需要修改 以上 (kubectl edit svc -n gitlab gitlab-svc)

 

此时,我们已经可以正常访问 gitlab,查看 clone 中的 url,如下图所示

 

 

安装 Harbor
​ 由于 Harbor 的组件实在是太多,因此,使用 helm 作为安装手段来简化安装过程。具体过程参照文档:https://goharbor.io/docs/2.7.0/install-config/harbor-ha-helm/

​ helm 是一种 k8s 安装工具,它通过模板化的方式,一次性构造出一个大型项目
————————————————

# 下载 harbor chart
helm repo add harbor https://helm.goharbor.io
# 将 chart 下载至本地,执行完这一步后,当前路径会出现一个 harbor 文件夹,里面是各种安装文件
helm fetch harbor/harbor --untar

 

为了简化过程,我们不对其中的任何一个组件进行外部定制,只为这些组件提供必要的持久化手段。
我们先自行创建 pv 和 pvc:

复制代码
# 此处使用 nfs 支持持久卷,为此需要创建多个目录以供挂载
for i in chartmuseum database jobservice redis registry trivy;do mkdir -p /data/nfs/harbor/$i; done
cat >> /etc/exports << EOF
/data/nfs/harbor/registry *(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/harbor/chartmuseum *(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/harbor/jobservice *(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/harbor/database *(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/harbor/trivy *(rw,insecure,sync,no_root_squash,subtree_check)
/data/nfs/harbor/redis *(rw,insecure,sync,no_root_squash,subtree_check)
EOF
# 更新 nfs
exportfs -r
# 查看 nfs 当前提供的挂载点
showmount -e

# 创建 pv + pvc
cat >> pvc-pv-chartmuseum.yaml << EOF
apiVersion: v1
kind: PersistentVolume
# pv 没有命名空间的限制
metadata:
  name: harbor-chartmuseum-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteMany
  nfs:
    server: 10.0.8.16
    path: /data/nfs/harbor/chartmuseum
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: harbor-chartmuseum-pvc
  namespace: harbor 
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
EOF
for i in database jobservice redis registry trivy;do cat pvc-pv-chartmuseum.yaml | sed "s/chartmuseum/$i/g" > pvc-pv-$i.yaml; done
kubectl apply -f .
# 查看 pvc、pv
kubectl get pv
kubectl get pvc -n harbor
复制代码

​ 现在,我们需要让 helm 创建的 harbor 组件使用我们的 pvc,因此,我们需要定制化这一部分功能。helm 的 chart 安装包,通常的文件结构如下:

<chart>--- conf               # 通常不需要关心
        |
        |- template           # 模板文件,就是 k8s 的 yaml 文件,在调用 helm install 指令时,helm 会根据这些模板,生成真正的 yaml 文件,并调用 kubectl apply 来启动
        |
        |- values.yaml        # 重点关心的文件,这个文件里面存放了所有可以定制化的参数。所谓的定制化,实际上就是将模板中的一些默认参数修改为我们希望的值,而这些值,就存放在 values.yaml 文件中。

​ 我们进入到 harbor 安装包,修改 value.yaml 文件,让 harbor 的组件使用我们自己的持久卷——不要被 value.yaml 文件的内容吓到了,我们关心的只有很小的一部分。

修改服务暴露方式。在自行搭建的小集群内,通常使用的暴露方式是 NodePort,因此我们修改 expose.type: nodePort,如下图:

 

修改外部 URL,即 externalURL:http://<your_k8s_ip>:30002 。如果不修改,成功部署 harbor 之后,无法登录到 harbor 管理界面,因为 harbor 只信任以这个 URL 访问的 http 请求。这也意味着,之后你也只能使用这个 url 才能登录到 harbor 中。

 

修改持久化方式。重点是修改 persistence 字段下的各个 existingClaim 字段为我们之前创建的 PVC 名称  

 

修改完成后,保存退出。最后安装即可:

# helm install 命令的格式是这样的:
# helm install <name> -n <namespace> <chart_path>
#     name: 名称,不重要,给人看的
#   namespace: 命名空间,指定后,所有组件都会被安装到这个命名空间下
#    chart_path: 安装包的路径
helm install harbor -n harbor harbor/

 

你可能遇到的问题:

执行完安装程序后,过了很久后,pod 一直处在 CrashLoopxxx 状态:创建 harbor 是一个很久的过程,你需要耐心等待,如果 10 分钟后还有大量 Pod 没有安装成功,建议从网络、集群状态方向入手解决问题。如果只有个别 Pod 没有启动成功,你可以尝试把这些 Pod 删除,让它们自动重建。

安装 gitlab runner
​config.toml 文件中的配置项及其功能可以查看官方文档: https://docs.gitlab.com/runner/executors/kubernetes.html#default-annotations-for-job-pods

概述
​gitlab-runner 是 gitlab 提供的一种执行 CICD pipline 的组件。它有多种执行器,每一个执行器都提供一种实现 pipline 的方式,例如:shell 执行器是使用 shell 指令实现,docker 执行器是使用 docker api 实现。其中,最有难度的一种是 kubernetes 执行器。这种执行器会使用 k8s api 来实现 CICD pipline。

​ runner 的 k8s 执行器是这样执行 pipline 的:

首先,runner 会通过 RBAC 认证获取到调用 k8s 集群 API 的权限。
runner 会监听 gitlab,当有合适的 job 时,runner 会自动抓取任务执行。请注意,一个流水线中可以有很多个 stage,这些 stage 是串行执行的,而一个 stage 中又可以有多个并行的 job,runner 抓取的任务是以 job 为单位,而不是 stage,更不是 pipline。
随后,runner 会调用 k8s API,创建一个用于执行该 job 的 pod。通常来说,runner 创建的所有 pod 有一个通用模板,我们需要在 runner 的 config.toml 配置文件中配置这个模板。但 pod 中具体使用什么镜像、在 pod 中执行什么命令,这些都是在后续的 .gitlab-ci.yml 文件中配置,并且随着 job 的不同而不同。
在完成了 job 内的工作后,runner 会将这个临时 pod 删除。
配置 ConfigMap
​ 将主节点 kubeconfig 内容添加到 secret 中。这个文件的内容是 kubectl 访问 k8s 集群的准入 Token,只有在指定了该 Token 后,才能使用 kubectl 指令来对集群内的各种资源进行增删改查。由于 runner 在 CICD 过程中需要对 k8s 集群进行操作,因此,每一个 runner 中都必须具备 Token以供 gitrunner 的 k8s 执行器使用。

​ 使用 secrete 将这个 Token 以卷挂载的方式加入到 runner 创建的 pod 中。

​ 温馨提示:请务必保证 config 文件中包含的证书与密钥没有过期

安装 helm

链接:https://www.cnblogs.com/zouzou-busy/p/16134885.html

配置chart 存储库

# 添加 chart 存储库
[root@master1 ~]# helm repo add gitlab https://charts.gitlab.io
"gitlab" has been added to your repositories

# 查看存储库
[root@master1 ~]# helm repo list
NAME      URL
gitlab    https://charts.gitlab.io

查看可以安装的 gitlab-runner chart

helm search repo -l gitlab/gitlab-runner

 

 

[root@node2 test]# helm search repo -l gitlab/gitlab-runner|grep  14.6.1
gitlab/gitlab-runner    0.36.1          14.6.1          GitLab Runner

获取对应版本的 chart 包

复制代码
[root@master gitlab-runner]#  helm fetch gitlab/gitlab-runner --version=0.36.1
[root@master gitlab-runner]# ls
gitlab-runner-0.36.1.tgz

[root@master gitlab-runner]# tar -zxf gitlab-runner-0.36.1.tgz
[root@master gitlab-runner]# cd gitlab-runner/
[root@master gitlab-runner]# ls
CHANGELOG.md Chart.yaml CONTRIBUTING.md LICENSE Makefile NOTICE README.md templates values.yaml

复制代码

主要的一个文件是 values.yaml 文件,各个字段配置说明

复制代码
image: #指定gitlab-runner镜像
imagePullPolicy: #镜像拉取策略
gitlabUrl: #gitlab地址
runnerRegistrationToken: #gitlab-runner注册用到的tocken
concurrent: #设置同行运行的runner个数
checkInterval: #定义检查gitlab新构建的频率
rbac: #角色设置
  create: true
  clusterWideAccess: true
metrics: #prometheus metrics数据暴露
  enabled: true
runners: #runners配置
  image:
  imagePullSecrets:
  imagePullPolicy:
  locked: #是否设置为特定的runner
  tags: #设置标签
  privileged: true
  secret: 
  namespace: 
  cache: {}
  builds: #构建资源限制
    cpuLimit: 200m
    memoryLimit: 256Mi
    cpuRequests: 100m
    memoryRequests: 128Mi
  services: {}
  helpers: {}
  serviceAccountName:
  nodeSelector: #worker调度选择器
resources: {} #资源限制
affinity: {} #节点亲和性
nodeSelector: {} #节点调度选择器
tolerations: [] #污点容忍度
envVars: #环境变量设置
  - name: RUNNER_EXECUTOR
    value: kubernetes
values.yaml
复制代码

我们需要修改 values.yaml 文件,修改的地方如下

 

 

 

 

 

 

 修改完上面的后保存,也可以根据自己的需求修改更多的内容

 

部署 gitlab-runner

我们创建一个 gitlab-runner 的 ns,把资源创建在这个下面

# 创建 ns
[root@master1 gitlab-runner]# kubectl create ns gitlab-runner
namespace/gitlab-runner created

使用 helm 创建资源

复制代码
# 创建资源,要和 gitlab-runner 目录同级

[root@master gitlab-runner]# helm install gitlab-runner --namespace gitlab-runner ./gitlab-runner
NAME: gitlab-runner
LAST DEPLOYED: Mon Jan 15 16:33:57 2024
NAMESPACE: gitlab-runner
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Your GitLab Runner should now be registered against the GitLab instance reachable at: "http://101.xx.xx.xx:32080/"


Runner namespace "gitlab-runner" was found in runners.config template.
[root@master gitlab-runner]#

 
复制代码

创建完成后查看 pod 和 deployment,可以看到只有一个 pod 在运行

[root@master gitlab-runner]# kubectl get pod,deploy,svc -n gitlab-runner
NAME                                               READY   STATUS    RESTARTS   AGE
pod/gitlab-runner-gitlab-runner-84fc6bb478-9k4rd   1/1     Running   0          110s

NAME                                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gitlab-runner-gitlab-runner   1/1     1            1           110s
[root@master gitlab-runner]#

在 gitlab 里查看 runner

 如果我们更新了 values.yaml 文件,只需要使用下面命令更新一下就可以了

# 更新
helm upgrade gitlab-runner --namespace gitlab-runner ./gitlab-runner

运行流水线进行测试

复制代码
这个命令用于在 Kubernetes 中创建一个名为 generic 的 Secret,并将您的 /root/.kube/config 文件中的内容作为数据值添加到该 Secret 中。

具体来说,这个命令的各个部分的含义如下:

kubectl create secret generic:表示要创建一个名为 generic 的 Secret。
--from-file=config=~/.kube/config:表示要从文件中读取数据值,并将其添加到 Secret 中。在这里,config 是数据值的名称,~/.kube/config 是要读取的文件路径。
-n gitlab:表示要将 Secret 创建在名为 gitlab 的命名空间中。
因此,这个命令的作用是将您的 ~/.kube/config 文件中的内容作为数据值添加到名为 generic 的 Secret 中,并将该 Secret 创建在名为 gitlab 的命名空间中。

您可以使用以下命令查看 Secret 的详细信息:

kubectl describe secret generic -n gitlab
这将显示 Secret 的详细信息,包括其创建时间、更新时间、数据值等。您可以通过这些信息来验证 Secret 是否已成功创建,并且数据值是否已正确添加。
复制代码
kubectl create secret generic generic --from-file=config=~/.kube/config -n gitlab

如果不添加会报错

 

.gitlab-ci.yml 文件内容如下

复制代码

default:
tags:
- kubernetes # 使用 k8s 的 runner

stages:
- build
- deploy


build:
stage: build
script:
- echo "我是 build"
- sleep 60

deploy:
stage: deploy
script:
- echo "我是 deploy"
- sleep 60

复制代码

运行流水线,查看 build 的日志

 这时候去集群上,查看 gitlab-runner 命名空间下的 pod

复制代码
[root@master ~]# kubectl get pod,deploy,svc -n gitlab-runner  
NAME                                               READY   STATUS    RESTARTS   AGE
pod/gitlab-runner-gitlab-runner-84fc6bb478-9k4rd   1/1     Running   0          61m
pod/runner-chrdj7sb-project-34-concurrent-0lwmvz   2/2     Running   0          24s

NAME                                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gitlab-runner-gitlab-runner   1/1     1            1           61m
[root@master ~]# kubectl get pod,deploy,svc -n gitlab-runner  
NAME                                               READY   STATUS    RESTARTS   AGE
pod/gitlab-runner-gitlab-runner-84fc6bb478-9k4rd   1/1     Running   0          61m
pod/runner-chrdj7sb-project-34-concurrent-0lwmvz   2/2     Running   0          29s
复制代码

 

当 build 的 job 运行完成之后,我们在去查看 pod,已经被销毁了

[root@master ~]# kubectl get pod,deploy,svc -n gitlab-runner  
NAME                                               READY   STATUS    RESTARTS   AGE
pod/gitlab-runner-gitlab-runner-84fc6bb478-9k4rd   1/1     Running   0          61m

NAME                                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gitlab-runner-gitlab-runner   1/1     1            1           61m

deploy 的 job 运行完成之后,也就销毁了

 

并发运行

我们在 value.yaml 里设置的并发数是 10,那我们写个并发的流水线来看看

复制代码
default:
  tags:
    - kubernetes 
    
stages:
  - build
  - deploy


build:
  stage: build
  script:
    - echo "我是 build"
    - sleep 60

build1:
  stage: build
  script:
    - echo "我是 build1"
    - sleep 60
  

build2:
  stage: build
  script:
    - echo "我是 build2"
    - sleep 60

deploy:
  stage: deploy
  script:
    - echo "我是 deploy"
    - sleep 60


deploy1:
  stage: deploy
  script:
    - echo "我是 deploy1"
    - sleep 60
复制代码

 

 这时候查看 pod

复制代码
[root@master ~]#  kubectl get pod,deploy,svc -n gitlab-runner
NAME                                               READY   STATUS    RESTARTS   AGE
pod/gitlab-runner-gitlab-runner-84fc6bb478-9k4rd   1/1     Running   0          77m
pod/runner-chrdj7sb-project-34-concurrent-05l6w7   2/2     Running   0          57s
pod/runner-chrdj7sb-project-34-concurrent-12nm4x   2/2     Running   0          56s
pod/runner-chrdj7sb-project-34-concurrent-2mfbsr   2/2     Running   0          56s

NAME                                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gitlab-runner-gitlab-runner   1/1     1            1           77m
[root@master ~]#
复制代码

等 job 运行完成之后就会删除对应的 pod

使用 k8s 的 runner 使用缓存

在 k8s 里的 runner 使用缓存默认是不行的,如下

复制代码
317字节
default:
  tags:
    - kubernetes # 使用 k8s 的 runner
    
stages:
  - build
  - deploy
  
build:
  stage: build
  cache: # 使用缓存
    paths:
      - abc.txt
  script:
    - echo "我是 build"
    - touch abc.txt
  
deploy:
  stage: deploy
  cache: # 使用缓存
    paths:
      - abc.txt
  script:
    - echo "我是 deploy"
    - ls
复制代码

 

 

使用制品 artifacts

复制代码
default:
  tags:
    - kubernetes # 使用 k8s 的 runner
    
stages:
  - build
  - deploy


build:
  stage: build
  script:
    - echo "我是 build"
    - touch abc.txt
  artifacts:
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" # 创建制品存档的名称
    when: on_success  # 制品何时进行收集
    expire_in: "1 week"  # 制品的过期时间,过期自动清理
    paths:  # 定义要收集的制品文件或者目录信息
      - abc.txt
  
deploy:
  stage: deploy
  script:
    - echo "我是 deploy"
    - ls
  dependencies:  # 只使用 build 阶段产生的制品,不写 dependencies 默认会下载所有阶段产生的制品
    - build
复制代码

 

 

posted @   IT老登  阅读(1774)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
历史上的今天:
2016-01-15 day2 作业二
访次: AmazingCounters.com 次
点击右上角即可分享
微信分享提示