My Note

自己理解のためのブログ

EKS ( Kubernetes ) のWorker NodeとContainerのログをDaemonSetのFluentdでS3に保存する

はじめに

今回はEKS環境でworkerノードのログとコンテナのログを永続化するためにFluentdを使ってログをS3に保存する方法について検証したので書いていきます。

環境と構成

  • EKS
    • Workerノード( Amazon Linux2 / ASG )
    • DaemonSet
      • Fluentd
      • IRSA
  • ログの保存先にS3
  • Kustomize

*) EnvごとにAWSアカウントが異なることを前提にしています。

f:id:yhidetoshi:20200704135649p:plain

保存するログの対象

今回、S3に転送する対象のログは以下の通りとします。

  • EKSのWorkerノード
    • /var/log/messages
    • /var/log/audit/audit.log
  • コンテナログ ( product-a のコンテナが稼働 )
    • /var/log/containers/

DaemonSetについて

kubernetes.io

DaemonSet は全て(またはいくつか)のNodeが単一のPodのコピーを稼働させることを保証します。Nodeがクラスターに追加されるとき、PodがNode上に追加されます。 fluentdやfilebeatのようなログ集計デーモンを各Node上で稼働させる。

DaemonSetで利用するFluentdについて

Kubernetesで利用するdaemonsetが公式GitHubで提供されているので、今回はこれを利用します。

github.com

今回はAWSのS3にログを保存するために、 v1.11.0-debian-s3-1.0 を利用しました。

fluentd-kubernetes-daemonset/docker-image/v1.11/debian-s3 at master · fluent/fluentd-kubernetes-daemonset · GitHub

IRSAについて

今回はFluentdからS3にログを保存するためFluentdにはS3にPUTする権限が必要になります。 権限を付与するために、IRSAを利用して権限を付与しています。今回はこの部分には触れません。 詳細は、以下の記事がとても参考になります。

dev.classmethod.jp

  • IRSAで付与するIAMポリリーの権限は以下のようにしました。
    • S3にobjectをputする権限
    • 保存するS3のバケットをkms暗号化している場合は、以下の設定も必要になります。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "*"
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": "kms:GenerateDataKey",
            "Resource": "arn:aws:kms:ap-northeast-1:XXX:key/xxxx"
        }
    ]
}

kustomizeを利用してデプロイする

kustomizeについては↓のリファレンスを。

kubectl.docs.kubernetes.io

base/ で用意するマニフェスト

base/ で共通となるマニフェストを作成してenvで異なる部分を overlay します。

fluentd
├── base
│   ├── daemonset.yaml
│   ├── kustomization.yaml
│   └── serviceaccount.yaml
└── overlays
    ├── dev
        ├── fluent.conf
        ├── kustomization.yaml
        └── patches
            ├── daemonset.yaml
            └── serviceaccount.yaml
  • base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: fluentd

resources:
  - daemonset.yaml
  - serviceaccount.yaml
  • base/serviceaccount.yaml
    • role-arnの部分は envで異なるために overlay します。
kind: ServiceAccount
apiVersion: v1
metadata:
  name: fluentd
  namespace: fluentd
  annotations:
    eks.amazonaws.com/role-arn: overlay

daemonset.yamlについて

daemonsetのPodでworkerノードに出力されているログを収集するために ノードのディレクトリをマウントします。

  • base/daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      serviceAccountName: fluentd
      containers:
        - name: fluentd
          image: fluentd:overlay
          env:
            - name: FLUENTD_SYSTEMD_CONF
              value: disable
            - name: S3_BUCKET_REGION
              value: ap-northeast-1
          resources:
            limits:
              memory: "200Mi"
          volumeMounts:
          - name: fluent-conf
            mountPath: /fluentd/etc
          - name: varlog
            mountPath: /var/log
          - name: varlibdockercontainers
            mountPath: /var/lib/docker/containers
            readOnly: true
      volumes:
        - name: fluent-conf
          configMap:
            name: fluent-conf
            items:
              - key: fluent.conf
                path: fluent.conf
        - name: varlog
          hostPath:
            path: /var/log
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers

