LoginSignup
23
15

More than 3 years have passed since last update.

CircleCIで試行錯誤した話

Last updated at Posted at 2018-12-07

紹介

ZOZOテクノロジーズでSREをやっています。
先ずは、いままでCircleCIについて書いてきた記事を紹介させてください

2018年:弊社のアドベントカレンダー

「CircleCI + AWS Lambda function + Slackを使ったChatOps環境構築」

その他

  1. 「Incoming webhookを使ってCircleCIのSlackへの通知をJob別に分ける」
  2. 「CircleCIで重複したWorkflow(Job)を止める」
  3. 「CircleCIで、直前に実行したJobによって次のJobで実行する処理を変える」
  4. 「CircleCIでDockerコマンドを使う」
  5. 「CircleCIで使われているコンテナの中身」

何を記事にするのか

今回は、上記の記事以外で、CircleCIを使う上で対処してきた内容について書きます
CIといえど、使い方は人それぞれなのですが、どなたかの助けになれればいいなと思っています

[ 項目 ]

  1. パッケージ管理ソフト(aptとかyum)でインストールしたバイナリファイルはキャッシュに保存できても、リストアできない
  2. CircleCIで使っているグローバルIPアドレスの範囲がわからない
  3. .から始まるディレクトリ内のファイルを編集できない
  4. CircleCIから外部にsshしたい
  5. 外部からCircleCIのコンテナにsshしたい
  6. pythonのライブラリ依存のエラーが突然起きる
  7. machine executor だと pythonのバージョンがデフォルトで2系になっている

パッケージ管理ソフト(aptとかyum)でインストールしたバイナリファイルはキャッシュに保存できても、リストアできない

例えば以下のようなconfig.yamlがあったとします

config.yml

version: 2
jobs:
  test_job:
    machine: true
    steps:
    - run:
        name: Install redis-cli
        command: |
          sudo apt update && sudo apt install -y redis-server
    - save_cache:
        paths:
        - "/usr/bin/redis-cli"
        key: {{ checksum ".circleci/config.yml" }}

  test_job2:
    machine: true
    steps:
      - restore_cache:
          name: Restore cache
          key: {{ checksum ".circleci/config.yml" }}

上記の test_job は成功します、ただし test_job2 はキャッシュをリストアする際に /usr/bin への書き込み権限がなく失敗します

エラーは以下のようになります

shell
Downloading cache archive...
Validating cache...

Unarchiving cache...
tar: usr/bin/redis-cli: Cannot open: Permission denied
tar: Exiting with failure status due to previous errors

Error untarring cache: exit status 2

/bin 以下にあるバイナリファイルをキャッシュするのは諦めましょう
Job毎にインストールするのをおすすめします

CircleCIで使っているグローバルIPアドレスの範囲がわからない

参考URL: https://support.circleci.com/hc/en-us/articles/115014372807-IP-Address-ranges-for-whitelisting-

CircleCI builds are currently run mainly from AWS East and West. 
Google Cloud Platform and additional services may be used in the future. 
For this reason we can't give a list of IP addresses that our cloud system will use.

要約すると「AWSとGCPとその他のサービスを使っている、もしくは使うつもりだからIPアドレスのリストは教えられないよ」と言っています

仕方ないので、CIを実行するたびにグローバルIPを調べるようにしました

参考URL: http://mgi.hatenablog.com/entry/2014/10/30/085403

以下のコマンドを使えばグローバルIPアドレスを取ってこれます

shell
$ curl -f -s ifconfig.me

ちなみに、ifconfig.me がサービスダウンすると、CIが失敗するので、以下のほうがいいかもしれません

shell
$ curl checkip.amazonaws.com

.から始まるディレクトリ内のファイルを編集できない

たまに、CIの中で .dir/sample.txt などのファイルを書き換えようとすると、エラーは発生しないが、ファイルが書き換えられていないときがあります

そういうときは ファイル書き換え → ファイルの置き換え とやったほうが確実です

config.yml
- run:
    command: |
      echo 'OK' > sample.txt
      cd sample.txt .dir/sample.txt

