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ログを確認してみます。
何も出ない、、、と思ったのですが
右上の出力範囲をいじれば出てくるようになりました。
ただ本来は、上部検索欄に「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
起動後は正常に起動したかを以下の通り接続して確認してみます。
「status red」となっており、うまくいっていないようです。
「docker-compose.yml」ないのvolumeマウント設定を削除してjvm.optionsの設定を無視して起動してみる。
うーん、うまくいくな。
色々悩んだところ、
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」という部分にログ情報のインデックスが作成されているようです。
「Crate」というボタンを押すことで、以下の通りログの内容も確認できました。
続きは明日以降行います。
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の修正方法が不明ですが、、、
明日以降はエラー対処またはFulentd、ElasticSearchを利用していきます。
HelmのV2とV3の差異
参考書に沿ってやっているが
参考書:V2
自分の環境:V3
のため色々難航している。
公式サイトでも以下の通り違いが出されている。
仕様変更点などは困ったらここを見ています。
今のところ自分が経験している違いは以下の通り
Tillerがない
V2ではTillerという概念があったが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
■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="/"
接続してみると以下の通り、うまくいったかな?
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を利用した権限制御のの実現の章はスキップ
手順的には
- ロール・紐付けリソースの作成
- 認証ユーザ・グループの作成・・・方式は様々(Service Acountトークン、静的トークンファイル、パスワードファイル、X509でのクライアント証明書、OpenID Connect)
- 作成した認証ユーザを利用
「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 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)
続きは明日以降