overlays/ で用意するマニフェスト

  • overlays/kustomization.yamlで設定するもの

    • kustomization.yamlで fluentdのconfを configMapGenerator で設定する
    • fluentdのimageを images で指定する
    • ServiceAccountとDaemonSetのマニフェストpatchesJson6902 で それぞれを overlay する
  • overlays/dev/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: fluentd

bases:
  - ../../base

configMapGenerator:
  - name: fluent-conf
    files:
      - fluent.conf

images:
  - name: fluentd:overlay
    newName: fluent/fluentd-kubernetes-daemonset
    newTag: v1.11.0-debian-s3-1.0

patchesJson6902:
  - target:
      version: v1
      kind: ServiceAccount
      name: fluentd
      namespace: fluentd
    path: patches/serviceaccount.yaml
  - target:
      version: v1
      kind: DaemonSet
      group: apps
      name: fluentd
      namespace: fluentd
    path: patches/daemonset.yaml
  • overlays/dev/patches/serviceaccount.yaml
    • iamロールはENVごとに異なるため、patchesで置き換える
- op: replace
  path: /metadata/annotations/eks.amazonaws.com~1role-arn
  value: arn:aws:iam::XXXXXXXXXXX:role/fluentd-xxxxx
  • overlays/dev/patches/daemonset.yaml
    • コンテナに割り当てるメモリ制限はENVごとに変更するため、pathcesで書き換えられるようにしています。
    • バケット名はENVごとに異なるため、pathcesで環境変数を追加しています。
- op: replace
  path: /spec/template/spec/containers/0/resources/limits/memory
  value: "500Mi"
- op: add
  path: /spec/template/spec/containers/0/env/-
  value:
    name: S3_BUCKET_NAME_COMMON
    value: test-common-logs-dev
- op: add
  path: /spec/template/spec/containers/0/env/-
  value:
    name: S3_BUCKET_NAME_PRODUCT_A
    value: test-product-a-logs-dev

fluent.confについて

設計

  • バケット名とリージョン名は環境変数でconfに展開する。
  • workerノードのログを S3_BUCKET_NAME_COMMONバケットに保存。
    • messages/ と audit/ のパスにそれぞれの種類ごとに分けて保存する。
  • product-aのログを S3_BUCKET_NAME_PRODUCT_Aバケットに保存。
    • nginx/ と api/ のパスにそれぞれの種類ごとに分けて保存する 。
  • APIキーでななく、IAMロールで権限を付与しているので、 check_apikey_on_start false とする。これを設定しないと、APIキーが設定されていなくエラーになった。
  • ログをS3に保存するときにオブジェクトの重複していないか確認させないように check_object false とする。
    • GETのAPIが結構な数が叩かれる可能性があるため。その代わりに、object名が重複しないように、%{hostname}-${tag}-%Y%m%d%H%M%S.%{file_extension} とした。
    • true にする場合は、s3:Getの権限が必要になる。
  • バケットに保存するパスは ログの名前( tag名 )/dt=yyyymmdd/hour=xx/オブジェクト名 とする。

fluentdの設定ファイル名について

ConfigMapで設定しているファイル名は fluentdのDockerfileの環境変数 ( ENV FLUENTD_CONF="fluent.conf" )に設定されているため fluent.conf にしています。詳細は↓。

# worker node log
## /var/log/messages
<source>
  @type tail
  path /var/log/messages
  tag common.messages
  pos_file /var/log/td-agent/messages.pos
  format syslog
</source>

## audit
<source>
  @type tail
  path /var/log/audit/audit.log
  tag common.audit
  pos_file /var/log/td-agent/audit.pos
  format ltsv
</source>

# container log
## product-a

### nginx
<source>
  @type tail
  path "/var/log/containers/product-a-nginx-*.log"
  pos_file /var/log/nginx.log.pos
  tag product-a.nginx
  read_from_head true
  <parse>
    @type json
    time_format %Y-%m-%dT%H:%M:%S.%NZ
  </parse>
</source>

