SUPER-G.EEK.JP

twitter: @hum_op_dev
github: ophum

argocdでデフォルトではないネームスペースを使う場合はtracking labelを変更したほうがよさそう

目次

この記事を書こうと思って argocd のドキュメントを見てたら似たようなことを書いてた。(けど本質的には別問題)

Switch resource tracking method¶

Also, while technically not necessary, it is strongly suggested that you switch the application tracking method from the default label setting to either annotation or annotation+label. The reasoning for this is, that application names will be a composite of the namespace’s name and the name of the Application, and this can easily exceed the 63 characters length limit imposed on label values. Annotations have a notably greater length limit.

https://argo-cd.readthedocs.io/en/stable/operator-manual/app-any-namespace/#switch-resource-tracking-method

変更する必要はないけど推奨とのこと。 理由は、label の文字数制限が 63 文字ということを挙げています。

複数の Namespace で Application リソースを扱えるように設定すると、デフォルト以外のネームスペースでデプロイすると、tracking 用の名前を <Namespace>_<アプリケーション名>といった形式に置き換えるため、文字数制限を超えてしまいデプロイできない可能性が生まれるためです。 そのため、文字数制限が label よりも長い annotations に変更することを推奨していました。

これ以外に別の問題にも当たったので紹介します。

tracking 用のラベルが汎用的なラベルを使っており、それを変更するコトによる問題

argocd はデフォルトで app.kubernetes.io/instanceという各所で使われているラベルを追跡用ラベルとして利用しています。

デフォルトではないネームスペースのアプリケーションの場合 <Namespace>_<アプリケーション名>という形式に置き換えるという話をしました。

これは文字通り app.kubernetes.io/instanceの値を置き換えます。 しかし、例えばラベルセレクターで指定している値は変更されません。 そうすると、ラベルセレクターで選択されなくなるのでアプリケーションが正常に動作しなくなります。

例: kube-prometheus-stack

kube-prometheus-stack という Helm Chart があります。 これを使うと、Prometheus Operator や NodeExporter など諸々をセットアップすることができます。

Prometheus Operator には ServiceMonitor というリソースがあります。 このリソースは任意の Service リソースを Prometheus で scrape する設定を行うためのリソースです。 この任意の Service リソースを選択するのにラベルセレクターを用いています。

1  selector:
2    matchLabels:
3    {{- with .Values.prometheus.monitor.selectorOverride }}
4      {{- toYaml . | nindent 6 }}
5    {{- else }}
6      {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }}
7    {{- end }}

https://github.com/prometheus-community/helm-charts/blob/91325827e969a04be5ff575b95a6d93ccd231095/charts/prometheus-node-exporter/templates/servicemonitor.yaml#L23-L29

デフォルトでは include "prometheus-node-exporter.selectorLabels"が展開されます。

この変数は _helpers.tplで定義されています。

1{{/*
2Selector labels
3*/}}
4{{- define "prometheus-node-exporter.selectorLabels" -}}
5app.kubernetes.io/name: {{ include "prometheus-node-exporter.name" . }}
6app.kubernetes.io/instance: {{ .Release.Name }}
7{{- end }}

https://github.com/prometheus-community/helm-charts/blob/91325827e969a04be5ff575b95a6d93ccd231095/charts/prometheus-node-exporter/templates/_helpers.tpl#L54-L60

このテンプレートを見ると release name が設定されることがわかります。

こんな感じの Application だと kube-prometheus-stack (デフォルトで Application の名前) になります。

 1apiVersion: argoproj.io/v1alpha1
 2kind: Application
 3metadata:
 4  name: kube-prometheus-stack
 5  namespace: argocds-other-ns
 6spec:
 7  syncPolicy:
 8    syncOptions:
 9      - CreateNamespace=true
10  project: default
11  sources:
12    - chart: kube-prometheus-stack
13      repoURL: https://prometheus-community.github.io/helm-charts
14      targetRevision: 62.3.1

つまり以下のように生成されます。(app.kubernetes.io/nameはデフォルトでチャート名が入ります)

1selector:
2  matchLabels:
3    app.kubernetes.io/name: kube-prometheus-stack
4    app.kubernetes.io/instance: kube-prometheus-stack

次に ServiceMonitor がマッチさせたい Service の定義を見ます。

1  labels:
2    {{- include "prometheus-node-exporter.labels" $ | nindent 4 }}
3    {{- with .Values.service.labels }}
4    {{- toYaml . | nindent 4 }}
5    {{- end }}

https://github.com/prometheus-community/helm-charts/blob/91325827e969a04be5ff575b95a6d93ccd231095/charts/prometheus-node-exporter/templates/service.yaml#L7-L11

prometheus-node-exporter.labels変数を見ます。これも _helpers.tplに定義されています。

 1{{/*
 2Common labels
 3*/}}
 4{{- define "prometheus-node-exporter.labels" -}}
 5helm.sh/chart: {{ include "prometheus-node-exporter.chart" . }}
 6app.kubernetes.io/managed-by: {{ .Release.Service }}
 7app.kubernetes.io/component: metrics
 8app.kubernetes.io/part-of: {{ include "prometheus-node-exporter.name" . }}
 9{{ include "prometheus-node-exporter.selectorLabels" . }}
10{{- with .Chart.AppVersion }}
11app.kubernetes.io/version: {{ . | quote }}
12{{- end }}
13{{- with .Values.commonLabels }}
14{{ tpl (toYaml .) $ }}
15{{- end }}
16{{- if .Values.releaseLabel }}
17release: {{ .Release.Name }}
18{{- end }}
19{{- end }}

https://github.com/prometheus-community/helm-charts/blob/91325827e969a04be5ff575b95a6d93ccd231095/charts/prometheus-node-exporter/templates/_helpers.tpl#L34-L52

いろいろありますが、{{ include "prometheus-node-exporter.selectorLabels" . }}とあるので以下のように生成されることがわかります。

1labels:
2  ...
3  app.kubernetes.io/name: kube-prometheus-stack
4  app.kubernetes.io/instance: kube-prometheus-stack
5  ...

ここで、生成したマニフェストのmetadata.labels."app.kubernetes.io/instance"を argocd が書き換えるので実際には以下のようなものがデプロイされます。

1labels:
2  ...
3  app.kubernetes.io/name: kube-prometheus-stack
4  app.kubernetes.io/instance: argocd-other-ns_kube-prometheus-stack
5  ...

Prometheus は ServiceMonitor を元にapp.kubernetes.io/instance: kube-prometheus-stackなものを scrape するので、argocd が label を書き換えた Service を scrape してくれないことがわかります。

まとめ