使用 CircleCI 的 Orbs 进行并行处理

本文是CircleCI Advent Calendar 2018第三天的文章。

上一篇文章是由@yasuhiroki撰写的,题为「即使将CircleCI的Only build pull requests关闭,我仍然想要在创建Pull Request时执行Job」。

首先

CircleCI

在这篇文章中进行解释的事情

    • CircleCIの並列処理の基本的なやり方

 

    CI/CDの処理時間を短縮する方法

在这篇文章中不要解释的事情

    • Ansibleの使い方

 

    • CircleCIの使い方

 

    • Dockerの使い方

 

    Orbsの解説、導入方法

这篇文章想要表达的意思是

    • Orbsを利用してパイプラインの再利用性を高めましょう

 

    • Orbsに定義出来ない処理、もしくはOrbsで定義すると再利用が難しくなる処理は「.circleci/config.yml」へ書きましょう

 

    • CircleCIで処理する必要がないものはあらかじめDockerイメージ化しレジストリへ登録しておきましょう(スナップショットの作成)

 

    CircleCIで利用する独自のDockerイメージはcron等を用いて頻繁にアップデートしましょう(スナップショットのリフレッシュ)

Ansible是什么?

Ansible(安得泊)是一款由红帽公司开发的开源配置管理工具。在启动服务器时,可以根据预先准备好的配置文件自动执行软件的安装和设置。特别适用于构建大规模计算机集群,有助于缩短时间并减少错误。除了配置管理外,还具备编排和软件部署功能。

引用自Ansible(软件)- 维基百科

关于Ansible需要注意的事项

Ansible通常被用于操作系统和网络设备。如果像本文所述在Docker中使用,无法百分百发挥Ansible的性能。

这篇文章只是拿CircleCI作为并行处理的例子来进行解释。

请确保在使用Ansible时使用操作系统环境而不是Docker。

场景

1. 目标

使用多个不同的发行版以及多个不同版本的Ansible来进行编程安装操作的持续集成。

为了加快CI/CD的速度,利用操作系统镜像的“快照”,并进行“并行处理”。

处理的流程

    1. 获取Playbook

 

    1. 进行静态解析(运行lint)

 

    执行Playbook

希望选择发行版本

    • CentOS7

 

    Ubuntu18

使用 Ansible 的版本

    • 2.7系(aptもしくはyumコマンドでインストールされるAnsible)

 

    • 2.7系(pipコマンドでインストールされるAnsible)

 

    2.8系

我们将进行6个并行处理,其中包括2个分发系统和3个Ansible系统。

circleci-2.png

安装程序

    cowsay – Wikipedia
cowsay.gif

使用Ansible编排剧本。

    TomonoriMatsumura/ansible_joke-programs_cowsay | GitHub

准备工作是将Docker镜像注册到注册服务中。

为了加快CI/CD的速度,我们会先创建一个操作系统镜像的快照。

创建Dockerfile

预先安装了「CentOS7」和「Ubuntu18」。

或者:
事先在「CentOS7」和「Ubuntu18」上安装了。

    • Ansible

 

    • Ansible-lint

 

    Git

创建并注册包含已安装Docker镜像的仓库。

以下是安装Ansible、Ansible-lint、Git到CentOS7的Dockerfile示例:

Dockerfile
从 centos:latest 派生RUN set -x && \
rm -f /etc/rpm/macros.image-language-conf && \
sed -i ‘/^override_install_langs=/d’ /etc/yum.conf && \
yum -y reinstall glibc-common && \
yum clean all && \
yum update -y && \
yum install -y epel-release git && \
yum -y install ansible && \
yum -y install expect python-devel python-pip && \
pip install –upgrade pip && pip install –upgrade setuptools && \
pip install ansible-lint

ENV LANG=”ja_JP.UTF-8″ \
LANGUAGE=”ja_JP:ja” \
LC_ALL=”ja_JP.UTF-8″

以下是一份安装Ansible、Ansible-lint和Git到Ubuntu18的Dockerfile示例。

