kubernetes
prometheus
kube-aws

kube-awsで作ったクラスタのetcdをprometheusのservice-discoveryで検出してメトリクスを取る

タイトルを削れなかった


ターゲット


  • kube-aws使っててちょっとわかる(なのでawsとkubernetesも当然)

  • prometheus使っててちょっとわかる(kubernetesで運用してるとなお好都合)

  • etcdのメトリクス取りたい!(いなさそう)


目次


  1. etcdのインスタンスを検出する

  2. etcdのメトリクスを取得する

  3. その他つらつら


1. etcdのインスタンスを検出する


理屈

kube-awsにより作られたkubernetesクラスタは、etcdのinstanceがcontrollerから独立しており、kubernetesクラスタの外にある状態になっています(見た感じそうなってるからそのはず)。

通常、prometheusをkubernetesで使う場合は、service-discoverykubernetes_sd_configを使って監視対象のリソースを探します。

が、上記の通りetcdのinstanceはkubernetesクラスタの外にあるためこれでは検出できません。

かと言ってクラスタを作った後にetcdのipを調べてprometheusのconfigのtargetsに書いていくなんてことはまっぴら御免です。

ですので、etcdのinstanceはec2_sd_configを使って検出します。

何もしないとprometheusに設定したuser/roleから見える全てのインスタンスを検出してしまい、とても散らかるので必要なものだけに絞っていきます。

今回はtagにkube-aws:role: etcdと、ちょうど良さそうなものがついていたのでこれを使います。

aaa.png

kube-awsの変更でこのtagがつかなくなる、なんてことがあるかもしれないので、自分でオリジナルのタグを付けるのもいいかもしれません。(cluster.yamlの記述でそういうのできたりするんですかね、よくわかってない)

ステージングのインスタンスも検出してしまう!なんて時は他にも自分の環境に応じて条件を加えます。

私の場合はvpcでの絞り込みも追加しました。


方法

prometheusのconfigにこんな感じのセクションを追加します


configmap.yaml

#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エンコードして作ります


secret.yaml

apiVersion: v1

kind: Secret
metadata:
name: etcd-secret
namespace: default
type: Opaque
data:
etcd-client.pem: "kekkounagaidehogehogehogehoge"
etcd-client-key.pem: "koitsumonagaidehogehogehogehoge"

私の場合はこんな感じのスクリプトでsecretを作ってます


make_secret.sh

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.のものにちょっと手を加えて


configmap.yaml

#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は今回に関係ある部分を抜粋するとこんな感じ


deployment.yaml

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.pemetcd-client-key.pemを使って:2379/metricsにアクセスすればいいのです。

問題なければこんな感じに通るはずです。(label整理してない)

bbb.png

grafanaでdashboardにすればそれっぽい

ccc.jpg


3.その他つらつら

これで取れるのはあくまでetcdのメトリクスであって、etcdインスタンスのメトリクスは取れません。

ちょっとしたcpuやmemoryのメトリクスならprocess_cpu_seconds_totalgo_memstats_*がありますが、足りないならnode-exporter等を配置する必要があります。

しかしこれは現状etcdインスンタンスが立った後に直接ログインしてインストールして公開して必要ならアクセス制限して…などの作業が必要になるため現実的ではありません(し、実際に可能かどうかも私にはわかりません)。

最初に述べたとおりkubernetesクラスタの外なので当然daemonsetも届きません。

なのでcloudwatch_exporterでcloudwatchのmetricsをprometheusに取り込むか、grafanaを使っているならcloudwatchを直接データソースにしてしまうなどが現実的かと思います。

(私は先述の「ちょっとしたcpuやmemoryのメトリクス」で間に合わせてます。)

kube-awsでクラスタを作る時にetcdインスタンスにnode-exporterが入ったりしてくれれば…

kube-awsはあまりしっかり触ってないので何か間違っていたらすみません。