### api
<source>
  @type tail
  path "/var/log/containers/product-a-api-*.log"
  pos_file /var/log/product-a-api.log.pos
  tag product-a.api
  read_from_head true
  <parse>
    @type json
    time_format %Y-%m-%dT%H:%M:%S.%NZ
  </parse>
</source>


# worker node
<match common.*>
  @type s3
  format json
  s3_bucket "#{ENV['S3_BUCKET_NAME_COMMON']}"
  s3_region "#{ENV['S3_BUCKET_REGION']}"
  s3_object_key_format %{path}%{time_slice}/%{hostname}-${tag}-%Y%m%d%H%M%S.%{file_extension}
  path worker-node/${tag[1]}/
  time_slice_format dt=%Y%m%d/hour=%H
  check_apikey_on_start false
  check_object false
  flush_interval 300s
  flush_at_shutdown true
  time_slice_wait 30s
  include_time_key true
  time_key time

  <buffer tag,time>
    @type file
    path "/var/log/fluentd-buffers-common-varlog/s3.buffer"
    chunk_limit_size 256MB
    timekey 5m
  </buffer>
</match>

# container
## product-a
<match product-a.*>
  @type s3
  format json
  s3_bucket "#{ENV['S3_BUCKET_NAME_PRODUCT_A']}"
  s3_region "#{ENV['S3_BUCKET_REGION']}"
  s3_object_key_format %{path}%{time_slice}/%{hostname}-${tag}-%Y%m%d%H%M%S.%{file_extension}
  path ${tag[1]}/
  time_slice_format dt=%Y%m%d/hour=%H
  check_apikey_on_start false
  check_object false
  flush_interval 300s
  flush_at_shutdown true
  time_slice_wait 30s
  include_time_key true
  time_key time

  <buffer tag,time>
    @type file
    path "/var/log/fluentd-buffers-product-a/s3.buffer"
    chunk_limit_size 256MB
    timekey 5m
  </buffer>
</match>

さいごに

今回は、マニフェストの管理はkustomizeを利用して EKS環境下のWorkerノードの一部のログとコンテナのログをKubernetesのDaemonSetでFluentd動かしてS3にログを保存しました。 kustomizeで管理しているマニフェストのデプロイはArgoCDを利用していますが今回は言及していません。DaemonSetで利用するFluentdのイメージは用途別にイメージが公開されているのでとても便利でした!

Slackでusergroupのidを確認する

はじめに

DatadogやMackerelなどで障害時にグループメンションで通知したい場合にslackのusergroup-id が必要だったので、その確認方法についての備忘録。

方法

usergroupの一覧を取得するにはslack apiusergroups.list を使います。

api.slack.com

ここにAPIコールするために必要な権限や引数を確認することができる。

f:id:yhidetoshi:20200613081421p:plain

APIをコールするためにTokenが必要になるが、Slack Appをまだ作成していない場合は、↓から作成する。

f:id:yhidetoshi:20200613082340p:plain

App名は任意に設定。

f:id:yhidetoshi:20200613084034p:plain

APIをコールするために先ほど確認した権限を付与する。

f:id:yhidetoshi:20200613084029p:plain

f:id:yhidetoshi:20200613084026p:plain

f:id:yhidetoshi:20200613084022p:plain

f:id:yhidetoshi:20200613084019p:plain

作成したAppをWorkspaceにインストールする。

f:id:yhidetoshi:20200613084014p:plain

ここでOAuth Tokenを確認。

f:id:yhidetoshi:20200613084010p:plain

Workspaceを選択して、先ほどのOAuth Tokenをセットして実行する。

f:id:yhidetoshi:20200613084432p:plain

実行OKであれば、usergroupのlistがjsonで取得できるので、欲しい情報をパースすればいい。

まとめ

スクショベースで手順を記載しました。usergroup idはSlackのwebGUIでは確認できなかったので、apiでのみ確認できるんだと思います。 以上、備忘録でした。

Terraform学習メモ1 ( mapとfor_eachでECRを作成 )

