Docker/K8S実践コンテナ開発入門@27日目

本日もKubernetsの勉強の続きです。

DaemonSetでfluentdの構築

書籍に従って、fluentdを構築します。
DaemonSetというのが新しく登場しますが、
Kubernetesクラスタで利用されている全てのNodeに対するPodを管理するためのリソース

これはログコレクタのような各ホストでエージェントとして配置したい用途に定期しているとのこと

書籍に従って「fluentd-daemonset.yaml」を作成した後に、
以下のコマンドでコンテナを配置します。

■コマンド

//コンテナ配置
 kubectl apply -f fluentd-daemonset.yaml 

//起動確認
kubectl -n kube-system get pod -l app=fluentd-logging

実行が確認できたら、今度はアプリケーションのPodを起動
書籍に従って「echo.yaml」を作成し、以下のコマンドで配置します。

■コマンド

//コンテナ配置
kubectl apply -f echo.yaml

//接続確認
curl http://localhost:30080

最初の方は「curl: (52) Empty reply from server」が何度か出ていたのですが、
数分放置しているとログが返却されました。

ローカルKubernetes環境で高築したKibanaeログを確認してみます。
f:id:lawrence-twin:20200527233831p:plain

何も出ない、、、と思ったのですが
右上の出力範囲をいじれば出てくるようになりました。

f:id:lawrence-twin:20200527234558p:plain

ただ本来は、上部検索欄に「kubernetes.labels.app: ech」と入力することで、
実行したechoに対するログが取得できるはずなのですが何も出ず、、、

kubectlで配置したfluentdのログをみると色々とwarnが出ているのでもしかしてうまくいっていない???
ひとまずはこの件は保留にします。

Docker/Kubernetesでのロギングの王道

Compose、Kubernetesでのロギングをやっていきましたが、
書籍ではロギング運用については以下のようにまとめられています。

■まとめ

  • アプリケーションのロギングは全て標準出力とする。コンテナ運用前提ではファイル出力サポートは不要
  • nginxなどのミドルウェアのログも全て標準出力にすべき
  • 標準出力はJSON形式とする
  • Kubernetesにおいては、fluentとdaemonsetで構成されるPodを各ホストに配置する
  • ラベルを適切に配置する

仕事で構築するかもしれないので、
上記は良く覚えておこうと思います。

Docker/K8S実践コンテナ開発入門@26日目

Dockerのロギングの勉強の続きをやっていきます。

fluentd logging driverの運用イメージについて

書籍の内容を抜粋すると、
「fluentdを各Dockerホストにエージエント的に配置し、Dockerのloggin driverで利用する方式」とのこと

■特徴

  • ホストに集約してしまうと冗長化を手厚く行う必要がある。
  • ログ分散型であれば、ホスト障害での影響をホストのみに抑えることができる
  • そのためにも、VMのイメージにfluentdを含めデプロイする前にプロビジョニングで配置するのが有効

また、機能を有効に扱うにあたって監視が必要だが、
特に注目しておくべき項目は以下の通り

■項目

  • buffer_queue_length バッファに保持されているChunkの数
  • buffer_total+queued_size バッファに保持されているChunkの総サイズ
  • retry-count リトライ回数

fluent.confに 「@type monitor_agent」を追加することでこれらの項目が取得可能。

Kubernetsにおけるログの管理

Docker composeではなく、Kubernetsのロギングを試してみます。
Dockerとは殆ど差は無く、コンテナは標準出力へ出力することにのみ集中し
コンテナ外で適切にログを管理すべきとのこと

KubernetesでElasticsearchとKibanaを構築する

書籍に従って「elasticsearch.yaml」、「kibana.yaml」を作成します。

createdとなっているが起動がうまくいっていないようです。
その場合は以下のログで事象を特定できる

■コマンド

//kube-systemで起動されているpodを表示
kubectl -n kube-system get pods

//ログ確認
kubectl -n kube-system logs <containerID>

※オプションの指定がないとデフォルトの「pod」が利用されるとのこと

■エラー

lawrence@Chocolate elakube % kubectl -n kube-system logs elasticsearch-7b775db986-krjhx 
[2020-05-26T12:48:45,524][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler]uncaught exception in thread [main]akeruncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: Unable to access 'path.scripts' (/usr/share/elasticsearch/config/scripts)
	at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:136) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:123) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:70) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:134) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:91) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:84) ~[elasticsearch-5.6.16.jar:5.6.16]