Dockerfile
从ubuntu:latest镜像中构建运行apt update -y命令,并安装language-pack-ja-base和language-pack-ja语言包
运行apt install -y software-properties-common命令
运行apt-add-repository -y ppa:ansible/ansible命令
运行apt update -y命令,并安装ansible
运行apt install -y curl python-dev git命令
从”https://bootstrap.pypa.io/get-pip.py”网址下载到”/tmp/get-pip.py”路径下
运行python /tmp/get-pip.py命令
运行pip install –upgrade pip命令并升级pip
运行pip install –upgrade setuptools命令并升级setuptools
运行pip install ansible-lint命令

设置环境变量LANG为”ja_JP.UTF-8″
设置环境变量LANGUAGE为”ja_JP:ja”
设置环境变量LC_ALL为”ja_JP.UTF-8″

将Docker镜像注册到Docker Hub。

在这篇文章中,我们将使用Docker Hub来管理注册表。

Docker Hub 提供了将 Dockerfile 推送到 GitHub 后自动构建 Docker 镜像的服务。

因此

    • 記事等で利用する

 

    OSSの活動で利用する

如果你想要披露所创建的Docker镜像的内容,这将是一个有用的工具。

使用Docker镜像

    • tomonorimatsumura/centos7-ansible – Docker Hub

 

    tomonorimatsumura/ubuntu18-ansible – Docker Hub

创建Ansible Playbook

我将使用这本Playbook。

Ansible Playbook 中定义了以下操作。

    1. 获取执行Playbook的Docker容器的发行版信息。

 

    根据发行版选择并执行适当的处理。
- hosts: all
  tasks:
    - name: Install cowsay with yum
      include_role:
        name: centos7
      when: ansible_distribution == "CentOS"

    - name: Install cowsay with apt
      include_role:
        name: ubuntu18
      when: ansible_distribution == "Ubuntu"
- name: Install cowsay with yum
  become: yes
  yum:
    name: cowsay
    state: present
- name: Install cowsay with apt
  become: yes
  apt:
    name: cowsay
    state: present

- name: Copy cowsay execution file to '/usr/local/bin/'
  become: yes
  copy:
    src: /usr/games/cowsay
    dest: /usr/local/bin/cowsay
    owner: root
    group: root
    mode: 0755

创建一个orb

在这篇文章中,我们将使用 CircleCI 2.1 引入的 Orbs,这将全面可用。

有关 orb 的处理

version: 2.1

commands:
  show-os-version:
    description: "Show OS version information"
    steps:
      - run:
          name: Show OS version
          command: |
            if [ -e /etc/os-release ]; then
              cat /etc/os-release
            elif [ -e /etc/redhat-release ]; then
              cat /etc/redhat-release
            else
              echo 'Invalid Image' 1>&2
              exit 1
            fi

  ansible-lint:
    description: "Execute ansible-lint command"
    steps:
      - run:
          name: Show ansible-lint version
          command: ansible-lint --version
      - run:
          name: Retrieve Ansible lint rules file
          command: |
            cd /tmp
            git clone https://github.com/TomonoriMatsumura/ansible_joke-programs_lint-rules
      - run:
          name: Execute ansible-lint
          command: |
            cd $CIRCLE_WORKING_DIRECTORY
            find . -type f -name '*.yml' | xargs ansible-lint -c /tmp/ansible_joke-programs_lint-rules/.ansible-lint-rules

  ansible-playbook:
    description: "Execute ansible-playbook command"
    steps:
      - run:
          name: Show Ansible version
          command: ansible --version
      - run:
          name: Execute Ansible Playbook
          command: |
            cd $CIRCLE_WORKING_DIRECTORY
            ansible-playbook -i localhost install.yml
      - run:
          name: Execute Ansible Playbook again, checking to make sure it's idempotent.
          command: |
            cd $CIRCLE_WORKING_DIRECTORY
            ansible-playbook -i localhost install.yml

executors:
  centos7-ansible-yum:
    docker:
      - image: tomonorimatsumura/centos7-ansible:yum
  centos7-ansible-stable:
    docker:
      - image: tomonorimatsumura/centos7-ansible:stable
  centos7-ansible-devel:
    docker:
      - image: tomonorimatsumura/centos7-ansible:devel
  ubuntu18-ansible-apt:
    docker:
      - image: tomonorimatsumura/ubuntu18-ansible:apt
  ubuntu18-ansible-stable:
    docker:
      - image: tomonorimatsumura/ubuntu18-ansible:stable
  ubuntu18-ansible-devel:
    docker:
      - image: tomonorimatsumura/ubuntu18-ansible:devel

