[Kubernetes]Redisを使用したPHPのゲストブックアプリケーションのデプロイ

#はじめに
KubernetesのマニュアルにはTutorialとしていくつか例が載っています。今回はその中で以下の例を実際にやってみたいと思います。

[例: Redisを使用したPHPのゲストブックアプリケーションのデプロイ](https://kubernetes.io/ja/docs/tutorials/stateless-application/guestbook/)
[例: PHP / Redisを使用したゲストブックの例にロギングとメトリクスを追加する](https://kubernetes.io/ja/docs/tutorials/stateless-application/guestbook-logs-metrics-with-elk/)

#ゲストブックアプリケーションのアーキテクチャー

>このチュートリアルでは、KubernetesとDockerを使用した、シンプルなマルチティアのウェブアプリケーションのビルドとデプロイの方法を紹介します。この例は、以下のコンポーネントから構成されています。
>
>- ゲストブックのエントリーを保存するための、シングルインスタンスのRedisマスター
>- 読み込みデータ配信用の、複数のレプリケーションされたRedisインスタンス
>- 複数のウェブフロントエンドのインスタンス

これから作るゲストブックアプリケーションのアーキテクチャーは上記のように書かれているのですが、図にすると以下のようになります。（私の理解です）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/1690749b-2f72-5620-3ec2-19f41759fb2f.png)

- redis master
- redis slave
- frontend

の順に作っていきます。

##Redisマスターのデプロイ
###Pod
ゲストブックアプリケーションでは、データを保存するためにRedisを使用します。ゲストブックはRedisのマスターインスタンスにデータを書き込みます。

以下のマニフェストをapplyします。Replica数1のPodをDeploymentでデプロイします。

```redis-master-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-master
  labels:
    app: redis
spec:
  selector:
    matchLabels:
      app: redis
      role: master
      tier: backend
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
        role: master
        tier: backend
    spec:
      containers:
      - name: master
        image: k8s.gcr.io/redis:e2e
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379
```
```
$ kubectl apply -f redis-master-deployment.yaml
deployment.apps/redis-master created
$ kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
redis-master-6b54579d85-l8hsn   1/1     Running   0          80s
```

logを確認すると、redisのロゴがアスキーアートで出てますね。

```
$ kubectl logs redis-master-6b54579d85-l8hsn
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 2.8.19 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in stand alone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 1
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

[1] 23 Aug 12:56:53.934 # Server started, Redis version 2.8.19
[1] 23 Aug 12:56:53.935 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
[1] 23 Aug 12:56:53.935 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
[1] 23 Aug 12:56:53.935 * The server is now ready to accept connections on port 6379
```

###Service
Redisマスターへの通信を制御するためにServiceが必要になります。ここではクラスタ内部のみの通信になりますので、ClusterIPをデプロイします。


```redis-master-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels:
    app: redis
    role: master
    tier: backend
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
    role: master
    tier: backend
```
```
$ kubectl apply -f redis-master-service.yaml
service/redis-master created
$ kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP    31d
redis-master   ClusterIP   10.101.227.29   <none>        6379/TCP   10s
```

##Redisスレーブのデプロイ
###Pod
ゲストブックアプリケーションでは、スレーブインスタンスからデータを読み込みます。Redisを理解していないのですが、マスターからスレーブにデータはレプリケーションされてるんでしょうね。きっと。

Replica数2のPodをDeploymentでデプロイします。

```redis-slave-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-slave
  labels:
    app: redis
spec:
  selector:
    matchLabels:
      app: redis
      role: slave
      tier: backend
  replicas: 2
  template:
    metadata:
      labels:
        app: redis
        role: slave
        tier: backend
    spec:
      containers:
      - name: slave
        image: gcr.io/google_samples/gb-redisslave:v3
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 6379
```
```
$ kubectl apply -f redis-slave-deployment.yaml
deployment.apps/redis-slave created
$ kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
redis-master-6b54579d85-l8hsn   1/1     Running   0          7m10s
redis-slave-799788557c-599w2    1/1     Running   0          31s
redis-slave-799788557c-f2lc6    1/1     Running   0          32s
```

###Service
マスターと同様に、スレーブ用にClusterIPをデプロイします。

```redis-slave-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  labels:
    app: redis
    role: slave
    tier: backend
spec:
  ports:
  - port: 6379
  selector:
    app: redis
    role: slave
    tier: backend
```

```
$ kubectl apply -f redis-slave-service.yaml
service/redis-slave created
$ kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP    31d
redis-master   ClusterIP   10.101.227.29   <none>        6379/TCP   4m59s
redis-slave    ClusterIP   10.109.67.11    <none>        6379/TCP   9s
```

##フロントエンド
ゲストブックアプリケーションには、HTTPリクエストをサーブするPHPで書かれたウェブフロントエンドがあります。このアプリケーションは、書き込みリクエストに対してはredis-master Serviceに、読み込みリクエストに対してはredis-slave Serviceに接続するように設定されています。

###Pod

Replica数3のPodをDeploymentでデプロイします。

```frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: guestbook
spec:
  selector:
    matchLabels:
      app: guestbook
      tier: frontend
  replicas: 3
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google-samples/gb-frontend:v4
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 80
```
```
$ kubectl apply -f frontend-deployment.yaml
deployment.apps/frontend created
$ kubectl get pods -l app=guestbook -l tier=frontend
NAME                        READY   STATUS    RESTARTS   AGE
frontend-56fc5b6b47-fx4gv   1/1     Running   0          3m3s
frontend-56fc5b6b47-qblhv   1/1     Running   0          3m3s
frontend-56fc5b6b47-qlph7   1/1     Running   0          3m3s
```

###Service

外部にゲストブックアプリケーションを公開するために、ここではLoadBalancerをデプロイします。

```frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: guestbook
    tier: frontend
```
```
$ kubectl apply -f frontend-service.yaml
service/frontend created
$ kubectl get svc
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
frontend       LoadBalancer   10.99.203.0     10.20.30.150   80:31257/TCP   4s
kubernetes     ClusterIP      10.96.0.1       <none>         443/TCP        31d
redis-master   ClusterIP      10.101.227.29   <none>         6379/TCP       16m
redis-slave    ClusterIP      10.109.67.11    <none>         6379/TCP       11m
```

##動作確認
外部からブラウザで接続し、ゲストブックアプリケーションの動作を確認します。
以下の画像のように接続と読み書きができるこが確認できます。

![2020-08-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/966cc9cb-250a-c338-39b9-79d5e829179f.png)

構築自体は公開されているマニフェストをapplyするだけですので簡単にできますが、それぞれの役割を確認しながら図に書くことでマイクロサービスの基本を学ぶことができました。

---

#ロギングとメトリクスの追加
続けてもう一つのTutorialとして、作成したゲストブックアプリケーションにロギングとメトリクス機能を追加します。

>このチュートリアルは、Redisを使用したPHPのゲストブックのチュートリアルを前提に作られています。Elasticが開発したログ、メトリクス、ネットワークデータを転送するオープンソースの軽量データシッパーであるBeatsを、ゲストブックと同じKubernetesクラスターにデプロイします。BeatsはElasticsearchに対してデータの収集、分析、インデックス作成を行うため、結果の運用情報をKibana上で表示・分析できるようになります。この例は、以下のコンポーネントから構成されます。

>- Redisを使用したPHPのゲストブックの実行中のインスタンス
- ElasticsearchとKibana
- Filebeat
- Metricbeat
- Packetbeat

##ClusterRoleBindingの追加
これから作成するkube-state-metricsとBeatsをkube-system namespaceにデプロイできるようにClusterRoleBindingを追加します。

```
$ kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=kosuke
clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-binding created
$ kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin-binding
Name:         cluster-admin-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind  Name    Namespace
  ----  ----    ---------
  User  kosuke
```

##kube-state-metricsのインストール
>Kubernetesのkube-state-metricsは、Kubernetes APIサーバーをlistenして、オブジェクトの状態に関するメトリクスを生成する単純なサービスです。

Red HatのOpenShiftではPrometheusのモニタリングで使われてますね。
[1.1. クラスターモニタリングについて](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.5/html/monitoring/cluster-monitoring#monitoring-stack-components-and-monitored-targets_about-cluster-monitoring)

Githubからクローンしてapplyします。

```
$ git clone https://github.com/kubernetes/kube-state-metrics.git kube-state-metrics
Cloning into 'kube-state-metrics'...
remote: Enumerating objects: 38, done.
remote: Counting objects: 100% (38/38), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 19889 (delta 15), reused 24 (delta 10), pack-reused 19851
Receiving objects: 100% (19889/19889), 16.64 MiB | 3.81 MiB/s, done.
Resolving deltas: 100% (12629/12629), done.
$ kubectl apply -f kube-state-metrics/examples/standard
clusterrolebinding.rbac.authorization.k8s.io/kube-state-metrics created
clusterrole.rbac.authorization.k8s.io/kube-state-metrics created
deployment.apps/kube-state-metrics created
serviceaccount/kube-state-metrics created
service/kube-state-metrics created
$ kubectl get pod -n kube-system kube-state-metrics-5c5cb55b4-pf5r5
NAME                                 READY   STATUS    RESTARTS   AGE
kube-state-metrics-5c5cb55b4-pf5r5   1/1     Running   0          31s
```
##Elasticsearchの準備
ここでは、Elasticsearchのクラウドサービスを利用します。
https://cloud.elastic.co/

ログイン画面で、Googleでログインしました。

以下の画面になりますので、「Start your free tiral」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/9d02728a-6755-6bec-bf35-608ac0d2b13f.png)

Elasticsearchをデプロイします。
Cloud Platformとリージョンを選択します。ここでは、GCPの東京リージョンを選択しました。

![2020-08-24 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/27a4d757-7fbb-e7c0-13d8-8dc2581213e7.png)

画像を取り忘れましたが、下にスクロールして名前を設定して「Create」みたいなボタンをクリックします。

そうすると以下の画面が表示されますので、パスワードをメモするかダウンロードします。
あとで、Secretを作成する際に使用します。


![2020-08-24 (4)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/c9d73b32-bbf8-4b95-2f8a-47efad8def44.jpeg)

デプロイされるのをしばらく待ちます。

![2020-08-24 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/3f4d4853-8ebb-7847-23fa-437df6704db8.png)

デプロイされると以下の画面になりますので、CloudIDをメモしておきます。

![2020-08-24 (6)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/ece5d0f7-addd-f6e5-5af6-6e84deb8d1c6.jpeg)

これでElasticsearchの準備は完了です。

##Beatsのパッケージのダウンロード

Githubからクローンします。
ちなみに、400MBくらいあって、私の環境ではディスクフルになってやり直しました。

```
$ git clone https://github.com/elastic/examples.git
Cloning into 'examples'...
remote: Enumerating objects: 63, done.
remote: Counting objects: 100% (63/63), done.
remote: Compressing objects: 100% (55/55), done.
remote: Total 6738 (delta 22), reused 20 (delta 6), pack-reused 6675
Receiving objects: 100% (6738/6738), 124.89 MiB | 4.09 MiB/s, done.
Resolving deltas: 100% (3258/3258), done.
Checking out files: 100% (804/804), done.
$ cd examples/beats-k8s-send-anywhere/
```

##Secretの作成
Elasticsearchを作成したときにメモしたパスワードとCloudIDを使用してSecretを作成します。

ダウンロードしたパッケージにあるファイルを編集します。念のため編集前にオリジナルをコピーしておきます。

```
$ cp ELASTIC_CLOUD_AUTH ELASTIC_CLOUD_AUTH.org
$ cp ELASTIC_CLOUD_ID ELASTIC_CLOUD_ID.org
```

コピーしたら、viなどで編集します。
編集したファイルを使って、Secretを作成します。

```
$ kubectl create secret generic dynamic-logging --from-file=./ELASTIC_CLOUD_ID --from-file=./ELASTIC_CLOUD_AUTH --namespace=kube-system
secret/dynamic-logging created
```

##Beatsのデプロイ
>マニフェストファイルはBeatごとに提供されます。これらのマニフェストファイルは、上で作成したSecretを使用して、BeatsをElasticsearchおよびKibanaサーバーに接続するように設定します。

###Filebeatのデプロイ
>Filebeatは、Kubernetesのノードと、ノード上で実行している各Pod内のコンテナから、ログを収集します。FilebeatはDaemonSetとしてデプロイされます。

マニフェストをapplyします。

```
$ kubectl apply -f filebeat-kubernetes.yaml
configmap/filebeat-dynamic-config created
clusterrolebinding.rbac.authorization.k8s.io/filebeat-dynamic created
clusterrole.rbac.authorization.k8s.io/filebeat-dynamic created
serviceaccount/filebeat-dynamic created
error: unable to recognize "filebeat-kubernetes.yaml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
```

DaemonSetでエラーになりました。APIバージョンが古いようです。
Kubernetes v1.18のDaemonSetのAPIバージョンを確認します。

```
$ kubectl explain DaemonSet | head
KIND:     DaemonSet
VERSION:  apps/v1

DESCRIPTION:
     DaemonSet represents the configuration of a daemon set.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
```

マニフェストを以下のように編集しました。

```filebeat-kubernetes.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-dynamic-config
  namespace: kube-system
  labels:
    k8s-app: filebeat-dynamic
    kubernetes.io/cluster-service: "true"
data:
  filebeat.yml: |-
    setup.dashboards.enabled: true
    setup.template.enabled: true

    setup.template.settings:
      index.number_of_shards: 1

    filebeat.modules:
      - module: system
        syslog:
          enabled: true
          #var.paths: ["/var/log/syslog"]
        auth:
          enabled: true
          #var.paths: ["/var/log/authlog"]

    filebeat.autodiscover:
      providers:
        - type: kubernetes
          templates:
            - condition.equals:
                kubernetes.labels.app: redis
              config:
                - module: redis
                  log:
                    input:
                      type: docker
                      containers.ids:
                        - ${data.kubernetes.container.id}
                  slowlog:
                    enabled: true
                    var.hosts: ["${data.host}:${data.port}"]
            - condition.contains:
                kubernetes.labels.tier: frontend
              config:
                - module: apache2
                  access:
                    input:
                      type: docker
                      containers.ids:
                        - ${data.kubernetes.container.id}
                  error:
                    input:
                      type: docker
                      containers.ids:
                        - ${data.kubernetes.container.id}
            - condition.equals:
                kubernetes.labels.app: mysql
              config:
                - module: mysql
                  error:
                    input:
                      type: docker
                      containers.ids:
                        - ${data.kubernetes.container.id}
                  slowlog:
                    input:
                      type: docker
                      containers.ids:
                        - ${data.kubernetes.container.id}

    processors:
      - drop_event:
          when.or:
              - and:
                  - regexp:
                      message: '^\d+\.\d+\.\d+\.\d+ '
                  - equals:
                      fileset.name: error
              - and:
                  - not:
                      regexp:
                          message: '^\d+\.\d+\.\d+\.\d+ '
                  - equals:
                      fileset.name: access
      - add_cloud_metadata:
      - add_kubernetes_metadata:
      - add_docker_metadata:

    cloud.auth: ${ELASTIC_CLOUD_AUTH}
    cloud.id: ${ELASTIC_CLOUD_ID}

    output.elasticsearch:
      hosts: ${ELASTICSEARCH_HOSTS}
      username: ${ELASTICSEARCH_USERNAME}
      password: ${ELASTICSEARCH_PASSWORD}
    setup.kibana:
      host: ${KIBANA_HOST}

---
apiVersion: apps/v1 #changed
kind: DaemonSet
metadata:
  name: filebeat-dynamic
  namespace: kube-system
  labels:
    k8s-app: filebeat-dynamic
    kubernetes.io/cluster-service: "true"
spec:
  selector: #added
    matchLabels: #added
     k8s-app: filebeat-dynamic #added
  template:
    metadata:
      labels:
        k8s-app: filebeat-dynamic
        kubernetes.io/cluster-service: "true"
    spec:
      serviceAccountName: filebeat-dynamic
      terminationGracePeriodSeconds: 30
      containers:
      - name: filebeat-dynamic
        image: docker.elastic.co/beats/filebeat:7.6.2
        imagePullPolicy: Always
        args: [
          "-c", "/etc/filebeat.yml",
          "-e",
        ]
        env:
        - name: ELASTIC_CLOUD_ID
          valueFrom:
            secretKeyRef:
              name: dynamic-logging
              key: ELASTIC_CLOUD_ID
              optional: true
        - name: ELASTIC_CLOUD_AUTH
          valueFrom:
            secretKeyRef:
              name: dynamic-logging
              key: ELASTIC_CLOUD_AUTH
              optional: true
        - name: ELASTICSEARCH_HOSTS
          valueFrom:
            secretKeyRef:
              name: dynamic-logging
              key: ELASTICSEARCH_HOSTS
              optional: true
        - name: KIBANA_HOST
          valueFrom:
            secretKeyRef:
              name: dynamic-logging
              key: KIBANA_HOST
              optional: true
        - name: ELASTICSEARCH_USERNAME
          valueFrom:
            secretKeyRef:
              name: dynamic-logging
              key: ELASTICSEARCH_USERNAME
              optional: true
        - name: ELASTICSEARCH_PASSWORD
          valueFrom:
            secretKeyRef:
              name: dynamic-logging
              key: ELASTICSEARCH_PASSWORD
              optional: true
        securityContext:
          runAsUser: 0
        volumeMounts:
        - name: config
          mountPath: /etc/filebeat.yml
          readOnly: true
          subPath: filebeat.yml
        - name: data
          mountPath: /usr/share/filebeat/data
        - name: varlog
          mountPath: /var/log
          readOnly: true
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: dockersock
          mountPath: /var/run/docker.sock
      volumes:
      - name: config
        configMap:
          defaultMode: 0600
          name: filebeat-dynamic-config
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: dockersock
        hostPath:
          path: /var/run/docker.sock
      - name: data
        emptyDir: {}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: filebeat-dynamic
subjects:
- kind: ServiceAccount
  name: filebeat-dynamic
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: filebeat-dynamic
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: filebeat-dynamic
  labels:
    k8s-app: filebeat-dynamic
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  verbs:
  - get
  - watch
  - list
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat-dynamic
  namespace: kube-system
  labels:
    k8s-app: filebeat-dynamic
```

編集したマニフェストで再度applyします。

```
$ kubectl apply -f filebeat-kubernetes.yaml
configmap/filebeat-dynamic-config unchanged
daemonset.apps/filebeat-dynamic created
clusterrolebinding.rbac.authorization.k8s.io/filebeat-dynamic unchanged
clusterrole.rbac.authorization.k8s.io/filebeat-dynamic unchanged
serviceaccount/filebeat-dynamic unchanged
```

```
$ kubectl get pod -n kube-system -l k8s-app=filebeat-dynamic
NAME                     READY   STATUS    RESTARTS   AGE
filebeat-dynamic-2bxv7   1/1     Running   0          119s
filebeat-dynamic-bvs22   1/1     Running   0          119s
```

今度は成功しました。

###Metricbeatのデプロイ
>Metricbeatの自動検出はFilebeatと同じ方法で設定します。

FIleBeatと同様にAPIのバージョンが古いので、マニフェストを編集します。DaemonSetとDeploymentの以下を編集します。

- APIバージョンの変更
- selectorの追加

```
$ kubectl apply -f metricbeat-kubernetes.yaml
configmap/metricbeat-setup-config created
job.batch/metricbeat-setup created
configmap/metricbeat-daemonset-config created
configmap/metricbeat-daemonset-modules created
daemonset.apps/metricbeat created
configmap/metricbeat-deployment-config created
configmap/metricbeat-deployment-modules created
deployment.apps/metricbeat created
clusterrolebinding.rbac.authorization.k8s.io/metricbeat created
clusterrole.rbac.authorization.k8s.io/metricbeat created
serviceaccount/metricbeat created
```

```
$ kubectl get pods -n kube-system -l k8s-app=metricbeat
NAME                          READY   STATUS    RESTARTS   AGE
metricbeat-5b9dfd9f8d-t7j7t   1/1     Running   0          2m
metricbeat-vs7rf              1/1     Running   0          2m
metricbeat-wznq4              1/1     Running   0          2m
```

###Packetbeatのデプロイ
>Packetbeatの設定は、FilebeatやMetricbeatとは異なります。コンテナのラベルに対するパターンマッチを指定する代わりに、関連するプロトコルとポート番号に基づいた設定を書きます

同様にDaemonSetのAPIバージョンの変更とselectorを追加してapplyします。

```
kubectl apply -f packetbeat-kubernetes.yaml
configmap/packetbeat-dynamic-config created
daemonset.apps/packetbeat-dynamic created
clusterrolebinding.rbac.authorization.k8s.io/packetbeat-dynamic created
clusterrole.rbac.authorization.k8s.io/packetbeat-dynamic created
serviceaccount/packetbeat-dynamic created
```

これで完了です。

##Kibanaでの確認
ElasticsearchとKibanaをほとんど使ったことがないので、これで正しいのかわからないのですが、ログは収集できているようです。
簡単にできますね。

![2020-08-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/3ea89859-2137-f9c0-ea63-da3c2d2faf65.png)

#まとめ
今回はマニュアルのTutorialを実際にやってみました。
構築自体はマニュアル通りにやるだけですので簡単ですが、実際のアーキテクチャなどを整理しながらやることで理解が深まりました。
ElasticsearchとKibanaは、「とりあえずできた」状態でまだ全然わかってないので、無料トライアルの間にもう少し触ってみたいと思います。あと10日。