Caused by: java.lang.IllegalStateException: Unable to access 'path.scripts' (/usr/share/elasticsearch/config/scripts)
	at org.elasticsearch.bootstrap.Security.addPath(Security.java:450) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.addFilePermissions(Security.java:282) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.createPermissions(Security.java:246) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.configure(Security.java:119) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:228) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:342) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:132) ~[elasticsearch-5.6.16.jar:5.6.16]
	... 6 more
Caused by: java.nio.file.FileSystemException: /usr/share/elasticsearch/config/scripts: Read-only file system
	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91) ~[?:1.8.0_201]
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102) ~[?:1.8.0_201]
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107) ~[?:1.8.0_201]
	at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384) ~[?:1.8.0_201]
	at java.nio.file.Files.createDirectory(Files.java:674) ~[?:1.8.0_201]
	at java.nio.file.Files.createAndCheckIsDirectory(Files.java:781) ~[?:1.8.0_201]
	at java.nio.file.Files.createDirectories(Files.java:767) ~[?:1.8.0_201]
	at org.elasticsearch.bootstrap.Security.ensureDirectoryExists(Security.java:492) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.addPath(Security.java:448) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.addFilePermissions(Security.java:282) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.createPermissions(Security.java:246) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Security.configure(Security.java:119) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:228) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:342) ~[elasticsearch-5.6.16.jar:5.6.16]
	at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:132) ~[elasticsearch-5.6.16.jar:5.6.16]
	... 6 more

Unable to access 'path.scripts' ...???
調べてみると同じような事象が起きている方が結構いる模様。

OSXだと起きてしまう?

色々調べた結果以下の設定を追加することで正常に起動しました。

■elastiserch.yaml
data:
elasticsearch.yml: |-
http.host: 0.0.0.0
path.scripts: /tmp/scripts //追加設定

log4j2.properties: |-
status = error

なんで上手くいくのかは良く分かりませんがともかくこれでいけます。

Docker/K8S実践コンテナ開発入門@25日目

今回はElasticsearchとKibanaを構築してみます。

Elasticsearch, Kibana構築

Elasticsearch・・・検索エンジン、様々なデータ処理に役立つ
Kibana・・・Elasticserachの可視化ツール

まずは、書籍に従って「docker-compose.yaml」と「jvm.options」を作成します。
jvm.options」はHeapサイズを抑えて軽量な形で作成されるようにしています。

作成後は以下のコマンドでイメージをビルドします。
■コマンド

docker-compose up -d

起動後は正常に起動したかを以下の通り接続して確認してみます。

■URL
http://localhost:5601

f:id:lawrence-twin:20200525211001p:plain

「status red」となっており、うまくいっていないようです。
「docker-compose.yml」ないのvolumeマウント設定を削除してjvm.optionsの設定を無視して起動してみる。
うーん、うまくいくな。
f:id:lawrence-twin:20200525211214p:plain

色々悩んだところ、
jvm.optionsの設定が以下の通り誤っていました。

正:-XX:+UseConcMarkSweepGC
誤:-XX::UseConcMarkSweepGC

vscodeで入力していますが、構文チェックに引っかかってくれないんですね。
ともかく以下の通り接続することは確認できました。

fluentdの構築

fluentdコンテナは、Elasticsearchへ収集したログを転送できるようにするためのもの
こちらは「fluent.conf」で転送先を設定します。
また「Dockerfile」を作成したら以下のコマンドを実行します。


■コマンド

docker image build -t ch08/fluentd-elasticsearch:latest .

fluentd logging driverでコンテナのログを転送

この後、fluentd loggin driverでコンテナのログを転送します。
書籍に従って「docker-compose.yml」を修正し、echoというこの書籍専用アプリとfluentdを追加します。
修正後は再起動と接続確認をします。

■コマンド

//再起動
docker-compose up -d

//確認
curl http://localhost:8080

次にログの確認を行うために、以下のコマンドを実行

■コマンド

curl http://localhost:9200/_cat/indices?v
zsh: no matches found: http://localhost:9200/_cat/indices?v

エラーが出てうまくいかないですね。どうやら「?」が悪さをしているみたい。
色々調べてみるとquoteで囲ってあげれば解消されるとのことで再度以下の通り実行