Terraformが0.12系がリリースされてから使える関数が増えてきているのでTerraformをまた勉強しはじめました。 そのときの "学習メモ" として書いていきます。(あくまで学習メモということで書いていきますので、間違い等あるかもなのでご了承ください🙏) 今回はmapとfor_eachを使って awsのECRを作成しました。

  • 環境
    • Terraform v0.12.20
    • tfenv 1.0.2
    • terraform-cloud

mapとfor_eachについて

  • mapについて

learn.hashicorp.com

  • for_eachについて

www.hashicorp.com

Terraformのコード

以下にECRを作成するために必要なコードを記載します。

www.terraform.io

ecrをterraformで作成するために今回は以下のパラメータを利用しました。

  • name
  • image_tag_mutability
  • scan_on_push

ECRでレポジトリを複数作成する場合には、レポジトリ毎に3つのパラメータを渡す必要があります。 variablesにそれぞれ変数を定義したり、 module の宣言もレポジトリ毎に作成するのは手間ですよね.. for_eachを利用する以外には、listとcount/index を使って作成することもできますが、version0.12.6からmapとfor_eachを組み合わせて使えるようになったので、 mapとfor_eachを使って効率良く作成することにします。

■ module側(呼び出し)

repositories という多次元連想配列のようにmapを宣言します。

module "ecr" {
  source = "../../modules/ecr"

  repositories = {
    api1-v1 = {
      name                 = "api-v1"
      image_tag_mutability = "MUTABLE"
      scan_on_push         = true
    },
    api-v2 = {
      name                 = "api-v2"
      image_tag_mutability = "IMMUTABLE"
      scan_on_push         = false
    },
  }
}

■ modulesの定義側(main.tf)

variable "repositories" {
  type = map
}


resource "aws_ecr_repository" "main" {
  for_each = var.repositories

  name                 = each.value.name
  image_tag_mutability = each.value.image_tag_mutability
  image_scanning_configuration {
    scan_on_push = each.value.scan_on_push
  }
}

for_each = var.repositories でmapをfor_eachで読み込み、each.value.key名 で指定したkey名のvalueを取得します。 こう定義することで、mapで宣言した値を api-v1, api-v2の単位で変数を渡してecrにレポジトリを作成しました。

MapをイメージするためにGoで定義した場合

↑のmapで変数を渡してレポジトリを作成するイメージを自分で理解するために、Goで多次元連想配列にしてみました。

repositories := make(map[string]map[string]interface{})

package main

import "fmt"

func main() {
    repositories := make(map[string]map[string]interface{})
    repositories["api-v1"] = make(map[string]interface{})
    repositories["api-v2"] = make(map[string]interface{})

    // api-v1 = {}
    repositories["api-v1"]["name"] = "api-v1"
    repositories["api-v1"]["image_tag_mutability"] = "MUTABLE"
    repositories["api-v1"]["scan_on_push"] = true

    // api-v2 = {}
    repositories["api-v2"]["name"] = "api-v2"
    repositories["api-v2"]["image_tag_mutability"] = "IMMUTABLE"
    repositories["api-v2"]["scan_on_push"] = false

    // output
    fmt.Println(repositories["api-v1"]["name"]) // api-v1
    fmt.Println(repositories["api-v1"]["image_tag_mutability"]) // MUTABLE
    fmt.Println(repositories["api-v1"]["scan_on_push"]) // true
    fmt.Println()
    fmt.Println(repositories["api-v2"]["name"]) // api-v2
    fmt.Println(repositories["api-v2"]["image_tag_mutability"]) // IMMUTABLE
    fmt.Println(repositories["api-v2"]["scan_on_push"]) // false
}

Amazon EKS on EC2 で mackerel-container-agentを使ってPodを監視する

はじめに

今回は EKS on EC2の環境においてmackerelを使ってPod監視した方法について書いていきます。 本ブログの前提ですが、EKSのクラスターとワーカーノードが用意されている状態で進めていきます。では早速本題に!

今回の監視で利用する mackerel-container-agent については↓のMackerel公式ブログについてまとめられています。

mackerel.io