我们将在orb中定义以下处理程序。

    1. 显示所使用Docker镜像的发布信息

 

    1. 使用Ansible-lint检查Playbook的语法

 

    执行Playbook

这是”commands”部分的内容。

    1. 显示操作系统版本

 

    1. 检查ansible配置的问题

 

    运行ansible剧本

每个都有对应的解决办法。

在executor部分定义了Docker镜像。

创建.circleci/config.yml文件

show-os-version-steps: &show-os-version-steps
  steps:
    - ansible/show-os-version

lint-steps: &lint-steps
  steps:
    - checkout
    - ansible/ansible-lint

playbook-steps: &playbook-steps
  steps:
    - checkout
    - ansible/ansible-playbook
    - run:
        name: Execute cowsay
        command: |
          export TERM=xterm
          cowsay "hello world!"

version: 2.1

orbs:
  ansible: orbss/ansible@volatile

jobs:
  Ce7-yum_os-version:
    executor:
      name: ansible/centos7-ansible-yum
    <<: *show-os-version-steps
  Ce7-yum_lint:
    working_directory: /tmp/ansible
    executor:
      name: ansible/centos7-ansible-yum
    <<: *lint-steps
  Ce7-yum_playbook:
    working_directory: /tmp/ansible
    executor:
      name: ansible/centos7-ansible-yum
    <<: *playbook-steps

  Ce7-stable_os-version:
    executor:
      name: ansible/centos7-ansible-stable
    <<: *show-os-version-steps
  Ce7-stable_lint:
    working_directory: /tmp/ansible
    executor:
      name: ansible/centos7-ansible-stable
    <<: *lint-steps
  Ce7-stable_playbook:
    working_directory: /tmp/ansible
    executor:
      name: ansible/centos7-ansible-stable
    <<: *playbook-steps

  Ce7-devel_os-version:
    executor:
      name: ansible/centos7-ansible-devel
    <<: *show-os-version-steps
  Ce7-devel_lint:
    working_directory: /tmp/ansible
    executor:
      name: ansible/centos7-ansible-devel
    <<: *lint-steps
  Ce7-devel_playbook:
    working_directory: /tmp/ansible
    executor:
      name: ansible/centos7-ansible-devel
    <<: *playbook-steps

  Ub18-apt_os-version:
    executor:
      name: ansible/ubuntu18-ansible-apt
    <<: *show-os-version-steps
  Ub18-apt_lint:
    working_directory: /tmp/ansible
    executor:
      name: ansible/ubuntu18-ansible-apt
    <<: *lint-steps
  Ub18-apt_playbook:
    working_directory: /tmp/ansible
    executor:
      name: ansible/ubuntu18-ansible-apt
    <<: *playbook-steps

  Ub18-stable_os-version:
    executor:
      name: ansible/ubuntu18-ansible-stable
    <<: *show-os-version-steps
  Ub18-stable_lint:
    working_directory: /tmp/ansible
    executor:
      name: ansible/ubuntu18-ansible-stable
    <<: *lint-steps
  Ub18-stable_playbook:
    working_directory: /tmp/ansible
    executor:
      name: ansible/ubuntu18-ansible-stable
    <<: *playbook-steps

  Ub18-devel_os-version:
    executor:
      name: ansible/ubuntu18-ansible-devel
    <<: *show-os-version-steps
  Ub18-devel_lint:
    working_directory: /tmp/ansible
    executor:
      name: ansible/ubuntu18-ansible-devel
    <<: *lint-steps
  Ub18-devel_playbook:
    working_directory: /tmp/ansible
    executor:
      name: ansible/ubuntu18-ansible-devel
    <<: *playbook-steps

