まえおき
Kubernetes を使い始めたのだが、公式のドキュメントが難解すぎたので目的別に整理した。
各ノードでコンテナを起動したい
Daemon Set を使う。
以下の例では、ホストの /var/log/myapp
ディレクトリに出力された myapp.log
ファイルを logstash
コンテナで監視する。簡略化のため Logstash はファイルの中身をそのまま出力している。通常は Filter Plugin を併用し Output Plugin で Elasticsearch に送る。
- 図
+-----------------------------------+
| node |
| +----------+ |
| | logstash | |
| | | |
| /var/log/myapp <-mount-*/log | |
| +----------+ |
+-----------------------------------+
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: logstash
spec:
template:
metadata:
labels:
app: daemon
spec:
volumes:
- name: log
hostPath:
path: /var/log/myapp
containers:
- name: logstash # ホストの /var/log/myapp/myapp.log を出力するだけのコンテナ
image: logstash
args:
- -e
- |
input {
file { path => '/log/myapp.log' }
}
output {
stdout { codec => rubydebug }
}
volumeMounts:
- name: log # ホストの /var/log/myapp ディレクトリに当たる
mountPath: /log
コンテナからコンテナに問い合わせたい
コンテナからコンテナに問い合わせたい(多対一の場合)
Service を使う。
Pod は Service に対応させられた Pod の名前解決ができることを利用する。
以下の例では logstash
コンテナが elasticsearch
コンテナに/log/myapp.log
パスにあるログを送信する。簡略化のため /log/myapp.log
には 30 秒おきに hello
と書き込むコンテナを立てている。通常は /log/myapp.log
パスにログを出力するようなアプリケーションを立てる。
Service を使うことで logstash
コンテナが elasticsearch
という名前で elasticsearch
コンテナに問い合わせられるようになっている。
+---------------+ +---------------+ +---------------+
| [ReplicaSet] | | [Service] | | [Pod] |
| +----------+ | | elasticsearch | | elasticsearch |
| | [Pod] | | | | | |
| | logstash *----+--*name resolution*----->*:9200/tcp |
| +----------+ | | +---------------+ +---------------+
| | [Pod] | | |
| | logstash *----+
| +----------+ | |
| | [Pod] | | |
| | logstash *----+
| +----------+ |
+---------------+
kind: Service
apiVersion: v1
metadata:
name: elasticsearch
spec:
selector:
app: elasticsearch
ports:
- port: 9200
targetPort: 9200
---
kind: Pod
apiVersion: v1
metadata:
name: elasticsearch
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: elasticsearch:2.4.1 # 5.0 だと起動に失敗したので前バージョン
ports:
- containerPort: 9200
---
kind: ReplicaSet
apiVersion: extensions/v1beta1
metadata:
name: logstash
spec:
replicas: 3
template:
metadata:
labels:
app: logstash
spec:
volumes:
- name: log
containers:
- name: logstash # /log/myapp.log のログを elasticsearch に送るだけのコンテナ
image: logstash:2.4.0-1 # Elasticsearch に合わせたバージョン
args:
- -e
- |
input {
file { path => '/log/myapp.log' }
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ['elasticsearch']
}
}
volumeMounts:
- name: log
mountPath: /log
- name: hello # /log/myapp.log に hello と30秒毎に書き込むだけのコンテナ
image: centos
args:
- bash
- -c
- |
while true; do
echo hello >> /log/myapp.log
sleep 30
done
volumeMounts:
- name: log
mountPath: /log
なお、Elasticsearch に Logstash から送信されたログを確認するためには、
kubectl run -it --rm centos --image centos
としてbash
を起動したコンテナの中で、
curl elasticsearch:9200/logstash-*/_search?pretty
と実行すればよい。コンテナはそのままexit
でbash
を終了すれば自動的に削除される。
コンテナからコンテナに問い合わせたい(一対一の場合)
Service を使ってもよいが Pod を使うと単純に書ける。
Pod の中の他のコンテナは localhost
で問い合わせられる。
以下の例では Elasticsearch と Kibana をセットで立てる。
kind: Pod
apiVersion: v1
metadata:
name: ek
labels:
app: ek
spec:
containers:
- name: elasticsearch
image: elasticsearch:2.4.1 # 5.0 だと起動に失敗したので前バージョン
- name: kibana
image: kibana:4.6.2 # Elasticsearch に合わせたバージョン
env:
- name: ELASTICSEARCH_URL
value: http://localhost:9200 # elasticsearch コンテナに繋がる
ports:
- containerPort: 5601
クラスタの外からコンテナにアクセスしたい
クラスタのノードが1台しかない場合
NodePort タイプのServiceを使う。
NodePort タイプはコンテナが起動したノードの
IPアドレスでアクセスできるようになる。
以下の例では、前節で作った Kibana に
http://(ノードのIPアドレス):30601
でアクセスできるようになる。
- もちろん、ファイアウォールやセキュリティグループなどが間にあれば
接続を許可する設定が必要になる。 - ちなみに、ポート番号が30601になっているのは、
ノードで使用可能なポート番号が
デフォルトでは30000~32767に設定されているためである。
kind: Service
apiVersion: v1
metadata:
name: ek-svc
spec:
ports:
- port: 5601
targetPort: 5601
nodePort: 30601
selector:
app: ek
type: NodePort
クラスタのノードが複数台ある場合
Kubernetes の外部にロードバランサを調達する。
Google Container Engine のようなクラウドサービスでは、
LoadBalancer タイプの Service を使うことで
ロードバランサの作成をサポートしている。
以下の例では、前節で作った Kibana に
http://{ロードバランサのIPアドレス}:5601
でアクセスできるようになる。
kind: Service
apiVersion: v1
metadata:
name: ek-lb
spec:
ports:
- port: 5601
targetPort: 5601
selector:
app: ek
type: LoadBalancer
コンテナの数を増やしたい
Replica Set や Job を使う。
Replica Set は継続的に実行されるようなコンテナを使用する。
Job は実行の完了を想定しているようなコンテナを使用する。
Replica Set
Replica Set は稼働中のコンテナが指定した数になるまで立て続ける。
デーモンのような、処理が終了しないことが想定されている場合に使う。
Job
Job は exit 0
で終了したコンテナの数が指定回数を満たすまで
コンテナを新規に立て続ける。
バッチのような、デーモンとは違って、
処理が終了することが想定されている場合に使う。
Dockerイメージをプルするときに認証したい
Secret を使う。
公式のドキュメント にその手順が書かれている通り、
まずは Secret を作成し、
それから Secret を使用してイメージのプルを行うように設定すればよい。
次のコマンドを使って Secret を作成できる。
kubectl create secret docker-registry
たとえば、
kubectl create secret docker-registry my-secret --docker-username=myname --docker-password=mypass --docker-email=myname@example.com
とすれば my-secret
という名前で Secret を作成できる。
Secret の中には Base64 エンコードされた上記の情報が含まれるようになるので、
取り扱いには十分に注意しなければならない。
次に Secret を使用するように設定する。
イメージをプルするときにデフォルトで上記の認証情報を使用したい場合は、
Service Account に Secret を設定する。
Service Account は Namespace ごとに作成されており、
Namespace に属するオブジェクトがデフォルトで使用する Service Account があるので、
そこに設定を追加する。
デフォルトの Namespace の デフォルト Service Account に設定する場合は、
kubectl edit sa default
とし、(sa は serviceaccount のエイリアス)
エディタが起動するので、
imagePullSecrets:
- name: my-secret
を末尾に追加し、保存してエディタを終了する。
Pod ごとに使用する Secret を分けたい場合は、
以下の例のように Pod に Secret を設定する。
kind: Pod
apiVersion: v1
metadata:
name: sample-foo
spec:
containers:
- name: sample-foo
image: httpd
imagePullSecrets:
- name: my-secret
コンテナに番号を付けて管理したい
Stateful Set を使う。
コンテナが自身の番号を知るには、ホスト名から切り出す。
ホスト名は {Stateful Set 名}-{番号}
となっている。