SplunkでKubernetesのログとメトリクスを監視してみよう

Kubernetesで稼働するコンテナ環境をSplunkで可視化してみました。
まずはデータの取り込み方と記事書いてみます。

シリーズ化して可視化やモニタリングについても記事書きたいなあ

-- 2018/07/09 追記 --
可視化とモニタリングについて記事書きました
[SplunkでKubernetesクラスター環境のログとメトリクスを可視化してモニタリング](https://qiita.com/kikeyama/items/6503e5d2a843c7faac52)

# はじめに
Splunkにインデックスされるデータはざっくり言うと下記4種類です。

1. CPUやメモリ等のリソース使用状況メトリクス
2. NodeやPod、Service、Namespace等のオブジェクト情報
3. Kubeletやプロキシ、APIサーバーのログ
4. コンテナのログ

# 環境準備
続いて環境準備デス。

## Splunk環境
OS: Amazon Linux on EC2
Splunk Enterprise 7.1.1

使うAppは以下
**Splunk Add-on for Kubernetes** v1.0.0
https://splunkbase.splunk.com/app/3976/
k8s関連のソースタイプとか、最小限の設定だけが入ってるみたい。
ダッシュボードは含まれていないから自分で作ることにします。

**Splunk Analysis Workspace** v0.18.4 beta
https://splunkbase.splunk.com/app/3976/
まだβ版ですがメトリクスのグラフをGUI簡単操作で手早く作れます。

あと、これも
**Splunk Connect for Kubernetes**
https://github.com/splunk/splunk-connect-for-kubernetes
KubeletやKube-Proxyのログ、コンテナのログ、PodやNode等のメトリクスを自動的に取得してSplunkにインデックスしてくれる代物です。
YAMLで設定作って `kubectl` 使ってKubernetesクラスター環境にデプロイします。

Connectorはデータ取得用のPodを使ってfluentd経由でSplunkのHTTP Event CollectorエンドポイントにPOSTします。

## Kubernetes環境
今回は検証環境ということで、AWSに [HeptioのCloudFormationテンプレート](https://aws.amazon.com/quickstart/architecture/heptio-kubernetes/) を使って構築しました。

OS: Ubuntu 16.04.4 LTS
Kubelet v1.10.3

Master x 1 / Node x 2 という構成で作りました。

# Splunk設定
Splunkの設定自体はカンタン

1. Appをインストールする
2. インデックスを作成
3. HECを有効にする

これだけです。

## SpkunkにAppをインストール
[**Splunk Add-on for Kubernetes**](https://splunkbase.splunk.com/app/3976/) と [**Splunk Analysis Workspace**](https://splunkbase.splunk.com/app/3976/) をインストールしましょう。

## インデックス作成
ログ系のインデックスとメトリクスのインデックスを作ります。
メトリクスは従来のログ用インデックスとは別に保存する必要があるため、別々に作ります。

ちなみに、インデックスはクラスター単位で作成するのが良いでしょう。

Splunk画面から 設定 ＞ インデックス に移動
新規インデックスを作成します。

ログ用は `k8s_events` という名前で新規作成
データタイプは `イベント` を選択
<img width="785" alt="Screen Shot 2018-06-22 4.04.42 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/97959e83-ed7c-6705-0104-9ff1c7093c8f.png">

メトリクス用は `k8s_metrics` という名前で新規作成
データタイプは `メトリック` を選択
<img width="784" alt="Screen Shot 2018-06-22 4.05.48 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/5cd1935c-fbef-8274-9b70-958699ebeaf4.png">



## HEC有効化
続いてHTTP Event Collectorを有効化します。
設定 ＞ データ入力から ＞ HTTPイベントコレクタ に移動して新規トークン作成
<img width="966" alt="Screen Shot 2018-06-22 4.09.02 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/53c89d7c-e3d9-1b99-3aaa-7cef33710f75.png">

一つのHECトークンでログ、メトリクス両方を受け取ります。
なので、作るトークンは一つだけ。

名前は適当に、何でもいいです。
<img width="632" alt="Screen Shot 2018-06-22 4.12.25 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/16b312b8-8783-33ab-3e9a-1ef0e75e6807.png">

次へ行って、ソースタイプやインデックスの指定

ソースタイプは自動のままでおk
※ 後で設定する Connector の方で適切にソースタイプ振り分けてくれます。
<img width="777" alt="Screen Shot 2018-06-22 4.12.44 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/6cfaaa16-f847-08cd-3632-41f9f224ad36.png">

インデックスは先ほど作った `k8s_events` と `k8s_metrics` を指定
<img width="850" alt="Screen Shot 2018-06-22 4.14.49 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/cd30e4f8-029a-a7a5-c22e-9eb3084a225f.png">

これでSplunk側の設定は完了

# Kubernetes設定

## Kubernetesクラスター作成
AWSにHeptio使って入れたので、テンプレートにしたがってCloudFormationでクラスター作成（詳細は割愛）

## ローカル準備
手元のローカル端末（Mac）に `kubectl` と `helm` をインストールします。
ローカルからsshで入ることなくKubernetes操作ができるようになります。

### kubectl インストール
まずは `brew` で kubectl インストール（参考：[Kubernetesドキュメント](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-with-homebrew-on-macos)）

```bash
brew install kubectl
```

続いて、先のステップで作成したHeptioのKuberntesから `kubeconfig` をダウンロード
任意のパスにKubernetes用フォルダ作って、そこに入れよう

```bash
SSH_KEY="<path/to/varMyKey.pem>"; scp -i $SSH_KEY -o ProxyCommand="ssh -i \"${SSH_KEY}\" ubuntu@<BastionHostPublicIP> nc %h %p" ubuntu@<MasterPrivateIP>:~/kubeconfig ./kubeconfig
```

DLした `kubeconfig` を環境変数に設定

```bash
export KUBECONFIG=$(pwd)/kubeconfig
```

試しにNode取得
コマンド実行はkubeconfig置いてあるディレクトリで実行すべし

```bash
kubectl get nodes
```

### helm インストール
`helm` はKubernetes上でのパッケージ管理で、yumのように使えるものです。

`brew` で helm インストール（参考：[Helmドキュメント](https://docs.helm.sh/using_helm/#from-homebrew-macos)）

```bash
brew install kubernetes-helm
```

Helmバージョン確認

```bash
$ helm version
Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}
```

バージョンは後で使うのでメモしておきましょう。

## Splunk Connect for Kubernetes設定
いよいよ本題です。

### Tillerセットアップ
KubernetesはRBACによるアクセス制御のため、Helmを使えるようにTillerを作成します。

**Splunk Connect for Kubernetes** を入れるためのNamespaceを作成

```bash
kubectl create ns splunk-connect-k8s
```

続いてTillerのYAMLはコチラ

```yaml:tiller.yaml
# https://docs.helm.sh/using_helm/#example-service-account-with-cluster-admin-role

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: splunk-connect-k8s
  #namespace: kube-system
  #namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
  #namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: splunk-connect-k8s
    #namespace: kube-system
    #namespace: default
```

Tiller作ってみましょう

```bash
kubectl create -f tiller.yaml
```

### Helm初期化
`helm init` で初期設定

```bash
$ helm init --service-account tiller --tiller-namespace splunk-connect-k8s --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.9.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
$HELM_HOME has been configured at /Users/splunk/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!
```

※ `2.9.1` の部分はお使いのHelmバージョンに置き換えてください。

`tiller` Service Accountが作成されたことを確認

```bash
$ kubectl get sa -n splunk-connect-k8s
NAME      SECRETS   AGE
default   1         1d
tiller    1         1d
```

### Connect for Kubernetes設定＆インストール
Splunkの公開GitHubにChartのテンプレートと変数設定のサンプルが入ってます。
https://github.com/splunk/splunk-connect-for-kubernetes/tree/master/helm-chart

**splunk-kubernetes-logging** はコンテナやk8s関連のログ
**splunk-kubernetes-metrics** はNodeやPodのメトリクス
**splunk-kubernetes-objects** はk8s関連オブジェクトの詳細情報

こちらのYAMLを使って **Splunk Connect for Kubernetes** をインストールします。

```yaml:my_values.yaml
#global settings
global:
  logLevel: info
  splunk:
    hec:
      protocol: https
      insecureSSL: false
      host: splunk_hec_endpoint_hostname
      token: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

#local config for logging chart
splunk-kubernetes-logging:
  journalLogPath: /run/log/journal
  splunk:
    hec:
      indexName: k8s_events

#local config for objects chart      
splunk-kubernetes-objects:
  rbac:
    create: true
  serviceAccount:
    create: true
    name: splunk-kubernetes-objects
  kubernetes:
    insecureSSL: true
  objects:
    core:
      v1:
        - name: pods
          #interval: 30
        - name: namespaces
          #interval: 30
        - name: nodes
          #interval: 60
        - name: services
          #interval: 30
        - name: config_maps
          #interval: 30
        - name: secrets
          #interval: 30
        #- name: volumes
          #interval: 30
        - name: persistent_volumes
          #interval: 30
        - name: service_accounts
          #interval: 30
        - name: persistent_volume_claims
          #interval: 30
        - name: resource_quotas
          #interval: 30
        - name: component_statuses
          #interval: 30
        - name: events
          mode: watch
    apps:
      v1:
        - name: deployments
          #interval: 30
        - name: daemon_sets
          #interval: 30
        - name: replica_sets
          #interval: 30
        - name: stateful_sets
          #interval: 30
  splunk:
    hec:
      indexName: k8s_events    

#local config for metrics chart
splunk-kubernetes-metrics:
  rbac:
    create: true
  serviceAccount:
    create: true
    name: splunk-kubernetes-metrics
  splunk:
    hec:
      indexName: k8s_metrics
```



`splunk_hec_endpoint_hostname` はSplunkでHECを受けるホスト名（もしくはFQDNやIPアドレス）
`XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` は先のステップで作成したHECトークンを指定

`indexName` には作成したインデックス名を指定
`splunk-kubernetes-logging` と `splunk-kubernetes-objects` はログ用のインデックス （ここでは `k8s_events`）
-`splunk-kubernetes-metrics` はメトリクス用のインデックス （ここでは `k8s_metrics`）


`helm install` で変数設定したYAMLを使って **Splunk Connect for Kubernetes** をインストール

```bash
$ helm install --name kikeyama -f my_values.yaml --namespace splunk-connect-k8s --tiller-namespace splunk-connect-k8s https://github.com/splunk/splunk-connect-for-kubernetes/releases/download/v1.0.0/splunk-connect-for-kubernetes-1.0.0.tgz
NAME:   kikeyama
LAST DEPLOYED: Tue Jun 19 23:08:56 2018
NAMESPACE: splunk-connect-k8s
STATUS: DEPLOYED

RESOURCES:
==> v1/ServiceAccount
NAME                       SECRETS  AGE
splunk-kubernetes-metrics  1        4s
splunk-kubernetes-objects  1        4s

==> v1/ClusterRole
NAME                                AGE
kikeyama-splunk-kubernetes-objects  4s

==> v1/ClusterRoleBinding
NAME                                AGE
kikeyama-splunk-kubernetes-metrics  4s
kikeyama-splunk-kubernetes-objects  4s

==> v1beta1/DaemonSet
NAME                                DESIRED  CURRENT  READY  UP-TO-DATE  AVAILABLE  NODE SELECTOR  AGE
kikeyama-splunk-kubernetes-logging  3        3        0      3           0          <none>         4s

==> v1beta1/Deployment
NAME                                DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
kikeyama-splunk-kubernetes-metrics  1        1        1           0          4s
kikeyama-splunk-kubernetes-objects  1        1        1           0          4s

==> v1/Pod(related)
NAME                                                 READY  STATUS             RESTARTS  AGE
kikeyama-splunk-kubernetes-logging-bl8q5             0/1    ContainerCreating  0         4s
kikeyama-splunk-kubernetes-logging-vqls4             0/1    ContainerCreating  0         4s
kikeyama-splunk-kubernetes-logging-xt7b4             0/1    ContainerCreating  0         4s
kikeyama-splunk-kubernetes-metrics-8695547795-kj62z  0/2    ContainerCreating  0         4s
kikeyama-splunk-kubernetes-objects-7b89c55dc8-7pnht  0/1    ContainerCreating  0         4s

==> v1/Secret
NAME                                TYPE    DATA  AGE
kikeyama-splunk-kubernetes-logging  Opaque  1     4s
kikeyama-splunk-kubernetes-metrics  Opaque  1     4s
kikeyama-splunk-kubernetes-objects  Opaque  1     4s

==> v1/ConfigMap
NAME                                DATA  AGE
kikeyama-splunk-kubernetes-logging  7     4s
kikeyama-splunk-kubernetes-metrics  1     4s
kikeyama-splunk-kubernetes-objects  1     4s


NOTES:


███████╗██████╗ ██╗     ██╗   ██╗███╗   ██╗██╗  ██╗██╗    
██╔════╝██╔══██╗██║     ██║   ██║████╗  ██║██║ ██╔╝╚██╗   
███████╗██████╔╝██║     ██║   ██║██╔██╗ ██║█████╔╝  ╚██╗  
╚════██║██╔═══╝ ██║     ██║   ██║██║╚██╗██║██╔═██╗  ██╔╝  
███████║██║     ███████╗╚██████╔╝██║ ╚████║██║  ██╗██╔╝
╚══════╝╚═╝     ╚══════╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝  ╚═╝╚═╝

Listen to your data.

Splunk Connect for Kubernetes is spinning up in your cluster.
After a few minutes, you should see data being indexed in your Splunk.

If you get stuck, we're here to help.
Look for answers here: http://docs.splunk.com
```

`kikeyama` の部分はご自身の好きな名前に置き換えてください。
これがPodの名前のPrefixになります。

###確認
以下の通り、Splunk Connect for KubernetesのPodが作成されています。

```bash
$ kubectl get pods -n splunk-connect-k8s
NAME                                                  READY     STATUS    RESTARTS   AGE
kikeyama-splunk-kubernetes-logging-bl8q5              1/1       Running   0          2d
kikeyama-splunk-kubernetes-logging-vqls4              1/1       Running   0          2d
kikeyama-splunk-kubernetes-logging-xt7b4              1/1       Running   0          2d
kikeyama-splunk-kubernetes-metrics-8695547795-kj62z   2/2       Running   0          2d
kikeyama-splunk-kubernetes-objects-7b89c55dc8-7pnht   1/1       Running   0          2d
tiller-deploy-7f9d844969-wns69                        1/1       Running   0          2d
```

# Splunk確認
Splunkにログインして確認してみましょう。

## ログ確認
以下のSPLでログが入っているか見てみましょう。

```
| tstats count latest(_time) as latest_time where index=k8s_events by index sourcetype 
| eval latest_time = strftime(latest_time, "%F %T")
```

<img width="1250" alt="Screen Shot 2018-06-22 5.50.37 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/4f2b0cdd-7ae4-790f-12e7-d9fa6655dfed.png">
OKですね。

## メトリクス確認
Splunk Analysis Workspace を入れると、サーチの画面上部に **メトリック** というメニューが出てきます。
<img width="487" alt="Screen Shot 2018-06-22 5.54.03 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/1595966b-e8aa-d316-decd-2957d1767168.png">

左側のナビゲーションから各種メトリックを選択できるので、ポチポチやってグラフ作成
<img width="1252" alt="kubernetes_metrics_by_pod.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/78b4883e-2f5e-1a3b-f66c-9012d99b0ed2.png">

# 最後に
これでデータは入ってきますが、ダッシュボード等の可視化はAdd-onに用意されていないので、自作する必要があります。
また、 **Splunk Add-on for Kubernetes** はSplunk製なのでサポートされるっぽいですが、 **Splunk Connect for Kubernetes** はGitHubに公開されているのみでコミュニティサポートになるようです。

ちなみに、自分でセットアップしてたときは `helm install` 実行時にRBACでひっかかったのか、何回もpermission errorが出て苦労しました。

```bash
$ helm install --name kikeyama --namespace splunk-connect-k8s -f my_values.yaml https://github.com/splunk/splunk-connect-for-kubernetes/releases/download/v1.0.0/splunk-connect-for-kubernetes-1.0.0.tgz
Error: release kikeyama failed: namespaces "splunk-connect-k8s" is forbidden: User "system:serviceaccount:kube-system:default" cannot get namespaces in the namespace "splunk-connect-k8s"
```

[こちら](https://github.com/kubernetes/helm/issues/3130) を参考に `helm init` しなおしたら上手くいきました。

他にもいろいろ手間取りましたが、上記手順でいけるはずです。 カンタンでしょ？

# おまけ
Kubernetesの状況をモニタリングするダッシュボード作ってみました。
<img width="1252" alt="kubernetes_overview_20180622.png" src="https://qiita-image-store.s3.amazonaws.com/0/174837/d2ca40ac-7e4b-14bd-9a6c-7258962f629d.png">

これについてはまた後日別の記事で。

Nginx Ingress入れてログをSplunkに取り込んでみたので、その記事も後日書きます（たぶん）