概要
Kubernetesでは、登録してあるNodeでPodが実行されます。
Podは、Kubernetesの用語で稼働するコンテナをまとめたもので、コンテナがひとつの場合もあれば複数の場合もあります。
そのため、Kubernetesの監視ではそのNodeを監視することになります。
ここでは、Prometheusを使ってNodeのメトリクスを監視する方法について紹介します。
環境
- Kubernetes 1.8
方法
KubernetesのPodとしてPrometheusを実行すると、稼働しているexporterのPodを、設定にもよりますがかなり簡単に判別して情報を取得することができます。
なので、まず最初に全てのNodeでひとつずつexporterとして、node_exporterのPodを稼働させ、次に設定を加えたPrometheusのPodを稼働させます。
ちなみに、コンテナとしてnode_exporterを使うのにNodeのメトリクスを取得できることに疑問を感じるかもしれませんが、DockerのコンテナではホストとCPUやメモリを共有しているので、コンテナからホストのメトリクスを取得することができます。
node_exporterの起動
全てのNodeでひとつずつPodを起動するには、DaemonSetを使用します。
DaemonSetを使用するyamlファイルは次のものになります。
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: node-exporter
spec:
template:
metadata:
labels:
app: node-exporter
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9100'
prometheus.io/path: /metrics
spec:
containers:
- name: node-exporter
image: prom/node-exporter:latest
imagePullPolicy: Always
ports:
- containerPort: 9100
hostNetwork: true
hostPID: true
nameやappの値などは適当に変更してください。
このyamlの内容をnode-exporter.yml
などの名前で保存して次のコマンドを実行し、node_exporterを稼働させます。
kubectl create -f node-exporter.yml
Prometheusの起動
データの永続化
Prometheusで収集した情報は、永続化させてPodを削除したときや作り直したときに、消去されないようにするべきです。
そこで、まず最初にストレージを確保するために、PersistentVolumeとPersistentVolumeClaimを作成します。
ここでは、ストレージをnfsとして確保します。もし、クラウドサービスなどの使っていてそのクラウドサービスのストレージを使うという場合は、適当なもので設定を置き換えてください。
では、PersistentVolumeを作成するために次のyamlを使います。
apiVersion: v1
kind: PersistentVolume
metadata:
name: prometheus-pv
labels:
name: prometheus-pv
spec:
capacity:
storage: "5Gi"
accessModes:
- ReadWriteMany
nfs:
server: *****
path: /***
nfsのserverやpathの値などの情報は適当に変えてください。
yamlの内容をprometheus-pv.yml
などのファイル名で保存します。
次にPersistentVolumeClaimを用意します。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: prometheus-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: "5Gi"
selector:
matchLabels:
name: prometheus-pv
yamlの内容をprometheus-pvc.yml
などのファイル名で保存します。
最後に、yamlを元に作成します。
kubectl create -f promethus-pv.yml
kubectl create -f prometheus-pvc.yml
設定ファイル
次に、Prometheusの設定ファイルを用意します。
KubernetesのPodとして動かすための設定があるため、設定は結構長いものとなります。
設定は、ConfigMapとして作成しそれをPrometheusでマウントします。
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'kubernetes-nodes'
tls_config:
insecure_skip_verify: true
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
insecure_skip_verify: true
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
- job_name: 'kubernetes-services'
metrics_path: /probe
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: service
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
action: keep
regex: true
- source_labels: [__address__]
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
target_label: kubernetes_name
- job_name: 'kubernetes-ingresses'
metrics_path: /probe
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: ingress
relabel_configs:
- source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
action: keep
regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
ほとんどがKubernetesのNodeで動いているPodを調べるための設定です。
このyamlをprometheus-configmap.yml
などで保存して、次のコマンドでConfigMapを作成します。
kubectl create -f prometheus-configmap.yml
起動
やっとPrometheusを起動するための準備が終わりました。
Prometheusの起動は、Deploymentを使います。
yamlは次のようになります。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: prometheus
labels:
app: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9090'
prometheus.io/path: /metrics
spec:
containers:
- image: prom/prometheus
name: prometheus
args: [ "--storage.tsdb.path=/prometheus-data", "--config.file=/etc/prometheus/prometheus.yml", "--storage.tsdb.no-lockfile" ]
volumeMounts:
- name: config
mountPath: /etc/prometheus
- name: prometheus-persistent-storage
mountPath: /prometheus-data
volumes:
- name: config
configMap:
name: prometheus
- name: prometheus-persistent-storage
persistentVolumeClaim:
claimName: prometheus-pvc
yamlをprometheus-deployment.yml
などの名前で保存し次のコマンドでprometheusを起動します。
kubectl create -f prometheus-deployment.yml
Serviceの用意
Prometheusを起動しただけでもいいのですが、KibanaやGrafanaといったものと連携など、外部からアクセスするにはServiceを用意する必要があります。
ここでは、Kubernetes内で公開するためのServiceのyamlを載せておきます。
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus-service
name: prometheus-service
spec:
type: ClusterIP
ports:
- name: prometheus
port: 9090
targetPort: 9090
protocol: TCP
selector:
app: prometheus
まとめ
実際にやってみて、Prometheusで収集した情報を永続化させるための設定が非常に大変でした。
誰かの参考になれば幸いです。