- 投稿日:2019-04-15T23:31:19+09:00
Docker php:7.3(7.2)-fpm-alpineベースでphp-ast extention導入
個人的にメンテしているdyoshikawa/laravelイメージでPhanを使えるようにしたかった。
php-ast導入が必要だったのでビルド方法の記録。OGProgrammer/php 7.2 with ast phan argon support
基本的には上記を参考にした。
DockerfileRUN git clone https://github.com/nikic/php-ast.git \ && cd php-ast \ && phpize \ && ./configure \ && make install \ && echo 'extension=ast.so' > /usr/local/etc/php/php.ini \ && cd .. && rm -rf php-astこんな記述をして
docker build
を走らせるとCannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF environment variable. Then, rerun this script.エラー。
PECL::memcacheインストールしようとしたらphpizeでこけた(泣)
dockerでPHP7.3+Laravel環境を15分で作る~2019年版どうもautoconfが足りてないようだ。
Dockerfile+ RUN apk add autoconf RUN git clone https://github.com/nikic/php-ast.git \ && cd php-ast \ && phpize \ && ./configure \ && make install \ && echo 'extension=ast.so' > /usr/local/etc/php/php.ini \ && cd .. && rm -rf php-ast
こうすると今度は下記のエラー。
configure: error: no acceptable C compiler found in $PATHxdebug インストール時の error: no acceptable C compiler について
gccが足りていないということらしい。
Dockerfile- RUN apk add autoconf + RUN apk add autoconf gcc RUN git clone https://github.com/nikic/php-ast.git \ && cd php-ast \ && phpize \ && ./configure \ && make install \ && echo 'extension=ast.so' > /usr/local/etc/php/php.ini \ && cd .. && rm -rf php-ast今度は下記。
configure: error: C compiler cannot create executablesg++が足りない。
Dockerfile- RUN apk add autoconf gcc + RUN apk add autoconf gcc g++ RUN git clone https://github.com/nikic/php-ast.git \ && cd php-ast \ && phpize \ && ./configure \ && make install \ && echo 'extension=ast.so' > /usr/local/etc/php/php.ini \ && cd .. && rm -rf php-astそして下記。
make not foundmakeがないということだろう。
Dockerfile- RUN apk add autoconf gcc g++ + RUN apk add autoconf gcc g++ make RUN git clone https://github.com/nikic/php-ast.git \ && cd php-ast \ && phpize \ && ./configure \ && make install \ && echo 'extension=ast.so' > /usr/local/etc/php/php.ini \ && cd .. && rm -rf php-astこれは通った。
完成形
FROM node:10-alpine AS node FROM php:7.3-fpm-alpine MAINTAINER dyoshikawa # install packages RUN apk add -U --no-cache \ bash \ git \ curl-dev \ libxml2-dev \ postgresql-dev \ libpng-dev \ libjpeg-turbo-dev \ zip \ libzip-dev \ unzip \ gmp-dev # install PHP extensions RUN docker-php-source extract RUN cp /usr/src/php/ext/openssl/config0.m4 /usr/src/php/ext/openssl/config.m4 RUN docker-php-ext-configure gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include RUN docker-php-ext-install pdo\ pdo_mysql \ mysqli \ pdo_pgsql \ pgsql \ mbstring \ curl \ ctype \ xml \ json \ tokenizer \ openssl \ gd \ zip \ gmp \ bcmath # install php-ast RUN apk add --no-cache gcc g++ make autoconf RUN git clone https://github.com/nikic/php-ast.git \ && cd php-ast \ && phpize \ && ./configure \ && make install \ && echo 'extension=ast.so' > /usr/local/etc/php/php.ini \ && cd .. && rm -rf php-ast # install composer RUN curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/local/bin/composer # install composer plugin RUN composer global require laravel/installer ENV PATH=~/.composer/vendor/bin:$PATH RUN composer global require hirak/prestissimo # install dockerize ENV DOCKERIZE_VERSION v0.6.1 RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz # add node.js npm COPY --from=node /usr/local /usr/local RUN apk add --no-cache python make g++ RUN rm /usr/local/bin/yarn /usr/local/bin/yarnpkg # add user RUN apk add sudo shadow RUN groupadd -g 1000 dyoshikawa RUN useradd -u 1000 -g 1000 dyoshikawa RUN sed -e 's/# %wheel ALL=(ALL) NOPASSWD: ALL/%wheel ALL=(ALL) NOPASSWD: ALL/g' \ -i /etc/sudoers RUN sed -e 's/^wheel:\(.*\)/wheel:\1,dyoshikawa/g' -i /etc/group RUN mkdir /home/dyoshikawa && chown 1000:1000 -R /home/dyoshikawa RUN mkdir /work && chown 1000:1000 -R /work WORKDIR /work USER dyoshikawa ENTRYPOINT [] CMD php artisan serve --host 0.0.0.0
- 投稿日:2019-04-15T23:29:33+09:00
php-alpineコンテナにxdebugをインストールする時にハマったメモ
xdebugをインストールする時に何回もコケたので、その時のエラーも含めて残します。
TL;DR
# apk add autoconf build-base # pecl install xdebug # docker-php-ext-enable xdebug実際のdockerファイルはこちら https://github.com/ucan-lab/docker-laravel5/blob/master/docker/php/Dockerfile
環境
- php 7.3.4
- https://hub.docker.com/_/php
- 7.3.4-fpm-alpine イメージ
- xdebug 2.7.1
php バージョン
# php -v PHP 7.3.4 (cli) (built: Apr 10 2019 00:12:43) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.4, Copyright (c) 1998-2018 Zend Technologiesxdebug をインストールの実行
xdebug をインストールを試みると
Cannot find autoconf
エラーが発生しました。# pecl install xdebug downloading xdebug-2.7.1.tgz ... Starting to download xdebug-2.7.1.tgz (230,653 bytes) .................................................done: 230,653 bytes 69 source files, building running: phpize Configuring for: PHP Api Version: 20180731 Zend Module Api No: 20180731 Zend Extension Api No: 320180731 Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF environment variable. Then, rerun this script. ERROR: `phpize' failed
autoconf
パッケージが見つからないエラーです。解決策
autoconf
をインストールする。# apk add autoconf (1/4) Installing m4 (1.4.18-r1) (2/4) Installing libbz2 (1.0.6-r6) (3/4) Installing perl (5.26.3-r0) (4/4) Installing autoconf (2.69-r2) Executing busybox-1.29.3-r10.trigger OK: 108 MiB in 48 packages
autoconf
をインストールできたので再実行を試みます...。xdebug インストールの再実行
xdebug をインストールを再度試みると
no acceptable C compiler found
エラーが発生しました。# pecl install xdebug downloading xdebug-2.7.1.tgz ... Starting to download xdebug-2.7.1.tgz (230,653 bytes) .................................................done: 230,653 bytes 69 source files, building running: phpize Configuring for: PHP Api Version: 20180731 Zend Module Api No: 20180731 Zend Extension Api No: 320180731 building in /tmp/pear/temp/pear-build-defaultuserbIEBoC/xdebug-2.7.1 running: /tmp/pear/temp/xdebug/configure --with-php-config=/usr/local/bin/php-config checking for grep that handles long lines and -e... /bin/grep checking for egrep... /bin/grep -E checking for a sed that does not truncate output... /bin/sed checking for cc... no checking for gcc... no configure: error: in `/tmp/pear/temp/pear-build-defaultuserbIEBoC/xdebug-2.7.1': configure: error: no acceptable C compiler found in $PATH See `config.log' for more details ERROR: `/tmp/pear/temp/xdebug/configure --with-php-config=/usr/local/bin/php-config' failedビルドするために必要な
gcc g++ make
パッケージが足りないエラーです。解決策1
build-base
ビルドのためのグループパッケージが用意されているので、これをインストールします。# apk add build-base (1/16) Installing binutils (2.31.1-r2) (2/16) Installing libmagic (5.35-r0) (3/16) Installing file (5.35-r0) (4/16) Installing gmp (6.1.2-r1) (5/16) Installing isl (0.18-r0) (6/16) Installing libgomp (8.3.0-r0) (7/16) Installing libatomic (8.3.0-r0) (8/16) Installing mpfr3 (3.1.5-r1) (9/16) Installing mpc1 (1.0.3-r1) (10/16) Installing gcc (8.3.0-r0) (11/16) Installing musl-dev (1.1.20-r4) (12/16) Installing libc-dev (0.7.1-r0) (13/16) Installing g++ (8.3.0-r0) (14/16) Installing make (4.2.1-r2) (15/16) Installing fortify-headers (1.0-r0) (16/16) Installing build-base (0.5-r1) Executing busybox-1.29.3-r10.trigger OK: 264 MiB in 64 packages解決策2
個別にインストールしてもok。インストールするパッケージが少ない分、個別にした方が速い。
# apk add gcc g++ make (1/4) Installing m4 (1.4.18-r1) (2/4) Installing libbz2 (1.0.6-r6) (3/4) Installing perl (5.26.3-r0) (4/4) Installing autoconf (2.69-r2) Executing busybox-1.29.3-r10.trigger OK: 108 MiB in 48 packagesxdebug インストールの再々実行
# pecl install xdebug downloading xdebug-2.7.1.tgz ... Starting to download xdebug-2.7.1.tgz (230,653 bytes) .................................................done: 230,653 bytes 69 source files, building running: phpize Configuring for: PHP Api Version: 20180731 Zend Module Api No: 20180731 Zend Extension Api No: 320180731 building in /tmp/pear/temp/pear-build-defaultusergcLNNb/xdebug-2.7.1 running: /tmp/pear/temp/xdebug/configure --with-php-config=/usr/local/bin/php-config ... 省略 ... Build process completed successfully Installing '/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so' install ok: channel://pecl.php.net/xdebug-2.7.1 configuration option "php_ini" is not set to php.ini location You should add "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so" to php.inixdebug のインストールが成功しました?
xdebug の有効化
# docker-php-ext-enable xdebug fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz (1/1) Installing .docker-php-ext-enable-deps (0) OK: 259 MiB in 61 packages (1/1) Purging .docker-php-ext-enable-deps (0) OK: 259 MiB in 60 packagesphp のバージョン確認
# php -v PHP 7.3.4 (cli) (built: Apr 10 2019 00:12:43) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.4, Copyright (c) 1998-2018 Zend Technologies with Xdebug v2.7.1, Copyright (c) 2002-2019, by Derick Rethans
with Xdebug ~
がついてるのでインストール&有効化できました!参考
- 投稿日:2019-04-15T23:18:57+09:00
EC2上で大容量データを扱うElasticsearchクラスターを構築する
背景
日あたり1億レコード、2千変数を超える(セミ)スキーマレスなデータをニアリアルタイムで投入・集計したいというニーズがあったときに、EC2上でどのように構築するのがいいか?
X-Packを使いたかったのでElasticsearch Serviceが使えず、Security Groupやチューニング余地、コスト等々の都合でElastic社のマネージドサービスも選択せず、なおかつX-Packのライセンス料を最小にしたかったのでノード数も少なくしたかった。概要
- Elasticsearch 6.4移行を想定(5.x でもほぼ共通だがノード間通信の暗号化が必須か否か、G1GCが使えるか否か、が違う)
- EC2インスタンスはメモリーが多いもの、256GB以上を選ぶ
- EBSではなく、SSD(所謂エフェメラルストレージ/揮発性のNVMe)が付いてくるインスタンス、ストレージが2台以上、できれば4台くらいあるものを選択し、RAIDでストライピングする
- ノード間の通信を暗号化するのに証明書を入れるが、手間を少なくするために一度Dockerイメージを作ってECRに入れる
- ノードあたりのヒープサイズは128GBとか、「JVMの32GB制限」を気にせず、G1GCを有効化することで大容量メモリーと性能をバランスする
- データノードの他に、独立したコーディネーターノードを建てる
構築手順
前提
- インスタンスタイプはi3.8xlarge を想定
- m5d、c5d、r5d等のNitro世代のディスク付きでも同じだが、ルートのEBSがNVMe扱いなのでデバイスの番号がずれるのでRAID構成時に注意する
- OSは初期状態のAmazon Linux
- ElasticsearchそのものはDocker上で動かすのであまり拘らなくて良いかもしれない
ホストマシンのチューニング
基本的な手順は公式ドキュメントと変わらないが、RAID構成をする
アップデートしてDockerをインストール
OS等の更新を適用し、Dockerをインストールしておく
yum -y update yum -y install dockerlimits.confに設定を追加
ファイルディスクリプタの上限を緩和、メモリーロックを無制限にする。
シェルで以下のように実行すれば追記される(くれぐれもlimits.confにコピペしない)bash -c 'echo root soft nofile 1048576 >> /etc/security/limits.conf' bash -c 'echo root hard nofile 1048576 >> /etc/security/limits.conf' bash -c 'echo * soft nofile 1048576 >> /etc/security/limits.conf' bash -c 'echo * hard nofile 1048576 >> /etc/security/limits.conf' bash -c 'echo * soft memlock unlimited >> /etc/security/limits.conf' bash -c 'echo * hard memlock unlimited >> /etc/security/limits.conf'sysctl.confに設定を追加
ネットワークとスワップの設定をする。こちらもシェルに貼り付ければ追記できる。
bash -c 'echo net.ipv4.tcp_tw_reuse = 1 >> /etc/sysctl.conf' bash -c 'echo net.ipv4.tcp_fin_timeout = 30 >> /etc/sysctl.conf' bash -c 'echo net.ipv4.ip_local_port_range = 16384 65535 >> /etc/sysctl.conf' bash -c 'echo vm.max_map_count = 262144 >> /etc/sysctl.conf' bash -c 'echo vm.swappiness = 1 >> /etc/sysctl.conf'/etc/rc.local に追記
/etc/rc.local
を開いて以下を追記する。
ホスト名はAWSのあまり知られていない(?)169.254.169.254
をたたいてインスタンスIDを得る。
RAIDの構成をここに書くのは、エフェメラルストレージだとシャットダウン後にデータが消えてRAIDの構成も失われるので、RAIDが構成されていなかったら構成しなおすため。
この例では i3.8xlarge を想定しているのでRAIDを組む対象デバイスが/dev/nvme0
から/dev/nvme3
の4台になっている。Nitro世代だと/dev/nvme1
から始まる。
/data
をElasticsearchのデータディレクトリにするのでこうしているが、パーミッションはちゃんと考えた方がよさそう。# Set Hostname hostname "$(curl -s http://169.254.169.254/latest/meta-data/instance-id |sed 's/\./-/g')" # Init RAID if [ ! -d /data ] then mkdir /data fi if [ ! -d /dev/md0 ] then # Initialize the RAID with four NVMe drives mdadm --create --verbose --level=0 /dev/md0 --name=DATA --raid-devices=4 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 mkfs.ext4 /dev/md0 mdadm --detail --scan | tee -a /etc/mdadm.conf # Just in case, Update the kernel option dracut -H -f /boot/initramfs-$(uname -r).img $(uname -r) # Mount the RAID mount -a fi chmod 777 /datafstabに追記
以下をシェルで実行して、構成したRAIDを起動時に
/data
にマウントするようにする。bash -c 'echo /dev/md0 /data ext4 defaults,nofail,noatime,discard 0 2 >> /etc/fstab'ホストを再起動
rebootElasticsearchコンテナを起動する
Dockerfileを作る
基本的にはElasticの公式イメージをベースとし、必要なプラグインを入れたりする。最近はX-Packは最初から入ってたりするので、あまり必要になるケースは多くないかもしれない。
ノード間の通信を暗号化することが必須になっているので、p12ファイルを生成してイメージに組み込んだ。(くれぐれもパブリックなリポジトリに入れないこと)FROM docker.elastic.co/elasticsearch/elasticsearch:6.6.2 #### 形態素解析のプラグイン等インストールする場合はここに列挙する RUN \ elasticsearch-plugin install --batch analysis-icu && \ elasticsearch-plugin install --batch analysis-kuromoji #### ノード間の通信の暗号化に使うp12ファイルを作っておいて、よしなに入れてやる RUN mkdir /usr/share/elasticsearch/config/certs ADD elastic-certificates.p12 /usr/share/elasticsearch/config/certs/elastic-certificates.p12 ADD elastic-stack-ca.p12 /usr/share/elasticsearch/config/certs/elastic-stack-ca.p12 RUN chown -R elasticsearch /usr/share/elasticsearch/config/certs RUN chgrp -R root /usr/share/elasticsearch/config/certs RUN chmod o-rx /usr/share/elasticsearch/config/certs RUN chmod 640 /usr/share/elasticsearch/config/certs/elastic-stack-ca.p12 RUN chmod 640 /usr/share/elasticsearch/config/certs/elastic-certificates.p12ビルドする
ビルドする。プラグインや証明書が入ったイメージができる。
ECRに入れやすいタグを付けておく。docker build -t 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2 .ECRに入れて置く
ECRにログインして、それからプッシュ。
aws ecr get-login --no-include-email --profile hoge | sudo /bin/bash docker push 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2Elasticsearchを起動する
個々のノードで以下のようにElasticsearchコンテナを立ち上げる。
-Xms
とXmx
はホストのメモリーの50%くらいにする。JVMの32GB(アドレス空間が32ビットか64ビットか問題)は気にしない。EC2だと31GBくらいで64ビットになった気がするけどマシンの性能が高いしG1GCを使うようにしてからなおさら気にならない。
-discovery.zen.ping.unicast.hosts
にクラスターを構成するマシンのIPアドレスを列挙する
- データを格納するディレクトリは、コンテナ内で場所は変更できなかった
-ELASTIC_PASSWORD
環境変数で、デフォルトユーザーのパスワードを指定するデータノード(データを格納したり、集計処理をする)
- データノードは
node.master
、node.data=true
、node.ingest
が全てtrue
docker pull 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2 docker run -d --net=host -v /data:/usr/share/elasticsearch/data \ -e "node.master=true" \ -e "node.data=true" \ -e "node.ingest=true" \ -e "ELASTIC_PASSWORD=P4ssW0rd" \ -e "node.name=$(curl -s http://169.254.169.254/latest/meta-data/instance-id |sed 's/\./-/g')" \ -e "ES_JAVA_OPTS=-Xms128G -Xmx128G -XX:-UseConcMarkSweepGC -XX:-UseCMSInitiatingOccupancyOnly -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=75" \ -e "network.host=0.0.0.0" \ -e "bootstrap.memory_lock=true" \ -e "discovery.zen.ping.unicast.hosts=3.0.0.1,3.0.0.2,3.0.0.3" \ -e "discovery.zen.minimum_master_nodes=1" \ -e "xpack.security.transport.ssl.enabled=true" \ -e "xpack.security.transport.ssl.verification_mode=certificate" \ -e "xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elastic-stack-ca.p12" \ -e "xpack.security.transport.ssl.truststore.path=/usr/share/elasticsearch/config/certs/elastic-certificates.p12" \ -e "thread_pool.bulk.queue_size=1000" \ -e "cluster.name=high-performance-es" \ --ulimit nofile=524288:524288 --ulimit memlock=-1:-1 \ --privileged \ --name elasticsearch \ 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2コーディネーターノード(入出力の窓口のみを担う)
- コーディネーターはクラスターのエンドポイントの役割を担い、入出力をデータノードに割り振る役割
node.master
、node.data=true
、node.ingest
が全てfalse
- インスタンスサイズは小さくて大丈夫だが、EC2で小さいインスタンスを使う場合、ネットワーク帯域が制限されるか、クレジットの枯渇でパフォーマンスが落ちることがあるので、そこそこ大きめのインスタンスがオススメ
- コーディネーターノードはゆとりがあるので、ここでKibanaを動かすといい
docker pull 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2 docker run -d --net=host -v /data:/usr/share/elasticsearch/data \ -e "node.master=false" \ -e "node.data=false" \ -e "node.ingest=false" \ -e "node.name=Coordinator" \ -e "ELASTIC_PASSWORD=P4ssW0rd" \ -e "ES_JAVA_OPTS=-Xms30G -Xmx30G -XX:-UseConcMarkSweepGC -XX:-UseCMSInitiatingOccupancyOnly -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=75" \ -e "network.host=0.0.0.0" \ -e "bootstrap.memory_lock=true" \ -e "discovery.zen.ping.unicast.hosts=3.0.0.1,3.0.0.2,3.0.0.3" \ -e "discovery.zen.minimum_master_nodes=1" \ -e "xpack.security.transport.ssl.enabled=true" \ -e "xpack.security.transport.ssl.verification_mode=certificate" \ -e "xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elastic-stack-ca.p12" \ -e "xpack.security.transport.ssl.truststore.path=/usr/share/elasticsearch/config/certs/elastic-certificates.p12" \ -e "thread_pool.bulk.queue_size=1000" \ -e "cluster.name=high-performance-es" \ --ulimit nofile=524288:524288 --ulimit memlock=-1:-1 \ --privileged \ --name elasticsearch \ 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2インデックス設定の調整
インデックスの設定はドキュメントのサイズ、入出力の頻度、性能要件、可用性等と相談する必要がある。特にエフェメラルストレージを使って性能を引き出している場合、ハードウェア障害が起こるとデータが失われるので、レプリカを持つのかEBSにバックアップを作るのかとか、恒久的なデータ保管は別のDBで担いElasticsearchは柔軟性と速度を重視するのかとか、選択と集中が必要。
性能に影響する設定としては以下のものが重要だと考えた。
- refresh_interval
- 投入したデータが反映されるまでの時間に影響する。長くすれば書き込み処理が粗くなるので軽くなるが、投入から集計までの時差=Latencyが延びる
- number_of_shards
- インデックスをクラスター内でいくつに分割するかの値。多すぎでも少なすぎでもよくないので難しいが、ノード数の4倍にした。インデックスあたりのドキュメント数や容量でも考える必要があるし、インデックスをどういう単位で分割するかにもよる。
- codec
- 圧縮設定。
best_compression
でいいと思う。圧縮と伸張はCPUを使うが、ディスクIOの方が問題になるので、書き込みと読み出しの時点でのサイズを最小にする方が早い印象。- number_of_replicas
- レプリカを作ればデータの保全はしやすいが、データを複製・同期するので遅くなる。最速を目指すならレプリカは作らない。
- ドキュメントに対する制約をいじって使わないデータを扱わないようにする
- max_docvalue_fields_search
- total_fields
- depth
- nested_fields
- analyzer
- 変数ごとに有効・無効を切り替えられるが、形態素解析をしないような変数では基本的に無効にしておく。
終わりに
- Dockerにしておくとアップデートの時に作業しやすい
- Kibanaの設定は人間の工数がかかっているデータなので、S3にバックアップする方が良い。Kibanaの設定も当然クラスター内にあるので、誤ったシャットダウンや障害、作業ミスで消えると困る。
- なにか色々はしょってる気がする
- 誤りや更新が必要なところはコメントください
- すでに7.0が出ている… プラグイン周りが変わったと思うけど他は使えるはず
- 投稿日:2019-04-15T22:25:48+09:00
laradockでLaravelの環境構築をしてみる(Mac)
ローカル環境はLaradockを利用して開発します。
最終的には以下のような構成になります。/(任意の名前) |-- laradock |-- laravel1.Dockerをインストールする
2.Laradockの入手
$ mkdir 任意のディレクトリ $ cd 任意のディレクトリ $ git clone https://github.com/LaraDock/laradock.git $ cd laradock3.laradockの設定ファイルの編集
最初にenv.exampleファイルをコピーして.envファイルを作成します。この.envファイルに環境構築時の設定情報を書き込んでいく。
$ cp env-example .envDATAの保存する場所を変更する。標準の設定だとルートディレクトリの配下にファイルが永続化されている。
任意のディレクトリ配下のlaradockディレクトリにファイルを保存するように変更します。# .env # Choose storage path on your machine. For all storage systems - DATA_PATH_HOST=~/.laradock/data + DATA_PATH_HOST=.laradock/data続いて、MYSQLの設定をしていく。
# .env ### MYSQL ################################################# MYSQL_VERSION=5.7 # versionを固定 MYSQL_DATABASE=homestead1 #データベース名を変更 MYSQL_USER=homestead1 #ユーザー名を変更 MYSQL_PASSWORD=hogehoge #パスワードを変更 MYSQL_PORT=3306 MYSQL_ROOT_PASSWORD=root MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d4.Dockerコンテナを起動する。
$ docker-compose up -d nginx mysql phpmyadmin5.composerをインストールする
laradockのディレクトリ内に移動して、workspaceのbashにログインする
$ docker-compose exec --user=laradock workspace bash $ cd training-laravel $ composer install6 laravelの.envの編集
laravelの.envに以下を貼り付ける
APP_NAME=Laravel APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=http://localhost LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3306 DB_DATABASE=homestead1 DB_USERNAME=homestead1 DB_PASSWORD=hogehoge BROADCAST_DRIVER=log CACHE_DRIVER=file QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"7.APP_KEYの生成と初回のマイグレーションを実行
$ docker-compose exec workspace php artisan migrate $ docker-compose exec workspace php artisan key:generate
- 投稿日:2019-04-15T19:44:56+09:00
DockerfileのARGはFROMに対しても使える
よく考えれば当たり前なのかもしれないが最近気付いたのでメモ
ARGで処理系のバージョン等を設定しておいてFROMにそれを埋め込めばmulti-stage buildを使う時にバージョンを一元管理できたりと色々便利そう
ARG RUBY_VERSION=2.6.2 ARG RAILS_ENV=production FROM ruby:${RUBY_VERSION}-alpine AS node_modules WORKDIR /opt/project RUN apk add --no-cache --update nodejs yarn ADD bin/yarn /opt/project/bin/ ADD package.json yarn.lock /opt/project/ ENV PATH=/opt/project/bin:${PATH} RUN yarn install FROM ruby:${RUBY_VERSION}-alpine AS bundle WORKDIR /opt/project RUN apk add --no-cache --update build-base mariadb-dev ADD bin/bundle /opt/project/bin/ ADD .ruby-version .gemrc Gemfile Gemfile.lock /opt/project/ ENV PATH=/opt/project/bin:${PATH} RUN \ if [ "${RAILS_ENV}" = "production" ]; then \ bundle install --jobs 8 --without development test --deployment; \ else \ bundle install --jobs 8 --without production --path vendor/bundle; \ fi FROM ruby:${RUBY_VERSION}-alpine WORKDIR /opt/project RUN apk add --no-cache --update mariadb-dev tzdata nodejs yarn COPY --from=bundle ${BUNDLE_APP_CONFIG} /opt/project/.bundle COPY --from=bundle /opt/project/vendor/bundle /opt/project/vendor/bundle COPY --from=node_modules /opt/project/node_modules /opt/project/node_modules ADD . /opt/project/api ENV RAILS_ENV=${RAILS_ENV} ENV BUNDLE_APP_CONFIG=/opt/project/.bundle ENV PATH=/opt/project/bin:${PATH} ENV RAILS_SERVE_STATIC_FILES=true RUN webpack EXPOSE 3000 ENTRYPOINT ["rails"] CMD ["server", "-b", "0.0.0.0"]
- 投稿日:2019-04-15T18:31:13+09:00
kind試す
いわゆる Kubernetes in Docker。(いわゆるもくそも、だから名前が "kind")
たくさんのクラスタがDockerコンテナ1つで上がる!?感じ。
Learningに使えるかという点で評価してみる。
とりあえずはセットアップと軽めのApp立ち上げ確認。
Pre Setup
- GCPにて、約メモリ8GB積んだCentOS7 x86_64を用意
- git
- docker 18.09.5
- kubectl 1.14.1
Install Golang
よしなに、
# curl -LO https://dl.google.com/go/go1.12.4.linux-amd64.tar.gz # tar zxf go1.12.4.linux-amd64.tar.gz # mv go /usr/local/bin/Install kind
# export GOPATH=/usr/local/bin/go/bin # export PATH=$PATH:$GOPATH # go get -u sigs.k8s.io/kindそこそこかかる
# export KINDPATH=/usr/local/bin/go/bin/bin # export PATH=$PATH:$KINDPATH # kind create cluster Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.13.4) ? ✓ Preparing nodes ? ✓ Creating kubeadm config ? ✓ Starting control-plane ?️ Cluster creation complete. You can now use the cluster with: export KUBECONFIG="$(kind get kubeconfig-path --name="kind")" kubectl cluster-infoそこそこかかる
docker コマンドうってみると・・・・
# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c7f23eb8af62 kindest/node:v1.13.4 "/usr/local/bin/entr…" About a minute ago Up About a minute 34487/tcp, 127.0.0.1:34487->6443/tcp kind-control-plane# kind get kubeconfig-path /root/.kube/kind-config-kind # export KUBECONFIG="$(kind get kubeconfig-path)" # kubectl cluster-info Kubernetes master is running at https://localhost:37608 KubeDNS is running at https://localhost:37608/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.Wordpressあげてみる
# kubectl get secrets NAME TYPE DATA AGE default-token-bkh8n kubernetes.io/service-account-token 3 36m mysql-pass-59cdgt95hd Opaque 1 14m # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mysql-pv-claim Bound pvc-a8f2baf5-5f5b-11e9-989b-0242a2b9ea4d 20Gi RWO standard 15m wp-pv-claim Bound pvc-a8f6eb33-5f5b-11e9-989b-0242a2b9ea4d 20Gi RWO standard 15m # kubectl get pods NAME READY STATUS RESTARTS AGE wordpress-c6b7fcdd-sfc8d 1/1 Running 0 15m wordpress-mysql-b4447dd8-xr668 1/1 Running 0 15m # kubectl get services wordpress NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE wordpress LoadBalancer 10.101.188.12 <pending> 80:32617/TCP 15mちゃんとあがっとるので、そとからアクセスできるようにポートフォワード
# kubectl port-forward --address 0.0.0.0 svc/wordpress 80:80=>ブラウザで確認、ばっちりあがる!
もいっちょクラスタCreate
# kind create cluster --name tk Creating cluster "tk" ... ✓ Ensuring node image (kindest/node:v1.13.4) ? ✓ Preparing nodes ? ✓ Creating kubeadm config ? ✓ Starting control-plane ?️ Cluster creation complete. You can now use the cluster with: export KUBECONFIG="$(kind get kubeconfig-path --name="tk")" kubectl cluster-info # kind get clusters tk kind追加されてる!ので宛先を変えて、再度Wordpress
# export KUBECONFIG="$(kind get kubeconfig-path --name="tk")" # kubectl cluster-info Kubernetes master is running at https://localhost:33629 KubeDNS is running at https://localhost:33629/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.なにがちがうって、さっきとちゃんとMasterの宛先ポートが違う。
同じYAML使ってWordpress上げて、ポートフォワーディングして、ブラウザアクセス。
ばっちりあがった。が・・・クラスタが2つで外からのアクセスをそれぞれのクラスタのPodにアクセスするようにするのは!?
ちゃんと確認・・・これから。
クラスタ・消す
kind delete cluster --name kind
すぐ消える
Ref
- 投稿日:2019-04-15T16:55:15+09:00
Windows10 - Vagrant - CentOS7 - docker, docker-compose 環境構築
update 2019.04.15
Windows10 : VirtualBox , Git , Vagrant
- Oracle VM VirtualBox : VirtualBox 6.0
- Git
- Git Bash ターミナル使用
- Vagrant by HashiCorp
(Git Bash : Windows) $ git --version git version 2.21.0.windows.1 $ vagrant --version Vagrant 2.2.4Vagrant : CentOS7
(Git Bash : Windows) $ cd /c/vagrant/centos7 $ vagrant init centos/7 $ vagrant up $ vagrant ssh(Git Bash : Vagrant - CentOS7) $ cat /etc/centos-release --- CentOS Linux release 7.6.1810 (Core) --- $ sudo yum -y updateVagrantfile : private network (hostonly)
- host(windows10)から、アクセス用
config.vm.network "private_network", ip: "192.168.33.10"Vagrantfile : synced folder
- VirtualBox Guest Additions インストール
$ vagrant plugin install vagrant-vbguest $ vagrant vbguest $ vagrant reload
- host(windows10)で、ファイル編集用
config.vm.synced_folder "./docker", "/docker", owner: "vagrant", group: "vagrant", type: "virtualbox", :mount_options => ['dmode=755', 'fmode=644']※ DNS解決できない場合...
CentOS7 : docker , docker-compose
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2 $ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo $ sudo yum makecache fast $ sudo yum install -y docker-ce $ sudo systemctl start docker $ sudo systemctl status docker $ sudo systemctl enable docker $ sudo usermod -aG docker vagrant ※ 再ログイン後、反映 $ groups --- vagrant docker --- $ docker --version --- Docker version 18.09.5, build e8ff056 ---
- docker hello world テスト
$ docker run hello-world --- ... Hello from Docker! This message shows that your installation appears to be working correctly. ... --- $ docker images --- REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 3 months ago 1.84kB ---CentOS7 : docker-compose
- 最新バージョン確認 : https://github.com/docker/compose/releases/
$ sudo curl -L https://github.com/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version --- docker-compose version 1.24.0, build 0aa59064 ---
- docker-compose hello world テスト
$ mkdir -p /docker/helloworld $ cd /docker/helloworld $ vi docker-compose.yml --- version: "3" services: hello: image: hello-world --- $ docker-compose run --- Creating network "helloworld_default" with the default driver Creating helloworld_hello_1 ... done Attaching to helloworld_hello_1 hello_1 | hello_1 | Hello from Docker! hello_1 | This message shows that your installation appears to be working correctly. hello_1 | hello_1 | To generate this message, Docker took the following steps: hello_1 | 1. The Docker client contacted the Docker daemon. hello_1 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. hello_1 | (amd64) hello_1 | 3. The Docker daemon created a new container from that image which runs the hello_1 | executable that produces the output you are currently reading. hello_1 | 4. The Docker daemon streamed that output to the Docker client, which sent it hello_1 | to your terminal. hello_1 | hello_1 | To try something more ambitious, you can run an Ubuntu container with: hello_1 | $ docker run -it ubuntu bash hello_1 | hello_1 | Share images, automate workflows, and more with a free Docker ID: hello_1 | https://hub.docker.com/ hello_1 | hello_1 | For more examples and ideas, visit: hello_1 | https://docs.docker.com/get-started/ hello_1 | helloworld_hello_1 exited with code 0 ---
- 投稿日:2019-04-15T13:52:11+09:00
DockerでGatsbyを使うときに「このページは動作していません」と出る問題について
DockerにGatsbyをインストールし、 https://www.gatsbyjs.org/tutorial/part-zero/ にある通りにHello world!を出そうとしたところ、
このページは動作していません
というエラーで表示が出来ませんでした。
なにこれ困る…。CheckPoint 1
Dockerfileの適当な場所にポートを解放する設定を書きます。
Dockerfile# Expose port EXPOSE 8000CheckPoint 2
docker run
コマンドにホストとコンテナのポートをつなぐオプションをつけて起動します。docker run -p 8000:8000 -it
ホスト側のポート:コンテナ側のポート
の順番です。CheckPoint 3
https://www.gatsbyjs.org/tutorial/part-zero/#view-your-site-locally のNotesにある通り、
gatsby develop --host=0.0.0.0としてホストオプションを指定します(上記サイトで--が一つ多いのはタイポみたいです)。
これで無事に http://localhost:8000/ にホストのブラウザからアクセスしてHello worldできました。
- 投稿日:2019-04-15T13:42:42+09:00
Docker環境でGLPIを9.2.1から9.3.3へアップグレード
DockerにてGLPIを利用して資産管理を行っています。
実際にGLPIで運用している日本語情報が非常に少ないです。
オフラインの機器を多数管理するような場合に非常に使いやすいと思います。前回記事の環境からアップグレードします。
※DBのバックアップは前回から変更ありません。
※OCS Inventory NGとの連携は行っていません。内容
- 9.2.1から9.3.3へのアップグレード時のデータベースエラー対応
- CASエラーについて
- データセンターのラック管理機能を利用する
環境
Docker version 18.09.4
docker-compose version 1.24.0
hostOS:CentOS7-minimalベースイメージ
https://github.com/fjudith/docker-glpi
※オリジナルはmariaDBが5.5ですが10.3を使っています。ディレクトリ構成
/glpi933
├── app
│ ├── Dockerfile
│ ├── datainjection-2.6.4.tar.gz
│ └── php.ini
├── db
│ ├── 2019mmddHHMMSS.sql
│ ├── Dockerfile
│ └── script
│ └── db_backup.sh
├── docker-compose.yml
└── glpi.env
※php.ini, db_backup.sh, glpi.envは前回と同じです。docker-compose.ymlversion: '2' services: db: build: ./db env_file: - ./glpi.env environment: - "TZ=Japan" volumes: - glpi-db93:/var/lib/mysql - ./db:/docker-entrypoint-initdb.d - glpi-db-backup93:/backup ports: - 32806:3306/tcp restart: always app: build: ./app volumes: - /etc/localtime:/etc/localtime:ro environment: - "TZ=Japan" volumes: - glpi-app93:/var/www/html/ - ./app/php.ini:/usr/local/etc/php/php.ini links: - db:mysql ports: - 8080:80/tcp restart: always volumes: glpi-db93: {} glpi-db-backup93: {} glpi-app93: {}Dockerfile #app ※前回から変更箇所のみ
バージョン指定
ENV GLPI_VERSION=9.3.3nanoをvimへ変更
RUN apt-get install --no-install-recommends -yqq \ zlib1g \ cron \ bzip2 \ wget \ vimプラグインのバージョンアップ
COPY datainjection-2.6.4.tar.gz /var/www/html/plugins/ WORKDIR /var/www/html RUN tar zxvf plugins/datainjection-2.6.4.tar.gz -C plugins/ && mv plugins/datainjection-2.6.4 plugins/datainjection RUN rm plugins/remove.txt EXPOSE 80 CMD apache2-foregroundDockerfile #db
FROM mariadb:10.3 RUN apt-get update RUN apt-get install -y vim locales RUN apt-get install -y language-pack-ja-base language-pack-ja RUN locale-gen ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LC_CTYPE ja_JP.UTF-8 RUN localedef -f UTF-8 -i ja_JP ja_JP.utf8 COPY /script/db_backup.sh /opt/ RUN chmod +x /opt/db_backup.sh RUN mkdir backup9.2.1から9.3.3へのアップグレード時のデータベースエラー対応
参考:GLPI 9.3 convert tables to innodb
流れとしては9.2.1から9.3.3へアップグレードしデータベースのマイグレーションを実施します。
9.4系へいきなりアップグレードするとinnodb_migration.phpが存在していないためマイグレーションできません。1.GLPI9.3.3イメージをビルド
ログイン時には以下のエラーが表示されます。
2.GUIでGLPIインストール
インストールを完了せずにマイグレーションを実行すると下記エラーが発生します。
※CASエラーについて
とりあえず無視しても良いようです。
参考:GLPI フォーラム
3.データベースをマイグレーション
appコンテナへ接続してからスクリプトを実行します。$ docker exec -it glpi933_app_1 bashコンテナログイン後
# php scripts/innodb_migration.php
4.起動確認
ブラウザで再度アクセスすると以下のようにエラーが消えています。
5.install.phpを削除
ついでにinstall.phpを削除します。$ docker exec -it glpi933_app_1 bashコンテナログイン後
# rm /install/install.php
6.データベースをバックアップ
配置済みのスクリプトを実行$ cd glpi933 $ docker exec glpi933_db_1 ./opt/db_backup.sh7.バックアップの保存場所
/var/lib/docker/volumes/glpi933_glpi-db-backup/_data/データセンターのラック管理機能
ラックイメージに情報資産で登録しているサーバを登録できます。
9.3より新たに追加された機能の一つです。判明している課題:ポジション(ラックの何段目)の前・後・右・左が指定できるのですが登録できる機器は
1段に一つのみとなっています。1段に2つの機器を置いている場合は登録できません。
しばらく運用してみてまた感想書きたいと思います。
前・後・右・左を指定しても以下のように表示は1段を専有
登録画面では前・後・右・左を指定可能
次回試したいこと
- Dockerでcron登録
- 自動実行機能の利用
- GLPI 9.4へのアップグレード
- 投稿日:2019-04-15T13:24:54+09:00
Docker for widnowsでdocker.errors.TLSParameterErrorが発生した場合
- 投稿日:2019-04-15T13:06:11+09:00
最もシンプルな docker-compose.yml の hello-world
Looking for the simplest "Hello-World" docker-compose YAML file
単純な動作確認のため、
docker run hello-world
と同じレベルでdocker-compose
のhello world
がしたい。TL;DR
docker-compose.ymlversion: "3" services: hello: image: hello-world:latest
- Download: https://keinos.github.io/hello-docker-compose/docker-compose.yml @ GitHub
- Source: https://github.com/KEINOS/hello-docker-compose/blob/master/docker-compose.yml @ GitHub
usage$ curl -O https://keinos.github.io/hello-docker-compose/docker-compose.yml $ docker-compose upTS;DR
CircleCI 実行時や Vagrantfile 内のスクリプトで Docker や Docker-Compose を自動インストールした際に、バージョン情報は返すものの、それ以外のコマンド・オプションが動かないことがありました。原因は、設定ミスで Docker デーモンの起動に失敗していたことでした。
そこで、CI を回す時や
vagrant up
時にdocker run hello-world
と同じくらい至極簡単な動作テストをdocker-compose
でしたかったのですが、「docker-compose
hello-world
simple
」とググっても Ubuntu ベースのサンプルしかありませんでした。単純に
docker-compose up
で起動するかのテストであるため、そこまで大きなイメージは必要ありません。「それなら、普通に docker のhello-wolrd
イメージを使えば良いじゃん」と聞こえてきたので、自分のググラビリティとして。実行例$ # 作業ディレクトリの作成 $ mkdir hello-world && cd $_ $ # ダウンロード(ソースをコピペして作成しても OK) $ curl -O https://keinos.github.io/hello-docker-compose/docker-compose.yml % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 62 100 62 0 0 227 0 --:--:-- --:--:-- --:--:-- 226 $ # 確認 $ ls docker-compose.yml $ cat docker-compose.yml version: "3" services: hello: image: hello-world:latest $ # 実行 $ docker-compose up Creating network "core_default" with the default driver Creating core_hello_1 ... done Attaching to core_hello_1 hello_1 | hello_1 | Hello from Docker! hello_1 | This message shows that your installation appears to be working correctly. hello_1 | hello_1 | To generate this message, Docker took the following steps: hello_1 | 1. The Docker client contacted the Docker daemon. hello_1 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. hello_1 | (amd64) hello_1 | 3. The Docker daemon created a new container from that image which runs the hello_1 | executable that produces the output you are currently reading. hello_1 | 4. The Docker daemon streamed that output to the Docker client, which sent it hello_1 | to your terminal. hello_1 | hello_1 | To try something more ambitious, you can run an Ubuntu container with: hello_1 | $ docker run -it ubuntu bash hello_1 | hello_1 | Share images, automate workflows, and more with a free Docker ID: hello_1 | https://hub.docker.com/ hello_1 | hello_1 | For more examples and ideas, visit: hello_1 | https://docs.docker.com/get-started/ hello_1 | core_hello_1 exited with code 0 $ # 終了結果 $ echo $? 0動作確認済み環境$ docker version Client: Version: 18.06.1-ce API version: 1.38 Go version: go1.10.8 Git commit: e68fc7a Built: Tue Aug 21 17:16:31 2018 OS/Arch: linux/amd64 Experimental: false Server: Engine: Version: 18.06.1-ce API version: 1.38 (minimum version 1.12) Go version: go1.10.8 Git commit: e68fc7a Built: Tue Aug 21 17:16:31 2018 OS/Arch: linux/amd64 Experimental: false $ $ docker-compose version docker-compose version 1.24.0, build 0aa59064 docker-py version: 3.7.2 CPython version: 3.6.8 OpenSSL version: OpenSSL 1.1.0j 20 Nov 2018 $ $ cat /etc/os-release NAME="Container Linux by CoreOS" ID=coreos VERSION=2023.5.0 VERSION_ID=2023.5.0 BUILD_ID=2019-03-09-0138 PRETTY_NAME="Container Linux by CoreOS 2023.5.0 (Rhyolite)" ANSI_COLOR="38;5;75" HOME_URL="https://coreos.com/" BUG_REPORT_URL="https://issues.coreos.com" COREOS_BOARD="amd64-usr"
- 投稿日:2019-04-15T12:10:39+09:00
atom使いのためのdockerとHydrogenによるお手軽python環境構築
atomを使いたい
dockerを使うとお手軽にjupyterを使えるpython環境が手に入ります。ただjupyterをそのまま使いたくないという謎のこだわりがある。
pythonを書くときの環境はjupyter notebookが便利。最近だとjupyterLabなんかも拡張機能とかもあって楽しいらしい。(参考:https://qiita.com/canonrock16/items/d166c93087a4aafd2db4)しかし、私はatomを使いたい。特別理由はないがatomを使いたい。
pythonに関してはatomにHydrogenというパッケージを導入すればjupyterライクに出力を得られる。ただ、SSHでリモートマシンに接続したり、dockerコンテナ上のカーネルに接続する場合多少の設定が必要になる。
今回は、いろいろあって環境がぐちゃぐちゃになったので、docker上にpython環境を用意しatom上でHydrogenを使う環境を整えたのでその流れをメモに残します。dockerコンテナの起動
docker imageを自分で用意する時間がなかったため、jupyter環境が最初から構築してあるimageを使わせてもらった。docker hubにいろいろあるが、自分はjupyter/scipy-notebookを使わせてもらった。
詳細は省かせていただきます。
1.docker imageをpulldocker pull jupyter/scipy-notebook2.docker imageをrun
docker run -p 8888:8888 -v ~/hoge:/home/jovyan/work jupyter-notebook start-notobook.sh —NotebookApp.token="yourpass"オプションとして、
- -p: コンテナのポートをホスト側に公開。
- -v: ボリュームをマウント。フォルダの同期のため。
- jupyter-notebook start-notobook.sh: jupyterのコマンドを使用するために必要なオプション.
- NotebookApp.token="yourtoken": jupyter側のコマンドで、tokenを指定
tokenは指定しないと毎回変わるので指定することをオススメ。
ここで、Executing the command: jupyter notebook --NotebookApp.token=yourtoken [I 14:19:25.923 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret [I 14:19:27.362 NotebookApp] JupyterLab extension loaded from /opt/conda/lib/python3.7/site-packages/jupyterlab [I 14:19:27.362 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab [I 14:19:27.365 NotebookApp] Serving notebooks from local directory: /home/jovyan [I 14:19:27.366 NotebookApp] The Jupyter Notebook is running at: [I 14:19:27.367 NotebookApp] http://(***):8888/?token=… [I 14:19:27.367 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).とでてきてdockerコンテナ上にjupyter kernelが起動できた。
ここまでできたら、Hydrogenへの設定へ。
Hydrogenの準備
調べればたくさん丁寧に説明してくれてる記事があるので、Hydrogenのインストール等は省略する。(こことか)
atomのpacageからHydrogenの設定画面へ行き、Kernel Gatewayというところに、こんな感じで記入。
nameは自分の好きなものを、baseUrlはdockerを起動したときにでてきたurlをコピペ、tokenは自分で設定したtokenを記入。
詳細はここ参照。Hydrogenからリモートカーネルへ接続
- atomの画面からコマンドパレットを開き,Hydrogen:Connect To Remote Kernelを選択。 2.remote kernelが見つかれば次のように出てくるので、使いたいカーネルを選択。
ここまできたら、あとは通常のHydrogenと同じように使えるはず。
まとめ
Hydrogenを使えば、atomのエディタ機能を使いながらjupyterのインタラクティブな機能をふんだんに使える。jupyter用のショートカットを覚える必要もない。docker使えば環境設定の必要もほぼいらない。python使う人はatomとHydrogen使いましょ。
(jupyter labとかは進化が目まぐるしいので、ちょっとさわってもいいかな・・・)ssh接続でリモートマシン上のカーネルを使いたいときも同じようにできると思います。
参考
Jupyterをブラウザで使うのをやめてAtomのHydrogenに移行した話
JupyterのDockerイメージまとめ
Hydrogen
jupyter docker stacks
- 投稿日:2019-04-15T11:30:45+09:00
[mastodon]v2.4.0→v2.4.1にアップデートした際のエラー
※とりま備忘録的に書いてます+ markdown文法 模索中です
環境
うちのmastdon
vps
docker
mastodon v2.4.0→v2.4.1v2.4.0→v2.4.1にアップデートした際に出たエラー
いつも通りに「docker-compose run --rm web rails db:migrate」とやっていたら、エラー吐いたので、対応模索する。
~/mstdntest$ docker-compose run --rm web rails db:migrate Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done [FATAL tini (11)] exec rails failed: No such file or directory~$ cd mstdntest/ ~/mstdntest$ docker-compose run --rm web rails assets:precompile Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done [FATAL tini (8)] exec rails failed: No such file or directory「rails」が見つからん
と仰っているのでパスを付与する~$ cd mstdntest/ ~/mstdntest$ docker-compose run --rm web ./bin/rails db:migrate Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done~/mstdntest$ docker-compose run --rm web ./bin/rails assets:precompile Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done Webpacker is installed ? ? Using /mastodon/config/webpacker.yml file for setting up webpack paths Compiling… Compiled all packs in /mastodon/public/packs ~/mstdntest$※assets:precompileは、5分ぐらいかかった
- 投稿日:2019-04-15T11:30:45+09:00
mastodon v2.4.0→v2.4.1にアップデートした際のエラー
※とりま備忘録的に書いてます+ markdown文法 模索中です
うちのmastdon
vps
docker
mastodon v2.4.0→v2.4.1v2.4.0→v2.4.1にアップデートした際に出たエラー
いつも通りに「docker-compose run --rm web rails db:migrate」とやっていたら、エラー吐いたので、対応模索する。
Consoledocker@altair:~/mstdntest$ docker-compose run --rm web rails db:migrate Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done [FATAL tini (11)] exec rails failed: No such file or directoryConsoledocker@altair:~$ cd mstdntest/ docker@altair:~/mstdntest$ docker-compose run --rm web rails assets:precompile Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done [FATAL tini (8)] exec rails failed: No such file or directory「rails」が見つからないよー
と仰っているのでパスを付与するConsoledocker@altair:~$ cd mstdntest/ docker@altair:~/mstdntest$ docker-compose run --rm web ./bin/rails db:migrate Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... doneConsoledocker@altair:~/mstdntest$ docker-compose run --rm web ./bin/rails assets:precompile Starting mstdntest_db_1 ... done Starting mstdntest_redis_1 ... done Webpacker is installed ? ? Using /mastodon/config/webpacker.yml file for setting up webpack paths Compiling… Compiled all packs in /mastodon/public/packs docker@altair:~/mstdntest$※assets:precompileは、5分ぐらいかかった
- 投稿日:2019-04-15T02:14:02+09:00
素の alpine でのコネクション確認
最近 ECS を使おうと docker を色々と触っているので、その知見を溜めておく。
今回は alpine で一切ツールを導入(
apk add
)せずにコネクション確認をするかというお話。「ヘルスチェック」ではなく「コネクション確認」という言葉を使っているのは、docker が持っているヘルスチェック機能とは違う話をするため。
応用はできるけど、もともとの動機は「アプリサーバーがDBマイグレーションを行う際に通信できる常態か知りたい」だった。tl;dr
nc
コマンドを使おう。
デフォルトでインストールされていて、なんなら UDP での接続チェックなんてのもできる。一定の時間、コネクション確認するスクリプトは次の通り。
host=${1:-"127.0.0.1"} port=${2:-80} retry=0 while [ $retry -lt 10 ]; do sleep $retry echo "connection check to $host:$port" nc -zn $host $port [ $? -eq 0 ] && exit 0 retry=`expr $retry + 1` echo "failed; sleep for ${retry}s" done && exit 1というわけで、以下は道のり
を書こうと思ったけど、まぁまた今度
- 投稿日:2019-04-15T00:53:54+09:00
Kubernetes上でアプリケーションデプロイをサクッと試してみる(コマンド例あり)
背景
最近アプリケーション実行環境としてコンテナ仮想環境は当たり前になりつつあると感じています。個人的にもサクッと新しい技術を(OSSなりツールなり)試したりするのにもローカルを汚さず素早く環境構築を行えるので、これがないと逆に効率が悪くなるなと思います。
そんな風潮の中で社内でもKubernetesによるアプリケーション環境構築や運用保守がなされており、(コンテナ仮想化ソフトはもう当たり前として)社内外でもk8sの存在感が絶大です。
僕自身はアプリケーションエンジニア(フロントエンド/バックエンドどちらも見る)ではありますが、k8sの知見を増やしたいと思い「Kubernetes実践入門」という書籍を参考にローカルにk8sでアプリケーションデプロイまで構築してみました。目次は書籍の章立てとはあまり関係なく試したことの備忘的な面が大きいですが、順序だてていますので試しに触って動かしてみたい方には参考になるかなと思います。目次
- 前提
- minikubeでクラスタを構築してみる
- インストール方法
- クラスタ構築
- クラスタの停止、削除する
- アドオンを管理する
- k8s上にアプリケーションをデプロイしてみる
- 簡易的にデプロイする
- アプリケーションのマニフェストを作成してデプロイする
前提
- MacbookPro, MacOS Mojave(version=10.14.3)
- VirtualBox(version=5.2.20 r125813)
- Homebrew(version=2.1.0)
- k8sのオブジェクトについて概ね理解している。
k8sには内部構造を抽象化しk8s内で利用しやすくするために独自のオブジェクトの概念があります。僕自身は以前k8sについて調べたことがあったので(知見として頭に入れただけで使えるようにはなってませんでした)あえてそこには触れませんが、記事内では固有名詞で頻出しますのでわからない方は以下の記事などで先に理解しておくことをお勧めします。(まぁそれを理解するのがもっとも難しいのですが。。。)
【参考記事】
minikubeでクラスタを構築してみる
ローカル環境でk8sを動かすためにminikubeを利用します。k8sの公式で提供しているので操作についてほとんど差異はないはずです。
インストール方法
# minikubeをインストール $ brew cask install minikube # kubernetes-cliをインストール $ brew install kubernetes-cliクラスタ構築
初回実行時はVMイメージのダウンロードから始まるので時間がかかるようです。
(実は、一度失敗してしまったのでこちらの記事を参考に再実行しました。)$ minikube start ? minikube v1.0.0 on darwin (amd64) ? Downloading Kubernetes v1.14.0 images in the background ... ? Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ... ? Downloading Minikube ISO ... 142.88 MB / 142.88 MB [============================================] 100.00% 0s ? "minikube" IP address is 192.168.99.100 ? Configuring Docker as the container runtime ... ? Version of container runtime is 18.06.2-ce ⌛ Waiting for image downloads to complete ... ✨ Preparing Kubernetes environment ... ? Downloading kubeadm v1.14.0 ? Downloading kubelet v1.14.0 ? Pulling images required by Kubernetes v1.14.0 ... ? Launching Kubernetes v1.14.0 using kubeadm ... ⌛ Waiting for pods: apiserver proxy etcd scheduler controller dns ? Configuring cluster permissions ... ? Verifying component health ..... ? kubectl is now configured to use "minikube" ? Done! Thank you for using minikube!クラスタの確認をしてみる
$ kubectl get nodes NAME STATUS ROLES AGE VERSION minikube Ready master 2m23s v1.14.0
minikube
という1台のNodeが稼働しています。クラスタの停止、削除する
minikubeはローカルでクラスタを実行しているため実行中ノードのリソースを占有するようです。よって利用しない場合はクラスを終了しておいた方がいいでしょう。
クラスタを停止して再度minikube start
した際は、停止前の状態のクラスタ起動します。削除した場合は初期状態のクラスタが構築されますのでリセットしたい場合に利用できると思います。# クラスタを停止する $ minikube stop # クラスタを削除する $ minikube deleteアドオンを管理する
minikubeにはよく使われる機能を拡張機能として利用できるアドオンがあります。
# アドオンの一覧を列挙する $ minikube addons list - addon-manager: enabled - dashboard: disabled - default-storageclass: enabled - efk: disabled - freshpod: disabled - gvisor: disabled - heapster: disabled - ingress: disabled - logviewer: disabled - metrics-server: disabled - nvidia-driver-installer: disabled - nvidia-gpu-device-plugin: disabled - registry: disabled - registry-creds: disabled - storage-provisioner: enabled - storage-provisioner-gluster: disabledデフォルトでいくつかのアドオンが有効になっています。アドオンを有効/無効にする場合は以下を実行します。
# アドオンを有効にする $ minikube addons enable {addon-name} # アドオンを無効にする $ minikube addons disable {addon-name}たとえば、クラスタのWEB管理画面であるdashboardは
minikube dashboard
を実行することでブラウザで表示されます。k8s上にアプリケーションをデプロイしてみる
サンプルアプリにはMattermostというSlackライクなチャットアプリケーションを利用します。
簡易的にデプロイする
ここからは、k8s上へのアプリデプロイを素早くやってみたい、デプロイされた後の動きをdashboardで確認してみたいと思い、プロセスや本番利用をすっ飛ばした簡易的なデプロイ手順を記載しています。本番環境では利用をおすすめしませんのでより本番に近い方法は こちら に進んでください。
アプリケーションをデプロイする -
kubectl create deployment
k8上にアプリケーションをデプロイする簡単な方法は
kubectl create deployment
を実行することです。アプリケーションの識別名とコンテナイメージの指定は必須です。
created
が返ればDeployment
オブジェクトが作成され、デプロイが開始したことを意味します。$ kubectl create deployment mattermost-preview --image k8spracticalguide/mattermost-preview:4.10.2 deployment.apps/mattermost-preview createdデプロイが開始されれば、
kubectl get deployment
を実行してDeploymentの状態を確認しましょう。何度か実行しているうちにAVAILABLEが1に変わると思います。$ kubectl get deployment mattermost-preview NAME READY UP-TO-DATE AVAILABLE AGE mattermost-preview 1/1 1 1 69sアプリケーションを公開する -
kubectl expose
デプロイが完了しても、クラスタ外からはアクセスできません。クラスタ外からアクセスできるようにするには
kubectl expose
コマンドを--type
オプションにNodePort
を指定して実行する必要があります。
ただ、僕自身現段階では「Nodeportはクラスタ外からアクセスするためのもの」という理解しかしていませんでした。。。$ kubectl expose --type NodePort --port 8065 deployment mattermost-preview service/mattermost-preview exposed以上でクラスタ外からアクセスできる状態になったので、ブラウザから確認してみます。ブラウザからアクセスするには、アプリケーションのアドレスとポート番号を調べ、ブラウザを開き・・という少々面倒ですので、それらを一括で実行してくれる
minikube service
コマンドを使います。$ minikube service mattermost-preview ? Opening kubernetes service default/mattermost-preview in default browser...アプリケーションのマニフェストを作成してデプロイする
上記では
kubectl create deployment
を利用して簡易的にDeploymentを作成しましたが、これではファイルとして履歴が残らないため、レビューしにくく、再利用ができず、問題発生時に原因究明しにくいなど本番環境で利用するには問題が起きそうです。
そのため本番利用を見据えては、Deploymentなどの宣言的設定をyamlやjsonなどで記述しバージョン管理を行うのが一般的かと思います。それらの設定ファイルをマニフェストと呼びます。ここからアプリコンテナは、mattermostのお試し用(mattermost-preview)ではなく、実利用版(mattermost)を利用していきます。
Deploymentマニフェストを作成する
いきなり0から作るのは難しいため、
--dry-run
オプションで雛形を作成し、修正しながら作成していくこととします。
※--dry-run
オプションは雛形作成のためのオプションではなく、実際にkubectrlがAPIを叩く前のリクエスト内容を取得するためのコマンドです。外部出力の--output
オプションと併用して雛形作成を行います。# mattermost(アプリ)の雛形を作成 $ kubectl create deployment mattermost --image k8spracticalguide/mattermost:4.10.2 -o yaml --dry-run > mattermost-deploy.yaml # mattermost-db(db)の雛形を作成 $ kubectl create deployment mattermost-db --image k8spracticalguide/mysql:5.7.22 -o yaml --dry-run > mattermost-db-deploy.yamlDeploymetnマニュフェストのPodテンプレートに環境変数を追加する
mattermostのイメージはDB用の設定値を環境変数で定義できるようになっています。
これらはデプロイする環境や構成によって変更する可能性があるため、コンテナイメージに直接持つのではなく、Deploymentオブジェクト作成時に設定するようにしたいと思います。
ConfigMapを使って設定値を管理、読み込みする
複数のPodテンプレート内に共通の設定値を与える場合、ConfigMapというオブジェクトに設定値を集約して設定値のばらつきによる不具合を抑えることができます。
# ConfigMapのマニフェストを作成する $ kubectl create cm common-env -o yaml --dry-run \ --from-literal MYSQL_USER=mm_user \ --from-literal MYSQL_PASSWORD=P@ssw0rd \ --from-literal MYSQL_DATABASE=mattermost > cm.yamlDeploymentの方は以下のように修正する。
mattermost-deploy.yaml(1~18行目は略) spec: containers: - image: k8spracticalguide/mattermost:4.10.2 name: mattermost + env: + - name: MM_USERNAME + valueFrom: # <- valueではなくvalueFromを使う + configMapKeyRef: + name: common-env # <- ConfigMap名を指定する + key: MYSQL_USER # <- dataマップのキーを指定する + - name: MM_PASSWORD + valueFrom: + configMapKeyRef: + name: common-env + key: MYSQL_PASSWORD + - name: DB_NAME + valueFrom: + configMapKeyRef: + name: common-env + key: MYSQL_DATABASE + - name: DB_HOST + value: mattermost-db resources: {} (略)
mattermost-db-deploy.yaml(1~18行目は略) spec: containers: - image: k8spracticalguide/mysql:5.7.22 name: mysql + env: + - name: MYSQL_ROOT_PASSWORD + value: rootpassword + envFrom: # <- envではなくenvFromに置き換える + - configMapRef: + name: common-env # <- ConfigMap名を指定する resources: {} (略)
別ファイルで設定値を管理、読み込みする
さらに、設定が膨大に増えると環境変数として渡すのではなく設定ファイルとしてまとめて設定値を渡す方が管理しやすくなることもあります。
# mattermostの設定ファイルをダウンロードしておく $ curl -L -O https://raw.githubusercontent.com/kubernetes-practical-guide/examples/master/ch3.4.2.2/config.json # ファイルからConfigMapのマニフェストを作成する $ kubectl create cm mm-config-file -o yaml --dry-run \ --from-file ./config.json > cm-file.yaml # ダウンロードした設定ファイルは不要なので削除する $ rm ./config.jsonDeploymentの方は以下のように修正する。
mattermost-deploy.yaml(1~38行目は略) - name: DB_HOST value: mattermost-db resources: {} + volumeMounts: + - name: cm-volume # <- マウントするVolume名を指定(a) + mountPath: /mm/config # <- コンテナ内のマウントポイント + volumes: + - name: cm-volume # <- (a)で指定するVolume名を定義 + configMap: + name: mm-config-file + items: # <- itemsを省略するとConfigMap内の全データがマウントされる + - key: config.json # <- ファイルとしてマウントするデータのキーを指定 + path: config.json # <- コンテナ内でのファイル名を指定 (略)
Serviceマニフェストを作成する
各PodはデプロイされるとIPアドレスが一時的に付与されますが、Podを上げ下げするたびにIPアドレスが変更され書き換えが必要になります。
その無駄を回避するため、PodのIPアドレスを仮想IPに束ね内部DNSで名前解決するServieオブジェクトが存在しています。クラスタ内部のためのServiceを作成する
$ kubectl create service clusterip mattermost-db --tcp 3306 -o yaml --dry-run > mattermost-db-service.yaml仮想IPに来たアクセスをどのPodへ振り分けするかはservie.yamlの
spec.selector
で指定します。mattermost-db-service.yamlapiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: mattermost-db name: mattermost-db spec: ports: - name: "3306" port: 3306 protocol: TCP targetPort: 3306 selector: # <- リクエストの振り分け先を指定するlabelセレクタ app: mattermost-db # <- DeploymentのPodテンプレートのlabelと合わせる必要がある type: ClusterIP status: loadBalancer: {}クラスタ外のための(公開用)Serviceを作成する
# mattermostのDeploymentにServiceを付与するので事前に立ち上げておく $ kubectl apply -f . # クラスタ外のための(公開用)Serviceを作成する $ kubectl expose --type NodePort --port 8065 deploy mattermost -o yaml --dry-run > mattermost-service.yaml※ NodePortを使えば手軽に外部公開できるようになりますが、直接Serviceを晒す事になったり、アクセスするNodeをどう選択するか問題になりがちです。いくらマニフェスト化して管理しやすくしてもまだ本番利用には不向きだと思いました。開発環境をサクッと構築したい時には便利です。
よって本番では、外部のロードバランサを使って公開するか、Ingressというクラスタ内部のロードバランサを使って公開する方法が有用ですが、今回は構築は実施しません。
(両者の違いについてはこちらが参考になりました。)マニフェストを適用する
上記の通り操作してくるとマニフェストファイル構成は以下のようになっているはず。
┌ cm-file.yaml ├ cm.yaml ├ mattermost-db-deploy.yaml ├ mattermost-db-service.yaml ├ mattermost-deploy.yaml └ mattermost-service.yamlマニフェストファイルを適用して各種k8sオブジェクトを作成する
$ kubectl apply -f .ブラウザからアクセスできることを確認するためにNodeのIP、Nodeに割り当てられたポート番号を調べます。
# NodeのIPアドレスを調べる $ minikube ip 192.168.99.100 # NodePortに割り当てられたのポート番号を調べる $ kubectl get svc mattermost NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mattermost NodePort 10.102.242.69 <none> 8065:31837/TCP 3m50sPORT(s)のカラムをみると、2つのポート番号が表示されていますが、
{アプリが待ち受けしているポート}:{Nodeに割り当てられたポート}
を表しています。よって
http://192.168.99.100:31837
でブラウザからアクセスできるはずです。今回は以上です。
サクッと利用してみたいのであればk8sのマネージドサービスも一般的かもしれませんが、利便性の反面、内部の仕組みが隠蔽されて仕組みを理解する題材には向いていないかなと思いましてローカルにminikubeでk8s環境を立ててみました。今回の内容はまだまだ入り口かとは思いますが、実際にアプリケーションをデプロイすることを実践してみてk8sの足がかりになったかなと思います。
- 投稿日:2019-04-15T00:53:54+09:00
Kubernetes上でアプリケーションデプロイをサクッと試してみる(コマンドあり)
背景
最近アプリケーション実行環境としてコンテナ仮想環境は当たり前になりつつあると感じています。個人的にもサクッと新しい技術を(OSSなりツールなり)試したりするのにもローカルを汚さず素早く環境構築を行えるので、これがないと逆に効率が悪くなるなと思います。
そんな風潮の中で社内でもKubernetesによるアプリケーション環境構築や運用保守がなされており、(コンテナ仮想化ソフトはもう当たり前として)社内外でk8sの存在感が絶大です。
僕自身はアプリケーションエンジニア(フロントエンド/バックエンドどちらも見る)ではありますが、k8sの知見を増やしたいと思い「Kubernetes実践入門」という書籍を参考にローカルにk8sでアプリケーションデプロイまで構築してみました。目次は書籍の章立てとはあまり関係ないですが特に重要と思われる部分だけピックアップし順序だてていますので試しに触って動かしてみたい方には参考になるかなと思います。目次
- 前提
- minikubeでクラスタを構築してみる
- インストール方法
- クラスタ構築
- クラスタの停止、削除する
- アドオンを管理する
- k8s上にアプリケーションをデプロイしてみる
- 簡易的にデプロイする
- アプリケーションのマニフェストを作成してデプロイする
前提
- MacbookPro, MacOS Mojave(version=10.14.3)
- VirtualBox(version=5.2.20 r125813)
- Homebrew(version=2.1.0)
- k8sのオブジェクトについて概ね理解している。
k8sには内部構造を抽象化しk8s内で利用しやすくするために独自のオブジェクトの概念があります。僕自身は以前k8sについて調べたことがあったので(知見として頭に入れただけで使えるようにはなってませんでした)あえてそこには触れませんが、記事内では固有名詞で頻出しますのでわからない方は以下の記事などで先に理解しておくことをお勧めします。(まぁそれを理解するのがもっとも難しいのですが。。。)
【参考記事】
minikubeでクラスタを構築してみる
ローカル環境でk8sを動かすためにminikubeを利用します。k8sの公式で提供しているので操作についてほとんど差異はないはずです。
インストール方法
# minikubeをインストール $ brew cask install minikube # kubernetes-cliをインストール $ brew install kubernetes-cliクラスタ構築
初回実行時はVMイメージのダウンロードから始まるので時間がかかるようです。
(実は、一度失敗してしまったのでこちらの記事を参考に再実行しました。)$ minikube start ? minikube v1.0.0 on darwin (amd64) ? Downloading Kubernetes v1.14.0 images in the background ... ? Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ... ? Downloading Minikube ISO ... 142.88 MB / 142.88 MB [============================================] 100.00% 0s ? "minikube" IP address is 192.168.99.100 ? Configuring Docker as the container runtime ... ? Version of container runtime is 18.06.2-ce ⌛ Waiting for image downloads to complete ... ✨ Preparing Kubernetes environment ... ? Downloading kubeadm v1.14.0 ? Downloading kubelet v1.14.0 ? Pulling images required by Kubernetes v1.14.0 ... ? Launching Kubernetes v1.14.0 using kubeadm ... ⌛ Waiting for pods: apiserver proxy etcd scheduler controller dns ? Configuring cluster permissions ... ? Verifying component health ..... ? kubectl is now configured to use "minikube" ? Done! Thank you for using minikube!クラスタの確認をしてみる
$ kubectl get nodes NAME STATUS ROLES AGE VERSION minikube Ready master 2m23s v1.14.0
minikube
という1台のNodeが稼働しています。クラスタの停止、削除する
minikubeはローカルでクラスタを実行しているため実行中ノードのリソースを占有するようです。よって利用しない場合はクラスを終了しておいた方がいいでしょう。
クラスタを停止して再度minikube start
した際は、停止前の状態のクラスタが起動します。削除した場合は初期状態のクラスタが起動されますのでリセットしたい場合に利用できます。# クラスタを停止する $ minikube stop # クラスタを削除する $ minikube deleteアドオンを管理する
minikubeにはよく使われる機能を拡張機能として利用できるアドオンがあります。
# アドオンの一覧を列挙する $ minikube addons list - addon-manager: enabled - dashboard: disabled - default-storageclass: enabled - efk: disabled - freshpod: disabled - gvisor: disabled - heapster: disabled - ingress: disabled - logviewer: disabled - metrics-server: disabled - nvidia-driver-installer: disabled - nvidia-gpu-device-plugin: disabled - registry: disabled - registry-creds: disabled - storage-provisioner: enabled - storage-provisioner-gluster: disabledデフォルトでいくつかのアドオンが有効になっています。アドオンを有効/無効にする場合は以下を実行します。
# アドオンを有効にする $ minikube addons enable {addon-name} # アドオンを無効にする $ minikube addons disable {addon-name}たとえば、クラスタのWEB管理画面であるdashboardは
minikube dashboard
を実行することでブラウザで表示されます。k8s上にアプリケーションをデプロイしてみる
サンプルアプリにはMattermostというSlackライクなチャットアプリケーションを利用します。
簡易的にデプロイする
ここからは、k8s上へのアプリデプロイを素早くやってみたい、デプロイされた後の動きをdashboardで確認してみたいと思い、簡易的なデプロイ手順を記載しています。本番環境では利用をおすすめしませんのでより本番に近い方法は こちら に進んでください。
アプリケーションをデプロイする -
kubectl create deployment
k8上にアプリケーションをデプロイする簡単な方法は
kubectl create deployment
を実行することです。アプリケーションの識別名とコンテナイメージの指定は必須です。
created
が返ればDeployment
オブジェクトが作成され、デプロイが開始したことを意味します。$ kubectl create deployment mattermost-preview --image k8spracticalguide/mattermost-preview:4.10.2 deployment.apps/mattermost-preview createdデプロイが開始されれば、
kubectl get deployment
を実行してDeploymentの状態を確認しましょう。何度か実行しているうちにAVAILABLEが1に変わると思います。$ kubectl get deployment mattermost-preview NAME READY UP-TO-DATE AVAILABLE AGE mattermost-preview 1/1 1 1 69sアプリケーションを公開する -
kubectl expose
デプロイが完了しても、クラスタ外からはアクセスできません。クラスタ外からアクセスできるようにするには
kubectl expose
コマンドを--type
オプションにNodePort
を指定して実行する必要があります。
現段階では「Nodeportはクラスタ外からNodeへアクセスするためのポート」という理解で良いと思います。。。$ kubectl expose --type NodePort --port 8065 deployment mattermost-preview service/mattermost-preview exposed以上でクラスタ外からアクセスできる状態になったので、ブラウザから確認してみます。ブラウザからアクセスするには、アプリケーションのアドレスとポート番号を調べ、ブラウザを開き・・という少々面倒ですので、それらを一括で実行してくれる
minikube service
コマンドを使います。$ minikube service mattermost-preview ? Opening kubernetes service default/mattermost-preview in default browser...アプリケーションのマニフェストを作成してデプロイする
上記では
kubectl create deployment
を利用して簡易的にDeploymentを作成しましたが、これではファイルとして履歴が残らないため、レビューしにくく、再利用ができず、問題発生時に原因究明しにくいなど本番環境で利用するには問題が起きそうです。
そのため本番利用を見据えては、Deploymentなどの宣言的設定をyamlやjsonなどで記述しバージョン管理を行うのが一般的かと思います。それらの設定ファイルをマニフェストと呼びます。ここからアプリコンテナは、mattermostのお試し用(mattermost-preview)ではなく、実利用版(mattermost)を利用していきます。
Deploymentマニフェストを作成する
いきなり0から作るのは難しいため、
--dry-run
オプションで雛形を作成し、修正しながら作成していくこととします。
※--dry-run
オプションは雛形作成のためのオプションではなく、実際にkubectrlがAPIを叩く前のリクエスト内容を取得するためのコマンドです。外部出力の--output
オプションと併用して雛形作成を行います。# mattermost(アプリ)の雛形を作成 $ kubectl create deployment mattermost --image k8spracticalguide/mattermost:4.10.2 -o yaml --dry-run > mattermost-deploy.yaml # mattermost-db(db)の雛形を作成 $ kubectl create deployment mattermost-db --image k8spracticalguide/mysql:5.7.22 -o yaml --dry-run > mattermost-db-deploy.yamlDeploymetnマニュフェストのPodテンプレートに環境変数を追加する
mattermostのイメージはDB用の設定値を環境変数で定義できるようになっています。
これらはデプロイする環境や構成によって変更する可能性があるため、コンテナイメージに直接持つのではなく、Deploymentオブジェクト作成時に設定するようにしたいと思います。
ConfigMapを使って設定値を管理、読み込みする
複数のPodテンプレート内に共通の設定値を与える場合、ConfigMapというオブジェクトに設定値を集約して設定値のばらつきによる不具合を抑えることができます。
# ConfigMapのマニフェストを作成する $ kubectl create cm common-env -o yaml --dry-run \ --from-literal MYSQL_USER=mm_user \ --from-literal MYSQL_PASSWORD=P@ssw0rd \ --from-literal MYSQL_DATABASE=mattermost > cm.yamlDeploymentの方は以下のように修正する。
mattermost-deploy.yaml(1~18行目は略) spec: containers: - image: k8spracticalguide/mattermost:4.10.2 name: mattermost + env: + - name: MM_USERNAME + valueFrom: # <- valueではなくvalueFromを使う + configMapKeyRef: + name: common-env # <- ConfigMap名を指定する + key: MYSQL_USER # <- dataマップのキーを指定する + - name: MM_PASSWORD + valueFrom: + configMapKeyRef: + name: common-env + key: MYSQL_PASSWORD + - name: DB_NAME + valueFrom: + configMapKeyRef: + name: common-env + key: MYSQL_DATABASE + - name: DB_HOST + value: mattermost-db resources: {} (略)
mattermost-db-deploy.yaml(1~18行目は略) spec: containers: - image: k8spracticalguide/mysql:5.7.22 name: mysql + env: + - name: MYSQL_ROOT_PASSWORD + value: rootpassword + envFrom: # <- envではなくenvFromに置き換える + - configMapRef: + name: common-env # <- ConfigMap名を指定する resources: {} (略)
別ファイルで設定値を管理、読み込みする
さらに、設定が膨大に増えると環境変数として渡すのではなく設定ファイルとしてまとめて設定値を渡す方が管理しやすくなることもあります。
# mattermostの設定ファイルをダウンロードしておく $ curl -L -O https://raw.githubusercontent.com/kubernetes-practical-guide/examples/master/ch3.4.2.2/config.json # ファイルからConfigMapのマニフェストを作成する $ kubectl create cm mm-config-file -o yaml --dry-run \ --from-file ./config.json > cm-file.yaml # ダウンロードした設定ファイルは不要なので削除する $ rm ./config.jsonDeploymentの方は以下のように修正する。
mattermost-deploy.yaml(1~38行目は略) - name: DB_HOST value: mattermost-db resources: {} + volumeMounts: + - name: cm-volume # <- マウントするVolume名を指定(a) + mountPath: /mm/config # <- コンテナ内のマウントポイント + volumes: + - name: cm-volume # <- (a)で指定するVolume名を定義 + configMap: + name: mm-config-file + items: # <- itemsを省略するとConfigMap内の全データがマウントされる + - key: config.json # <- ファイルとしてマウントするデータのキーを指定 + path: config.json # <- コンテナ内でのファイル名を指定 (略)
Serviceマニフェストを作成する
各PodはデプロイされるとIPアドレスが一時的に付与されますが、Podを上げ下げするたびにIPアドレスが変更され書き換えが必要になります。
その無駄を回避するため、PodのIPアドレスを仮想IPに束ね内部DNSで名前解決するServieオブジェクトが存在しています。クラスタ内部のためのServiceを作成する
$ kubectl create service clusterip mattermost-db --tcp 3306 -o yaml --dry-run > mattermost-db-service.yaml仮想IPに来たアクセスをどのPodへ振り分けするかはservie.yamlの
spec.selector
で指定します。mattermost-db-service.yamlapiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: mattermost-db name: mattermost-db spec: ports: - name: "3306" port: 3306 protocol: TCP targetPort: 3306 selector: # <- リクエストの振り分け先を指定するlabelセレクタ app: mattermost-db # <- DeploymentのPodテンプレートのlabelと合わせる必要がある type: ClusterIP status: loadBalancer: {}クラスタ外のための(公開用)Serviceを作成する
# mattermostのDeploymentにServiceを付与するので事前に立ち上げておく $ kubectl apply -f . # クラスタ外のための(公開用)Serviceを作成する $ kubectl expose --type NodePort --port 8065 deploy mattermost -o yaml --dry-run > mattermost-service.yaml※ NodePortを使えば手軽に外部公開できるようになりますが、直接Serviceを晒す事になったり、アクセスするNodeをどう選択するか問題になりがちです。いくらマニフェスト化して管理しやすくしてもまだ本番利用には不向きだと思いました。開発環境をサクッと構築したい時には便利です。
よって本番では、外部のロードバランサを使って公開するか、Ingressというクラスタ内部のロードバランサを使って公開する方法が有用ですが、今回は構築は実施しません。
(両者の違いについてはこちらが参考になりました。)マニフェストを適用する
上記の通り操作してくるとマニフェストファイル構成は以下のようになっているはず。
┌ cm-file.yaml ├ cm.yaml ├ mattermost-db-deploy.yaml ├ mattermost-db-service.yaml ├ mattermost-deploy.yaml └ mattermost-service.yamlマニフェストファイルを適用して各種k8sオブジェクトを作成する
$ kubectl apply -f .ブラウザからアクセスできることを確認するためにNodeのIP、Nodeに割り当てられたポート番号を調べます。
# NodeのIPアドレスを調べる $ minikube ip 192.168.99.100 # NodePortに割り当てられたのポート番号を調べる $ kubectl get svc mattermost NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mattermost NodePort 10.102.242.69 <none> 8065:31837/TCP 3m50sPORT(s)のカラムをみると、2つのポート番号が表示されていますが、
{アプリが待ち受けしているポート}:{Nodeに割り当てられたポート}
を表しています。よって
http://192.168.99.100:31837
でブラウザからアクセスできるはずです。今回は以上です。
サクッと利用してみたいのであればk8sのマネージドサービスも一般的かもしれませんが、利便性の反面、内部の仕組みが隠蔽されて仕組みを理解する題材には向いていないかなと思いましてローカルにminikubeでk8s環境を立ててみました。今回の内容はまだまだ入り口かとは思いますが、実際にアプリケーションをデプロイすることを実践してみてk8sの足がかりになったかなと思います。
- 投稿日:2019-04-15T00:49:21+09:00
Cloud Runを試してみる
Cloud Runとは
Google Cloud Next '19 San Francisco で発表された、GCPの新サービス、
Cloud Runを試してみる。
コンテナを作成しデプロイするだけで、サーバレスで実行できるようになるらしい。
コンテナ上でアプリケーションが動くため、どんな言語で作成されたものでも実行可能。公式チュートリアル
https://cloud.google.com/run/docs/quickstarts
Dockerイメージを作成する
以下の3ファイルを作成
requirements.txtFlask==1.0.2 gunicorn==19.9.0DockerfileFROM python:3.7 ENV PORT=8080 WORKDIR /usr/src/app COPY requirements.txt ./ COPY app.py ./ RUN pip install --no-cache-dir -r requirements.txt CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:appapp.pyfrom flask import Flask app = Flask(__name__) @app.route('/') @app.route('/<id>') def hello(word=’World’): return f'Hello {word}!!' if __name__ == '__main__': app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))ビルドして、GCRにプッシュ
PROJECT_ID=<YOUR_PROJECT> IMAGE=cloud-run-sample docker build -t gcr.io/${PROJECT_ID}/${IMAGE} . gcloud docker -- push gcr.io/${PROJECT_ID}/${IMAGE}デプロイ
GCPコンソールからCloud Runを選択、「CREATE SERVICE」を選択
先程ビルドしたコンテナイメージを選択し、サービス名、ロケーションを入力。
「未認証の呼び出しを許可」にチェックを入れ、作成。
デプロイが終わると、URLが割り当てられるので、ブラウザでアクセスし、
アプリケーションが動いていることが確認できる。まとめ
コンテナさえあれば簡単にデプロイできる。
初めてアクセスするときは5~10秒くらいかかる。コンテナ起動の時間なのか?
Cloud Functionsとどう使い分けるべきか検証したい。