22.云原生之GitLab CICD实战及解析【干货】

云原生专栏大纲

文章目录

CICD流程:

  1. 使用maven打包项目
  2. 制作docker镜像
  3. 推送镜像到harbor仓库
  4. 部署到k8s

GitLab Runner k8s执行器工作流程

在 GitLab Runner 中使用 Kubernetes (k8s) 执行器时,以下是其工作流程的一般概述:

  1. 配置 Kubernetes 集群:首先,你需要在 GitLab Runner 所在的机器上配置和连接到 Kubernetes 集群。这包括安装和配置 kubectl 命令行工具,并确保 Runner 具有访问 Kubernetes 集群的权限。
  2. 注册 Runner:使用 gitlab-runner register 命令注册一个新的 Runner,选择 kubernetes 作为执行器。在注册过程中,你需要提供 GitLab 实例的 URL、Runner 的描述、Kubernetes 集群的相关配置等信息。
  3. 配置 Runner:完成注册后,GitLab Runner 将生成一个配置文件,其中包含与 Kubernetes 执行器相关的配置信息,例如 Kubernetes API 的地址、访问凭证等。这些配置将被保存在 Runner 的配置目录中。
  4. 运行作业:当有作业需要执行时,GitLab CI/CD 将向 GitLab Runner 发送作业请求。Runner 将根据作业的定义和配置,使用 Kubernetes API 向 Kubernetes 集群提交一个 Pod 规范,描述作业的运行环境和要运行的容器。
  5. 创建 Pod:Kubernetes 集群接收到 Runner 提交的 Pod 规范后,将根据规范创建一个 Pod。Pod 是 Kubernetes 中的最小调度单位,可以包含一个或多个容器。
  6. 容器运行:一旦 Pod 创建成功,Kubernetes 将根据 Pod 规范在集群中选择一个合适的节点,并在该节点上创建和运行容器。容器将根据作业定义的镜像和命令来执行相应的操作,例如构建、测试或部署。
  7. 监听作业状态:GitLab Runner 会定期查询 Kubernetes API 来获取作业的状态信息。这包括容器的运行状态、日志输出等。Runner 将这些信息返回给 GitLab CI/CD,以便实时监控作业的进度和结果。
  8. 提交结果:作业完成后,GitLab Runner 将收集作业的结果,包括日志输出、环境变量等,并将其提交给 GitLab CI/CD。这些结果将在 GitLab CI/CD 界面上显示,并可以用于后续的流程控制和报告生成。
  9. 清理资源:一旦作业完成,Kubernetes 将根据配置自动清理相关的 Pod 和容器。这确保了资源的有效使用和释放。

通过将 GitLab Runner 与 Kubernetes 执行器结合使用,你可以在 Kubernetes 集群中动态地创建和管理容器化的作业环境,实现高度可扩展的持续集成和持续交付流程。

注册配置kubernetes runner

注册器kubernetes 的gitlab runner,使用参考Kubernetes executor官网Executors | GitLab
执行器 | 极狐GitLab

helm方式部署优势:

  1. 省去了注册kubernetes执行器很多细节,kubernetes执行器是最复杂的一个

helm方式部署缺点:

  1. helm方式部署的github-runner使用了特定的镜像,启动后很多目录用户没有操作权限
  2. 该镜像不能以特权用户启动
  3. 配置挂载路径和gitlab官网使用镜像挂载路径存在区别

kubernetes runner配置

通过修改 Pod 规范为每个构建作业创建一个 PVC

若要为每个生成作业创建 PersistentVolumeClaim,请确保查看如何启用 Pod Spec 功能

Kubernetes 允许创建一个附加到 Pod 生命周期的临时 PersistentVolumeClaim。 如果在 Kubernetes 集群上启用了动态预配,这将起作用,允许 每个请求一个新的卷,该也将与 Pod 的生命周期相关联。PVC

启用动态配置后,可以按如下方式修改:

yaml 复制代码
[[runners.kubernetes.pod_spec]]
  name = "ephemeral-pvc"
  patch = '''
    containers:
    - name: build
      volumeMounts:
      - name: builds
        mountPath: /builds
    - name: helper
      volumeMounts:
      - name: builds
        mountPath: /builds
    volumes:
    - name: builds
      ephemeral:
        volumeClaimTemplate:
          spec:
            storageClassName: <The Storage Class that will dynamically provision a Volume>
            accessModes: [ ReadWriteOnce ]
            resources:
              requests:
                storage: 1Gi
  '''

自定义卷装载

要存储作业的 builds 目录,请定义自定义卷挂载到 已配置(默认)。 如果您使用 PVC 卷, 基于接入模式, 您可能被限制为在一个节点上运行作业。builds_dir/builds

yaml 复制代码
concurrent = 4

[[runners]]
  # usual configuration
  executor = "kubernetes"
  builds_dir = "/builds"
  [runners.kubernetes]
    [[runners.kubernetes.volumes.empty_dir]]
      name = "repo"
      mount_path = "/builds"
      medium = "Memory"

持久性并发构建卷

默认情况下,Kubernetes CI 作业中的构建目录是临时的。 如果您想在作业中持久化 Git 克隆(以使其正常工作), 您必须为生成文件夹装载持久性卷声明。 由于多个作业可以同时运行,因此您必须 使用一个卷,或为每个电位设置一个卷 同一运行器上的并发作业。后者可能性能更高。

yaml 复制代码
concurrent = 4

[[runners]]
  executor = "kubernetes"
  builds_dir = "/mnt/builds"
  [runners.kubernetes]
    [[runners.kubernetes.volumes.pvc]]
      # CI_CONCURRENT_ID identifies parallel jobs of the same runner.
      # name是pvc名称如"build-pvc-$CI_CONCURRENT_ID"
      name = "k8s-running-pod-data"
      mount_path = "/mnt/builds"