まずは、mackerel-container-agent を動かすための環境を構築していきます。構築する環境はnginxコンテナとサイドカーにmackerel-container-agentが動くPodを作成します。 Manifestの管理ツールには kustomize を利用します。

  • 検証環境のバージョン

環境構築

マニフェストを作成

.
├── common
│   ├── kustomization.yaml
│   ├── mackerel-rbac.yaml
│   ├── mackerel-serviceaccount.yaml
│   └── secret-mackerel-apikey.yaml
└── nginx
    ├── configmap-mackerel.yaml
    ├── deployment.yaml
    ├── kustomization.yaml
    └── service.yaml

commonディレクトリについて

ServiceAccount , ClusterRoleBinding, Secret のmanifestをそれぞれ作成します。

ServiceAccountClusterRoleBindingマニフェストの作成は↓のMackerel公式ブログを参考にしています。

mackerel.io

  • kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - mackerel-rbac.yaml
  - mackerel-serviceaccount.yaml
  - secret-mackerel-apikey.yaml
  • $ kubectl kustomize . ( manifest全体 )
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mackerel-serviceaccount
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: mackerel-container-agent-clusterrole
rules:
- apiGroups:
  - ""
  resources:
  - nodes/proxy
  - nodes/stats
  - nodes/spec
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mackerel-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: mackerel-container-agent-clusterrole
subjects:
- kind: ServiceAccount
  name: mackerel-serviceaccount
  namespace: default
---
apiVersion: v1
data:
  MACKEREL_APIKEY: <base64エンコードした値>
kind: Secret
metadata:
  name: mackerel-apikey
type: Opaque

kustomizeでmanifestを適用する。 $ kubectl apply -k . コマンドを実行。

MACKEREL_APIKEY の中身はbase64だとデコードできてしまうので、ブログ上では <base64エンコードした値> としています。

ServiceAccountとClusterRoleBindingについて

mackerel-container-agentがKubernetesクラスタからメトリクスを取得するために ServiceAccountとClusterRoleBinding を設定する必要があります。

  • mackerel公式ブログより

    kubeletで認証が有効な場合には、mackerel-container-agentがこれらのリソースを参照できるよう、ServiceAccountに対してRoleを設定する必要となります。

$ kubectl get sa | grep mackerel
mackerel-serviceaccount   1         8d

$ kubectl get clusterrole.rbac | grep mackerel
mackerel-container-agent-clusterrole

$ kubectl get clusterrolebinding.rbac | grep mackerel
mackerel-clusterrolebinding

nginxディレクトリについて

  • kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - service.yaml
  - configmap-mackerel.yaml

ConfigMap, Service, Deployment のmanifestを作成します。

  • $ kubectl kustomize . ( manifest全体 )
apiVersion: v1
data:
  mackerel.yaml: |-
    plugin:
      checks:
        tcp:
          command: "check-tcp --hostname=localhost --port=80 --warning=5"

    readinessProbe:
      tcp:
        port: 80
kind: ConfigMap
metadata:
  name: mackerel-container-agent
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-test
spec:
  ports:
  - nodePort: 31080
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-test
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-test
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
      - env:
        - name: MACKEREL_KUBERNETES_KUBELET_READ_ONLY_PORT
          value: "0"
        - name: MACKEREL_CONTAINER_PLATFORM
          value: kubernetes
        - name: MACKEREL_APIKEY
          valueFrom:
            secretKeyRef:
              key: MACKEREL_APIKEY
              name: mackerel-apikey
        - name: MACKEREL_ROLES
          value: dev:web
        - name: MACKEREL_AGENT_CONFIG
          value: /etc/mackerel/mackerel.yaml
        - name: MACKEREL_KUBERNETES_KUBELET_HOST
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: MACKEREL_KUBERNETES_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MACKEREL_KUBERNETES_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        image: mackerel/mackerel-container-agent:plugins
        imagePullPolicy: Always
        name: mackerel-container-agent
        resources:
          limits:
            memory: 128Mi
        volumeMounts:
        - mountPath: /etc/mackerel/
          name: mackerel-agent-volume
      serviceAccountName: mackerel-serviceaccount
      volumes:
      - configMap:
          name: mackerel-container-agent
        name: mackerel-agent-volume

