• gitlab pipeline 构建容器镜像方法


    gitlab pipeline 构建容器镜像方法

    随着 k8s 的流行,用容器的方式来交付软件产品也变得越来越普遍,那么在 gitlab ci/cd 流程中如何更快捷、更安全的方式来构建容器镜像呢?目前主要有两大的方式:

    • docker 构建镜像
    • Kaniko 构建镜像

    1. docker 构建镜像

    1.1 shell executor 方式

    注册 runner,使用 shell executor

    gitlab-runner register -n \
      --url https://jihulab.com/ \
      --registration-token REGISTRATION_TOKEN \
      --executor shell \
      --description "My Runner"
    

    在 runner 主机上安装 docker:Install Docker Engine | Docker Documentation

    添加 runner 到 docker 组

    usermod -aG docker gitlab-runner
    

    验证 gitlab-runner 用户是否能够访问 docker

    sudo -u gitlab-runner -H docker info
    

    在 pipeline 中使用 docker 打包镜像并上传到镜像仓库:

    before_script:
      - docker info
      - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    
    build:
      stage: build
      script:
        - docker pull $CI_REGISTRY_IMAGE:latest || true
        - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
        - docker push $CI_REGISTRY_IMAGE:latest
        - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
      rules:
        - if: $CI_COMMIT_TAG
    
    • 镜像仓库使用的时 gitlab 提供的 REGISTRY,也可以替换成自行搭建的仓库

    • 使用了 --cache 加速镜像构建

    1.2 挂载 docker.sock 文件方式

    使用 docker executor,runner 配置类似以下内容:

    [[runners]]
      url = "https://jihulab.com/"
      token = RUNNER_TOKEN
      executor = "docker"
      [runners.docker]
        tls_verify = false
        image = "docker:19.03.12"
        privileged = false
        disable_cache = false
        volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
      [runners.cache]
        Insecure = false
    

    使用以下注册方法可以生成上面配置内容:

    gitlab-runner register -n \
      --url https://jihulab.com/ \
      --registration-token REGISTRATION_TOKEN \
      --executor docker \
      --description "My Docker Runner" \
      --docker-image "docker:19.03.12" \
      --docker-volumes /var/run/docker.sock:/var/run/docker.sock
    

    在 pipeline 中使用 docker 打包镜像并上传到镜像仓库:

    image: docker:19.03.12
    
    before_script:
      - docker info
      - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    
    build:
      stage: build
      script:
        - docker pull $CI_REGISTRY_IMAGE:latest || true
        - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
        - docker push $CI_REGISTRY_IMAGE:latest
        - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
      rules:
        - if: $CI_COMMIT_TAG
    

    1.3 dind(docker-in-docker) 方式

    这种方式不需要挂载宿主机的socket文件,但是需要以 --privileged 权限来以 dind 镜像创建一个容器

    1.3.1 使用 docker executor

    开启 TLS

    docker 19.03.12 版本后,默认开启 TLS

    runner 配置类似以下内容:

    [[runners]]
      url = "https://jihulab.com/"
      token = TOKEN
      executor = "docker"
      [runners.docker]
        tls_verify = false
        image = "docker:19.03.12"
        privileged = true
        disable_cache = false
        volumes = ["/certs/client", "/cache"]
      [runners.cache]
        Insecure = false
    
    • privileged = true 必须

    使用以下注册方法可以生成上面配置内容:

    gitlab-runner register -n \
      --url https://jihulab.com/ \
      --registration-token REGISTRATION_TOKEN \
      --executor docker \
      --description "My Docker Runner" \
      --docker-image "docker:19.03.12" \
      --docker-privileged \
      --docker-volumes "/certs/client"
    

    在 pipeline 中使用 docker in docker 打包镜像并上传到镜像仓库:

    image: docker:19.03.12
    
    variables:
      DOCKER_DRIVER: overlay2
      DOCKER_HOST: tcp://docker:2376
      DOCKER_TLS_CERTDIR: "/certs"
    
    services:
      - docker:19.03.12-dind
    
    before_script:
      - docker info
      - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    
    build:
      stage: build
      script:
        - docker pull $CI_REGISTRY_IMAGE:latest || true
        - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
        - docker push $CI_REGISTRY_IMAGE:latest
        - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
      rules:
        - if: $CI_COMMIT_TAG
    

    关闭 TLS

    runner 配置类似以下内容:

    [[runners]]
      url = "https://jihulab.com/"
      token = TOKEN
      executor = "docker"
      [runners.docker]
        tls_verify = false
        image = "docker:19.03.12"
        privileged = true
        disable_cache = false
        volumes = ["/cache"]
      [runners.cache]
        Insecure = false
    

    在 pipeline 中使用 docker in docker 打包镜像并上传到镜像仓库:

    image: docker:19.03.12
    
    variables:
      DOCKER_DRIVER: overlay2
      DOCKER_HOST: tcp://docker:2375
      DOCKER_TLS_CERTDIR: ""
    
    services:
      - docker:19.03.12-dind
    
    before_script:
      - docker info
      - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    
    build:
      stage: build
      script:
        - docker pull $CI_REGISTRY_IMAGE:latest || true
        - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
        - docker push $CI_REGISTRY_IMAGE:latest
        - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
      rules:
        - if: $CI_COMMIT_TAG
    

    1.3.2 使用 kubernetes executor

    开启 TLS

    使用 Helm Chart 方式安装 runner,更新配置文件 values.yaml 加载证书目录

    runners:
      config: |
        [[runners]]
          [runners.kubernetes]
            image = "ubuntu:20.04"
            privileged = true
          [[runners.kubernetes.volumes.empty_dir]]
            name = "docker-certs"
            mount_path = "/certs/client"
            medium = "Memory"
    

    在 pipeline 中使用 docker in docker 打包镜像并上传到镜像仓库:

    image: docker:19.03.12
    
    variables:
      DOCKER_DRIVER: overlay2
      DOCKER_HOST: tcp://docker:2376
      DOCKER_TLS_CERTDIR: "/certs"
      DOCKER_TLS_VERIFY: 1
      DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
      
    services:
      - docker:19.03.12-dind
    
    before_script:
      - docker info
      - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    
    build:
      stage: build
      script:
        - docker pull $CI_REGISTRY_IMAGE:latest || true
        - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
        - docker push $CI_REGISTRY_IMAGE:latest
        - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
      rules:
        - if: $CI_COMMIT_TAG
    

    2. Kaniko 构建镜像

    使用 docker in docker 方式构建镜像时有以下问题:

    • 需要使用 privileged mode ,存在安全隐患
    • 因为需要额外运行 Docker daemon 进程,性能和速度上不太理想

    Kaniko 是谷歌开源的一款用来构建容器镜像的工具。与 docker 不同,Kaniko 并不依赖于 Docker daemon 进程,完全是在用户空间根据 Dockerfile 的内容逐行执行命令来构建镜像,这就使得在一些无法获取 docker daemon 进程的环境下也能够构建镜像,比如在标准的Kubernetes Cluster上。

    使用 kaniko,runner 只能使用以下类型的 executor:

    2.1 使用 Kaniko 打包镜像

    如果想使用 Kaniko 打包镜像,需要以下条件:

    • kaniko debug 镜像:gcr.io/kaniko-project/executor:debug,国内可能无法下载,可以使用 willdockerhub/kaniko-executor:debug 代替,也可以使用微软国内镜像源:gcr.azk8s.cn/kaniko-project/executor:debug(gcr.io 的镜像都可以使用这个方法下载)
    • entrypoint 必须重写 overridden,否则打包脚本无法运行
    • 需要配置 config.json,其中包含远程仓库的登陆认证信息

    示例:

    build:
      stage: build
      image:
        # name: gcr.io/kaniko-project/executor:debug
        name: willdockerhub/kaniko-executor:debug
        entrypoint: [""]
      script:
        - mkdir -p /kaniko/.docker
        - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
        - >-
          /kaniko/executor
          --context "${CI_PROJECT_DIR}"
          --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
          --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
      rules:
        - if: $CI_COMMIT_TAG
    
    • 查看 Kaniko 帮助:docker run --rm willdockerhub/kaniko-executor:debug

    2.2 自签证书 registry

    如果本地镜像仓库使用的自签证书,会遇到报错:

    $ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push
    INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image
    error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority
    

    解决方法如下:

    before_script:
      - mkdir -p /kaniko/.docker
      - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
      - |
        echo "-----BEGIN CERTIFICATE-----
        ...
        ...
        ...
        -----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt
    
  • 相关阅读:
    【APIO2008】免费道路[最小生成树 kruskal]
    【2019.8.13】
    【矩阵】
    [POI2008]BLO-Blockade [tarjan 割点]
    poj1458 最长公共子序列 (动态规划)
    最长上升子序列
    poj1163 数字三角形 (动态规划)
    快速幂 (分治)
    求排列的逆序数(分治)
    快速排序 (分治)
  • 原文地址:https://www.cnblogs.com/leffss/p/16105839.html
Copyright © 2020-2023  润新知