为容器设置安全策略

  • 设置 Pod 安全上下文。

  • 重写以及生成和帮助程序容器。run_as_userrun_as_group

  • 指定所有服务容器都继承 Pod 安全上下文并从 Pod 安全上下文继承。run_as_userrun_as_group

    concurrent = 4
    check_interval = 30
    [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"
    [runners.kubernetes]
    helper_image = "gitlab-registry.example.com/helper:latest"
    [runners.kubernetes.pod_security_context]
    run_as_non_root = true
    run_as_user = 59417
    run_as_group = 59417
    fs_group = 59417
    [runners.kubernetes.init_permissions_container_security_context]
    run_as_user = 1000
    run_as_group = 1000
    [runners.kubernetes.build_container_security_context]
    run_as_user = 65534
    run_as_group = 65534
    [runners.kubernetes.build_container_security_context.capabilities]
    add = ["NET_ADMIN"]
    [runners.kubernetes.helper_container_security_context]
    run_as_user = 1000
    run_as_group = 1000
    [runners.kubernetes.service_container_security_context]
    run_as_user = 1000
    run_as_group = 1000

选择 类型 必填 描述
run_as_group int 用于运行容器进程入口点的 GID。
run_as_non_root 布尔 指示容器必须以非 root 用户身份运行。
run_as_user int 用于运行容器进程入口点的 UID。
capabilities.add 字符串列表 运行容器时要添加的功能。
capabilities.drop 字符串列表 运行容器时要删除的功能。
selinux_type 字符串 与容器进程关联的 SELinux 类型标签。

设置拉取策略

使用文件中的参数指定单个或多个拉取策略。 该策略控制如何提取和更新映像,并应用于生成映像、帮助程序映像和任何服务。pull_policyconfig.toml

要确定要使用的策略,请参阅有关拉取策略的 Kubernetes 文档

对于单个拉取策略:

复制代码
[runners.kubernetes]
  pull_policy = "never"

对于多个拉取策略:

复制代码
[runners.kubernetes]
  # use multiple pull policies
  pull_policy = ["always", "if-not-present"]

当您定义多个策略时,将尝试每个策略,直到成功获取映像。 例如,当您使用 时,如果策略由于临时注册表问题而失败,则使用该策略。[ always, if-not-present ]if-not-presentalways

要重试失败的拉取,请执行以下操作:

复制代码
[runners.kubernetes]
  pull_policy = ["always", "always"]

GitLab 的命名约定与 Kubernetes 的命名约定不同。

运行器拉取策略 Kubernetes 拉取策略 描述
空白 空白 使用 Kubernetes 指定的默认策略。
if-not-present IfNotPresent 仅当执行作业的节点上尚不存在映像时,才会拉取该映像。您应该注意一些安全注意事项
always Always 每次执行作业时都会拉取映像。
never Never 永远不会拉取映像,并且要求节点已经拥有它。

配置 Pod DNS 设置

使用以下选项配置 Pod 的 DNS 设置

选项 类型 必须 描述
nameservers string 列表 将用作 Pod 的 DNS 服务器的 IP 地址列表
options KubernetesDNSConfigOption 一个可选的对象列表,其中每个对象可能有一个名称参数(必需)和一个值参数(可选)
searches string 列表 用于在 Pod 中查找主机名的 DNS 搜索域列表

config.toml 文件中的配置示例:

复制代码
concurrent = 1
check_interval = 30
[[runners]]
  name = "myRunner"
  url = "https://gitlab.example.com"
  token = "__REDACTED__"
  executor = "kubernetes"
  [runners.kubernetes]
    image = "alpine:latest"
    [runners.kubernetes.dns_config]
      nameservers = [
        "1.2.3.4",
      ]
      searches = [
        "ns1.svc.cluster-domain.example",
        "my.dns.search.suffix",
      ]

      [[runners.kubernetes.dns_config.options]]
        name = "ndots"
        value = "2"

      [[runners.kubernetes.dns_config.options]]
        name = "edns0"

KubernetesDNSConfigOption:

选项 类型 必须 描述
name 字符串 配置选项名称。
value *string 配置选项值。

kubesphere应用仓库中部署

  1. 添加仓库:https://charts.gitlab.io
  2. 修改values.yml
yaml 复制代码
#以下两个在gitlab页面获取
gitlabUrl: http://192.168.31.3:83 # 使用k8s内部gitlab svc地址
runnerRegistrationToken: "GR1348941EfP6qKATzEULxDtvkvAg" #gitlab-runner注册用到的tocken

concurrent: 10 #最大作业并发数
checkInterval: 30 #新作业检查间隔
tags: "k8s" #runner的标签
#rbac权限打开
rbac:
  create: true
  resources: ["pods", "pods/exec", "secrets","configmaps"]
  verbs: ["get", "list", "watch", "create", "patch", "delete","update"]
runners:
  # 下述配置
  config: |
  1. 查看部署情况

在kubesphere应用仓库部署结果如下,部署到了ksnode26节点上:

  1. 使用特权模式:在创建容器时,使用--privileged参数来启动特权模式。这将使容器拥有更高的权限,并允许执行需要特权的操作。例如,使用docker run --privileged命令来启动容器。
  2. 允许特权提升:如果你不想在整个容器中启用特权模式,可以使用--cap-add参数来允许特定的权限提升。例如,使用docker run --cap-add=SYS_ADMIN命令来允许容器在运行时获取系统管理权限。
  3. 挂载可写目录:如果根目录是只读的,你可以尝试将一个可写的目录挂载到容器中,并在该目录中执行需要写入的操作。使用-v参数来挂载目录,例如,使用docker run -v /path/on/host:/path/in/container命令将主机上的目录挂载到容器中。

部署细节

部署后进入终端发现一些目录无操作权限,这是Docker容器的安全限制导致,可设置容器访问控制

启动命令
yaml 复制代码
/usr/bin/dumb-init,--,/bin/bash,/configmaps/entrypoint

查看/configmaps:

这个命令是使用了/usr/bin/dumb-init作为初始进程,然后运行/bin/bash作为子进程,并将/configmaps/entrypoint作为参数传递给/bin/bash。

/usr/bin/dumb-init是一个轻量级的进程初始化器,它可以帮助正确处理子进程的信号和进程间通信。它在容器环境中经常被使用,以确保进程的正确启动和终止。

/bin/bash是一个常见的Unix和Linux系统中的命令解释器。它提供了一个交互式的命令行界面,可以运行命令和脚本,并提供了丰富的功能和工具集。

/configmaps/entrypoint是一个文件路径,它可能是一个配置映射(ConfigMap)中的入口点脚本。ConfigMap是Kubernetes中用于存储配置数据的一种资源类型。入口点脚本通常用于在容器启动时执行一些初始化操作或配置加载。

综合起来,这个命令的作用是使用dumb-init作为初始进程,启动一个bash子进程,并将/configmaps/entrypoint作为参数传递给bash。这可能是在容器环境中运行的一个脚本或配置文件的启动方式。具体的功能和目的需要查看/configmaps/entrypoint文件的内容来确定。

环境变量
yaml 复制代码
CI_SERVER_URL:http://192.168.31.3:83/
RUNNER_EXECUTOR:kubernetes
REGISTER_LOCKED:true
RUNNER_TAG_LIST:k8s
挂载情况
config.toml

配置文件使用临时挂载,挂载路径/home/gitlab-runner/.gitlab-runner/config.toml,默认配置如下

yaml 复制代码
concurrent = 10
check_interval = 30
log_level = "info"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "gitlab-k8s-runner-gitlab-runner-6fff86bf78-nbjrn"
  url = "http://192.168.31.3:83/"
  id = 7
  token = "HxBNrMvn89soRxaKiR4v"
  token_obtained_at = 2024-01-24T09:31:39Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "kubernetes"
  [runners.cache]
    MaxUploadedArchiveSize = 0
  [runners.kubernetes]
    host = ""
    bearer_token_overwrite_allowed = false
    image = "alpine"
    namespace = "base"
    namespace_overwrite_allowed = ""
    node_selector_overwrite_allowed = ""
    pod_labels_overwrite_allowed = ""
    service_account_overwrite_allowed = ""
    pod_annotations_overwrite_allowed = ""
    [runners.kubernetes.pod_security_context]
    [runners.kubernetes.init_permissions_container_security_context]
    [runners.kubernetes.build_container_security_context]
    [runners.kubernetes.helper_container_security_context]
    [runners.kubernetes.service_container_security_context]
    [runners.kubernetes.volumes]
    [runners.kubernetes.dns_config]

/entrypoint文件

yaml 复制代码
#!/bin/sh

# gitlab-runner data directory
DATA_DIR="/etc/gitlab-runner"
CONFIG_FILE=${CONFIG_FILE:-$DATA_DIR/config.toml}
# custom certificate authority path
CA_CERTIFICATES_PATH=${CA_CERTIFICATES_PATH:-$DATA_DIR/certs/ca.crt}
LOCAL_CA_PATH="/usr/local/share/ca-certificates/ca.crt"

update_ca() {
  echo "Updating CA certificates..."
  cp "${CA_CERTIFICATES_PATH}" "${LOCAL_CA_PATH}"
  update-ca-certificates --fresh >/dev/null
}

if [ -f "${CA_CERTIFICATES_PATH}" ]; then
  # update the ca if the custom ca is different than the current
  cmp -s "${CA_CERTIFICATES_PATH}" "${LOCAL_CA_PATH}" || update_ca
fi

# launch gitlab-runner passing all arguments
exec gitlab-runner "$@"

这个Shell脚本的作用是更新GitLab Runner的CA证书。

首先,它定义了一些变量:

  • DATA_DIR 变量设置为 /etc/gitlab-runner,表示GitLab Runner的数据目录。
  • CONFIG_FILE 变量使用了KaTeX parse error: Expected '}', got 'EOF' at end of input: {CONFIG_FILE:-DATA_DIR/config.toml}的语法,表示如果CONFIG_FILE变量未定义,则使用$DATA_DIR/config.toml作为默认值。
  • CA_CERTIFICATES_PATH 变量使用了KaTeX parse error: Expected '}', got 'EOF' at end of input: ...IFICATES_PATH:-DATA_DIR/certs/ca.crt}的语法,表示如果CA_CERTIFICATES_PATH变量未定义,则使用$DATA_DIR/certs/ca.crt作为默认值。
  • LOCAL_CA_PATH 变量设置为 /usr/local/share/ca-certificates/ca.crt,表示本地系统中的CA证书路径。