workflows:
  version: 2
  ansible-playbook:
    jobs:
      - Ce7-yum_os-version
      - Ce7-yum_lint:
          requires:
            - Ce7-yum_os-version
      - Ce7-yum_playbook:
          requires:
            - Ce7-yum_lint


      - Ce7-stable_os-version
      - Ce7-stable_lint:
          requires:
            - Ce7-stable_os-version
      - Ce7-stable_playbook:
          requires:
            - Ce7-stable_lint


      - Ce7-devel_os-version
      - Ce7-devel_lint:
          requires:
            - Ce7-devel_os-version
      - Ce7-devel_playbook:
          requires:
            - Ce7-devel_lint


      - Ub18-apt_os-version
      - Ub18-apt_lint:
          requires:
            - Ub18-apt_os-version
      - Ub18-apt_playbook:
          requires:
            - Ub18-apt_lint


      - Ub18-stable_os-version
      - Ub18-stable_lint:
          requires:
            - Ub18-stable_os-version
      - Ub18-stable_playbook:
          requires:
            - Ub18-stable_lint


      - Ub18-devel_os-version
      - Ub18-devel_lint:
          requires:
            - Ub18-devel_os-version
      - Ub18-devel_playbook:
          requires:
            - Ub18-devel_lint

关于锚点和别名

anchorの設定aliasの配置show-os-version-steps: &show-os-version-steps<<: *show-os-version-stepslint-steps: &lint-steps<<: *lint-stepsplaybook-steps: &playbook-steps<<: *playbook-steps

表上的描述是指「.circleci/config.yml」中可用的Anchors & Aliases功能。您可以在定义锚点后将别名指定到特定位置。

请参考这个链接了解更详细的情况。

在工作流中并行执行作业

在工作流程(workflows)部分,我们编写处理代码以使每个作业(Job)并行执行。有关在CircleCI中定义作业执行顺序的详细方法,请参考此链接。

关于使用的ORB版本

在Orbs中,可以通过”circleci/config.yml”来指定orb的版本。然而,在这篇文章中,我们始终使用”volatile”来获取最新版本。

在实际使用Orbs时,有时候指定特定版本号而不是最新版本可能更好。对于版本的指定描述,最好根据需要灵活使用。

总结

我介绍了在CircleCI中并行运行CI的方法。通过使用这种方法,您可以使用不同版本的Ruby + Rails或者PHP + Laravel并行处理验证,这样就可以进行验证了。

也许可以考虑开发能够兼容框架和语言版本的选项。

CircleCI的并发处理要点。

    • Orbsを利用してパイプラインの再利用性を高める

 

    • Orbsに定義出来ない処理、もしくはOrbsで定義すると再利用が難しくなる処理は「.circleci/config.yml」へ書く

 

    • CircleCIで処理する必要がないものはあらかじめDockerイメージ化しレジストリへ登録する(スナップショットの作成)

 

    CircleCIで利用する独自のDockerイメージはcron等を用いて頻繁にアップデートする(スナップショットのリフレッシュ)

我认为您应该意识到这一点。特别是包含容器的操作系统镜像快照会对CI/CD的速度产生重大影响,仅次于并行处理。快照应该有意识地采用。

未来的挑战

並列處理報告的問題

这次使用的「.circleci/config.yml」有一个问题。问题是并行处理时无法指定执行Job的顺序。

理想的的流程线路

circleci-2.png

实际的管道

スクリーンショット 2018-11-29 17.37.29のコピー.png

我想将流水线以线性方式显示,但是 CircleCI 似乎会按照处理顺序显示作业?因此会输出与我期望的不同的内容。

希望能够改善这种行为,但目前不知道方法。

请参考以下链接

安装

    • Ansible (ソフトウェア) – Wikipedia

 

    • Ansible is Simple IT Automation

 

    TomonoriMatsumura/ansible_joke-programs_cowsay | GitHub

CircleCI 循环CI

关于Orbs

    Creating Orbs – CircleCI

关于 Anchor & Aliases

    YAML – config.yml | CircleCI

关于并行处理

    Using Workflows to Schedule Jobs – CircleCI

新闻报道的验证

    この記事のレポート

牛说

    cowsay – Wikipedia

Docker 镜像仓库

    • Docker Hub

 

    • Docker HubでDockerfileを公開する AUTOMATED BUILD – Qiita

 

    • tomonorimatsumura/centos7-ansible – Docker Hub

 

    tomonorimatsumura/ubuntu18-ansible – Docker Hub

结果

明天的 CircleCI 年度日历2018文章将由 @ganta 先生负责。

广告
将在 10 秒后关闭
bannerAds