■コマンド

curl 'http://localhost:9200/_cat/indices?v'
health status index             uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   .kibana           -Txh4uOtQI-b6VJ7Y9BayA   1   1          1            0      3.2kb          3.2kb
yellow open   logstash-20200525 OMTsNg0RTkSpXPDwr6ukhg   5   1         12            0     64.4kb         64.4kb

期待通りの結果が取得できました。
この「logstash-yyyymmdd」という部分にログ情報のインデックスが作成されているようです。

f:id:lawrence-twin:20200525223205p:plain

「Crate」というボタンを押すことで、以下の通りログの内容も確認できました。

f:id:lawrence-twin:20200525223259p:plain

続きは明日以降行います。

Docker/K8S実践コンテナ開発入門@24日目

つまづいている点は一旦置いておいておき、
「コンテナの運用」についての勉強をしていきます。

ロギングの運用

コンテナでは開発のみではなく、運用上の理解が必要
ログの効率的な管理などについて勉強していきます。

コンテナにおけるロギング

  • ライブラリの殆どにはログローテートやフォーマッターの機能などが備えられている。
  • Dockerでは、ログライブラリを使ってもファイルではなく標準出力することやFluentdなどのログコレクタで収集することも多い
  • 総じて、Docker容易にログ収集可能
標準出力とログ

書籍2.1.2 で利用していたアプリケーションを利用する。

■コマンド

lawrence@Chocolate job % docker container run -it --rm -p 8080:8080 gihyodocker/echo:latest
2020/05/24 14:05:42 start server
2020/05/24 14:06:09 received request   //curl http://localhost:8080を実行

これは標準出力だけですが、次にホストに出力されているかを見てみます。
ログはLinuxKit上の仮想マシン上に出力されるとのこと

containerを特定した後に、以下のコマンドで確認する。
※「docker ps」で行けると思ったのですが、これだとコンテナIDが最初の12桁しか出力されないので、
オプションをつけて「docker ps --no-trunc」を実行することで情報がフルで取得できます。

■確認コマンド

docker run -it --rm -v /var/lib/docker/containers:/json-log alpine ash

/json-log # cd 04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad
/json-log/04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad # ls
04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad-json.log  hosts
checkpoints                                                                mounts
config.v2.json                                                             resolv.conf
hostconfig.json                                                            resolv.conf.hash
hostname
/json-log/04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad # ls -ltr
total 36
-rw-r--r--    1 root     root            71 May 24 14:05 resolv.conf.hash
-rw-r--r--    1 root     root            68 May 24 14:05 resolv.conf
drwx------    2 root     root          4096 May 24 14:05 mounts
-rw-r--r--    1 root     root           174 May 24 14:05 hosts
-rw-r--r--    1 root     root            13 May 24 14:05 hostname
drwx------    2 root     root          4096 May 24 14:05 checkpoints
-rw-r--r--    1 root     root          1513 May 24 14:05 hostconfig.json
-rw-------    1 root     root          2698 May 24 14:05 config.v2.json
-rw-r-----    1 root     root           209 May 24 14:06 04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad-json.log
/json-log/04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad # cat 04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad-json.log 
{"log":"2020/05/24 14:05:42 start server\r\n","stream":"stdout","time":"2020-05-24T14:05:42.1282499Z"}
{"log":"2020/05/24 14:06:09 received request\r\n","stream":"stdout","time":"2020-05-24T14:06:09.007967Z"}
/json-log/04ebc8a5fdb0636e205eafd1d6602476d4469c4ad75996976c80a0bc93d8d3ad # 


これでJSON形式で出力されていることが確認できました。
コンテナでロギングしていくのがどれがベストなのかは次の章で触れられます。

なおDockerコンテナのログがjson形式でログに出力されているのは、json-fileというdockerデフォルトのlogging driverによるもの
種類は以下の通り

  • syslog
  • journald
  • awslogs
  • gcplogs
  • fluentd

syslog, journaldはlinux標準
aws, gcpはそれぞれのcloudのものですね。
fulentdはOSSのログ管理ツールのようです。

コンテナのログの運用

重要なのは以下の点

  • コンテナの中でログを出力してしまうと、コンテナ削除=docker削除となる。
  • コンテナ内に出力したログがホストに出力される仕組みを活用するのがシンプル