接下来,脚本定义了一个名为 update_ca 的函数。该函数的作用是更新CA证书。它执行以下操作:

  • 打印消息 "Updating CA certificates..."。
  • 使用 cp 命令将 C A C E R T I F I C A T E S P A T H 的内容复制到 {CA_CERTIFICATES_PATH}的内容复制到 CACERTIFICATESPATH的内容复制到{LOCAL_CA_PATH}。
  • 使用 update-ca-certificates --fresh 命令更新系统的CA证书。

然后,脚本使用条件语句检查${CA_CERTIFICATES_PATH}文件是否存在。如果文件存在,则执行以下操作:

  • 使用 cmp 命令比较 C A C E R T I F I C A T E S P A T H 和 {CA_CERTIFICATES_PATH}和 CACERTIFICATESPATH和{LOCAL_CA_PATH}的内容是否相同。如果不相同,则调用 update_ca 函数更新CA证书。

最后,脚本使用 exec 命令运行 gitlab-runner 命令,并将脚本的参数("$@")传递给 gitlab-runner 命令。这将启动GitLab Runner并执行相应的操作。

总体而言,这个脚本的目的是确保GitLab Runner的CA证书是最新的,并在启动GitLab Runner之前执行必要的更新操作。

/configmaps 目录
  • check-live

    #!/bin/bash
    set -eou pipefail

    if ! /usr/bin/pgrep -f ".*register-the-runner" > /dev/null && ! /usr/bin/pgrep -f "gitlab.*runner" > /dev/null ; then
    exit 1
    fi

    name=(awk -F'"' '/^ name = ".*"/ { print 2 }' "{HOME%/root}/.gitlab-runner/config.toml") url=(awk -F'"' '/^ url = ".*"/ { print 2 }' "{HOME%/root}/.gitlab-runner/config.toml")

    gitlab-runner verify -n "name" -u "url" 2>&1 | grep -E "is alive|is valid"

  • config.template.toml

    [[runners]]
    [runners.kubernetes]
    namespace = "base"
    image = "alpine"

  • config.toml

    shutdown_timeout = 0
    concurrent = 10
    check_interval = 30
    log_level = "info"

  • entrypoint

    #!/bin/bash
    set -e

    export CONFIG_PATH_FOR_INIT="/home/gitlab-runner/.gitlab-runner/"
    mkdir -p {CONFIG_PATH_FOR_INIT} cp /configmaps/config.toml {CONFIG_PATH_FOR_INIT}

    Set up environment variables for cache

    if [[ -f /secrets/accesskey && -f /secrets/secretkey ]]; then
    export CACHE_S3_ACCESS_KEY=(cat /secrets/accesskey) export CACHE_S3_SECRET_KEY=(cat /secrets/secretkey)
    fi

    if [[ -f /secrets/gcs-applicaton-credentials-file ]]; then
    export GOOGLE_APPLICATION_CREDENTIALS="/secrets/gcs-applicaton-credentials-file"
    elif [[ -f /secrets/gcs-application-credentials-file ]]; then
    export GOOGLE_APPLICATION_CREDENTIALS="/secrets/gcs-application-credentials-file"
    else
    if [[ -f /secrets/gcs-access-id && -f /secrets/gcs-private-key ]]; then
    export CACHE_GCS_ACCESS_ID=(cat /secrets/gcs-access-id) # echo -e used to make private key multiline (in google json auth key private key is oneline with \n) export CACHE_GCS_PRIVATE_KEY=(echo -e $(cat /secrets/gcs-private-key))
    fi
    fi

    if [[ -f /secrets/azure-account-name && -f /secrets/azure-account-key ]]; then
    export CACHE_AZURE_ACCOUNT_NAME=(cat /secrets/azure-account-name) export CACHE_AZURE_ACCOUNT_KEY=(cat /secrets/azure-account-key)
    fi

    if [[ -f /secrets/runner-registration-token ]]; then
    export REGISTRATION_TOKEN=$(cat /secrets/runner-registration-token)
    fi

    if [[ -f /secrets/runner-token ]]; then
    export CI_SERVER_TOKEN=$(cat /secrets/runner-token)
    fi

    Register the runner

    if ! sh /configmaps/register-the-runner; then
    exit 1
    fi

    Run pre-entrypoint-script

    if ! bash /configmaps/pre-entrypoint-script; then
    exit 1
    fi

    Start the runner

    exec /entrypoint run
    --working-directory=/home/gitlab-runner

