GitLab CI Runner をProxy環境下で動かす
前提
とあるネットワークのセグメント配下に設置されたVM -> GitLabへの通信はProxyを通す必要があり、かつそのVMがGitLab CI Runnerの役割を果たしている時の話し
準備
上記のページに沿ってci runnerをインストールしたらOK
ハマりどころ
インストール後はci runnerをgitlabに登録することになる。ただしProxyの設定をしておかないと登録はできるがGitLabからCIをキックできずにハマる。
なのでその次のステップの登録はちょっとまって欲しい。
Proxyの設定
上記のissueのコメントの Adding Proxy variables to the runner config, so it get's builds assigned from the gitlab behind the proxy
に書いてあるとおり、 /etc/systemd/system/gitlab-runner.service.d/http-proxy.conf
などを作って、systemd側からproxyの設定をgitlab ci runnerに渡してあげる必要がある
Proxyの設定を登録したら
上記の通り、gitlab ci runnerを登録したら良い
与太話
自分がgitlab ci runnerをproxy配下で動かそうと試行錯誤している途中で、gitlabのデータがおかしくなって、gitlab ci runnerがweb uiから登録解除というか削除できなくなってしまった。
そのような場面に陥ったら以下のissueを参考にすると良い。CLI側からもci runnerを登録解除できる。登録解除に必要なTokenなどは /etc/gitlab-ci-multi-runner/config.toml
を参照したら見つけられるはず。
PHP, Python, Golang を NGINX Unit で動かしてみた
NGINX Unit
ホームページは以下
もしくはミラーだけどGitHubが以下となる
RestAPIやJSONで設定できる、phpのPHP-FPMやpythonのwsgiサーバーなど言語ごとのアプリケーション・サーバーを集約したアプリケーションサーバーという感じ。なのでNginxの後ろで動くサーバーという認識で大丈夫なのかな?
まだversionは0.1なので、今後どんどん成長していくはず。
現状は以下に対応しているとのこと
Python 2.6, 2.7, 3
PHP 5, 7
Go 1.6 or later
ざっくりとした所感
- プロダクトに関して
- 現状のドキュメントに関して
と、言うことで、3つの言語で動かした際の動かし方を残しておく (最初にドキュメントを読んで、詰まった際の補助資料くらいに思うと良いはずです。)
動かし方
インストール後のサービスの動かし方
systemctl enable unitd.service systemctl start unitd.service
気づき
curl --unix-socket /run/control.unit.sock http://localhost/
で設定を確認できる.systemctl restart unitd.service
をしたら設定が揮発する模様?
各言語ごとの動かし方をまとめ
要点だけ
PHP
設定で指定する root
に index
で指定するファイルを置くだけ
Python
設定で指定するpath
に wsgi.py
を設置, wsgi.py
の中で application
がwsgiアプリケーションになっていればOK
例えばFlaskなら以下の様な感じ
#!/usr/bin/env python from flask import Flask application = Flask(__name__) @application.route("/") def index(): return "<h1>Hello NGINX Unit</h1>"
Golang
こっちが一筋縄では行かなかった。
まず、unit
をインストールしているだけではダメでCentOSでは unit-devel
をインストールしておく必要があることと、
export GOPATH=/home/user/go_apps
をしておいた後に、 unit
パッケージをインポートして使う。
上記の状態で、以下のようなソースをビルドし、設定の executable
で指定したパスに配置する。
package main import ( "fmt" "net/http" "unit" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello NGINX Unit</h1>") }) unit.ListenAndServe(":8000", nil) }
普通のgolangのアプリと違うのは、 ListenAndServe
するのが、httpではなく unit
な点だと思う
個人的感想
NGINXが新しくサーバーをリリースする!というのは個人的に驚き。
ApacheよりもNGINXに慣れ親しんでいる世代ということもあり、頑張ればソースコードを読み切る事ができそうな気がする規模なので読みたい。
以下は全部この記事を書いた際のメモ
とりあえず動かしてみる
CentOS7でやってみる
[root@mycentos7 go-app]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core)
↑のインストールにそって yum -y install unit
で問題なくうまくいく
ドキュメント的にはインストールで終わっているので動かし方を探ると以下の感じで動き出す。定石どおり。
[root@mycentos7 unit]# systemctl status unitd ● unitd.service - NGINX Unit Loaded: loaded (/usr/lib/systemd/system/unitd.service; disabled; vendor preset: disabled) Active: inactive (dead)
systemctl enable unitd systemctl start unitd
[root@mycentos7 unit]# systemctl status unitd ● unitd.service - NGINX Unit Loaded: loaded (/usr/lib/systemd/system/unitd.service; enabled; vendor preset: disabled) Active: active (running) since Fri 2017-09-08 00:42:25 JST; 6s ago Process: 2502 ExecStart=/usr/sbin/unitd $UNITD_OPTIONS (code=exited, status=0/SUCCESS) Main PID: 2503 (unitd) CGroup: /system.slice/unitd.service ├─2503 unit: main [/usr/sbin/unitd --log /var/log/unitd.log --pid /run/unitd.pid] ├─2505 unit: controller └─2506 unit: router
プロセスとしては動いていそう。
[root@mycentos7 unit]# ps aux | grep unitd root 2503 0.0 0.0 16168 632 ? Ss 00:42 0:00 unit: main [/usr/sbin/unitd --log /var/log/unitd.log --pid /run/unitd.pid] root 2516 0.0 0.0 112644 964 pts/0 R+ 00:44 0:00 grep --color=auto unitd
lsofを叩いてもunitdが掴んでいるポートはなさそう?
[root@mycentos7 log]# lsof -i COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME chronyd 715 chrony 1u IPv4 13918 0t0 UDP localhost:323 chronyd 715 chrony 2u IPv6 13919 0t0 UDP localhost:323 sshd 1038 root 3u IPv4 16617 0t0 TCP *:ssh (LISTEN) sshd 1038 root 4u IPv6 16626 0t0 TCP *:ssh (LISTEN) master 1648 root 13u IPv4 17586 0t0 TCP localhost:smtp (LISTEN) master 1648 root 14u IPv6 17587 0t0 TCP localhost:smtp (LISTEN) dhclient 2260 root 6u IPv4 18318 0t0 UDP *:bootpc dhclient 2260 root 20u IPv4 18307 0t0 UDP *:46788 dhclient 2260 root 21u IPv6 18308 0t0 UDP *:gilatskysurfer
ドキュメントを読むと
By default, the Unit API is available in the control socket file unit.control.sock.
と書いてあるので、探すと /run/control.unit.sock
があることがわかった。
[root@mycentos7 log]# find / -name 'control.unit.sock' /run/control.unit.sock
ミニマルと呼ばれている設定を投げつけることにする
ドキュメントどおり以下の設定ファイルを
{ "listeners": { "*:8300": { "application": "blogs" } }, "applications": { "blogs": { "type": "php", "workers": 20, "root": "/www/blogs/scripts", "index": "index.php" } } }
curl -X PUT -d @./start.json --unix-socket /run/control.unit.sock http://localhost/
で投げつける
レスポンスは以下の様
{ "success": "Reconfiguration done." }
ではphpを設置してみる。
[root@mycentos7 ~]# mkdir -p /www/blogs/scripts [root@mycentos7 ~]# touch /www/blogs/scripts/index.php [root@mycentos7 ~]# echo -e "<?php\n\nphpinfo();" > /www/blogs/scripts/index.php [root@mycentos7 ~]# cat /www/blogs/scripts/index.php <?php phpinfo();
curl localhost:8300
できちんと反応する
自分のホストのIPだと反応がないと思ったが、firewalldを切ったらきちんと反応した.
ちなみにドキュメントの何処かに書いて有りそうだが、 curl --unix-socket /run/control.unit.sock http://localhost/
で設定を確認できる.
また systemctl restart unitd.service
をしたら設定が揮発した。たぶんココらへんは今後改良される点なはず。
Python 編
こうなったらpythonもためしたい。
またしてもドキュメントどおりの設定を投げつけ、
{ "applications": { "blogs": { "type": "php", "user": "nobody", "group": "nobody", "workers": 20, "root": "/www/blogs/scripts", "index": "index.php" }, "wiki": { "type": "python", "user": "nobody", "group": "nobody", "workers": 10, "path": "/www/wiki", "module": "wsgi" } }, "listeners": { "*:8300": { "application": "blogs" }, "*:8400": { "application": "wiki" } } }
/www/wiki/wsgi.py
を以下のように作る
[root@mycentos7 wiki]# cat wsgi.py #!/usr/bin/env python from flask import Flask application = Flask(__name__) @application.route("/") def index(): return "<h1>Hello NGINX Unit</h1>"
こちらもそつなく動く
golang 編
ついでだからgolangも書いておく。今度はドキュメントからチョット変更して以下のような設定を投げつける
{ "applications": { "blogs": { "type": "php", "user": "nobody", "group": "nobody", "workers": 20, "root": "/www/blogs/scripts", "index": "index.php" }, "wiki": { "type": "python", "user": "nobody", "group": "nobody", "workers": 10, "path": "/www/wiki", "module": "wsgi" }, "go_server": { "type": "go", "executable": "/www/server/bin/server", "user": "nobody", "group": "nobody" } }, "listeners": { "*:8300": { "application": "blogs" }, "*:8400": { "application": "wiki" }, "*:8500": { "application": "go_server" } } }
でもって以下のようなコードを作って... と思ったら、golangは普通にnet/http
を使うのではダメな模様
https://github.com/nginx/unit/issues/8/ に書いてある/usr/share/doc/unit/examples/go-app/let-my-people.go
を覗くと unit
というパッケージがある
package main import ( "fmt" "net/http" "unit" ) func handler(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "text/plain"); fmt.Fprintf(w, "Method : %s\n", r.Method) fmt.Fprintf(w, "URL : %s\n", r.URL.Path) fmt.Fprintf(w, "Host : %s\n", r.Host) } func main() { http.HandleFunc("/", handler) unit.ListenAndServe("8000", nil) }
上記をissue真似て, sudo yum -y install unit-devel
をしたあとexport GOPATH=/home/user/go_apps
, 以下のファイルを go build
して /www/server/bin/server
としてファイルを設置したら curl localhost:8500
が上手くいった.
package main import ( "fmt" "net/http" "unit" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello NGINX Unit</h1>") }) unit.ListenAndServe(":8000", nil) }
備忘録 自宅リージョン 2017/08/26
↑の記事から半年の間に色々と試した結果、自宅の構成が固まってきたので備忘録を書こうと思った。
vSphere環境を自由に使える状態になったので、ミドルウェアの使いかたの学習やちょっとしたアプリ開発でVMがほしいときにクラウドサービスを使う必要が無くなった。
(ちなみにvSphereとかはライセンスの問題で定期的に入れ替えて使っている)
機材
半年前から買い足した機材は2台
Ubiquiti Networks Edgerouter ER-X(日本国内)
- 出版社/メーカー: Ubiquiti
- メディア: Personal Computers
- この商品を含むブログを見る
- 出版社/メーカー: ネットギア
- 発売日: 2016/02/18
- メディア: Personal Computers
- この商品を含むブログを見る
NASはvSphere環境でvmotionしたくて買った。自宅でもvMotionできると何かと便利な気がする。最近Synologyが良いと聴くけど基本的に機材の良し悪しはよくわからない事と、switchや以前から使っている無線ルーターがNETGEARなのでNASもNETGEARにした。
あと本当はNUCを1台買い足しているけれど、メモリが高騰していて買えていないので投入できていない
現状のネットワーク図
学習用途を兼ねているし、ネットワークの設計や仮想化環境の扱いはほぼ素人なので、その手の人から見たら無駄や設計ミスがあると思う。
基本的にはhomeのセグメントに接続しているmacからmyprivateのセグメントに置いたVMへsshで繋いで検証とかを行っている。Edgerouterとvyosでルーティングしている
- 共通
- homeのセグメント
- managementのセグメント
- 有線でつなぐためにあけてある
- 冷静に考えて無駄な気がしている
- mycloudのセグメント
- 実際はswitchにぶら下がっている
- 物理ホストやNAS, vCenterサーバーなどを置く所
- myprivateのセグメント
- 適当にVLANを切っている
- 検証用のVMを置く所
反省と今後
vSphereの仕様上、VMの足を生やす上限は10個までとなっているので、検証で切りたいセグメントが10を超えたらリソース消費との兼ね合いでvyosをチョットずつ継ぎ足していくのかな?とか考えている。
この環境を作る途中、困ったタイミングで適当にVMKernelを作ったりしたのでipの払い出しがいい加減な所がちょこちょこある。もっとvSpereの仕様とかを把握したほうが良いはず。
またこの環境は基本冗長構成が取られてないし、各機器の監視なども特にしていないのでチョットずつ育てていこうかな?と言う気持ちになっている。
git remote がhttpsでbasic認証している時の自動化方法
前提となる話
gitのリモートには git://
と https://
が使える。要はsshかhttpsかという違いで、諸事情によりsshを利用せずhttpsを使いたい場面がある。
sshならばパスフレーズのないdeploy keyなどを用意したら、あとはキーの取り回しをどうしたら良いか?で事が済むが、httpsかつ認証が必要なリモートリポジトリを扱う際はパスワードを入力する必要が出て来る。
httpsを利用した際の認証はbasic認証なので、 git clone
をする際に認証情報を埋めたら自動化できるのだが、git remote -v
で認証情報が丸見えとなる。(と言うか、自分の作った環境を先輩に見せたら丸見えの状態で非常に恥ずかしかった) ので、以下のURLで示されている方法は得策ではない。
.netrc
を利用するといちいちパスワードを入力する必要も無い。しかし通常は平文、チョット気を使うと暗号化できたりするが、何れにせよユーザーとパスワードを保存した状態となるので、様々な人が触るサーバーで .netrc
を使うのは得策と言えないだろう。
加えてスクリプトから扱う専用のユーザーをリモートリポジトリのサーバーに作りたくない。リモートリポジトリ側のユーザー管理が雑になる可能性があるので、極力普段使っているユーザーの認証情報で済ませたい。
ではansibleやjenkinsなどの自動化ツールを使った際に認証付きhttpsリポジトリを扱うのはどうしたら良いか?という点に話を移すと、対話が必要なときは expect
コマンドなどで頑張るのが回答の候補に上がるだろう。個人的には expect
とか泥臭すぎると思うのでその方法は避けたい。
ということで今回は以下の前提で話を進める
git credential helper
環境変数経由で渡せるとansibleとかjenkinsで簡単に自動化ができるなぁと思いながら、gitを調べていたら credential helper なるものが有るのを発見した。
使いかたとか設定方法は大体上記に書いてある。
git config --global credential.helper cache
と設定すると、ファイルには設定を保存せず、ある程度の時間認証情報を保持してくれるようになるとのこと。
加えて以下を実行すると認証情報が渡せるとのこと。
git credential fill
惜しい。なにが惜しいか?というと、さらっと調べる限り、標準入力等では git credential fill
に情報を渡すことはできなさそう?だった。
自動化方法
Git - 認証情報の保存 には 独自の認証情報キャッシュ
という項目がある。
サクッと読むと git hook
と同じように、独自コマンドを利用することが可能らしい。サンプルに乗っているRubyをパクって、環境変数を渡すようにしたら良さげ。
ということで、以下のようなスクリプトを実行権限付きで、 /usr/local/bin/git-credential-env
とかで設置し、 git config --global credential.helper env
とかすると、環境変数経由で認証情報を渡せるようになる。
あとは、ansibleのenvironmentやjenkinsのパラメーター付きビルドで GIT_PROTOCOL
, GIT_REMOTE_HOST
, GIT_USER
, GIT_PASSWORD
を指定してやるといい感じに自動化できる。
GIT_PROTOCOL=https GIT_REMOTE_HOST=github.com GIT_USER=hoge GIT_PASSWORD=fuga ./git-credential-env.sh get protocol=https host=github.com username=hoge password=fuga
注意点
#builderscon に参加してきました。
に参加してきました。
企業スポンサーのチケットで参加してきた形になるので、細かいレポート的なことは会社のブログで書くことになるので、自分のブログでは個人的な感想とかを書き残そうかと思います。
個人のブログとは言え、所属する会社との関係も多少あるので書いておきます
本記事での発言は個人の責任で、所属する組織を代表するものではありません。
参加したセッション
一応buildescon2017が開催されている時間帯は全部いました。
- 前夜祭
- オンプレミスデータセンター撤退!
- データストア撤退の歴史
- PaaS完全撤退の歴史
- ブロックストレージとの戦い、そして撤退
- 初日
- 2日目
難しいなと思ったこと
楽しくない話しは先に書いておきます。
リアルのイベントを開催すると集客人数とかセッションごとの人の分散とかを想定しづらいのだろうなぁと思いました。前夜祭やランチセッション等で利用していた会場は若干席不足感が否めなかったです。ただ会場サイズには限りがあると思いますし、参加者全員を収容できる場所なんてなかなかないはずなので難しいなぁと思った次第です。もっとスポンサーとか集まると解消するのでしょうかね?
お昼ごはん
ランチセッションで提供されたお弁当美味しかったです。
羨ましいなあと思ったこと
しゃもじ。
会社で振り回したかったなぁという気持ちです。
真面目な感想
まずSNSでの拡散禁止になっていた前夜祭が めちゃくちゃ おもしろかった!!! 拡散禁止になるレベルの話なので面白くないわけが無いのですが、やっぱり聞いたら面白かったです。各社 ~お腹が痛くなるような~ 苦難を乗り越えて今があるんだなぁって感じです。この様な話を聴くと、SNS拡散禁止のリアルなイベントに参加する価値がとても高いなぁと感じました。
2014,2015のyapcに参加し、1年飛んでbuildersconに参加したのですが、カルチャーが受け継がれているなぁと思いました。プログラミングを始めたのが大体2013年で、始めた当時からyapc ~ buildersconがあった身分なのですが、今年も各セッションで頑張る気持ちが高まる話が聞けて色々頑張るぞ!!!って気持ちになってます。
加えて、個人的なブログなので好き勝手書くと、PHPでwebアプリケーションを書いている人がいっぱいいて羨ましい気持ちになりました。現在のお仕事も楽しいので不満等は全く無いのですが、PHPを書くことは無く、むしろPHPを別のモノに置き換える仕事がメインで、PHPでプログラミングを覚えてきた身としては寂しさがあるのです。(PHPの話しを書いていてふと思ったのですが今年はPerlがメインな話がもしかしたら無かった?)
今後に向けて
2014年(過去のセッションの動画や資料をあさっているのでそれをカウントするともうチョット昔)から、builderscon界隈のコニュニティからは知見を頂きっぱなしになっているので、来年はLTとか本編のプロポーザルを書こうと思います。自分がやって来たことに対する知見等をコミュニティに還元できればなぁと思ってます。
しゃもじは欲しかったので、来年もそのようなサプライズがあることを期待しつつ個人スポンサーするのを忘れないようにしたい気持ちもあります。
また、所属している会社がスポンサーをさせてもらった割に、お金しかだせていないのはなんだか申し訳ない気持ちになったので来年は個人的に、スタッフとして協力も出来ればよいなぁと考えています。
要はbuilderscon最高だと思っているので、何かしらでもっと協力をさせてもらいたいなぁと思っています。
最後に
どうせブログのアカウント名をググると自分の各種アカウントしか出てこないはずなので。
もうclosingも間近ですが、今回の幕間CMを出していた会社の名前、できれば「富士通」ではなく「富士通クラウドテクノロジーズ」で認識していればありがたいです。 #builderscon
— やま(´・_・`)ぐち (@yaaamaaaguuu) 2017年8月5日
現在 #builderscon で提供させていただいている、弊社エンジニア紹介動画を、youtubeにアップロードしました。皆さんに名前を覚えていただけるとうれしいです! https://t.co/51puCduXgX
— 富士通クラウドテクノロジーズ株式会社 (@Fujitsu_FJCT) 2017年8月4日
ありがとうございました。
Docker Compose の fluentd ロギングドライバの設定で環境変数を使いたい時に見るページ
ロギングドライバの設定で環境変数を使いたい
個人的にはfluentd driverを使う時のタグの文字列を環境変数を利用して組み立てたかった
ドキュメントと記事
https://docs.docker.com/engine/admin/logging/log_tags/docs.docker.com
https://docs.docker.com/engine/admin/logging/fluentd/docs.docker.com
要は上記をきちんと読めば分かること(だけど自分は詰まった)
使うまでの3ステップ
- envファイルを読み込む
--log-opt
にenv=HOGE
で利用したい環境変数を渡す--log-opt
にtag=(.ExtraAttributes nil).HOGE
の様な形で引き渡す
compose-fileに落とし込むと以下の様な感じ
env_file: .env logging: driver: fluentd options: env=HOGE,HUGA tag="(.ExtraAttributes nil).HOGE-(.ExtraAttributes nil).HUGA"
gitリポジトリをCIするのに Jenkins Pipeline もしくは Jenkinsfileが辛いなぁと思った話
背景
- いくつかでCIをやってみた
- システムではなくソースコードをCIしたい
- 本家?のJenkinsはやってみてなかった
- GUIでポチポチ形式が割りと嫌
- そう言えばJenkinsfileがあるらしい
- 宣言的にCIの内容を書ける
- チャレンジしてみよう
Jenkinsfileとは
- GroovyでCIのjobのステップを宣言するやつ
- とは言えJenkins上でプログラムだと何でも動かせるので制約がいくつか付いている
- 制限突破をするための設定があるので余り気にならない可能性はある
- Jobの実行時にYes/Noをinputできるようにしている
辛さ
ちょっと触って詰まって調べた程度なので間違いはあるかもしれません
- Jenkinsが想定している前提が広いこと
- 他のCIならばgitとリポジトリに対するイベントが前提となっていると思う
- Jenkinsfileが閉じていること
- いろいろやろうとするとJenkinsfile外との連携を考える必要が出てくる
- Jenkinsfileの良さを殺している
雑記
冒頭で述べたように個人的にはGUIでしか設定できないのは嫌なのだが、「Jobの内部はJenkinsfile, 外部とのやり取りはGUIで設定」という現状は結局GUIでの設定に依存していてはっきり言って不便。
ソースコードをCIするだけならば、GitlabCIもしくはSaaSのCIが圧倒的に便利。前提として考えているワークフローがJenkinsとそれ以外では違いすぎる。
JenkinsはOSSだから文句を垂らすならコントリビュートする努力をしたほうが良いのだろうけど、便利な代替があるので、不便なJenkinsfileを改善する努力もするつもりが無い。
自分の観測範囲だとJenkinsはスクリプトにGUIを提供するためのラッパーツールっぽくて、CIツールとしてはあまり使われていない。多分だけど自分の観測範囲外でも同じような使われかたをしているのでは?と思えるJenkinsfileの機能だと思った(Job実行時のyes/noとか)。ただ僕にとってはスクリプトをラップしたGUIとか何も有り難みが無い。結局設定されているスクリプトを見るし、直接たたいてオプションとか調べるし。調べた後はJenkinsが無駄なGUI層として残ることになる。
が、スクリプトをラップしたGUIは、スクリプトを読めない人でも安心して実行することができる利点?があるので、Jenkinsはそっちの方で生き残るのかな?
ココまで書いて、「自分が主体的に使うシーンを想定すると割りと辛い気持ちになり、他人のためにスクリプトのラッパーを用意してあげるだけならばJenkinsで良いのかも。」と思った。