ConfigMapについて ( pluginを利用した監視設定 )

agentのconfをConfigMapで作成します。80番ポートをcheck-tcpを利用します。 readinessProbe でportチェックOKだったらhostsに登録される設定をしています。

pluginの使い方の説明は↓のブログ記事に記載されています。 mackerel.io

apiVersion: v1
data:
  mackerel.yaml: |-
    plugin:
      checks:
        tcp:
          command: "check-tcp --hostname=localhost --port=80 --warning=5"

    readinessProbe:
      tcp:
        port: 80
kind: ConfigMap
metadata:
  name: mackerel-container-agent

mackerelの公式プラグインが同梱されているコンテナイメージは mackerelの公式イメージとしてDockerHubで公開されています。

  • プラグインを利用する場合の Dockerイメージ
    • mackerel/mackerel-container-agent:plugins
  • プラグインを利用しない場合のDockerイメージ
    • mackerel/mackerel-container-agent:latest

Docker Hub

Deploymentについて

Deploymentのマニフェストを作成するために、mackerel-container-agentをセットアップする必要があります。 そこで、↓の公式ブログを参照しました。

mackerel.io

  • deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test
spec:
  selector:
    matchLabels:
      app: nginx-test
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      serviceAccountName: mackerel-serviceaccount # mackerelで必要な serviceAccountNameを指定
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
        - name: mackerel-container-agent
#          image: mackerel/mackerel-container-agent:latest # コンテナリソースだけ監視する場合はこのイメージ
          image: mackerel/mackerel-container-agent:plugins # pluginを利用して監視する場合はこのイメージ
          imagePullPolicy: Always
          resources:
            limits:
              memory: 128Mi # 使用するメモリを制限
          env:
            - name: MACKEREL_KUBERNETES_KUBELET_READ_ONLY_PORT
              value: "0"
            - name: MACKEREL_CONTAINER_PLATFORM
              value: kubernetes
            - name: MACKEREL_APIKEY
              valueFrom: # 登録したSecretからAPI-Keyを参照する
                secretKeyRef:
                  name: mackerel-apikey
                  key: MACKEREL_APIKEY
            - name: MACKEREL_ROLES # 管理コンソールで定義しているRoleを指定。 `サービス名 : ロール名`
              value: dev:web
            - name: MACKEREL_AGENT_CONFIG # mackerel-container-agentのconfを指定する
              value: /etc/mackerel/mackerel.yaml
            - name: MACKEREL_KUBERNETES_KUBELET_HOST
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: MACKEREL_KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: MACKEREL_KUBERNETES_POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          volumeMounts: # mackerel-container-agentのconfを適用するために volumeMountsとvolumesを定義
            - name: mackerel-agent-volume
              mountPath: /etc/mackerel/
      volumes:
        - name: mackerel-agent-volume
          configMap:
            name: mackerel-container-agent

kustomizeでmanifestを適用する。 $ kubectl apply -k . コマンドを実行。

Mackerelの管理画面 ( モニタリング結果 )

Pod名でMackerel管理画面のHostsに追加された!

  • $ kubectl get po | grep nginx
nginx-test-6bfdcff679-4n7rz   2/2     Running   0          7h26m

f:id:yhidetoshi:20200126165048p:plain

今年買ってよかったもの(開発環境周り)

2019年もう終わりですね!今年は家でリモートワークすることも多く、個人開発する時間もだいぶ増えたので 環境を整えました。その中で買ったよかったものを書いていきますー!

椅子

前の椅子が壊れかけて...ニトリで試しに座ったらめっちゃよかったので購入

item.rakuten.co.jp

デスク

L字型のデスク

www.nitori-net.jp

www.nitori-net.jp

結構スペースあってノートPC2台とモニター1台置くにはちょうどいい大きさだった。

ヘッドフォン

QUIETCOMFORT 35 WIRELESS HEADPHONES II

これも長年使ったやつがもうダメだったので買い換えた!もうサイコー!!

