タイトルを削れなかった
ターゲット
- kube-aws使っててちょっとわかる(なのでawsとkubernetesも当然)
- prometheus使っててちょっとわかる(kubernetesで運用してるとなお好都合)
- etcdのメトリクス取りたい!(いなさそう)
目次
- etcdのインスタンスを検出する
- etcdのメトリクスを取得する
- その他つらつら
1. etcdのインスタンスを検出する
理屈
kube-awsにより作られたkubernetesクラスタは、etcdのinstanceがcontrollerから独立しており、kubernetesクラスタの外にある状態になっています(見た感じそうなってるからそのはず)。
通常、prometheusをkubernetesで使う場合は、service-discovery
のkubernetes_sd_config
を使って監視対象のリソースを探します。
が、上記の通りetcdのinstanceはkubernetesクラスタの外にあるためこれでは検出できません。
かと言ってクラスタを作った後にetcdのipを調べてprometheusのconfigのtargetsに書いていくなんてことはまっぴら御免です。
ですので、etcdのinstanceはec2_sd_config
を使って検出します。
何もしないとprometheusに設定したuser/roleから見える全てのインスタンスを検出してしまい、とても散らかるので必要なものだけに絞っていきます。
今回はtagにkube-aws:role: etcd
と、ちょうど良さそうなものがついていたのでこれを使います。
kube-awsの変更でこのtagがつかなくなる、なんてことがあるかもしれないので、自分でオリジナルのタグを付けるのもいいかもしれません。(cluster.yamlの記述でそういうのできたりするんですかね、よくわかってない)
ステージングのインスタンスも検出してしまう!なんて時は他にも自分の環境に応じて条件を加えます。
私の場合はvpcでの絞り込みも追加しました。
方法
prometheusのconfigにこんな感じのセクションを追加します
#scrape kube-aws etcd
- job_name: 'kube-aws-etcd'
ec2_sd_configs:
- region: ap-northeast-1
port: 2379 #etcdのポート
relabel_configs:
- source_labels: [__meta_ec2_tag_kube_aws_role]
regex: 'etcd'
action: keep
- source_labels: [__meta_ec2_vpc_id]
regex: 'vpc-1234abcd'
action: keep
2. etcdのメトリクスを取得する
理屈
etcdはデフォルトで/metircs
にprometheus用のメトリクスを出力しています。
なので通常であれば、検出したインスタンスの/metrics
にアクセスするだけです。
しかし今回はひとつ壁があって、アクセスするのにkeyやらcertやらが必要になっています。
(ここはドキュメントやコードを読まずにひたすら総当たりで調べたので何か間違ってたらすいません。とにかく取得はできますので…)
これはkube-awsでクラスタを作る際の、kube-aws render credentials
によって生み出される(だったような)
- credentials/etcd-client-key.pem
- credentials/etcd-client.pem
を使います。
これらはnodeを作る際、/etc/kubernetes/ssl/
に配置されるようで、それならprometheusコンテナでvolumeマウントして使えばいい
…と思ったのですが、rootにしかread権限がついてなかったので諦めて、普通にsecretを作りました。
prometheusをrootで起動してる人はマウントで使えるかもしれません。
方法
まずはsecretですが、上記のpemを例によってbase64エンコードして作ります
apiVersion: v1
kind: Secret
metadata:
name: etcd-secret
namespace: default
type: Opaque
data:
etcd-client.pem: "kekkounagaidehogehogehogehoge"
etcd-client-key.pem: "koitsumonagaidehogehogehogehoge"
私の場合はこんな感じのスクリプトでsecretを作ってます
FILE="secret.yaml"
cat << EOF >>${FILE}
apiVersion: v1
kind: Secret
metadata:
name: etcd-secret
namespace: default
type: Opaque
data:
EOF
echo ' etcd-client.pem: "'$(/bin/cat credentials/etcd-client.pem | base64)\" >>${FILE}
echo ' etcd-client-key.pem: "'$(/bin/cat credentials/etcd-client-key.pem | base64)\" >>${FILE}
configは1.のものにちょっと手を加えて
#scrape kube-aws etcd
- job_name: 'kube-aws-etcd'
scheme: https
tls_config:
key_file: /mnt/ssl/etcd-client-key.pem #deploymentでmountするpathとsecretのdataのname
cert_file: /mnt/ssl/etcd-client.pem #上に同じ
insecure_skip_verify: true
ec2_sd_configs:
- region: ap-northeast-1
port: 2379 #etcdのポート
relabel_configs:
- source_labels: [__meta_ec2_tag_kube_aws_role]
regex: 'etcd'
action: keep
- source_labels: [__meta_ec2_vpc_id]
regex: 'vpc-1234abcd'
action: keep
- action: labelmap
regex: __meta_ec2_(.+)
こんな感じのものを追加します。
deploymentは今回に関係ある部分を抜粋するとこんな感じ
spec:
template:
spec:
containers:
- name: prometheus
image: prom/prometheus:latest
volumeMounts:
- name: etcd-ssl-volume
mountPath: /mnt/ssl/ #configと揃っていればなんでも
- name: secrets-volume
volumes:
- name: etcd-ssl-volume
secret:
secretName: etcd-secret
defaultMode: 420
Pod派の人やprometheusをkubernetesで運用してない人はよしなにやりましょう。
要は、ec2_sd_config
でインスタンスを探して、etcd-client.pem
とetcd-client-key.pem
を使って:2379/metrics
にアクセスすればいいのです。
問題なければこんな感じに通るはずです。(label整理してない)
3.その他つらつら
これで取れるのはあくまでetcdのメトリクスであって、etcdインスタンスのメトリクスは取れません。
ちょっとしたcpuやmemoryのメトリクスならprocess_cpu_seconds_total
やgo_memstats_*
がありますが、足りないならnode-exporter等を配置する必要があります。
しかしこれは現状etcdインスンタンスが立った後に直接ログインしてインストールして公開して必要ならアクセス制限して…などの作業が必要になるため現実的ではありません(し、実際に可能かどうかも私にはわかりません)。
最初に述べたとおりkubernetesクラスタの外なので当然daemonsetも届きません。
なのでcloudwatch_exporterでcloudwatchのmetricsをprometheusに取り込むか、grafanaを使っているならcloudwatchを直接データソースにしてしまうなどが現実的かと思います。
(私は先述の「ちょっとしたcpuやmemoryのメトリクス」で間に合わせてます。)
kube-awsでクラスタを作る時にetcdインスタンスにnode-exporterが入ったりしてくれれば…
kube-awsはあまりしっかり触ってないので何か間違っていたらすみません。