docker, fig, k8sで遊ぶ
どう考えても異常に便利だし、どう見ても流行ってるし、2015年になる前に現状に追いつきたい
先人の知見を基に単に試すだけで新しいことは何もしてない
- やる前の状態
そういえばMesosやMarathonとかもあったけど、全てdockerコンテナで動かすって仮定すればk8sで賄えるって感じなんだろうか
- 目標はこのへんを適当に触ってある程度概念とか理解出来たら良い
はじめの環境(後で変わるかも?)
- boot2dockerでやる
boo2docker shellinit
で初期設定とか済ませておく
docker pull ubuntu:latest
してubuntuのimageで最初は始める
dockerコマンドの基本
全部docker help <command>
に書いてるし、↓の試した
(ドキュメントもあるけどhelpで十分過ぎる)
- docker run
: コマンドを実行 -i
: interactive-t
: tty--rm
: 実行後に消す--name
: 名前つける-d
:daemonとして実行detachだった(backgroundで実行みたいな感じ)
- docker rm <container_id>: コンテナ消す
- docker ps
-a
: all-l
: latest-f
: filter-q
: container id だけ出す
- docker commit <container_id>: 止まってるコンテナとか指定して現状のimageとして保存する
docker run -ti ubuntu /bin/bash
> apt-get -y update && apt-get install -y golang && exit
docker commit $(docker os -ql) snapshot/golang
- docker images: image一覧
- docker rmi
: image消す docker attach, detach, start, stop, logs,...
run --rm
しないとstatus=exitedなコンテナが残りまくる- 掃除:
docker rm $(docker ps -aq -f=status=exited)
普通に触る分にはこれぐらい
- 色々進めてく中でこの辺のコマンドやオプションも覚えたから追記する
docker inspect <container_id>
: ipaddressとか色んな情報見れるdocker run --net=<bridge|...> ...
- 通常dockerは
docker0
って仮想ブリッジを通してコンテナ毎にinteraceを作ってく - これが
net=bridge
のデフォルト挙動で、その辺を変えたり出来る
- 通常dockerは
docker run --link <container>:<alias> ...
: 他のコンテナとリンクさせるdocker port <container_id> <port>
: ipやポートフォワードの情報
Dockerfile
定義方法
ドキュメント Dockerfile - Docker Documentation
Dockerfileに作りたいimageのレシピみたいのを書く
作ったDockerfileはDocker Hubにリポジトリとして置けて、ここに色んな公式Dockerfileとかもある
FROM <image>
orgFROM <image>:<tag>
MAINTAINER <name>
RUN <command>
: buildする時に実行されるやつ- 引数ある時:
RUN ["command", "arg"]
- 引数ある時:
EXPOSE <port>
: コンテナ内部から見たポート番号を指定して開放ENV <key> <value>
: 環境変数ADD <src> <dest>
: コンテナの中に外のファイルをコピーする- urlが指定できる・圧縮ファイルが自動解凍される
COPY <src> <dest>
: コンテナの中に外のファイルをコピーする- urlが指定できない・圧縮ファイルが自動解凍されない
CMD <command>
: コンテナ起動時に実行されるENTRYPOINT <command>
: コンテナ起動時に実行される- docker runの引数をパラメータとして扱う
VOLUME ["/data"]
: 外部からボリュームとしてマウントするディレクトリUSER <name>
: コンテナ起動時のユーザ名WORKDIR <dir>
: CMDが実行されるディレクトリを指定ONBUILD <instruction>
: build完了後のhook
【翻訳】いいDockerイメージを構築するには? ーDockerfileのベストプラクティスにもあるけど、build toolとか必要最低限に抑えつつ、RUNのコマンドは繋げれるものはつなげた方が良いっぽい
適当に公式のdocker-nginx/Dockerfile · nginxinc/docker-nginx持ってくると、まぁ全部読める
ポイントとしては、RUN apt-get install
には-y
をつけたり、上のベストプラクティスにもあるように、必要なくなったファイルを消すとか
devian:wheezy
(debian Repository | Docker Hub Registry - Repositories of Docker Images)を最初に指定して、ここから積んでくってイメージ勝手に持ってる
FROM debian:wheezy MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com" RUN apt-key adv --keyserver pgp.mit.edu --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 RUN echo "deb http://nginx.org/packages/mainline/debian/ wheezy nginx" >> /etc/apt/sources.list ENV NGINX_VERSION 1.7.8-1~wheezy RUN apt-get update && apt-get install -y nginx=${NGINX_VERSION} && rm -rf /var/lib/apt/lists/* # forward request and error logs to docker log collector RUN ln -sf /dev/stdout /var/log/nginx/access.log RUN ln -sf /dev/stderr /var/log/nginx/error.log VOLUME ["/var/cache/nginx"] EXPOSE 80 443 CMD ["nginx", "-g", "daemon off;"]
そういえばdocker run
も-e --env``-u --user
,-v --volume
,-w --workdir
オプションがある
外部にnginxのログを置きたい場合には上記ログ系の設定を除きつつdocker run -v /tmp/nginx_log:/var/log/nginx nginx_image
のようにすれば良い
Dockerfileを試す
- ubuntuにnginxを乗っけてみる(普通にapt-getして入れる)
以下のようなDockerfile
を用意してdocker build -t snapshot/nginx .
でimageを作成
nginxはデフォルトでデーモンになるので、ならないように実行しておく
FROM ubuntu:latest RUN apt-get update && apt-get install -y nginx EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
docker images
でsnapshot/nginx
があることを確認docker run -d -p 80:80 snapshot/nginx
-p
は外側のポートと内側のポートをforwarding
docker ps
でnginxのコンテナが動き続けてるはずcurl http://localhost/
とかするとnginxのレスポンスが得られたから成功
docker stop $(docker ps -ql)
やdocker rm $(docker ps -aq -f=status=exited)
とか、help見なくても打てるようになったのも成功
fig
Dockerfileを基にimageさえ出来てしまえばコンテナの環境は万全の状態になってるはず
でも実際はその上に何かしらのサービスを動かしたりするんだけど、どこのポートを繋いだり、どうやって起動するのかってのをまとめて実行させたりってのをfigが全てラップしてくれたりする?
docker自体に--link
って他のコンテナとリンクする機能があるんだけど、その関連も勝手にfig.ymlに書いといたらやってくれるのが良さそう
ちなみにmotemen/github-issue-badgeって超便利なのがあるんだけど、ここにもDockerfile
とfig.yml
が用意されてるから、fig up
ですぐ動くものが手に入る(これHerokuのdeployボタンもあるしすごい)
Fig | Fast, isolated development environments using Docker が普通に良さそうだからこれに従って試してみる
- OSX上で動かしたいんで
sudo pip install -U fig
でインストール- なんか色々警告出たけど
fig --version
出来るしスルー
- なんか色々警告出たけど
- figの場合ヘルプは
fig -h
orfig --help
fig.ymlの定義方法
fig.yml
の定義方法を見たら、どういう概念があるとかも分かる気がする
↓で試したfig.yml
見ながら確認、どうやらYAMLのトップがサービス名で、サービス毎の設定を書く感じっぽい
image
: dockerのimageを指定- アプリには手元にDockerfileを使って、DBとかには外のimageを持ってくるとか
build
: Dockerfileのあるディレクトリを指定command
: アプリの起動などのデフォルトコマンドlinks
: 他のサービスとリンクするports
: 開放するポート及び、ポートフォワードHOST:CONTAINER
- YAMLの都合上、文字列で指定するのが望ましい
expose
: linkされているサービスのみ用いることが出来るportを指定volumes
: 外部からボリュームをマウントさせる際のパスを指定HOST:CONTAINER
や、HOST:CONTAINER:ro
(ro
はアクセスモード)と指定
volumes_from
: 他のサービスを指定してボリュームをマウントさせるenvironment
: 環境変数を配列でもディクショナリでも指定出来るkey: value
みたいなディクショナリをenvironment:
の下に書くとかそういう感じ
net
: ネットワークモード?docker
の--net
と同じ値を用いるらしいdocker run
のオプションに--net
ってのがあるらしい、DockerのHost networking機能 | SOTAからそのまま引用するけど、この記事読んだ方が良い--net=bridge
:仮想ブリッジdocker0に対して新しくネットワークスタックを作成する(default)--net=container
:<コンテナ名|コンテナID>:他のコンテナのネットワークスタックを再利用する--net=host
:ホストのネットワークスタックをコンテナ内で利用する--net=none
:ネットワークスタックを作成しない
- dockerのネットネットワークはホストのdocker0って仮想ブリッジにvethのインターフェースを通して、IPマスカレード(ipやportを変換)した上えでコンテナのeth0に繋がる
- コンテナ毎にインタフェースが増えるの、某所でdocker問題ッて言われてるやつこれか
- dockerのコンテナへのIPマスカレードが実際に影響与えるのかって下の記事で色々見ていた
dns
: DNSサーバを指定出来る(8.8.8.8とか)- その他:
docker run
のオプションと同じ事出来るってさworking_dir
,entrypoint
,user
,hostname
,domainname
,mem_limit
,privileged
net
のとこで思わずdockerについてのネットワーク周りを学べてしまった
Dockerのネットワークの基礎 | SOTA とか良かった
試す
試したいけどそういえばコマンドを確認してないから軽く触れる
- コマンドが複数個あって、ドキュメントもある
- 大体のコマンドが予想出来そうなものばかりだけど、迷いそうなのとか面白いのだけ書く
build
: サービス名に対して、buildする -> からのrun
scale
: サービス毎に、何個のコンテナを起動するのかを指定出来るup
: サービスに対して(re)build, create, start, attachするってさ
公式に乗ってるサンプルから1個試す
Flaskのサンプルは普通にRedisとか使う感じでまぁ十分figの利点が分かりそう
Dockerfile
: まぁ分かるfig.yml
: 同じの使うけど確認する- redisとwebってサービスを用意する、これらはもちろん別のコンテナに乗る
- redisは(手元にあったら別だけど)外部のredisってimageを使って、webはbuildを指定してるから手元のDockerfileからimageを作る
- webサービスがredisを使うから、linksでつなぐ
web: build: . command: python app.py ports: - "5000:5000" volumes: - .:/code links: - redis redis: image: redis
後はfig up -d
とかすると、5000のポートを叩くとアクセス出来る(boot2docker ip
した先に)
- figは勝手に現在のディレクトリ名を使って
workdir_web
とworkdir_redis
ってimageを作る fig run web
みたいなアクセスが出来るから、設定をYAMLに書いてさえしまえば、dockerってコマンドがいらなくなる感じで良いfig run web cat /etc/hosts
みたいなのすると、コンテナの中でredisとどう繋がってるが見える- ホスト側からは
docker inspect $(docker ps -lq)
とかするとweb版の詳細が見れる - redis側設定の
NetworkSettings.IPAddress
の値と中から見た/etc/hosts
の中身が同じである事が確認出来る
複数個のコンテナを使う場合にfigはdockerの機能をラップしてくれて便利って感じだ(1個でも"fig up
しろ"って言えるから便利だけど)
Kubernetes(k8s)
dockerの基本をやって、figで上手いこと複数個のコンテナを動かす方法を学んだし、最後はk8sで複数個のコンテナを動かすホストを複数個...みたいのをしてみたい
どうでもいいけどkubernetesってe
多いな
構成
kubernetes/DESIGN.md at master · GoogleCloudPlatform/kubernetes
(Monitoring Kubernetes - Hatena Developer Blog)
- ks8は分散マイクロサービスのような複数個のコンテナを扱うアプリケーションのためのもの
- Master(Minionを制御するやつ)とMinion(様々なコンテナが入ってるやつ)がいる
- MinionはMasterに対するNodeとなり、そのの中でdockerが動いてて <=> Host?
- その中にkubelet、cAdvisor、proxyがあって
- proxyからさらに中に複数個あるpodに飛ばす
- 同一のMinionの上で同じようにスケジューリングされるべきコンテナの集まりがpod
- podには複数のラベルを付けることが出来る(key=value)
- ...
後はYAML書いて、k8sが用意したcli叩くだけって感じで試せそう
試す
Getting Started - kubernetesにGCE、AWS、CloudStack使ったりするサンプルがあるけど、雑に試せたら良いから適当なの選ぶ
予め用意されたVagrantを使って試す
- Vagrant上でやるのが安定な気がする(これでパッと試して雰囲気感じて終わって良いという気持ち)
- releasesのページからkubernetes落としてきて、そこにあるVagrantfileをそのままつかう
- このVagrantを使うとデフォルトではMasterが1台あって、Minionが3台立ち上がるようになっている
vagrant ssh master
してsystemctl -a | grep kube
の結果下の3つのサービスが見つかる
kube-apiserver.service loaded active running Kubernetes API Server kube-controller-manager.service loaded active running Kubernetes Controller Manager kube-scheduler.service loaded active running Kubernetes Scheduler Plugin
systemctrl status <>
すると各々こんな感じで立ち上げられてる事がわかる- kube-apiserver:
- kube-controller-manager:
/usr/local/bin/kube-scheduler -master=127.0.0.1:8080
- 同様に
vagrant ssh minion-1
をしてsystemctl -a | grep kube
するとこんな感じ
kube-proxy.service loaded active running Kubernetes Kube-Proxy Server kubelet.service loaded active running Kubernetes Kubelet Server
- 確かにデザインに沿ったサービスが動いてる事が確認出来る
- MasterへのREST APIを利用するためのコマンドを使う
- vagrantから出てローカルに戻り、
export KUBERNETES_PROVIDER=vagrant
って設定 ./cluster/kubecfg.sh --help
ってすると色々出てくるkubecfg [OPTIONS] get|list|create|delete|update <events|minions|pods|replicationControllers|serices>[/<id>]
- なるほどREST
- ドキュメント見ても良さそう kubernetes/cli.md at master · GoogleCloudPlatform/kubernetes
- 認証必要って言われたけど、どうやら
vagrant up
は間違いで、vagrant halt
からの./cluster/kube-up.sh
が正解っぽい(中身は./cluster/vagrant/util.sh
のkube-up
になる) - 大体分かったし面倒になってきた
- vagrantから出てローカルに戻り、
クラスタ操作のためのコマンド
./cluster/kube-[up|down].sh
でクラスタを立ち上げたり落としたり出来る./cluster/kube-push.sh
で新しい更新内容をクラスタに反映出来る- vagrantの場合、
vagrant provision
するだけ
- vagrantの場合、
./cluster/kube-cfg.sh
は上で書いたけどRESTAPI叩くやつ./cluster/kube-ctl.sh
はkubectl controls the Kubernetes cluster manager
って書いてるな- 設定ファイルを更新したりproxyを動かしたり出来るっぽい
一から作ってみる的な?
kubernetes/README.md at master · GoogleCloudPlatform/kubernetes
もうやる気なくなったのでやめた
追記
docker の新機能であるmachine, swarm, composeについても触ろうと思ってたけど↓の辺で大体分かったからもういいや