https://www.bose.co.jp/ja_jp/products/headphones/over_ear_headphones/quietcomfort-35-wireless-ii.html

キーボード

Ergodox EZ (赤軸 消音)

分割キーボードを初めて購入!最初は慣れるのにちょっと時間かかったけど、かなりハマってきた!!

ergodox-ez.com

欲を言えばあとは4Kモニターにすれば完璧かもしれない...

来年も頑張りたい!!

mackerel-client-goを使ってMackerelのグラフにアノテーションをする

はじめに

今回はMackerelのグラフにアノテーションをしますー! アノテーションについては↓の記事をみてください!

mackerel.io

アノテーションする

今回はmackerel-client-goを使ってグラフにアノテーションをしました。

github.com

NatureRemoのセンサー情報を取得しているので、サービス NatureRemo に対して作成しています。 環境変数api-keyをセットして実行しています。

package main

import (
    "fmt"
    "os"
    "time"

    "github.com/mackerelio/mackerel-client-go"
)

var (
    service = "NatureRemo"
    title = "たいとる"
    description = "Description"
    mkrKey  = os.Getenv("MKRKEY")
    client  = mackerel.NewClient(mkrKey)
)

func main() {
    nowTime := time.Now()
    toTime := nowTime.Add(1 * time.Minute)

    _, err := client.CreateGraphAnnotation(&mackerel.GraphAnnotation{
        Title:       title,
        Description: description,
        From:        nowTime.Unix(),
        To:          toTime.Unix(),
        Service:     service,
    })
    if err != nil {
        fmt.Println(err)
    }
}

結果

アノテーションができてますね! f:id:yhidetoshi:20191215140725p:plain

さいごに

今回、mackerel-client-goを使ってグラフにアノテーションしました。この機能を使うと、 デプロイのタイミングだったりバッチ処理を回したりというときにアノテーションしておくとあとでデバッグが楽になりそうですね!

ECS Fargateで mackerel-container-agent をサイドカーで動かす

はじめに

ECS Fargateで mackerel-container-agent をサイドカーで動かしてコンテナを監視します!

前回の↓記事でECS FargateでGoコンテナをデプロイしました。 が、この記事では省略していたコンテナ監視とSSMパラメータストアとの連携について書いていきますー。

yhidetoshi.hatenablog.com

タスクを定義する

こちらの公式記事を参考にしました。

mackerel.io

  • 前回のブログ taskdef.json から mackerel-container-agent の部分抜粋
{
      "name": "mackerel-container-agent",
      "image": "mackerel/mackerel-container-agent:latest",
      "essential": false,
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/go-scraping-api",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "memory": 128,
      "environment" : [
        {
          "name": "MACKEREL_CONTAINER_PLATFORM",
          "value": "fargate"
        },
        {
          "name": "MACKEREL_ROLES",
          "value": "dev:fargate"
        }
      ],
      "secrets": [
        {
          "name": "MACKEREL_APIKEY",
          "valueFrom": "mackerel_agent_apikey"
        }
      ]
    }

環境変数とSSMパラメータストア

環境変数をSSMパラメータストアから参照する方法について! 環境変数を利用するために environment で定義して環境変数の key/value をセットします。 次に、パラメータストアにSecureStringで登録した値を参照するに secrets で定義し、name に環境変数名、 valueFrom に ssmパラメータストアのkey名を書きました。

f:id:yhidetoshi:20191213223257p:plain

"environment" : [
        {
          "name": "MACKEREL_CONTAINER_PLATFORM",
          "value": "fargate"
        },
        {
          "name": "MACKEREL_ROLES",
          "value": "dev:fargate"
        }
      ],
      "secrets": [
        {
          "name": "MACKEREL_APIKEY",
          "valueFrom": "mackerel_agent_apikey"
        }
      ]

Mackerelの管理画面で確認

バッチリとれてますね!!

f:id:yhidetoshi:20191213224641p:plain

さいごに

今回はECS Fargateのコンテナ監視に mackerel-container-agent をサイドカーで動かしました。 taskdefファイルにこのように定義するだけでいいので手間なくカンタンでした!