コンテナのログローテート

オプション「--log-opt」でログローテートのパラメータが設定可能
■コマンド

docker container run -it --rm -p 8080:8080 \
--log-opt max-size=1m \
--log-opt max-file=5 \
gihyodocker/echo:latest

個別のDockerだけでなく、
DaemonのAdvancedmでJSONが設定可能なようです。
私のDockerバージョンだとAdvancedの修正方法が不明ですが、、、
f:id:lawrence-twin:20200525000518p:plain

明日以降はエラー対処またはFulentd、ElasticSearchを利用していきます。

HelmのV2とV3の差異

参考書に沿ってやっているが
参考書:V2
自分の環境:V3

のため色々難航している。
公式サイトでも以下の通り違いが出されている。

helm.sh

helm.sh

仕様変更点などは困ったらここを見ています。

helm.sh

今のところ自分が経験している違いは以下の通り

Tillerがない

V2ではTillerという概念があったがV3ではなくなっている。
これによってローカルサーバ立ち上げが若干面倒になっている。

デフォルトのリポジトリがない

ローカルリポジトリがデフォルトであったようだが、
V3ではないので自分で追加する必要がある。※苦戦中

helm searchの仕様が違う

V2ではhelm search だったが、
V3ではhelm serarch となっている。
typeにはhub または repoが入る。

helm initがない

V2であったhelm initがなくなっている。

helm serveがない

コマンドがなくなっている。さらに実行したい場合はChartMuseumとservecm pluginが必要
まずはservecmpluginを入れた後に「helm servecm」で実行すればChartMuseumも入る。

これ以上参考書との差異が発生しないことを祈ります。
(諦めてv2入れればいいのですがそれはそれで悔しいのでこのまま続行します。)

Docker/K8S実践コンテナ開発入門@23日目

Dockerの勉強続きです。

書籍には「stableリポジトリはデフォルトで利用できるようになっていて、」
という文言があるのですがこれはv2の話のようです。
私の環境ではデフォルトでは利用できませんでしたので、以下のコマンドを実行しました。

■追加コマンド

helm repo add stable https://kubernetes-charts.storage.googleapis.com

以下のコマンドで確認

■確認コマンド

helm search repo stable/redmine

インストールを試してみる
■コマンド

//インストール
helm install -f redmine.yaml redmine stable/redmine --version 4.0.0

//check
helm ls

■リソースが作成されているか確認

lawrence@Chocolate job % kubectl get service,deployment --selector release=redmine
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/redmine-mariadb   ClusterIP   10.104.184.160   <none>        3306/TCP       32m
service/redmine-redmine   NodePort    10.100.105.61    <none>        80:32413/TCP   32m

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/redmine-redmine   1/1     1            1           32m

※デプロイには10分程度時間がかかりました。

redmineのTYPEがNodePortとなっており、
ポート番号が32413なのでそちらを利用してredmineに接続をしてみる。

■接続URL
http://localhost:32413
f:id:lawrence-twin:20200522092354p:plain


■helmのupgradeコマンド

helm upgrade -f redmine.yaml redmine stable/redmine --version 4.0.0

Chartのアンインストールは以下のコマンド
■コマンド

helm delete redmine


ロールバック機能として以下のコマンドもあるようだが、、、
■コマンド

helm ls --all

しかし、何も出ない。
v2ではデフォルトでリビジョンを残してくれているようですが、v3では残してくれないようです。
オプションで「--keep-history」が必要?と思われます。

完全削除の場合、書籍では「--purge」とのことですが
v3には存在しないflagであるため、おそらくデフォルトが完全削除になっています。

RBACに対応したアプリケーションをインストール

の章はskip

tillerへのserviceAccount追加とのことですが、v3ではtillerがないため

独自のchartを作成する

書籍に従って、nginxとechoで構成されるアプリケーションのChartを作成する。

localリポジトリを有効にする

まずは利用できるリポジトリを以下のコマンドで確認
■コマンド

helm repo list


以下のコマンドでWebサーバを起動する。
■起動コマンド

helm serve &

しかし、以下のエラーが発生

lawrence@Chocolate job % helm serve &
[1] 68359
lawrence@Chocolate job % Error: unknown command "serve" for "helm"
Run 'helm --help' for usage.