这个Shell脚本的作用是配置GitLab Runner的运行环境,并执行GitLab Runner的入口点命令。

首先,set -e 表示在脚本中如果有任何命令执行失败(返回非零退出码),则立即退出脚本。

接下来,脚本导出了一个名为 CONFIG_PATH_FOR_INIT 的环境变量,设置为 /home/gitlab-runner/.gitlab-runner/。然后使用 mkdir -p 命令创建了该路径。

然后,脚本使用 cp 命令将 /configmaps/config.toml 文件复制到 ${CONFIG_PATH_FOR_INIT} 目录中。

接下来,脚本使用条件语句检查一些文件是否存在。如果文件存在,则将其内容读取到相应的环境变量中。具体的环境变量如下:

  • CACHE_S3_ACCESS_KEY 和 CACHE_S3_SECRET_KEY:从 /secrets/accesskey 和 /secrets/secretkey 读取内容。
  • GOOGLE_APPLICATION_CREDENTIALS:从 /secrets/gcs-applicaton-credentials-file 或 /secrets/gcs-application-credentials-file 读取文件路径。
  • CACHE_GCS_ACCESS_ID 和 CACHE_GCS_PRIVATE_KEY:从 /secrets/gcs-access-id 和 /secrets/gcs-private-key 读取内容。
  • CACHE_AZURE_ACCOUNT_NAME 和 CACHE_AZURE_ACCOUNT_KEY:从 /secrets/azure-account-name 和 /secrets/azure-account-key 读取内容。
  • REGISTRATION_TOKEN:从 /secrets/runner-registration-token 读取内容。
  • CI_SERVER_TOKEN:从 /secrets/runner-token 读取内容。