ちなみに、machineを使っていると、デフォルトのShellは dash になっています
これの影響なのかな??

shell
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19  2014 /bin/sh -> dash

# bashもちゃんとあります
$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1021112 May 16  2017 /bin/bash

CircleCIから外部にsshしたい

CircleCIの公式のドキュメントだと以下のようになっています

参考URL: https://circleci.com/docs/2.0/configuration-reference/#add_ssh_keys

config.yml

steps:
  - add_ssh_keys:
      fingerprints:
        - "b7:35:a6:4e:9b:0d:6d:d4:78:1e:9a:97:2a:66:6b:be"

ちなみに。上記のfingerprintを書いても失敗した気がします
やっていることは .ssh/ にfingerprint名で暗号鍵を置いているだけです

shell
# イメージ

$ ls ~/.ssh/id_rsa_*
/home/circleci/.ssh/id_rsa_b735a64e9b0d6dd4781e9a972a666bbe

# `id_rsa_` 以降がfingerprintsから `:` を抜いた文字列になっている

以下のようにすればsshできます。sshする際に鍵を指定しなくてもいいみたいです。

config.yml

steps:
  - add_ssh_keys
  - run: ssh < domain name or IP Address >

外部からCircleCIのインスタンスにsshしたい

CircleCIのWebサイトにアクセスし、実行済みのJobにアクセス、
右上のプルダウンを押し Rerun job with SSH でJobを起動します。

スクリーンショット 2018-12-06 20.36.57.png

ターミナル (shell) で $ ssh -p XXXXXXXX:XXXX を実行

スクリーンショット 2018-12-06 20.38.56.png

ちなみに、公開鍵はCircleCIと連携させているGitHub/BitBucketアカウントに登録されているものを使っているみたいです
なので、sshしたときに聞かれるパスワードはGitHub/Bitbucketからgit cloneをするときに聞かれるパスワードと同じです

プルダウンが出てこないときは、連携しているサービスに公開鍵が登録されていない可能性があります

pythonのライブラリ依存のエラーが突然起きる

これが一番やっかいでした・・・

例えば、以下のような場合

config.yml

    - run:
        name: Install python module and awsebcli
        command: |
          sudo apt update && sudo apt install -y python-dev python-pip
          pip install awsebcli --upgrade --user

pip install するとライブラリの依存でインストールできないというエラーがでることがあります
Jobの実行に使っているのがコンテナなら、Dockerhubでコンテナのタグを探し、以下のように設定すればOKです

config.yml

    docker:
      - image: ubuntu:14.04

タグが latest でなければ、中身のライブラリのバージョンが変わることはないと思います

ちなみに、machineもバージョン指定が可能です ( pythonのバージョン管理には何度泣かされたか・・・ )

config.yml

jobs:
  build:
    machine:
      image: circleci/classic:2017-01

ちなみに以下のように、ライブラリのバージョンを固定してもOKです

shell

pip install awsebcli==3.14.5 --upgrade --user

machine executor だと pythonのバージョンがデフォルトで2系になっている

machine executor は shell scriptを使ってライブラリをインストール管理しているらしいです

参考URL: https://circleci.com/docs/2.0/vm-service/#customization

ちなみにGitHubではこんな感じで Python 2.7.11 がデフォルトバージョンになっています。

Dockerfile
ADD circleci-provision-scripts/python.sh /opt/circleci-provision-scripts/python.sh
RUN circleci-install python 2.7.10
RUN circleci-install python 2.7.11
RUN circleci-install python 3.4.3
RUN circleci-install python 3.5.1
RUN sudo -H -i -u ubuntu pyenv global 2.7.11

最終的に pyenv global 2.7.11 となっているので、 3系を使いたい場合は以下のようにします

config.yml
- run:
    command: |
      pyenv global 3.5.1

感想

いろいろと苦労を書きましたが、結果的にCircleCIはGitHubとの連携や各種APIが優れているので、すごく使いやすいです。
個人的には、GitHubをお使いであれば非常におすすめです!
ここまで、読んでいただきありがとうございました
また、CircleCIのアドベントカレンダーに参加できたことを光栄に思います

23
15
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
15