kube-state-metrics を Container Insights に送る
kube-state-metrics を Container Insights に送る方法を確認したメモ。
クラスターの作成
1.24でクラスターを作成する。ノードなしで作成する。
CLUSTER_NAME="mycluster" cat << EOF > cluster.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ap-northeast-1 version: "1.24" vpc: cidr: "10.0.0.0/16" availabilityZones: - ap-northeast-1a - ap-northeast-1c cloudWatch: clusterLogging: enableTypes: ["*"] iam: withOIDC: true EOF
eksctl create cluster -f cluster.yaml
ノードを作成する。
cat << EOF > m1.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ap-northeast-1 managedNodeGroups: - name: m1 minSize: 2 maxSize: 2 desiredCapacity: 2 privateNetworking: true iam: attachPolicyARNs: - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore EOF
eksctl create nodegroup -f m1.yaml
Adminロールにも権限をつけておく。
CLUSTER_NAME="mycluster" USER_NAME="Admin:{{SessionName}}" AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/Admin" eksctl create iamidentitymapping --cluster ${CLUSTER_NAME} --arn ${ROLE_ARN} --username ${USER_NAME} --group system:masters
Prometheus のデプロイ
helmefile.yaml
に以下を追加する。
repositories: - name: prometheus-community url: https://prometheus-community.github.io/helm-charts releases: - name: prometheus namespace: prometheus createNamespace: true chart: prometheus-community/prometheus version: 23.0.0 values: - ./prometheus/values.yaml
prometheus/values.yaml
を作成する。
# https://github.com/prometheus-community/helm-charts/blob/main/charts/prometheus/values.yaml server: persistentVolume: enabled: false alertmanager: enabled: false kube-state-metrics: enabled: true prometheus-node-exporter: enabled: true prometheus-pushgateway: enabled: false
デプロイする。
helmfile apply
Container Insights のログ収集のデプロイ
Fluent Bit 用の IAM ロールを作成する。
eksctl create iamserviceaccount \ --cluster=${CLUSTER_NAME} \ --namespace=amazon-cloudwatch \ --name=fluent-bit \ --attach-policy-arn=arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy \ --approve \ --role-only
helmefile.yaml
に以下を追加する。
releases: - name: container-insights chart: ./container_insights namespace: amazon-cloudwatch createNamespace: true
マニフェストをダウンロードして container_insights
フォルダに配置する。
curl -O https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/fluent-bit/fluent-bit.yaml
ConfigMap のマニフェストを作成する。
ClusterName=${CLUSTER_NAME} RegionName=ap-northeast-1 FluentBitHttpPort='2020' FluentBitReadFromHead='Off' [[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On' [[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On' kubectl create configmap fluent-bit-cluster-info --dry-run=client -o yaml \ --from-literal=cluster.name=${ClusterName} \ --from-literal=http.server=${FluentBitHttpServer} \ --from-literal=http.port=${FluentBitHttpPort} \ --from-literal=read.head=${FluentBitReadFromHead} \ --from-literal=read.tail=${FluentBitReadFromTail} \ --from-literal=logs.region=${RegionName} -n amazon-cloudwatch > fluent-bit-cluster-info.yaml
fluent-bit.yaml
の IRSA 用のアノテーションを修正する。
eksctl get iamserviceaccount --cluster ${CLUSTER_NAME}
apiVersion: v1 kind: ServiceAccount metadata: name: fluent-bit namespace: amazon-cloudwatch annotations: eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/eksctl-mycluster-addon-iamserviceaccount-ama-Role1-1OSUU3XOAFAJZ
デプロイする。
helmfile apply
Container Insights のインフラメトリクス収集のデプロイ
ADOT Collector 用の IAM ロールを作成する。
k create ns aws-otel-eks eksctl create iamserviceaccount \ --cluster=${CLUSTER_NAME} \ --namespace=aws-otel-eks \ --name=aws-otel-sa \ --attach-policy-arn=arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy \ --approve \ --role-only
helmefile.yaml
に以下を追加する。
releases: - name: adot-collector chart: ./adot_collector namespace: aws-otel-eks createNamespace: true
マニフェストをダウンロードして adot_collector
フォルダに配置する。
curl -O https://raw.githubusercontent.com/aws-observability/aws-otel-collector/main/deployment-template/eks/otel-container-insights-infra.yaml
Namespace は作成済みなので削除する。
IRSA のアノテーションを付与する。
--- # create cwagent service account and role binding apiVersion: v1 kind: ServiceAccount metadata: name: aws-otel-sa namespace: aws-otel-eks annotations: eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/eksctl-mycluster-addon-iamserviceaccount-aws-Role1-1SKD8JAEOLGKW --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: aoc-agent-role rules: - apiGroups: [""] resources: ["pods", "nodes", "endpoints"] verbs: ["list", "watch", "get"] - apiGroups: ["apps"] resources: ["replicasets"] verbs: ["list", "watch", "get"] - apiGroups: ["batch"] resources: ["jobs"] verbs: ["list", "watch"] - apiGroups: [""] resources: ["nodes/proxy"] verbs: ["get"] - apiGroups: [""] resources: ["nodes/stats", "configmaps", "events"] verbs: ["create", "get"] - apiGroups: [""] resources: ["configmaps"] verbs: ["update"] - apiGroups: [""] resources: ["configmaps"] resourceNames: ["otel-container-insight-clusterleader"] verbs: ["get","update", "create"] - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["create","get", "update"] - apiGroups: ["coordination.k8s.io"] resources: ["leases"] resourceNames: ["otel-container-insight-clusterleader"] verbs: ["get","update", "create"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: aoc-agent-role-binding subjects: - kind: ServiceAccount name: aws-otel-sa namespace: aws-otel-eks roleRef: kind: ClusterRole name: aoc-agent-role apiGroup: rbac.authorization.k8s.io --- # create Daemonset apiVersion: apps/v1 kind: DaemonSet metadata: name: aws-otel-eks-ci namespace: aws-otel-eks spec: selector: matchLabels: name: aws-otel-eks-ci template: metadata: labels: name: aws-otel-eks-ci spec: containers: - name: aws-otel-collector image: public.ecr.aws/aws-observability/aws-otel-collector:latest env: - name: K8S_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: HOST_IP valueFrom: fieldRef: fieldPath: status.hostIP - name: HOST_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: K8S_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace imagePullPolicy: Always command: - "/awscollector" - "--config=/conf/otel-agent-config.yaml" volumeMounts: - name: rootfs mountPath: /rootfs readOnly: true - name: dockersock mountPath: /var/run/docker.sock readOnly: true - name: containerdsock mountPath: /run/containerd/containerd.sock - name: varlibdocker mountPath: /var/lib/docker readOnly: true - name: sys mountPath: /sys readOnly: true - name: devdisk mountPath: /dev/disk readOnly: true - name: otel-agent-config-vol mountPath: /conf resources: limits: cpu: 200m memory: 200Mi requests: cpu: 200m memory: 200Mi volumes: - configMap: name: otel-agent-conf items: - key: otel-agent-config path: otel-agent-config.yaml name: otel-agent-config-vol - name: rootfs hostPath: path: / - name: dockersock hostPath: path: /var/run/docker.sock - name: varlibdocker hostPath: path: /var/lib/docker - name: containerdsock hostPath: path: /run/containerd/containerd.sock - name: sys hostPath: path: /sys - name: devdisk hostPath: path: /dev/disk/ serviceAccountName: aws-otel-sa
ConfigMap は別ファイルに切り出す。
--- apiVersion: v1 kind: ConfigMap metadata: name: otel-agent-conf namespace: aws-otel-eks labels: app: opentelemetry component: otel-agent-conf data: otel-agent-config: | extensions: health_check: receivers: awscontainerinsightreceiver: processors: batch/metrics: timeout: 60s exporters: awsemf: namespace: ContainerInsights log_group_name: '/aws/containerinsights/{ClusterName}/performance' log_stream_name: '{NodeName}' resource_to_telemetry_conversion: enabled: true dimension_rollup_option: NoDimensionRollup parse_json_encoded_attr_values: [Sources, kubernetes] metric_declarations: # node metrics - dimensions: [[NodeName, InstanceId, ClusterName]] metric_name_selectors: - node_cpu_utilization - node_memory_utilization - node_network_total_bytes - node_cpu_reserved_capacity - node_memory_reserved_capacity - node_number_of_running_pods - node_number_of_running_containers - dimensions: [[ClusterName]] metric_name_selectors: - node_cpu_utilization - node_memory_utilization - node_network_total_bytes - node_cpu_reserved_capacity - node_memory_reserved_capacity - node_number_of_running_pods - node_number_of_running_containers - node_cpu_usage_total - node_cpu_limit - node_memory_working_set - node_memory_limit # pod metrics - dimensions: [[PodName, Namespace, ClusterName], [Service, Namespace, ClusterName], [Namespace, ClusterName], [ClusterName]] metric_name_selectors: - pod_cpu_utilization - pod_memory_utilization - pod_network_rx_bytes - pod_network_tx_bytes - pod_cpu_utilization_over_pod_limit - pod_memory_utilization_over_pod_limit - dimensions: [[PodName, Namespace, ClusterName], [ClusterName]] metric_name_selectors: - pod_cpu_reserved_capacity - pod_memory_reserved_capacity - dimensions: [[PodName, Namespace, ClusterName]] metric_name_selectors: - pod_number_of_container_restarts # cluster metrics - dimensions: [[ClusterName]] metric_name_selectors: - cluster_node_count - cluster_failed_node_count # service metrics - dimensions: [[Service, Namespace, ClusterName], [ClusterName]] metric_name_selectors: - service_number_of_running_pods # node fs metrics - dimensions: [[NodeName, InstanceId, ClusterName], [ClusterName]] metric_name_selectors: - node_filesystem_utilization # namespace metrics - dimensions: [[Namespace, ClusterName], [ClusterName]] metric_name_selectors: - namespace_number_of_running_pods service: pipelines: metrics: receivers: [awscontainerinsightreceiver] processors: [batch/metrics] exporters: [awsemf] extensions: [health_check]
デプロイする。
helmfile apply
Container Insights の Prometheus メトリクス収集のデプロイ
ADOT Collector 用の IAM ロールを作成する。
eksctl create iamserviceaccount \ --cluster=${CLUSTER_NAME} \ --namespace=aws-otel-eks \ --name=aws-otel-collector \ --attach-policy-arn=arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy \ --approve \ --role-only
マニフェストをダウンロードして adot_collector
フォルダに配置する。
curl -O https://raw.githubusercontent.com/aws-observability/aws-otel-collector/main/deployment-template/eks/otel-container-insights-prometheus.yaml
Namespace は作成済みなので削除する。
IRSA のアノテーションを付与する。このマニフェストでは AppMesh/HAProxy/JMX/Memcached/Nginx のメトリクスを収集するための固定の定義が使われるので、カスタマイズした定義を使うため、インフラメトリクス収集用の定義を参考にして、ConfigMap をマウントするようにする。
--- apiVersion: v1 kind: ServiceAccount metadata: name: aws-otel-collector namespace: aws-otel-eks annotations: eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/eksctl-mycluster-addon-iamserviceaccount-aws-Role1-T5JD5TS9NP53 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: otel-prometheus-role rules: - apiGroups: - "" resources: - nodes - nodes/proxy - services - endpoints - pods verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses verbs: - get - list - watch - nonResourceURLs: - /metrics verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: otel-prometheus-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: otel-prometheus-role subjects: - kind: ServiceAccount name: aws-otel-collector namespace: aws-otel-eks --- apiVersion: apps/v1 kind: Deployment metadata: name: aws-otel-collector namespace: aws-otel-eks labels: name: aws-otel-collector spec: replicas: 1 selector: matchLabels: name: aws-otel-collector template: metadata: labels: name: aws-otel-collector spec: serviceAccountName: aws-otel-collector containers: - name: aws-otel-collector image: public.ecr.aws/aws-observability/aws-otel-collector:latest command: - "/awscollector" - "--config=/conf/otel-agent-config.yaml" env: - name: AWS_REGION value: ap-northeast-1 - name: OTEL_RESOURCE_ATTRIBUTES value: ClusterName=mycluster imagePullPolicy: Always resources: limits: cpu: 256m memory: 512Mi requests: cpu: 32m memory: 24Mi volumeMounts: - name: otel-agent-config-vol mountPath: /conf volumes: - name: otel-agent-config-vol configMap: name: otel-agent-conf-prometheus items: - key: otel-agent-config path: otel-agent-config.yaml
この Issue コメントを参考にして、カスタム定義を入れた ConfigMap を作成する。スクレイプは static_configs で固定の設定なので、kube-state-metrics をデプロした Namespace 名と Service 名に合わせる必要がある。
--- apiVersion: v1 kind: ConfigMap metadata: name: otel-agent-conf-prometheus namespace: aws-otel-eks labels: app: opentelemetry component: otel-agent-conf data: otel-agent-config: | extensions: health_check: receivers: prometheus: config: global: scrape_interval: 1m scrape_timeout: 10s scrape_configs: - job_name: 'kube-state-metrics' static_configs: - targets: [ 'prometheus-kube-state-metrics.prometheus.svc.cluster.local:8080' ] processors: resourcedetection/ec2: detectors: [ env ] timeout: 2s override: false resource: attributes: - key: TaskId from_attribute: job action: insert - key: receiver value: "prometheus" action: insert exporters: awsemf: namespace: ContainerInsights/Prometheus log_group_name: "/aws/containerinsights/{ClusterName}/prometheus" log_stream_name: "{TaskId}" resource_to_telemetry_conversion: enabled: true dimension_rollup_option: NoDimensionRollup metric_declarations: - dimensions: [ [ ClusterName, deployment, namespace ], [ ClusterName, namespace ], [ ClusterName ] ] metric_name_selectors: - "^kube_deployment_spec_replicas$" - "^kube_deployment_status_replicas$" - "^kube_deployment_status_replicas_ready$" - "^kube_deployment_status_replicas_available$" - "^kube_deployment_status_replicas_unavailable$" label_matchers: - label_names: - service.name regex: "^kube-state-metrics$" - dimensions: [ [ ClusterName, statefulset, namespace ], [ ClusterName, namespace ], [ ClusterName ] ] metric_name_selectors: - "^kube_statefulset_replicas$" - "^kube_statefulset_status_replicas$" - "^kube_statefulset_status_replicas_ready$" - "^kube_statefulset_status_replicas_available$" label_matchers: - label_names: - service.name regex: "^kube-state-metrics$" - dimensions: [ [ ClusterName, daemonset, namespace ], [ ClusterName, namespace ], [ ClusterName ] ] metric_name_selectors: - "^kube_daemonset_status_desired_number_scheduled$" - "^kube_daemonset_status_number_ready$" - "^kube_daemonset_status_number_available$" - "^kube_daemonset_status_number_unavailable$" label_matchers: - label_names: - service.name regex: "^kube-state-metrics$" - dimensions: [ [ ClusterName, namespace, phase ], [ ClusterName, phase ], [ ClusterName ] ] metric_name_selectors: - "^kube_pod_status_ready$" - "^kube_pod_status_scheduled$" - "^kube_pod_status_unschedulable$" - "^kube_pod_status_phase$" label_matchers: - label_names: - service.name regex: "^kube-state-metrics$" - dimensions: [ [ ClusterName, condition ] ] metric_name_selectors: - "^kube_node_status_condition$" label_matchers: - label_names: - service.name regex: "^kube-state-metrics$" service: pipelines: metrics: receivers: [prometheus] processors: [resourcedetection/ec2, resource] exporters: [awsemf]
デプロイする。
helmfile apply
確認
/aws/containerinsights/mycluster/prometheus ロググループを確認する。TaskId がとれていないのか、ログストリーム名が設定できていないが、EMF 形式のログが送られている。
{ "ClusterName": "mycluster", "OTelLib": "otelcol/prometheusreceiver", "Version": "1", "_aws": { "CloudWatchMetrics": [ { "Namespace": "ContainerInsights/Prometheus", "Dimensions": [ [ "ClusterName", "daemonset", "namespace" ], [ "ClusterName", "namespace" ], [ "ClusterName" ] ], "Metrics": [ { "Name": "kube_daemonset_status_number_available" }, { "Name": "kube_daemonset_status_number_unavailable" }, { "Name": "kube_daemonset_status_desired_number_scheduled" }, { "Name": "kube_daemonset_status_number_ready" } ] } ], "Timestamp": 1688664351790 }, "daemonset": "kube-proxy", "http.scheme": "http", "kube_daemonset_annotations": 1, "kube_daemonset_created": 1688650419, "kube_daemonset_labels": 1, "kube_daemonset_metadata_generation": 1, "kube_daemonset_status_current_number_scheduled": 2, "kube_daemonset_status_desired_number_scheduled": 2, "kube_daemonset_status_number_available": 2, "kube_daemonset_status_number_misscheduled": 0, "kube_daemonset_status_number_ready": 2, "kube_daemonset_status_number_unavailable": 0, "kube_daemonset_status_observed_generation": 1, "kube_daemonset_status_updated_number_scheduled": 2, "namespace": "kube-system", "net.host.name": "prometheus-kube-state-metrics.prometheus.svc.cluster.local", "net.host.port": "8080", "prom_metric_type": "gauge", "receiver": "prometheus", "service.instance.id": "prometheus-kube-state-metrics.prometheus.svc.cluster.local:8080", "service.name": "kube-state-metrics" }
どのメトリクスをとるかはもう少し精査が必要だが、メトリクスもとれている。
補足
ADOT Collector ではなく、CloudWatch Prometheus Agent でも同じことが可能。
スクレイプ設定は以下のようになる。
--- # create configmap for prometheus scrape config apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: amazon-cloudwatch data: # prometheus config prometheus.yaml: | global: scrape_interval: 1m scrape_timeout: 10s scrape_configs: - job_name: 'kube-state-metrics' static_configs: - targets: [ 'kube-state-metrics.kube-system.svc.cluster.local:8080' ]
マッピング設定は以下のようになる。ADOT Collector の場合と微妙に違うので注意。
--- # create configmap for prometheus cwagent config apiVersion: v1 kind: ConfigMap metadata: name: prometheus-cwagentconfig namespace: amazon-cloudwatch data: # cwagent json config cwagentconfig.json: | { "logs": { "metrics_collected": { "prometheus": { "prometheus_config_path": "/etc/prometheusconfig/prometheus.yaml", "emf_processor": { "metric_declaration": [ { "source_labels": ["job"], "label_matcher": "^kube-state-metrics$", "dimensions": [ [ "ClusterName", "deployment", "namespace" ], [ "ClusterName", "namespace" ], [ "ClusterName" ] ], "metric_selectors": [ "^kube_deployment_spec_replicas$", "^kube_deployment_status_replicas$", "^kube_deployment_status_replicas_ready$", "^kube_deployment_status_replicas_available$", "^kube_deployment_status_replicas_unavailable$" ] }, { "source_labels": ["job"], "label_matcher": "^kube-state-metrics$", "dimensions": [ [ "ClusterName", "statefulset", "namespace" ], [ "ClusterName", "namespace" ], [ "ClusterName" ] ], "metric_selectors": [ "^kube_statefulset_replicas$", "^kube_statefulset_status_replicas$", "^kube_statefulset_status_replicas_ready$", "^kube_statefulset_status_replicas_available$" ] }, { "source_labels": ["job"], "label_matcher": "^kube-state-metrics$", "dimensions": [ [ "ClusterName", "daemonset", "namespace" ], [ "ClusterName", "namespace" ], [ "ClusterName" ] ], "metric_selectors": [ "^kube_daemonset_status_desired_number_scheduled$", "^kube_daemonset_status_number_ready$", "^kube_daemonset_status_number_available$", "^kube_daemonset_status_number_unavailable$" ] }, { "source_labels": ["job"], "label_matcher": "^kube-state-metrics$", "dimensions": [ [ "ClusterName", "namespace", "phase" ], [ "ClusterName", "phase" ], [ "ClusterName" ] ], "metric_selectors": [ "^kube_pod_status_ready$", "^kube_pod_status_scheduled$", "^kube_pod_status_unschedulable$", "^kube_pod_status_phase$" ] }, { "source_labels": ["job"], "label_matcher": "^kube-state-metrics$", "dimensions": [ [ "ClusterName", "condition" ] ], "metric_selectors": [ "^kube_node_status_condition$" ] } ] } } }, "force_flush_interval": 5 } }
送られた EMF のログは以下のようになっていた。
{ "CloudWatchMetrics": [ { "Metrics": [ { "Name": "kube_daemonset_status_number_ready" }, { "Name": "kube_daemonset_status_desired_number_scheduled" }, { "Name": "kube_daemonset_status_number_available" }, { "Name": "kube_daemonset_status_number_unavailable" } ], "Dimensions": [ [ "ClusterName", "daemonset", "namespace" ], [ "ClusterName", "namespace" ], [ "ClusterName" ] ], "Namespace": "ContainerInsights/Prometheus" } ], "ClusterName": "fully-private", "Timestamp": "1688665159898", "Version": "0", "daemonset": "efs-csi-node", "instance": "kube-state-metrics.kube-system.svc.cluster.local:8080", "job": "kube-state-metrics", "kube_daemonset_annotations": 1, "kube_daemonset_created": 1687945935, "kube_daemonset_labels": 1, "kube_daemonset_metadata_generation": 1, "kube_daemonset_status_current_number_scheduled": 2, "kube_daemonset_status_desired_number_scheduled": 2, "kube_daemonset_status_number_available": 2, "kube_daemonset_status_number_misscheduled": 0, "kube_daemonset_status_number_ready": 2, "kube_daemonset_status_number_unavailable": 0, "kube_daemonset_status_observed_generation": 1, "kube_daemonset_status_updated_number_scheduled": 2, "namespace": "kube-system", "prom_metric_type": "gauge" }
読書メモ: 専門医が教える鼻と睡眠の深い関係 鼻スッキリで夜ぐっすり
鼻うがい関連の本を何冊か読もうと思ったが、堀田修先生の本がほとんどだったので、堀田修先生以外の本で探して読んだ本。ちょうど去年の今頃睡眠の本を読んでたころに、目にとまっていたが読まなかった本でもある。
全体的な感想
タイトルの通り、以前読んだ睡眠の本と、鼻うがいの本の両方を合わせた本だった。睡眠と鼻うがいに関しては新しい情報はあまりなかったが、よい睡眠睡眠のためには鼻呼吸ができ、鼻の状態がよいことが大事であるということが書かれている。鼻炎に関連する治療法が一通り書かれていて参考になる。睡眠時無呼吸症候群に関する話題も多い。自分が睡眠時無呼吸症候群ではないかと疑い、10 年くらい前に検査を受けたことを思い出した。そのときは異常判定はされなかった。
3 つに要約
- 睡眠時無呼吸症候群の治療法である CPAP は、鼻呼吸が前提であり、鼻呼吸ができないと CPAP は使えない。
- 幼少期に口呼吸の期間が長いと、顎の発達がわるくなり歯並びが悪くなったり、学習能力が悪くなったりするので、子どものいびきや鼻づまりには要注意。
- 身体のさまざまな不調の原因として上咽頭炎がある可能性があり、EAT による治療は効果がある可能性がある。
気になった部分の引用
ネーザルサイクルを直訳すると「鼻の周期」という意味ですが、左右の鼻が周期を持つ理由として、粘膜が腫れている側の呼吸を休止させることにより、鼻の換気機能を修復しているといわれています。他にも、休止中に免疫物質を運搬し、免疫機能を強化しているのだろうとも考えられています。ネーザルサイクルの周期は人によって異なりますが、昼間は2~3時間ごとに左右交代しているものの、夜間寝ているときはもっとゆったりと遅いサイクルになり、寝返りやレム睡眠に移行したときに左右が入れ替わりやすいようです。
左右の鼻というのは交互に通りやすい方が交代しているらしい。
ステロイド点鼻薬には即効性はないものの、用法通り使用することにより効果が維持されることを期待して使用します。また、用法通りに使用し続けることにより、アレルギー性鼻炎の治療効果が最も高いとされています。一方、市販の点鼻薬は血管収縮薬が含まれているため、即効性があり、楽になることからつい乱用されがちな面があります。この市販の点鼻薬を長期にわたって使用すると、薬が切れたときに鼻づまりが余計にひどくなる、「薬剤性鼻炎」という状態になってしまいます。
最近もらった点鼻薬を見てみたら、血管収縮剤の含まれているタイプだったので、もともとあまり使っていなかったが、乱用はしない方がよいのだと思った。
本来、息をするとき、胸とお腹は一緒に膨らんで、しぼんで……という動きをします。睡眠時にいびきをかく、時々息が止まってしまう、といった子どもでは、睡眠中に胸とお腹の動きが一緒に動かず逆転し、まるでシーソーのような動きの呼吸をすることがあります。これを「呼吸努力」と言います。よく観察してみてください。
子どもが「呼吸努力」していないか確認してみたが、大丈夫そうであったので安心した。
1日1回、舌下に投与し3年を目標に治療を継続しますが、治療効果はスギ花粉で70%前後、ダニアレルギーでは80~90%と高い治療効果が期待されます。また、3年で治療を終了した後もその効果は4~5年経過した後も80%以上持続されていると報告されています(前出「鼻アレルギー診療ガイドライン」より)。長い期間を要する治療法ですが、これにより症状の程度を優位に抑えてくれることは、それこそが大きな意味を有しており、鼻閉にまつわる眠りに関する問題や症状を改善しうる治療だと思います。
自分はハウスダストとスギ花粉のアレルギーがあるので、舌下免疫療法に興味がある。20 年前は舌下免疫療法はなくて、減感作療法をやったことがあるが、ちゃんと続けられなかった。
そのため私は、毎晩のようにトイレ覚醒が多い方には寝る前3時間以降、極力水分を取らないようにとお伝えしています。薬を飲んだり、夏にのどが渇いたりしたときには、のどをうるおす程度の量に、水以外であればノンカフェインのものを飲むように勧めています。
夜トイレに起きてしまうことは多いのだが、水分を控えるのはあまりよくないような気がしてやっていなかったが、多少控えようと思った。
読書メモ: ウイルスを寄せつけない! 痛くない鼻うがい
花粉症なのか体調を崩したのをきっかけに、数年前に買ったっきり放置していた「ハナクリーン EX」を使ってみたところ、快適に鼻うがいができたので、鼻うがいについて勉強してみたくなり読んだ。
本とは関係ないが、昔から鼻うがいはやりたかったが上手くできたことがなく、それが「ハナクリーン EX」を使ったら簡単にできたのは感動的な体験であった。
ちなみに、耳鼻咽喉科でアレルギーのテストをやってもらったところ、ハウスダストが強めのアレルギーがあり、スギ花粉にも弱めのアレルギーがあった。
全体的な感想
鼻うがいの本であるが、この著者としては、EAT という上咽頭炎の治療法を本丸と考えているようであり、鼻うがいは補助的な位置づけと感じた。鼻うがいの効能についての研究がいくつか紹介されているが、エビデンスとしては弱いものが多いようだった。時期的に、鼻うがいに新型コロナウイルスの予防と治療の可能性があることが、科学的エビデンスがないと断った上で述べられている。全般的に、エビデンスに基づいた記載が少なく、逆に、鼻うがいには科学的な根拠はさほどないのかなという印象をもってしまった。
3 つのポイントに要約
- 風邪の症状の震源地は上咽頭にあるので、鼻うがいによってウイルス等を洗い流すのは効果的。
- 慢性上咽頭炎はさまざまな体の不調の原因となる。EAT という治療法が効果的。
- 鼻うがいは 1% 程度の生理食塩水が快適であるが、2%程度の高張食塩水のほうが効果的。予防目的には 1%、治療目的では 2% を使うなど使い分けるとよい。
気になった部分の引用
日本では、鼻うがいの洗浄液として人の体液と同じ濃度の生理食塩水を使うのが一般的ですが、高張食塩水(濃い食塩水)の方が粘膜のむくみや炎症を軽減しやすいとの報告がこれまでに多数あります。鼻炎と副鼻腔炎の症例の報告をまとめて解析したところ、生理食塩水よりも高張食塩水が症状を改善する効果が勝ることが示唆されています。しかしその一方で、高張食塩水の鼻うがいは、炎症を引き起こすヒスタミンやサブスタンスP*hを作り出し、鼻づまり・鼻水・疼痛の原因になりうることも報告されています。簡単にいうと、「鼻うがいの効果は高張食塩水の方が期待できるが、副反応も出やすい」ということになります。ですから、「風邪予防のために行う毎日の『鼻うがい』には約1%の食塩水を使い、風邪かなと思ったら食塩水の濃度を約2%にする」といった具合に、用途に応じて濃度を変えるのが良いかもしれません。
こう書いてあったので、試しに 2% で試してみたところ、鼻うがい自体は少しツンとして不快になったが、その後の鼻の通りはよい感じがする。
私は外来の診療をしていて、「一年中風邪をひいている」「季節の変わり目には必ず風邪をひく」「周りの人の風邪をすぐもらう」と話す患者さんが少なからずいることに気づきました。そういう人は、他人の風邪はすぐもらってしまうのに自分の風邪は人にうつさない、という特徴があります。このような人を調べてみると、風邪をひいていないときも激しい慢性上咽頭炎がみられることが分かりました。つまり、風邪を引き起こしているのはウイルスではないのです。もともと慢性上咽頭炎を起こしていて、寒さや過労などで慢性上咽頭炎が悪化したときに、風邪をひいたと感じているのです。
自分も季節の変わり目や、疲れがたまったときに体調を崩すので、慢性上咽頭炎を持っているのかもしれないと思い、興味がわいた。
口呼吸の習慣があると風邪をひきやすいだけでなく、口の奥の両側にある扁桃腺の炎症を起こしやすくなります。扁桃に慢性的な炎症が起こると、扁桃炎自体の症状は軽くても、IgA腎症をはじめとする腎臓の病気や掌蹠膿疱症という治りにくい皮膚炎など、さまざまな病気を引き起こす原因となります。
体調が悪くなったとき、自覚症状として扁桃腺が腫れる感じがするのと、最近の健康診断で腎臓のスコアがよくないが、これが口呼吸や慢性上咽頭炎に関係があるのかもしれない。
そしてウイルス感染以外で上咽頭炎の原因として比較的多いのが「GERD(胃食道逆流症)」です。これは胃酸を含んだ胃の内容物が、胃から食道に逆流することによって発生する疾患で、食道裂孔ヘルニアがあるとGERDを起こしやすくなります。
これも自分がまさに逆流性食道炎で治療中なので、これも上咽頭炎とつながるのかとびっくりした。EAT による慢性上咽頭炎の治療にがぜん興味がわいたので、機会を見つけて受けてみたい。