然后,脚本分别执行 /configmaps/register-the-runner 和 /configmaps/pre-entrypoint-script 脚本。如果其中任何一个脚本执行失败(返回非零退出码),则脚本会退出并返回1。

最后,脚本使用 exec 命令执行 /entrypoint run 命令,并传递 --working-directory=/home/gitlab-runner 参数。这将启动GitLab Runner,并设置工作目录为 /home/gitlab-runner。

总体而言,这个脚本的目的是设置GitLab Runner的配置文件和环境变量,然后执行GitLab Runner的入口点命令以启动Runner。

  • pre-entrypoint-script

  • register-the-runner

    #!/bin/bash
    MAX_REGISTER_ATTEMPTS=30

    Reset/unset the not needed flags when an authentication token

    RUN_UNTAGGED=""
    ACCESS_LEVEL=""

    for i in (seq 1 "{MAX_REGISTER_ATTEMPTS}"); do
    echo "Registration attempt {i} of {MAX_REGISTER_ATTEMPTS}"
    /entrypoint register
    {RUN_UNTAGGED} \ {ACCESS_LEVEL}
    --template-config /configmaps/config.template.toml
    --non-interactive

    复制代码
    retval=$?
    
    if [ ${retval} = 0 ]; then
      break
    elif [ ${i} = ${MAX_REGISTER_ATTEMPTS} ]; then
      exit 1
    fi
    
    sleep 5

    done

    exit 0

/secrets

runner-token文件内容空

runner-registration-token文件内容:GR1348941EfP6qKATzEULxDtvkvAg

runner 默认配置问题

上述方式部署存在runner pod重启,config.toml配置被重置情况,原因在于下述启动命令中,/configmaps中的脚本。

复制代码
/usr/bin/dumb-init,--,/bin/bash,/configmaps/entrypoint

/configmaps挂载为了ConfigMap,默认存在如下问题:

  1. 重启runner 后config.toml配置会被重置为初始配置
  2. 重启runner 后构建后的文件丢失
  3. 内网harbor域名解析问题

需修改ConfigMap下config.template.toml 配置:

复制代码
[[runners]]
  builds_dir = "/builds"
  [runners.kubernetes]
    namespace = "base"
    image = "alpine"
    pull_policy = "if-not-present"
    [[runners.kubernetes.volumes.pvc]]
      name = "k8s-running-pod-data"
      mount_path = "/builds"
    [[runners.kubernetes.volumes.host_path]]
      name = "docker"
      mount_path = "/var/run/docker.sock"
      host_path = "/var/run/docker.sock"
    [[runners.kubernetes.host_aliases]]
      ip = "192.168.31.11"
      hostnames = ["harbor域名"]

最后生成config.toml 配置如下

runner注册配置可直接修改config.toml 配置文件,无需重启即可生效

复制代码
concurrent = 10
check_interval = 30
log_level = "info"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "k8s-gitlab-runner-gitlab-runner-58d796f689-n6phl"
  url = "http://192.168.31.3:83"
  id = 63
  token = "EzF_D7wPTwAjfvxjnvdS"
  token_obtained_at = 2024-01-28T09:56:06Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "kubernetes"
  builds_dir = "/builds"
  [runners.cache]
    MaxUploadedArchiveSize = 0
  [runners.kubernetes]
    host = ""
    bearer_token_overwrite_allowed = false
    image = "alpine"
    namespace = "base"
    namespace_overwrite_allowed = ""
    pull_policy = ["if-not-present"]
    node_selector_overwrite_allowed = ""
    pod_labels_overwrite_allowed = ""
    service_account_overwrite_allowed = ""
    pod_annotations_overwrite_allowed = ""
    [runners.kubernetes.pod_security_context]
    [runners.kubernetes.init_permissions_container_security_context]
    [runners.kubernetes.build_container_security_context]
    [runners.kubernetes.helper_container_security_context]
    [runners.kubernetes.service_container_security_context]
    [runners.kubernetes.volumes]

      [[runners.kubernetes.volumes.host_path]]
        name = "docker"
        mount_path = "/var/run/docker.sock"
        host_path = "/var/run/docker.sock"

      [[runners.kubernetes.volumes.pvc]]
        name = "k8s-running-pod-data"
        mount_path = "/builds"

    [[runners.kubernetes.host_aliases]]
      ip = "192.168.31.11"
      hostnames = ["harbor域名"]
    [runners.kubernetes.dns_config]

gitlab-ci.yml流水线

可参考官网GitLab CI/CD examples | 预定义的 CI/CD 变量参考

打包项目

  1. 打包
yaml 复制代码
variables:
  MAVEN_OPTS: >-
    -Dmaven.repo.local=/builds/maven #maven下载文件路径
    -Dorg.slf4j.simpleLogger.showDateTime=true
    -Djava.awt.headless=true
  MAVEN_CLI_OPTS: >-
    --batch-mode
    --errors
    --fail-at-end
    --show-version
    --no-transfer-progress
    -DinstallAtEnd=true
    -DdeployAtEnd=true
    
package:
  stage: package
  image: maven:3.6.3-jdk-8
  tags:
    - k8s
  script:
    - pwd
    - mvn clean package -Dmaven.test.skip=true
    # 将打包后target拷贝到指定目录
    - rm -rf /builds/project-target/devops-web
    - rm -rf /builds/project-target/devops-service
    - cp -rf ./devops-web /builds/project-target/devops-web
    - cp -rf ./devops-service /builds/project-target/devops-service

上述考虑问题:

  1. 首次拉取镜像可能超时失败

提前在宿主机上拉取镜像

  1. maven镜像源、依赖缓存

将保存maven下载文件路径挂载出来,将下载好的资源上传

  1. 打包好后jar需要存放,后续制作镜像使用

将maven打包后的制品拷贝到挂载路径下

执行日志解析
  1. 拉取镜像日志如下:

执行作业时,会拉取镜像构建maven环境,在k8s集群所有节点上执行发现maven:3.6.3-jdk-8拉取在ksnode20节点上

yaml 复制代码
docker ps | grep maven
  1. 拉取代码日志如下:

进入gitlab-runner终端查看拉取的代码:

  1. 执行shell脚本
  1. 构建项目,拉取maven依赖