[1] + exit 1 helm serve

helmの公式を確認すると、
Removal of helm serve
helm serve ran a local Chart Repository on your machine for development purposes. However, it didn't receive much uptake as a development tool and had numerous issues with its design. In the end, we decided to remove it and split it out as a plugin.

For a similar experience to helm serve, have a look at the local filesystem storage option in ChartMuseum and the servecm plugin.」

削除されていました。。。

servecm pluginを入れれば良さそう?なので以下のコマンドを実行

■コマンド

//plugin 導入
helm plugin install https://github.com/jdolitsky/helm-servecm

//servecm実行
helm servecm

//ChartMuseumがないとのことで
yes

//インストール後以下のコマンドで起動
helm servecm --port=8879 --context-path=/charts \
--storage="local" \
> --storage-local-rootdir="/"

接続してみると以下の通り、うまくいったかな?
f:id:lawrence-twin:20200522125955p:plain

Chartの雛形を作成する

■作成コマンド

helm create echo

Deployment、Service, Ingress, のyamlをそれぞれ作成し
Chartをパッケージングする。
ここの章ではyamlの定義を変数化しておき個別の値はvalues.yamlを作成しておくことで、
パッケージングの処理の際に置換されるように作成される。
本番運用でもこちらの利用方法は一般的な気がしますね。

■パッケージングコマンド

helm package echo

書籍ではローカルリポジトリに追加されるようですが、
v3なのか追加されず。以下のコマンドで追加されないか試してみるもの、エラーが発生し進まず。
lawrence@Chocolate job % helm install local/echo ./echo-0.1.0.tgz
Error: parse error at (echo/templates/ingress.yaml:34): undefined variable "$ingresPath"

ここから先はまた明日対応予定。

Docker/K8S実践コンテナ開発入門@22日目

本日も続き、

ユーザ管理とRole-Based Acess Control(RBAC)

Kubernetsのユーザ概念

  • 認証ユーザ・・・クラスタ外からKubernetesを操作する。
  • ServiceAcount・・・Kuberntes内部で管理、PodがAPIを操作するためのユーザ

RBACを利用した権限制御のの実現の章はスキップ

手順的には

  1. ロール・紐付けリソースの作成
  2. 認証ユーザ・グループの作成・・・方式は様々(Service Acountトークン、静的トークンファイル、パスワードファイル、X509でのクライアント証明書、OpenID Connect)
  3. 作成した認証ユーザを利用

「kubectl config use-context 」で変更できそう。

ServiceAccountを利用すると、PodのKubernets APIへのアクセスをセキュアにすることができる。

Helm

  • デプロイ先に依存する設定値だけを定義し、それをもとにデプロイできる仕組みがHelm
  • Kubernetes chartsを管理するためのツール

書籍に載っている実践手順を試してみる。
まずコマンドラインのインストールだが、こちらからダウンロード可能
github.com

私の環境では、homebrewが入っているので以下コマンドでインストール

■コマンド

brew install kubernetes-helm

HelmはKurbernetesクラスタに対しての初期化処理が必要なため以下のコマンドを実行

■コマンド

helm init

しかし、エラーが発生
色々調べていたところ以下記事の通り実施ができない(というか不要)になっているようです。
qiita.com

Tillerというサーバアプリケーションがいらない子?になってしまっているようです。

■バージョン確認

heml versin

Helmの概念

  • Helmはクライアント(cli)とサーバ(Tiller)で構成される

とあるのですが、Tillerはv3になってからクビになっているのでサーバ部分がhelmが担っているのでしょうか?

リポジトリ

Helmリポジトリの種類

  • local・・・ローカルパッケージ
  • stable・・・安定したリポジトリ
  • incubator・・・

リポジトリ追加コマンド

helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/

リポジトリから利用できるcharは以下のコマンドで確認可能

■chart検索

helm search <repo or hub>

※書籍では「helm search」のみですが、v3ではできないようです。

Helmのインストール

実際に試してみる

■コマンド

helm install -f redmine.yaml --name redmine stable/redmine --version 4.0.0

しかし、以下のエラーでうまくいかず、、、
lawrence@Chocolate job % helm install -f redmine.yaml redmine stable/redmine --version 4.0.0
Error: failed to download "stable/redmine" (hint: running `helm repo update` may help)

続きは明日以降