ラベル CentOS7 の投稿を表示しています。 すべての投稿を表示
ラベル CentOS7 の投稿を表示しています。 すべての投稿を表示

2019/09/01

neovim で plugin を利用せずに sudo を使う

root 権限が必要なファイルを neovim や vim で編集する事があると思います。
その際、 sudoers で許可されているユーザならば
  • :write ! sudo tee % > /dev/null
で sudo を使って root として書き込むことができます。

ですが、 neovim では
  • :write ! sudo tee % > /dev/null
    • sudo: no tty present and no askpass program specified
    • shell returned 1
と言われて sudo が使えません。


解決策

以下のようなコマンドを定義することで対応できます。 このコマンドは vim と neovim の両方で利用できます。

vim で利用する場合は ~/.vimrc に追記します。
neovim で利用する場合は ~/.cofig/nvim/init.vim に追記します。


使い方

  • $ nvim /etc/hosts
    • root 権限が必要なファイルを開いて編集します。保存の際は
  • :SudoWriteCurrentBuffer
    • を実行します。
    • パスワードを入力すれば root で書き込む事ができます。


動作確認をした環境

大元の環境(vim と neovim で動作確認済)
  • OS: macOS Mojave 10.14.6 (18G95)
  • Homebrew: 2.1.11
    • Homebrew/homebrew-core: (git revision 883ee; last commit 2019-09-01)
  • neovim: v0.3.8
  • vim: 8.0.1365
  • sudo: version 1.8.17p1
    • Sudoers policy plugin version 1.8.17p1
    • Sudoers file grammar version 45
    • Sudoers I/O plugin version 1.8.17p1
  • docker: 19.03.1, build 74b1e89

    docker を使っていくつかの distribution でも動作を確認
    • Alpine linux: 3.10.2
      • neovim: v0.3.7
      • vim: 8.1.1365
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • CentOS: release 7.6.1810 (Core)
      • vim: 7.4.1099
      • sudo: version 1.8.23
        • Sudoers policy plugin version 1.8.23
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.23
    • Fedora: release 30
      • vim: 8.1.1912
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • Ubuntu: 18.04.3
      • vim: 8.0.1453
      • sudo: version 1.8.21p2
        • Sudoers policy plugin version 1.8.21p2
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.21p2
    • Debian: 10.0 (buster-20190812)
      • vim: 8.1.1401
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27


    何故 neovim では sudo が使えないのか

    ここから先は先程の Vimscript を作るに至った経緯を書きます。
    興味のある方はご覧ください。

    まず sudo の error message
    • sudo: no tty present and no askpass program specified
    を見ると、 tty と askpass が無いと言っています。


    tty と askpass

    実際、vim では
    • : ! tty
      • /dev/ttys004 
    などが得られますが、 neovim では
    • : ! tty
      • not a tty
      • shell returned 1
    と言われてしまいます。

    askpass は使ったことが無いのですが、fedora の container で dnf search すると
    の様に、いくつかの askpass が確認できます。のでちょっと試してみます。
    • x11-ssh-askpass
    • openssh-askpass
    • ksshaskpass
    という感じで全然起動してくれません。
    ですがエラーの内容的に display を開こうとしているのが分かります。
    なので、おそらく GUI で password を聞くような物だと思われます。


    askpass を作る

    askpass について調べていると、どうやら
    • password を stdout に出力するもの
    であることが分かりました

    よって
    • neovim 内で password を取得
    • password を stdout に出力する
    • password の履歴はどこにも残さない
    ようなものを作れば解決できそうです。

    それで完成したのが /tmp/askpass を作るこの Vimscript です。

    本当はファイル名は固定でなく tempfile 的な物で対応するなど、改善点はいくつも存在するかと思います。
    ですが私は Vimscript に明るくないので、"3つの条件を満たして動けばOK" という条件で作成しました。
    他により良い対応方法があればご指摘頂けると幸いです。


    その他の解決策

    調べた結果、 suda.vim というプラグインがあるようです。
    また、他にも sudo.vim など、似たようなプラグインはいくつかあるらしいです。

    これを使わなかった理由としては
    • docker のコンテナ内で作業をする事が多々ある
    • init.vim を配置するスクリプトは既にある
    • plugin を install するスクリプトはまだ無い
    • 全コンテナに plugin を入れるのも面倒だし結構サイズがある
      • $ du -sh ~/.config/nvim/repos
        • 100M    /Users/atton/.config/nvim/repos
    などがあります。

    また、"sudo が使えるならこの際 root になってしまう" という解決策もあるのですが
    • 前述した理由の後半3つ
    • 複数人数のユーザが使う環境だと、 /root 配下に自分専用の設定を置くことになる
    のでこちらも無しで。

    他には、 "sudoers で NOPASSWD を設定する" という解決策もあります。
    が、sudo を no password でガンガン使えば実質 root で作業しているのと変わらず、危険すぎるのでこちらも無し。

    ということでこの Vimscript を書くに至った、という訳なのです。


    おまけ: 環境変数の unlet

    スクリプト内部では askpass の場所を示す SUDO_ASKPASS を設定している部分があります。
    具体的には
    • let $SUDO_ASKPASS  = s:askpass_path
    ですね。

    この環境変数を定義していると、 sudo -A した際に指定したファイルが実行されます。
    一応、 :SudoWriteCurrentBuffer の実行後にはなるべく元の環境に戻すために
    • unlet $SUDO_ASKPASS
    を書いていた時もありました。

    ですが動作確認中、 Vim 8.0.1365 で unlet 時にエラーが出てしまいました。
    また 、-A を指定しなければ sudo の動作は変わらないので 、残っていても無害と判断して unlet しない形になりました。


    おまけ: shebang を指定しないとどうなるのか

    ちなみに askpass の shebang を消すと
    • sudo: unable to run /tmp/askpass: Exec format error
    • sudo: no password was provided
    と言われる為、きちんと書いておく必要があります。


    おまけ: x flag を付けないとどうなるのか

    setfperm(s:askpass_path, "rwxr-xr-x")  をせずに 644 のままだと
    • sudo: unable to run /tmp/askpass: Permission denied
      • sudo: no password was provided
      と言われるので、こちらもきちんと指定しておく必要があります。


      参考

      2018/07/22

      Docker Registry の backup と restore

      前回は Image の Backup/Restore について書きました。
      これで Image を指定してバックアップ可能になったのですが、Registry に登録される Image が1つとは限らない。
      ということで Docker Registry ごと全イメージをバックアップしてみる。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Docker: version 1.13.1, build 774336d/1.13.1
      • Kernel: 3.10.0-693.5.2.el7.x86_64


      Docker Registry を tar にする

      さて、Registry はコンテナ内部に登録イメージのファイルを持ってます。
      ファイルごとバックアップを取りたいので、戦略としてはコンテナのバックアップを取る。
      今度使うのは docker export コマンド

      • $ docker run -d -p 5000:5000 --name registry registry:latest
      • $ docker push hogehoge
      • $ docker export registry > registry-backup.tar
      これで Registry のコンテナが tar ファイルになります。


      Docker Registry を復元する

      さて、 tar ファイルから復元したいと思います。
      • $ docker import - registry:latest < registry-backup.tar
      今回はタグの情報とかは無いので自分で指定する。
      というかコンテナからイメージを作るので実質 docker commit みたいなものか。

      tar から作られた registry:latest を実行します。
      • $ docker run -d -p 5000:5000 --name registry registry:latest
      お? 動かない。 
      /usr/bin/docker-current: Error response from daemon: No command specified.
      と言ってくる。CMD の情報が吹っ飛んでるのか。
      Github にある Registry の Dockerfile を見ると、'docker-registry' とすれば良いかな。
      • $ docker run -d -p 5000:5000 --name registry registry:latest docker-registry
      動かない。今度は
      /usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"docker-registry\": executable file not found in $PATH
      か。そんなコマンドは無いらしい。 
      もうコンテナ内に入ってしまうかな。export 前の registry に対して
      • $ docker exec -it registry bash
      すると
      rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"bash\": executable file not found in $PATH"
      おお、bash すら無いのか。sh も無ければ最早 user interactive に何もできないコンテナだ。

      • $ docker exec -it registry sh
      流石に sh はありました。find もある。
      find で docker-registry を探しても無い。
      他に探索していると registry というのが /bin/registry にあった。
      実行すると serve か garbage-collect と help がサブコマンドにある。serve してみます。
      • $ registry serve
      文句言ってきました。具体的には
      configuration error: configuration path unspecified
      と。 docker-registry の configuration path って何だろう。
      どこかに mount してたらそれを参照してくれるから設定変更可能、とかそういう意図なんだろうか。

      とかとか、いろいろ試した結果、ps で path が分かりました。
      Process ID 1 のやつが
      registry serve /etc/docker/registry/config.yml
      で動いていました。
      と、いうことで、実行するコマンドは
      $ docker run -d -p 5000:5000 --name registry registry:latest registry serve /etc/docker/registry/config.yml
      で Import した Registry を復元できました。やったね。


      おまけ

      /etc/docker/registry/config.yml を読むと storage.filesystem.rootdirectory が /var/lib/registry
      だったので、run する時に -v で /var/lib/registry に Host の Directory を mount しておけば Image の保存が楽だった説が。

      それと、Docker EE だと、 DTR (Docekr Trusted Registry) の backup/restore 手順が提供されています
      きちんとサポートを受けたい場合は Docker EE を使うのもアリかも。


      参考

      2018/07/15

      Docker Image の backup と restore

      さて、Docker Registry を立てたは良いものの、マシンが壊れたりすると悲しい事態になります。
      Build 元と Registry で二重になってはいるのですが、両方が同じマシンだと悲しい事態が発生する可能性がありますね。
      と、いうことで Build した Docker の Image をファイルに書き出したり、そのファイルからイメージを復元します。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Docker: version 1.13.1, build 774336d/1.13.1
      • Kernel: 3.10.0-693.5.2.el7.x86_64


      Docker Image をファイルへバックアップする

      Docker そのものはファイル群を /var/lib/docker の下に持ってます。
      Image は default だと overlay2 で作成されます。
      overlay2 は差分でファイルを管理するファイルシステムなので、そういったメタ情報もバックアップしないといけない。
      つまりは cp とか rsync だと事故る可能性があります。

      さて、何を使うのが正しいかと言えば公式です。具体的には docker save コマンド
      Image を構成する全レイヤをきちんと tar に書き出してくれます。
      実行例として、hogehoge Image をバックアップするのはこんな感じ。
      • $ docker image save hogehoge > backup.tar
      この tar をバックアップ先 HDD 等に持っていけば良い。


      Docker Image をファイルから復元する

      バックアップする方法は分かりました。
      次はバックアップからの復元。
      docker load コマンドを使います。具体的には
      • $ docker image load < backup.tar
      で終わり。
      Image の repository name や tag も tar に入っているので、それらの情報も全部復元されます。楽。


      参考

      2018/07/08

      自前の Docker Registry を Systemd で管理する

      前回の記事では自前で Docker Registry を立ててみました。
      ですが、これだと docker run しただけなので、マシンを再起動すると上がってこない。
      ということで systemd の unit にしてしまって自動起動させるようにしました。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Docker: version 1.13.1, build 774336d/1.13.1
      • Kernel: 3.10.0-693.5.2.el7.x86_64


      systemd の unit を書く

      ググると誰かが書いた unit がいくつかヒットしました。これとかこれとか。
      これらを参考に unit を書きます。とはいっても、考慮する具体的な内容は
      • registry の container の name は決めうち
        • unit を書くのを楽にするため
        • volume は面倒なので mount しない
      • registry の dependency には docker がある
        • サービスの起動順番の指定
      くらいのものです。

      ということで、できたのが
      です。こいつを
      • /usr/lib/systemd/system/docker-registry.service
      に配置。それから怒涛の systemctl 。
      • $ sudo systemctl daemon-reload
        • unit の reload で認識させる
      • $ sudo systemctl start docker-registry
        • systemd 経由で docker-registry を起動してみる。
        • docker ps するときちんと生きてます。
      • $ sudo systemctl restart docker
        • docker を再起動してもちゃんと生きてる。
        • dependency の設定も上手くいってそうです。
      • $ sudo systemctl enable docker-registry
        • んで、マシン起動時に起動するように
      • $ sudo reboot
        • そして再起動。
        • 再起動後にもきちんと registry が上がってました。良し良し。

      ってな感じで再起動しても docker-registry が上がるようになりました。
      めでたしめでたし。


      参考

      2018/07/01

      自前の Docker Registry を立てて、 Build した Image を保存する

      さて、Docker を使っていて Image を作った後、他の人に配るにはいくつか方法があります。
      export/import したりとか、dockerhub に置いたりとか、自前で Registry を立てたりとか。
      今回は自前で Docker Registry を立ててみようと思います。


      環境(docker client と registry server の両方は同じ環境)

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Docker: version 1.13.1, build 774336d/1.13.1
      • Kernel: 3.10.0-693.5.2.el7.x86_64


      Registry を立てる

      Image が提供されているのでコマンド一発でおしまい。
      • registry-server$ docker run -d -p 5000:5000 --name registry registry:2
      便利ですね。


      Config とか

      立てるのは簡単ですが、外から使うにはいくつか設定がいります。
      まずは firewall で 5000 番を開放します。
      • registry-server$ sudo firewall-cmd --add-port=5000/tcp --permanent
      • registry-server$ sudo firewall-cmd --reload
      これでOK。ということで push してみましょう。
      • docker-client$ docker image tag hoge 192.168.0.1:5000/hoge
      • docker-client$ docker push 192.168.0.1:5000
      怒られます。
      Get https://192.168.0.1:5000/v1/_ping: http: server gave HTTP response to HTTPS client
      クライアント側が https で繋ぎにいってるのに http を返してきてる、と。
      調べたところ、http でアクセスする registry と指定すれば良いらしいです。

      と、いうことで指示通りに /etc/docker/daemon.json に書く。
      • docker-client$ sudo echo '{ "insecure-registries":["192.168.0.1:5000"] }' > /etc/docker/daemon.json
      • docker-client$ sytemctl restart docker
      • docker-client$ docker push 192.168.0.1:5000
      これで通りました。良し良し。

      今日日 https 必須感もありますし、https にするのが正しい気もしますが、動いたのでまずは一段落。


      参考

      2018/06/17

      Mac に fontforge を直接入れずに Docker を使って Ricty を作成する

      私は普段 Terminal で作業する時、フォントは Ricty を使っています。
      Ricty は Inconsolata と Migu 1M の合成フォントで、生成スクリプトが公開されています。
      合成には fontforge を使うのですが、 brew で入れると結構な数の依存パッケージが入ります。
      fontforge  は普段使いしていないので、おそらく Ricty の生成以外に使わない。
      なので Mac に直接 fontforge を入れず、コンテナに入れて合成してみます。


      環境

      • OS: macOS Sierra 10.12.6
      • Docker for mac: 18.03.1-ce, build 9ee9f40
        • Distribution: CentOS Linux release 7.4.1708 (Core)
        • fontforge: 20120731
      • Ricty: 4.1.1
        • Inconsolata: v2.001
        • Migu 1M: 20150712


      mac 側の事前準備(ダウンロード)

      事前にダウンロードが必要なのはフォント2つ。
      具体的には Inconsolata と Migu 1M の .ttf ファイルです。
      加えて、Ricty の生成スクリプト ricty_generator.sh もダウンロードしておきます。
      Migu 1M は unzip して、とりあえず全ファイルを ~/Downloads へ mv。

      最終的な ~/Downloads はこんな感じになりました。
      $ ls Downloads
      Inconsolata-Bold.ttf  Inconsolata-Regular.ttf  ipag00303  migu-1m-bold.ttf  migu-1m-regular.ttf  migu-README.txt  mplus-TESTFLIGHT-060  ricty_generator.sh


      Docker に ~/Downloads を mount して合成

      さて、合成に必要なファイル群は ~/Downloads に集まりました。
      これを mount したコンテナを立ち上げて合成します。

      具体的なコマンドはこんな感じ。run に渡す用のスクリプトを書いた方がスマートかも。
      • $ docker run -v ~/Downloads/:/root/fonts -it centos:7
        • # yum install -y fontforge
        • # cd /root/fonts
        • # chmod u+x ricty_generator.sh
        • # ./ricty_generator.sh -n 4.1.1 Inconsolata-{Regular,Bold}.ttf migu-1m-{regular,bold}.ttf
      生成されたフォントにバージョン番号を付けておきたいので、 "-n 4.1.1" オプションを指定しておきます。
      実行した結果、~/Downloads はこんな感じになりました。
      $ ls ~/Downloads
      Inconsolata-Bold.ttf Inconsolata-Regular.ttf Ricty4.1.1-Bold.ttf Ricty4.1.1-BoldOblique.ttf
      Ricty4.1.1-Oblique.ttf Ricty4.1.1-Regular.ttf Ricty4.1.1Discord-Bold.ttf
      Ricty4.1.1Discord-BoldOblique.ttf Ricty4.1.1Discord-Oblique.ttf Ricty4.1.1Discord-Regular.ttf
      ipag00303 migu-1m-bold.ttf migu-1m-regular.ttf migu-README.txt mplus-TESTFLIGHT-060
      ricty_generator.sh
      きちんと生成されていますね。良し良し。

      2018/06/10

      Docker Universal Control Plane を CentOS7 で起動してみる

      前回の記事では CentOS7 に Docker EE を入れました
      さて、何故入れたかと言えば Docker Universal Control Plane(UCP) を使ってみたかったからです。

      Unix User を dockergroup に所属させることで、複数のユーザが root でなくても docker を利用できます。
      しかし、他人が run した container に attach 可能。場合によってはよろしくない。
      何か解決策が無いかと調べたところ UCP を見付けました。

      UCP には Permission Control があって、Full Control の権限をユーザに与えても
      The user can view and edit volumes, networks, and images, They can create containers without any restriction, but can't see other users' containers.
      とのことで、別のユーザのコンテナは見られない。
      なので、root でない複数ユーザが、相互に干渉せず docker を使えそうです。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Kernel: 3.10.0-693.5.2.el7.x86_64
      • Docker: docker-ee-17.03.0.ee.1-1.el7.centos.x86_64
      • Docker Universal Control Plane: 2.2.6


      run UCP

      公式の document に従って UCP のイメージを run します。
      • $ docker image pull docker/ucp:2.2.6
      • $ docker container run --rm -it --name ucp -v /var/run/docker.sock:/var/run/docker.sock docker/ucp:2.2.6 install --host-address 127.0.0.1 --interactive
        • --interactive が付いてるので適宜入力します
        • 具体的には Admin username や password とかですね
      さてこれで起動……しません。
      INFO[0000] Initializing a new swarm at 127.0.0.1     
      FATA[0034] the following required ports are blocked on your host: 12385, 12376, 12383, 443, 12384, 12379, 12387, 12386, 12381, 12382, 2376, 12380.  Check your firewall settings 
      と言われました。おお、結構な数の port 使うな。

      ということで firewall に穴を開けます。
      • # for i in 12376 4789 12386 2376 443 12381 12380 12382 12383 12384 12385 12379 12387 ; firewall-cmd --add-port=$i/tcp --permanent
      • # firewall-cmd --reload
      くらいかな。

      そして再度 run してみる。今度は
      FATA[0031] The following required ports are already in use on your host - 2377.  You may specify an alternative port number to 2377 with the --swarm-port argument.
      と言われた。あれ。何が 2377 使ってるんだ?
      • $ netstat -lntp
      すると確かに 2377 が listen になってる。 process name は dockerd か。

      結論から言うと、一回目で起動した swarm が生きてたのが原因でした。なので
      • $ docker swarm leave --force
      して抜ける。さて三度目のトライ。コマンドは変わらず
      • $ docker run -it --rm --name ucp -v /var/run/docker.sock:/var/run/docker.sock docker/ucp:2.2.6 install --interactive
      で実行します。お、起動したっぽいですね。三度目の正直。
      INFO[0007] Generating UCP Client Root CA
      INFO[0007] Deploying UCP Service
      INFO[0035] Installation completed on raven (node abcdefghijklmnopqrstuvwxy)
      ...
      INFO[0035] Login to UCP at https://127.0.0.1:443
      https//127.0.0.1 にアクセスすると UCP の画面が出てきました。ログインも可能。良し良し。


      参考

      2018/06/03

      Docker EE を CentOS 7 に install する

      Enterprise Edition の Docker を CentOS 7 に入れてみたのでそのメモ


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Kernel: 3.10.0-693.5.2.el7.x86_64
      • Docker: docker-ee-17.03.0.ee.1-1.el7.centos.x86_64


      yum-config-manager --add-repo

      まずは公式のドキュメントに従います。
      Enterprise Edition の Docker は無料では使えないので、 subscription を買う必要があります。
      なのですが、一ヶ月無料お試しもできるので、s

      trial が始まるとユーザアカウント固有の URL が貰えます。
      • $ export DOCKERURL="<DOCKER-EE-URL>"
      のところですね。ちなみに具体的なURL は
      • $ export DOCKERURL='https://storebits.docker.com/ee/centos/<uuid>'
      でした。たぶん uuid は user ごとに違いそうなのでここには書きません。

      DOCKERURL も分かったので、後は公式ドキュメント指示通りに続けます。
      • $ sudo -E sh -c 'echo "$DOCKERURL/rhel" > /etc/yum/vars/dockerurl'
      • $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
      • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/rhel/docker-ee.repo"
      • $ sudo yum -y install docker-ee
      でインストール……されないですね。
      [Errno 14] curl#6 - "Could not resolve host: storebits.docker.com; Unknown error"
      と言ってきますが、 dig では storebits.docker.com は返ってくる。謎。


      DOCKERURL

      結論から言うと、 DOCKERURL が間違っていました。
      RHEL のドキュメントの DOCKERURL は
      • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/rhel/docker-ee.repo"
      ですが、store.docker.com から提供された URL は
      • https://storebits.docker.com/ee/centos/<uuid>
      なので、どうも帳尻が合っていない。
      いろいろ試した結果、 CentOS 用のキュメントは RHEL とは別にありました。
      おお、そこまで区別してるのか。 sensitive だ。

      ということで CentOS 用のドキュメントに従って
      • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/centos/docker-ee.repo"
      • $ sudo yum -y install docker-ee
      で Install できました。良し。


      おまけ: docker-ee.repo

      ちなみに DOCKERURL をブラウザで開くとファイル一覧が見られます。
      ちょっと見た結果 yum の repo と rpm が置かれていました。
      にしても、 yum の repo の仕様なのか、 docker-ee.repo が
      • DOCKERURL/docker-ee.repo
      • DOCKERURL/centos/docker-ee.repo
      みたいに2つあって、どっちが正しいのか悩んだり。両方とも正しい可能性もあるな。



      参考

      2018/04/08

      CentOS7 で root 以外のユーザも Docker を操作できるようにする

      基本的に Docker を使う時は root です。
      しかし複数人数で Docker を利用したい場合、全員に root をあげるのは良くない。
      調べたところ docker というグループに所属させることで、 root でなくても Docker を操作できるらしい


      環境

      • OS:CentOS Linux release 7.4.1708 (Core) 
      • Kernel: 3.10.0-693.5.2.el7.x86_64
      • Docker: version 17.06.2-ee-7, build 925df35


      dockerroot group

      さて docker group の gid でも見るかと
      • $ cat /etc/group | grep docker
        • dockerroot:x:985:
      すると docker group が無い。
      が、 dockerroot というものがある。
      • $ sudo gpasswd -a atton dockerroot
      して所属させてみる。
      しかし、
      • $ docker ps 
      すると見られない。


      Socket の Owner

      どうやら /var/run/docker.sock の owner は root:root らしい。
      docker を yum install したら dockerroot group を作るのに何故 owner は root のみなんだろ。
      まー root 以外に操作させないように念のため、ってことなのかな。

      とりあえず dockerroot が読み書きできるように変更。
      • $ sudo chown root:dockerroot /var/run/docker.sock
      そして一旦 exit して
      • $ docker ps
      すると見られた。
      • $ docker -it run ubuntu:16.04 bash
      しても動く。良し良し。


      権限とか

      ちなみにコンテナ内部で
      • $ whoami
      すると root と言われる。
      あと、他人が起動したコンテナも操作できてしまう。

      なので
      複数人数で Docker 操作+他人のコンテナに干渉しない
      場合は wrapper を作るか、他の手段に頼る必要がありそう。


      参考

      2017/12/10

      CentOS 7 上に CUDA 9 環境を構築する

      CentOS7 上に CUDA 9 を入れることがあったのでそのメモ。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • CUDA: 9.0
      • GPU: Nvidia GTX 1070


      GPU を認識しているか確認

      CentOS 側が GPU を認識しているかどうかは
      • lspci
      などで分かります。出力の中にGPUの名前があればOK。


      CUDA のインストール

      ドライバは入っているものとします。というか特殊なGPUで以外 xorg-x11-drv-nvidia-libs などを入れると動いたり。
      この辺は試行錯誤したので minimal な手順が残ってなかったり……。
      ということでドライバ周りは飛ばして、CUDA のインストールをします。

      まずは NVIDIA の公式サイトから、CUDA をダウンロードします。ここのページでOSやバージョンを選んでいく。
      今回は Linux + x86_64 + RHEL + 7 + rpm(network) を使います。

      後は出てきたコマンドに従うだけ。
      • wget http://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-repo-rhel7-9.0.176-1.x86_64.rpm
      • sudo rpm -i cuda-repo-rhel7-9.0.176-1.x86_64.rpm
      • sudo yum clean all
      • sudo yum install -y cuda
      rpm(network) だと、インストールの際に依存パッケージも入るので、これでおしまい。
      1G とか降ってくるので、コマンドは短かくても結構時間がかかったりします。

      なお、記事を書いている時点(2017/12/10) では 7.5, 8.0 も入れることができます。
      具体的には
      • $ sudo yum install -y cuda-8-0
      のようにバージョンを指定してあげるとOK。
      バージョンを省略すると最新の CUDA が入ります。

      /usr/local/cuda 以下にいろいろと入るので、PATH などを設定します。具体的には

      などですね。


      GPU が動いてるか確認

      • $ nvidia-smi
      あたりでGPUの状態が分かります。結果は

      のように出力されます。この場合GPUの使用率は100%なので、かなり頑張っていますね。


      参考

      2017/10/23

      CentOS7 で VLAN を設定する

      オンプレサーバ + VLAN で区切られた network を想定します。
      オンプレサーバで VM を提供する場合、1つの NIC が複数の VLAN に足が生えてる状態する必要があります。
      その設定をした時のログ。


      環境

      • OS: CentOS Linux release 7.2.1511 (Core)
      • Kernel: 3.10.0-327.10.1.el7.x86_64


      VLAN に足が生える想定の Interface (Bridge)を作る

      VLAN 1つに対して1つの Bridge を作成します。
      例えば VLAN 111 に足を生やすとしたら

      などを /etc/sysconfig/network-scripts/ifcfg-br111 として作成します。
      brctl とかで状態を見られたりしますね。


      VLAN を指定して、実 Interface から Bridge する

      VLAN に足を生やす元の Interface は bond0 としましょう。
      先程作った br に対して実際の Interface の VLAN=yes 版をブリッジします。

      とかを /etc/sysconfig/network-scripts/ifcfg-bond0.111 に書きます。
      これで br111 は VLAN 111 に通信できます。
      こちら側のファイルも VLAN ごとに設定を作成する必要がありますね。

      • # systemctl restart network
      してきちんと network が上がってきて通信できるか確認しましょう。
      複数の VLAN が1ポート内で入り混ざることを、スイッチ側にも設定しないといけない気もしますが、そこは私がやらなかったので割愛。


      参考





      CentOS7 で複数の NIC を束ねて bonding する

      オンプレのサーバだと複数の NIC を積んでいることがあります。
      それらの NIC を束ねて帯域幅を増やしたり、NIC を冗長化するなど活用法は多々あります。
      今回は束ねて帯域幅を増やす設定のログを残しておきます。


      環境

      • OS: CentOS Linux release 7.2.1511 (Core)
      • Kernel: 3.10.0-327.10.1.el7.x86_64
      • NIC: ifcfg-(p2p1|p2p2|p3p1|p3p2) として認識している


      束ねる集約先になる、仮想の Interface を作る

      まずは集約先の Interface を作ります。

      とかを /etc/sysconfig/network-scripts/ifcfg-bond0 に作成。
      mode=4 だと LACP で束ねてくれます。


      物理NIC の Interface で集約先を指定

      物理NIC の Interface で集約先を指定。
      とかを /etc/sysconfig/network-scripts/ifcfg-p2p1 に作成。
      具体的には Master に bond0 を指定して、SLAVE=yes にします。
      これを ifcfg-(p2p1|p2p2|p3p1|p3p2) 全てに適用してみます。そうすると4本を1つに束ねられる。
      最後は、設定をファイルに書き込んだ後に
      • # systemctl restart network
      で適用。これできちんと network が上がってきたらOK。
      単純に考えると帯域幅が4倍になってるはずです。

      参考

      2017/10/12

      systemd 制御下のプロセスの SEGV を追う

      systemd で起動したプロセスがいつの間にか死んでる。
      systemctl status を確認すると SEGV している。SEGV ......
      SEGV の原因を追うために systemd 管理下のプロセスで core を取る方法とかのログ。
      ちなみにそのプロセスは FreeRADIUS ですね。


      コアを dump するように

      • $ vim /etc/security/limits.d/core.conf
      • $ vim /etc/sysctl.d/core.conf

      コアを取るように設定。
      • $ reboot
      したら設定の適用完了。


      動作確認

      きちんと取れるか、死んでたプロセスに

        • $ kill -11 <pid>
        とかしたら core が取れるか確認できます。


        その後

        取れたコアを使って gdb で原因を追っていく。
        その際に bt などが使えないのがつらいので
        • $ yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/9c/hogehogefugafuga

        とかしておく。
        こうすると freeradius-debuginfo が入って bt とかを見られるようになる。
        とかとかしながらデバッグして原因を突き止めたのがこの記事です。


        環境

        • OS: CentOS Linux release 7.4.1708 (Core) 
        • kernel: 3.10.0-693.2.2.el7.x86_64
        • systemd: 219 +PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN
        • FreeRADIUS: 3.0.4

        CentOS7 で GFS2 を構築/本番運用したノウハウまとめ

        GFS2 を構築したり運用した時のノウハウを共有。
        どちらかと言うと「こういう事もあったなー」的なエピソードのまとめです。


        systemctl restart network はしてはいけない

        死にます。
        単一ノードの reboot は問題無くできます。
        といって network の restart はノードが fence されてしまってクラスタから切り離されます。
        クラスタから切り離されるのはまだ良い方で、最悪 HACluster 全体を巻き込んで死にます。
        具体的には gfs2 を mount しているディレクトリに ls したら永遠に返ってこない。
        全体を reboot で復活します。
        network の configuration を変える時は pcs stop --all とかしてくださいね。


        fsck.gfs2 は(直る時もある|直らない時もある)

        死んだ時にはファイルが壊れたりするのですが、場合によれば fsck.gfs2 で直ります。
        ただし、直らない時もあります。具体的には24時間以上かかっても終わらない。
        gfs2 のサイズを大きく(テラオーダー)作ったのが原因かもしれませんが、直らない時は直らないです。
        gfs2 を作った後に小さくすることはできませんが、大きくすることはできるます。
        なので、最初は小さいサイズから作るのが良さそうです。


        CPU/Network の利用率が100%になると fence される

        各ノードの死活管理には fence というものを使います。
        初期設定だと Network の利用率が100% になった時、ノードがクラスタから外されます。
        あとは CPU の使用率が高すぎる時とか。
        VMイメージのバックアップを取るためにノードが死んだりしました。
        まー1ノードくらい落ちても動くための HACluster だから良いのかもしれないけれど。


        umount までできるスクリプトを組んでおく + PowerChute との連携はしっかり

        当然ですが、gfs2 上にあるファイルに読み書きしている時には umount できません。
        例えば VM を gfs2 に置いてると、destroy する必要があります。
        停電した際に電源が UPS に切り替わった時、 umount できないと焦ります。
        スクリプトとかを書いておいて、よしなにしてくれるようにした方が良いでしょう。
        出来れば pcs で管理して、gfs2 を止める時に kvm で動いている VM を全て destroy した方が良いです。
        あとは停電対策として PowerChute とかとも連携すると良いですね。


        scsi-shooter は暇なノードに置いておくと良い

        fence を行なうノードはクラスタに1つで良いです。
        なので、全ノードが fence 用のプロセスを起動している訳ではない。
        死活監視のプロセスなので忙しいノードよりは暇なノードに置いた方が良いことが多いです(さっきの100%問題とか)。


        公式ドキュメントを読もう

        というかgfs2の参考文献とかだと公式ドキュメントしかなかったりします。
        設定から何から書かれているので読みましょう。


        環境

        • OS: CentOS Linux release 7.2.1511 (Core) 
        • Kernel: 3.10.0-327.10.1.el7.x86_64
        • pcs: 0.9.143


        参考

        2017/10/10

        Docker でデータの保存先をデフォルトの場所から変更する

        Docker は CentOS7 だと image などを /var/lib/docker 以下に保存します。
        しかし、その場所を使わずに他の場所へと変更することも可能です。
        例えば、SSD のドライブに置くようにしたらイメージの読み書きが早くなるでしょう。
        データの場所を変更するには /etc/sysconfig/docker を編集して -g オプションを追加します。
        具体的にはこんな感じ。

        これで

        • # systemctl restart docker
        すると、 -g で指定したディレクトリにデータが保存されるようになります。やったね。


        環境

        • OS: CentOS Linux release 7.2.1511 (Core)
        • Kernel: 3.10.0-327.10.1.el7.x86_64
        • Docker: version 1.12.6, build c4618fb/1.12.6


        参考

        2017/10/09

        virsh vol-create-from を使って異なる storage pool 間でイメージをコピーする

        libvirt はVMイメージの置き場として Storage Pool というものを提供しています。
        Storage Pool は libvirt が操作可能な記憶領域です。
        例えば、 Akatsuki による VM 貸し出しのフローは

        • テンプレート用のVMイメージをテンプレートのストレージプールから読み取る
        • 貸し出し用ストレージプールにテンプレートのVMイメージをコピー
        • 貸し出しインスタンスとしてコピーされたものを起動する
        といった形式になっています。



        状況

        • ストレージプール a と b がある
        • ストレージプール a に hoge.img がある
        • hoge.img をストレージプール b に fuga.img として複製したい


        状況を再現するコマンド

        とりあえず前提条件のストレージプール a と b を作ります。
        今回のストレージプールはディレクトリタイプ。
        他にも特定のデバイスをプールにするタイプなどいろいろあります。
        • # virsh pool-define-as a dir - - - - /path/to/a
        • # virsh pool-build a
        • # virsh pool-start a
        • # virsh pool-autostart a
        • # virsh pool-define-as b dir - - - - /path/to/b
        • # virsh pool-build b
        • # virsh pool-start b
        • # virsh pool-autostart b
        これで2つのストレージプールができました。

        そして a に hoge.img を作ります。
        • # virsh vol-create-as  --pool a hoge.img 10G
        イメージができました。vol-list で確認します。

        この hoge.img を b にコピーしたい。

        やり方はいくつかありますが、今回は vol-create-from を使う方針でいきます。
        その場合は xml が必要なので dumpxml で作っておきます。
        • # virsh vol-dumpxml  --pool a hoge.img > fuga.xml
        fuga.xml  の key や path を hoge の情報から、所望の情報に変更しましょう。
        今回は /path/to/b/fuga.img になるように書き換えます。

        そして vol-create-from でコピー。
        • # virsh vol-create-from --inputpool a --vol hoge.img --pool b  --file fuga.xml 
        再度 vol-list で確認します。

        fuga.img が作成できていることが分かります。やったね。


        環境

        • OS: CentOS Linux release 7.4.1708 (Core)
        • Kernel: 3.10.0-693.2.2.el7.x86_64
        • virsh: 3.2.0


        参考

        2017/07/18

        ActiveLDAP が Timeout Module を使っていた

        かなり前の記事になりますが、ActiveLDAP が Process.fork を使っているせいで PostgreSQL との相性が悪いバグがありました。
        具体的には Timeout を指定すると fork したプロセスを使って Timeout を確認しているせいで pg の connection を使いはたしてしまう、というのが原因でした。

        本当に具合が悪い時は Ruby がコアダンプを吐いて死ぬ時もあったので、直してしまってRuby会議2017のLTネタ にでもしようと思って調査を続行。
        最新版では再現しないのでソースを読んでみたらそもそも Process.fork をしていない。
        Timeout というものに block を渡している
        なんと Timeout なる Module があるようで、それに時間の処理を一任しているようです。

        Timeout Module 知らなかった。
        Timeout の処理って面倒なので自分が次に Timeout の処理を書くことがあったら使おうと思いましたまる。
        ソース読むのはおもしろかったけれどネタが無くなってしまったな。どうしようかな。

        2017/06/22

        Jenkins でビルドの情報を Slack に投稿する

        Jenkins ネタでもう一つ。
        ビルドの開始や失敗、成功を Slack に流したくなったのでそのログ。


        環境

        • CentOS Linux release 7.0.1406 (Core)
        • Docker version 1.12.6, build 1398f24/1.12.6
        • Jenkins ver. 2.46.3
        • Slack Notification Plugin 2.2


        構築方法(Slack)

        • Slack 側の Add Integration で Jenkins を指定
        • 通知させたいチャンネル名を指定
        • 発行された token をコピーしておく


        構築方法(Jenkins)

        • Manage Jenkins > Plugin Management > Available
          • Slack Notification Plugin をチェック
          • install without restart 
        • Manage Jenkins > Plugin Management
          • team subdomain: 通知したい Slack の subdomain
          • 例えば hoge.slack.com なら hoge
          • Integration Token は先程コピーした  token で
          • Channel は通知したいチャンネル
          • Is Bot User ? にはチェックを入れない
        • Test Connection できちんと Slack にポストされていれば設定はOKです


        構築方法(Jenkins Project)

        • 通知させたい Project の Configure を開く
        • Post-build Actions
          • に Slack Notifications を追加
          • 通知させたいイベントにチェックを入れる
        • Project > serval > Post-build Actions > Advanced
          • は特別設定しなければ先程のグローバル設定が使われるので空白で良いです
          • 私は Notification message includes を commit list with authors only に設定しました


        まとめ

        この設定をすることで  Jenkins がビルドした時に Slack へ通知が行なわれます。
        今回面倒だったこととしては、 Is Bot User? にチェックを入れていた時、Test Connection ではきちんと通知がされるのに、ビルドした時だけは通知がされないという絶妙な状態になることがありました。どうしてチェックを入れたらダメなのだろ。


        参考

        2017/06/20

        Docker で古いコンテナとイメージを消す

        Docker で適当にコンテナを作っていたり、CI とかをしていると使われなくなったコンテナが大量に積もっていきます。
        それを適当に消したのでそのメモ。


        環境

        • CentOS Linux release 7.0.1406 (Core)
        • Docker version 1.12.6, build 1398f24/1.12.6


        コマンド

        • docker ps -aq | tail -30 | xargs  docker rm
        基本的には古いものから消していく方針で。
        images の option で -q を付けると hash だけを出してくれます。
        あと -f で特定の条件のみで絞りこみをしてくれるようです。
        • docker ps -qaf "status=exited"
        とかすると止まってるのだけ出してくれる。
        動いてるコンテナは -f を付けない限り消さないので、 とりあえず全部 rm に渡してしまうのもありかも。

        あとはイメージを消すだけです
        • docker images -aq | xargs docker rmi
        こいつも使われているイメージは -f を付けない限り残してくれる。
        なのでとりあえず消せそうなもの全部消そうとしてみる、とか可能です。

        • docker images -qf dangling=true
        とかでタグが付いていないイメージだけを対象にする、というコマンドが参考記事にありましたが、今回はタグが付いているイメージもあるので -aq で。


        まとめ

        • docker ps -aq | xargs  docker rm
        • docker images -aq | xargs docker rmi
        とかでとりあえず起動していないコンテナ以外消えます。
        新しい docker だと docker image prune とかあるらしいのでもっと楽かも。


        参考文献

        2017/06/13

        Volume 指定を忘れた Docker からデータを取り出す

        Jenkinsをたてた時、最初はボリュームを指定せずに docker run していました。
        後からポートフォワードを追加しようと思って、一旦イメージを commit 。
        そのイメージにオプションを追加して起動しても Jenkins が初期化されている。

        どうやらボリュームを指定していないとどこかにボリュームを勝手に作るらしい。
        なので今まで作業していた分を commit してもコンテナに反映されない。
        ということでどこかに作られたボリュームを探せればデータを復旧できそう。

        • docker inspect <container-name>
        するといろいろ出てくるがその中に怪しいものが。
        Mounts の Source にパスがあるのでこいつっぽい。

        • cp -r /var/lib/docker/volumes/98ef888300af713d65b6d7534d835c7bd2e95270ad5eb016da749bbbb5f6d409/_data hoge
        • docker run -itd -P -v /foo/bar/hoge:/var/jenkins_home jenkins
        とかすると復活。やったね。

        環境

        • CentOS Linux release 7.0.1406 (Core) 
        • Docker version 1.12.6, build 1398f24/1.12.6