参数 描述
-Dmaven.test.skip=true 跳过测试阶段
-Dmaven.compiler.source 指定源代码的编译版本
-Dmaven.compiler.target 指定生成的字节码的目标版本
-Dmaven.repo.local 指定本地仓库的路径
-Dmaven.settings=path 指定自定义的 Maven 配置文件路径
-Dmaven.wagon.http.ssl.insecure=true 允许使用不安全的 SSL 连接(仅限于特殊情况)
-Dmaven.wagon.http.ssl.allowall=true 接受所有 SSL 证书(仅限于特殊情况)
-Dmaven.test.failure.ignore=true 忽略测试失败,继续构建过程
-Dmaven.test.error.ignore=true 忽略测试错误,继续构建过程
-Dmaven.test.skip.exec=true 跳过执行测试,但仍然编译测试代码
-Dmaven.test.failure.ignore=true 忽略测试失败,继续构建过程
-Dmaven.test.skip.exec=true 跳过执行测试,但仍然编译测试代码
-Dmaven.test.failure.ignore=true 忽略测试失败,继续构建过程
-Dmaven.test.skip.exec=true 跳过执行测试,但仍然编译测试代码
-Dmaven.test.failure.ignore=true 忽略测试失败,继续构建过程
-Dmaven.test.skip.exec=true 跳过执行测试,但仍然编译测试代码

制作并推送镜像

kaniko方式

https://blog.51cto.com/zhangxueliang/5478060

yaml 复制代码
build:
  stage: build
  image:
    name: registry.cn-hongkong.aliyuncs.com/cmi/kaniko-project_executor:debug
    entrypoint: [""]
  tags:
    - k8s
  script:
    - /kaniko/executor
      --skip-tls-verify
      --insecure
      --context "${CI_PROJECT_DIR}"
      --dockerfile "/devops-web/Dockerfile"
      --destination "harbor.yxym.com/library/devops-web:kaniko"
  except:
    - tags
docker:cli方式
yaml 复制代码
docker-build:
#  image: docker:latest
  image: docker:cli
  services:
    - docker:dind
  stage: build
  script:
    - docker login -u admin -p Harbor12345 harbor域名
    - cd /builds/project-target
    - docker build -t devops-web:dind -f ./devops-web/Dockerfile  ./devops-web/
    - docker tag devops-web:dind harbor域名/library/devops-web:dind
    - docker push harbor域名/library/devops-web:dind
验证

登录gitlab查看流水线:

登录harbor查看镜像是否推送到仓库

部署到k8s

yaml 复制代码
deploy:
  image: google/cloud-sdk
  stage: deploy
  environment: staging
  script:
    - kubectl patch deployment $STAGING_SERVICE_NAME -p '{"spec":{"template":{"spec":{"containers":[{"name":"'"$STAGING_SERVICE_NAME"'","image":"'"$CI_REGISTRY_IMAGE:$CI_BUILD_REF"'"}]}}}}'
相关推荐
Serverless社区2 小时前
进阶指南:BrowserUse + Agentrun Sandbox 最佳实践指南
运维·阿里云·云原生·serverless·函数计算
Gold Steps.5 小时前
K8S基于 Argo Rollouts 的高级版本发布实践
云原生·容器·kubernetes
王九思6 小时前
Docker访问权限问题
docker·云原生·容器
孤岛悬城6 小时前
61 K8s之Pod控制器与配置资源管理
云原生·容器·kubernetes
噎住佩奇6 小时前
kubeadm方式部署单节点k8s
云原生·容器·kubernetes
追光的孩子7 小时前
window雷池WAF安装运行文档
云原生·eureka
不做码农好多年,该何去何从。7 小时前
云原生k8s(一)
云原生·容器·kubernetes
Y.O.U..8 小时前
Kubernetes-PV(PersistentVolume)和PVC(PersistentVolumeClaim)
云原生·容器·kubernetes
Curvatureflight8 小时前
Kubernetes完全指南:从集群搭建到生产部署
云原生·容器·kubernetes
博思云为8 小时前
企业级智能PPT生成:Amazon云+AI驱动,全流程自动化提效
人工智能·语言模型·云原生·数据挖掘·云计算·语音识别·aws