├── hooks
└── pre-commit
├── .github
└── workflows
│ └── auto-approve.yml
├── compile-agents-yaml.sh
├── README.md
├── metadata-agent.yaml
├── heapster.yaml
├── rbac-setup.yaml
├── logging-agent.yaml
└── agents.yaml
/hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ./compile-agents-yaml.sh
4 |
5 |
--------------------------------------------------------------------------------
/.github/workflows/auto-approve.yml:
--------------------------------------------------------------------------------
1 | # Automatically approve PRs created by our release robot account.
2 | name: Auto approve
3 | on: pull_request
4 |
5 | jobs:
6 | auto-approve:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: hmarr/auto-approve-action@v2.0.0
10 | if: github.actor == 'stackdriver-instrumentation-release'
11 | with:
12 | github-token: "${{ secrets.GITHUB_TOKEN }}"
13 |
--------------------------------------------------------------------------------
/compile-agents-yaml.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eu
2 | #
3 | # Copyright 2018 Google LLC
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | echo "# THIS FILE IS AUTO-GENERATED DO NOT EDIT" > agents.yaml
18 |
19 | GLOBIGNORE="rbac-setup.yaml:agents.yaml"
20 | for f in *.yaml; do
21 | cat $f
22 | echo -e "\n---"
23 | done >> agents.yaml
24 |
25 | echo "agents.yaml has been generated for you."
26 |
27 | git add agents.yaml
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stackdriver Kubernetes Configs
2 |
3 | A collection of Kubernetes configurations to integrate with Stackdriver
4 | products. For now, it supports [Stackdriver Logging](https://cloud.google.com/logging/)
5 | and [Stackdriver Monitoring](https://cloud.google.com/monitoring/). This repo is only used
6 | for [manual installation](https://cloud.google.com/monitoring/kubernetes-engine/customizing)
7 | on existing clusters.
8 |
9 | ## Setting up git hooks
10 |
11 | From the root directory of this repo, please run the following command:
12 |
13 | ```
14 | ln -s "$(realpath hooks/pre-commit)" "$(git rev-parse --git-dir)/hooks/pre-commit"
15 | ```
16 |
17 | This will ensure that all commits run the
18 | [`compile-agents-yaml.sh`](#compile-agents-yaml) command.
19 |
20 | ## Compile Agents YAML
21 |
22 | From the root directory of this repo, you can run the following command:
23 |
24 | ```
25 | ./compile-agents-yaml.sh
26 | ```
27 |
28 | This will ensure that all commits re-generate the `agents.yaml` file to keep it
29 | up-to-date with other YAML file changes.
30 |
31 |
--------------------------------------------------------------------------------
/metadata-agent.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: stackdriver-metadata-agent
6 | cluster-level: "true"
7 | name: stackdriver-metadata-agent-cluster-level
8 | namespace: stackdriver-agents
9 | spec:
10 | replicas: 1
11 | selector:
12 | matchLabels:
13 | app: stackdriver-metadata-agent
14 | cluster-level: "true"
15 | template:
16 | metadata:
17 | labels:
18 | app: stackdriver-metadata-agent
19 | cluster-level: "true"
20 | spec:
21 | containers:
22 | - env:
23 | - name: CLUSTER_NAME
24 | valueFrom:
25 | configMapKeyRef:
26 | name: cluster-config
27 | key: cluster_name
28 | - name: CLUSTER_LOCATION
29 | valueFrom:
30 | configMapKeyRef:
31 | name: cluster-config
32 | key: cluster_location
33 | - name: GOOGLE_APPLICATION_CREDENTIALS
34 | valueFrom:
35 | configMapKeyRef:
36 | name: google-cloud-config
37 | key: credentials_path
38 | - name: PROMETHEUS_PORT
39 | value: "8888"
40 | args:
41 | - -logtostderr
42 | - -v=1
43 | image: gcr.io/stackdriver-agents/metadata-agent-go:1.3.0
44 | imagePullPolicy: IfNotPresent
45 | name: metadata-agent
46 | resources:
47 | requests:
48 | cpu: 40m
49 | memory: 50Mi
50 | ports:
51 | - name: metadata-agent
52 | containerPort: 8888
53 | terminationMessagePath: /dev/termination-log
54 | terminationMessagePolicy: File
55 | volumeMounts:
56 | - mountPath: /etc/google-cloud/
57 | name: google-cloud-config
58 | - mountPath: /etc/ssl/certs
59 | name: ssl-certs
60 | dnsPolicy: ClusterFirst
61 | restartPolicy: Always
62 | schedulerName: default-scheduler
63 | securityContext: {}
64 | serviceAccount: metadata-agent
65 | serviceAccountName: metadata-agent
66 | tolerations:
67 | - operator: "Exists"
68 | effect: "NoExecute"
69 | - operator: "Exists"
70 | effect: "NoSchedule"
71 | terminationGracePeriodSeconds: 5
72 | volumes:
73 | - configMap:
74 | defaultMode: 420
75 | name: google-cloud-config
76 | name: google-cloud-config
77 | - hostPath:
78 | path: /etc/ssl/certs
79 | type: Directory
80 | name: ssl-certs
81 | strategy:
82 | rollingUpdate:
83 | maxUnavailable: 1
84 | type: RollingUpdate
85 |
--------------------------------------------------------------------------------
/heapster.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | k8s-app: stackdriver-heapster
6 | version: v1.6.1
7 | name: heapster
8 | namespace: stackdriver-agents
9 | spec:
10 | replicas: 1
11 | selector:
12 | matchLabels:
13 | k8s-app: stackdriver-heapster
14 | strategy:
15 | rollingUpdate:
16 | maxSurge: 1
17 | maxUnavailable: 1
18 | type: RollingUpdate
19 | template:
20 | metadata:
21 | creationTimestamp: null
22 | labels:
23 | k8s-app: stackdriver-heapster
24 | version: v1.6.1
25 | spec:
26 | containers:
27 | - env:
28 | - name: CLUSTER_NAME
29 | valueFrom:
30 | configMapKeyRef:
31 | name: cluster-config
32 | key: cluster_name
33 | - name: CLUSTER_LOCATION
34 | valueFrom:
35 | configMapKeyRef:
36 | name: cluster-config
37 | key: cluster_location
38 | - name: GOOGLE_APPLICATION_CREDENTIALS
39 | valueFrom:
40 | configMapKeyRef:
41 | name: google-cloud-config
42 | key: credentials_path
43 | command:
44 | - /heapster
45 | - --source=kubernetes.summary_api:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true
46 | - --sink=stackdriver:?cluster_name=$(CLUSTER_NAME)&cluster_location=$(CLUSTER_LOCATION)&zone=$(CLUSTER_LOCATION)&use_old_resources=false&use_new_resources=true&min_interval_sec=100&batch_export_timeout_sec=110
47 | image: gcr.io/stackdriver-agents/heapster-amd64:v1.6.1
48 | imagePullPolicy: Always
49 | livenessProbe:
50 | failureThreshold: 3
51 | httpGet:
52 | path: /healthz
53 | port: 8082
54 | scheme: HTTP
55 | initialDelaySeconds: 180
56 | periodSeconds: 10
57 | successThreshold: 1
58 | timeoutSeconds: 5
59 | name: heapster
60 | resources:
61 | limits:
62 | cpu: 88m
63 | memory: 204Mi
64 | requests:
65 | cpu: 88m
66 | memory: 204Mi
67 | terminationMessagePath: /dev/termination-log
68 | terminationMessagePolicy: File
69 | volumeMounts:
70 | - mountPath: /etc/google-cloud/
71 | name: google-cloud-config
72 | - command:
73 | - /pod_nanny
74 | - --cpu=80m
75 | - --extra-cpu=0.5m
76 | - --memory=140Mi
77 | - --extra-memory=4Mi
78 | - --threshold=5
79 | - --deployment=heapster
80 | - --container=heapster
81 | - --poll-period=300000
82 | - --estimator=exponential
83 | env:
84 | - name: MY_POD_NAME
85 | valueFrom:
86 | fieldRef:
87 | apiVersion: v1
88 | fieldPath: metadata.name
89 | - name: MY_POD_NAMESPACE
90 | valueFrom:
91 | fieldRef:
92 | apiVersion: v1
93 | fieldPath: metadata.namespace
94 | image: gcr.io/google_containers/addon-resizer:1.7
95 | imagePullPolicy: IfNotPresent
96 | name: heapster-nanny
97 | resources:
98 | limits:
99 | cpu: 50m
100 | memory: 112360Ki
101 | requests:
102 | cpu: 50m
103 | memory: 112360Ki
104 | terminationMessagePath: /dev/termination-log
105 | terminationMessagePolicy: File
106 | dnsPolicy: ClusterFirst
107 | restartPolicy: Always
108 | schedulerName: default-scheduler
109 | securityContext: {}
110 | serviceAccount: heapster
111 | serviceAccountName: heapster
112 | terminationGracePeriodSeconds: 30
113 | volumes:
114 | - configMap:
115 | defaultMode: 420
116 | name: google-cloud-config
117 | name: google-cloud-config
118 |
--------------------------------------------------------------------------------
/rbac-setup.yaml:
--------------------------------------------------------------------------------
1 | # How to apply this YAML file:
2 | # $ kubectl apply -f rbac-setup.yaml --as=admin --as-group=system:masters
3 | #
4 | # Namespace for Stackdriver Agents related components.
5 | apiVersion: v1
6 | kind: Namespace
7 | metadata:
8 | name: stackdriver-agents
9 | ---
10 | # Config map for setting GOOGLE_APPLICATION_CREDENTIALS.
11 | apiVersion: v1
12 | data:
13 | credentials_path: ""
14 | kind: ConfigMap
15 | metadata:
16 | name: google-cloud-config
17 | namespace: stackdriver-agents
18 | ---
19 | # Config map for setting CLUSTER_NAME and CLUSTER_LOCATION env vars.
20 | apiVersion: v1
21 | data:
22 | cluster_name: ""
23 | cluster_location: ""
24 | kind: ConfigMap
25 | metadata:
26 | name: cluster-config
27 | namespace: stackdriver-agents
28 | ---
29 | # Service account for Metadata Agent.
30 | apiVersion: v1
31 | kind: ServiceAccount
32 | metadata:
33 | name: metadata-agent
34 | namespace: stackdriver-agents
35 | ---
36 | # ClusterRole with permissions required by Metadata Agent.
37 | apiVersion: rbac.authorization.k8s.io/v1
38 | kind: ClusterRole
39 | metadata:
40 | name: stackdriver-user:metadata-agent
41 | namespace: stackdriver-agents
42 | rules:
43 | - apiGroups:
44 | - '*'
45 | resources:
46 | - '*'
47 | verbs:
48 | - watch
49 | - get
50 | - list
51 | ---
52 | # ClusterRoleBinding for Metadata Agent.
53 | apiVersion: rbac.authorization.k8s.io/v1
54 | kind: ClusterRoleBinding
55 | metadata:
56 | name: stackdriver-user:metadata-agent
57 | namespace: stackdriver-agents
58 | roleRef:
59 | apiGroup: rbac.authorization.k8s.io
60 | kind: ClusterRole
61 | name: stackdriver-user:metadata-agent
62 | subjects:
63 | - kind: ServiceAccount
64 | name: metadata-agent
65 | namespace: stackdriver-agents
66 | ---
67 | # Service account for Logging Agent.
68 | apiVersion: v1
69 | kind: ServiceAccount
70 | metadata:
71 | name: logging-agent
72 | namespace: stackdriver-agents
73 | ---
74 | # ClusterRole with permissions required by Logging Agent
75 | # filter_kubernetes_metadata plugin.
76 | apiVersion: rbac.authorization.k8s.io/v1
77 | kind: ClusterRole
78 | metadata:
79 | name: stackdriver-user:logging-agent
80 | namespace: stackdriver-agents
81 | rules:
82 | - apiGroups:
83 | - ""
84 | resources:
85 | - pods
86 | - namespaces
87 | verbs:
88 | - watch
89 | - get
90 | - list
91 | ---
92 | # ClusterRoleBinding for Logging Agent.
93 | apiVersion: rbac.authorization.k8s.io/v1
94 | kind: ClusterRoleBinding
95 | metadata:
96 | name: stackdriver-user:logging-agent
97 | namespace: stackdriver-agents
98 | roleRef:
99 | apiGroup: rbac.authorization.k8s.io
100 | kind: ClusterRole
101 | name: stackdriver-user:logging-agent
102 | subjects:
103 | - kind: ServiceAccount
104 | name: logging-agent
105 | namespace: stackdriver-agents
106 | ---
107 | # Service account for Heapster.
108 | apiVersion: v1
109 | kind: ServiceAccount
110 | metadata:
111 | name: heapster
112 | namespace: stackdriver-agents
113 | ---
114 | # ClusterRole with permissions required by Heapster.
115 | apiVersion: rbac.authorization.k8s.io/v1
116 | kind: ClusterRole
117 | metadata:
118 | name: stackdriver-user:heapster
119 | namespace: stackdriver-agents
120 | rules:
121 | - apiGroups:
122 | - ""
123 | resources:
124 | - events
125 | - namespaces
126 | - nodes
127 | - nodes/stats
128 | - pods
129 | verbs:
130 | - get
131 | - list
132 | - watch
133 | - apiGroups:
134 | - extensions
135 | resources:
136 | - deployments
137 | verbs:
138 | - get
139 | - list
140 | - watch
141 | ---
142 | # ClusterRoleBinding for Heapster.
143 | apiVersion: rbac.authorization.k8s.io/v1
144 | kind: ClusterRoleBinding
145 | metadata:
146 | name: stackdriver-user:heapster
147 | namespace: stackdriver-agents
148 | roleRef:
149 | apiGroup: rbac.authorization.k8s.io
150 | kind: ClusterRole
151 | name: stackdriver-user:heapster
152 | subjects:
153 | - kind: ServiceAccount
154 | name: heapster
155 | namespace: stackdriver-agents
156 |
--------------------------------------------------------------------------------
/logging-agent.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: DaemonSet
3 | metadata:
4 | labels:
5 | app: stackdriver-logging-agent
6 | name: stackdriver-logging-agent
7 | namespace: stackdriver-agents
8 | spec:
9 | selector:
10 | matchLabels:
11 | app: stackdriver-logging-agent
12 | template:
13 | metadata:
14 | labels:
15 | app: stackdriver-logging-agent
16 | spec:
17 | containers:
18 | - env:
19 | - name: NODE_NAME
20 | valueFrom:
21 | fieldRef:
22 | apiVersion: v1
23 | fieldPath: spec.nodeName
24 | - name: K8S_NODE_NAME
25 | valueFrom:
26 | fieldRef:
27 | apiVersion: v1
28 | fieldPath: spec.nodeName
29 | - name: GOOGLE_APPLICATION_CREDENTIALS
30 | valueFrom:
31 | configMapKeyRef:
32 | name: google-cloud-config
33 | key: credentials_path
34 | - name: CLUSTER_NAME
35 | valueFrom:
36 | configMapKeyRef:
37 | name: cluster-config
38 | key: cluster_name
39 | - name: CLUSTER_LOCATION
40 | valueFrom:
41 | configMapKeyRef:
42 | name: cluster-config
43 | key: cluster_location
44 | image: gcr.io/stackdriver-agents/stackdriver-logging-agent:1.10.3
45 | imagePullPolicy: IfNotPresent
46 | livenessProbe:
47 | exec:
48 | command:
49 | - /bin/sh
50 | - -c
51 | - |
52 | LIVENESS_THRESHOLD_SECONDS=${LIVENESS_THRESHOLD_SECONDS:-300}; STUCK_THRESHOLD_SECONDS=${LIVENESS_THRESHOLD_SECONDS:-900}; if [ ! -e /var/run/google-fluentd/buffers ]; then
53 | exit 1;
54 | fi; touch -d "${STUCK_THRESHOLD_SECONDS} seconds ago" /tmp/marker-stuck; if [[ -z "$(find /var/run/google-fluentd/buffers -type f -newer /tmp/marker-stuck -print -quit)" ]]; then
55 | rm -rf /var/run/google-fluentd/buffers;
56 | exit 1;
57 | fi; touch -d "${LIVENESS_THRESHOLD_SECONDS} seconds ago" /tmp/marker-liveness; if [[ -z "$(find /var/run/google-fluentd/buffers -type f -newer /tmp/marker-liveness -print -quit)" ]]; then
58 | exit 1;
59 | fi;
60 | failureThreshold: 3
61 | initialDelaySeconds: 600
62 | periodSeconds: 60
63 | successThreshold: 1
64 | timeoutSeconds: 1
65 | name: logging-agent
66 | resources:
67 | limits:
68 | cpu: "1"
69 | memory: 300Mi
70 | requests:
71 | cpu: 100m
72 | memory: 200Mi
73 | terminationMessagePath: /dev/termination-log
74 | terminationMessagePolicy: File
75 | volumeMounts:
76 | - mountPath: /var/run
77 | name: varrun
78 | - mountPath: /var/log
79 | name: varlog
80 | - mountPath: /var/lib/docker/containers
81 | name: varlibdockercontainers
82 | readOnly: true
83 | - mountPath: /etc/google-fluentd/google-fluentd.conf
84 | subPath: google-fluentd.conf
85 | name: output-config-volume
86 | - mountPath: /etc/google-fluentd/config.d
87 | name: input-config-volume
88 | - mountPath: /etc/google-cloud/
89 | name: google-cloud-config
90 | serviceAccount: logging-agent
91 | serviceAccountName: logging-agent
92 | dnsPolicy: ClusterFirst
93 | restartPolicy: Always
94 | schedulerName: default-scheduler
95 | securityContext: {}
96 | tolerations:
97 | - operator: "Exists"
98 | effect: "NoExecute"
99 | - operator: "Exists"
100 | effect: "NoSchedule"
101 | volumes:
102 | - hostPath:
103 | path: /var/run
104 | type: ""
105 | name: varrun
106 | - hostPath:
107 | path: /var/log
108 | type: ""
109 | name: varlog
110 | - hostPath:
111 | path: /var/lib/docker/containers
112 | type: ""
113 | name: varlibdockercontainers
114 | - configMap:
115 | defaultMode: 420
116 | name: logging-agent-output-config
117 | name: output-config-volume
118 | - configMap:
119 | defaultMode: 420
120 | name: logging-agent-input-config
121 | name: input-config-volume
122 | - configMap:
123 | defaultMode: 420
124 | name: google-cloud-config
125 | name: google-cloud-config
126 | updateStrategy:
127 | rollingUpdate:
128 | maxUnavailable: 1
129 | type: RollingUpdate
130 | ---
131 | # Config map for Logging Agent input and corresponding filter plugins.
132 | apiVersion: v1
133 | kind: ConfigMap
134 | metadata:
135 | name: logging-agent-input-config
136 | namespace: stackdriver-agents
137 | data:
138 | 1.containers.input.conf: |-
139 | # This configuration file for Fluentd is used
140 | # to watch changes to Docker log files that live in the
141 | # directory /var/lib/docker/containers/ and are symbolically
142 | # linked to from the /var/log/containers directory using names that capture the
143 | # pod name and container name. These logs are then submitted to
144 | # Google Cloud Logging which assumes the installation of the cloud-logging plug-in.
145 | #
146 | # Example
147 | # =======
148 | # A line in the Docker log file might look like this JSON:
149 | #
150 | # {"log":"2014/09/25 21:15:03 Got request with path wombat\\n",
151 | # "stream":"stderr",
152 | # "time":"2014-09-25T21:15:03.499185026Z"}
153 | #
154 | # The original tag is derived from the log file's location.
155 | # For example a Docker container's logs might be in the directory:
156 | # /var/lib/docker/containers/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b
157 | # and in the file:
158 | # 997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b-json.log
159 | # where 997599971ee6... is the Docker ID of the running container.
160 | # The Kubernetes kubelet makes a symbolic link to this file on the host
161 | # machine in the /var/log/containers directory which includes the pod name,
162 | # the namespace name and the Kubernetes container name:
163 | # synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log
164 | # ->
165 | # /var/lib/docker/containers/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b-json.log
166 | # The /var/log directory on the host is mapped to the /var/log directory in the container
167 | # running this instance of Fluentd and we end up collecting the file:
168 | # /var/log/containers/synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log
169 | # This results in the tag:
170 | # var.log.containers.synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log
171 | # where 'synthetic-logger-0.25lps-pod' is the pod name, 'default' is the
172 | # namespace name, 'synth-lgr' is the container name and '997599971ee6..' is
173 | # the container ID.
174 | # The record reformer is used to extract pod_name, namespace_name and
175 | # container_name from the tag and set them in a local_resource_id in the
176 | # format of:
177 | # 'k8s_container...'.
178 | # The reformer also changes the tags to 'stderr' or 'stdout' based on the
179 | # value of 'stream'.
180 | # local_resource_id is later used by google_cloud plugin to determine the
181 | # monitored resource to ingest logs against.
182 |
183 | # Json Log Example:
184 | # {"log":"[info:2016-02-16T16:04:05.930-08:00] Some log text here\n","stream":"stdout","time":"2016-02-17T00:04:05.931087621Z"}
185 | # CRI Log Example:
186 | # 2016-02-17T00:04:05.931087621Z stdout F [info:2016-02-16T16:04:05.930-08:00] Some log text here
187 |
188 | @type tail
189 | path /var/log/containers/*.log
190 | pos_file /var/run/google-fluentd/pos-files/gcp-containers.pos
191 | # Tags at this point are in the format of:
192 | # reform.var.log.containers.__-.log
193 | tag reform.*
194 | read_from_head true
195 |
196 | @type multi_format
197 |
198 | format json
199 | time_key time
200 | time_format %Y-%m-%dT%H:%M:%S.%NZ
201 |
202 |
203 | format /^(?
206 |
207 |
208 |
209 |
210 | @type parser
211 | format /^(?\w)(?
217 |
218 |
219 | # This plugin uses environment variables KUBERNETES_SERVICE_HOST and
220 | # KUBERNETES_SERVICE_PORT to talk to the API server. These environment
221 | # variables are added by kubelet automatically.
222 | @type kubernetes_metadata
223 | # Interval in seconds to dump cache stats locally in the Fluentd log.
224 | stats_interval 300
225 | # TTL in seconds of each cached element.
226 | cache_ttl 30
227 | # Skip fetching unused metadata.
228 | skip_container_metadata true
229 | skip_master_url true
230 | skip_namespace_metadata true
231 |
232 |
233 |
234 | # We have to use record_modifier because only this plugin supports complex
235 | # logic to modify record the way we need.
236 | @type record_modifier
237 | enable_ruby true
238 |
239 | # Extract "kubernetes"->"labels" and set them as
240 | # "logging.googleapis.com/labels". Prefix these labels with
241 | # "k8s-pod" to distinguish with other labels and avoid
242 | # label name collision with other types of labels.
243 | _dummy_ ${if record.is_a?(Hash) && record.has_key?('kubernetes') && record['kubernetes'].has_key?('labels') && record['kubernetes']['labels'].is_a?(Hash); then; record["logging.googleapis.com/labels"] = record['kubernetes']['labels'].map{ |k, v| ["k8s-pod/#{k}", v]}.to_h; end; nil}
244 |
245 | # Delete this dummy field and the rest of "kubernetes" and "docker".
246 | remove_keys _dummy_,kubernetes,docker
247 |
248 |
249 |
250 | @type record_reformer
251 | enable_ruby true
252 |
253 | # Extract local_resource_id from tag for 'k8s_container' monitored
254 | # resource. The format is:
255 | # 'k8s_container...'.
256 | "logging.googleapis.com/local_resource_id" ${"k8s_container.#{tag_suffix[4].rpartition('.')[0].split('_')[1]}.#{tag_suffix[4].rpartition('.')[0].split('_')[0]}.#{tag_suffix[4].rpartition('.')[0].split('_')[2].rpartition('-')[0]}"}
257 | # Rename the field 'log' to a more generic field 'message'. This way the
258 | # fluent-plugin-google-cloud knows to flatten the field as textPayload
259 | # instead of jsonPayload after extracting 'time', 'severity' and
260 | # 'stream' from the record.
261 | message ${record['log']}
262 | # If 'severity' is not set, assume stderr is ERROR and stdout is INFO.
263 | severity ${record['severity'] || if record['stream'] == 'stderr' then 'ERROR' else 'INFO' end}
264 |
265 | tag ${if record['stream'] == 'stderr' then 'raw.stderr' else 'raw.stdout' end}
266 | remove_keys stream,log
267 |
268 |
269 | # Detect exceptions in the log output and forward them as one log entry.
270 |
271 | @type detect_exceptions
272 |
273 | remove_tag_prefix raw
274 | message message
275 | stream "logging.googleapis.com/local_resource_id"
276 | multiline_flush_interval 5
277 | max_bytes 500000
278 | max_lines 1000
279 |
280 | 2.pods.input.conf: |-
281 | # This configuration file for Fluentd is used
282 | # to watch changes to Kubernetes pod log files live in the
283 | # directory /var/log/pods/NAMESPACE_NAME_UID. The file name
284 | # is used to capture the pod namespace, name and uid. These
285 | # logs are then submitted to Google Cloud Logging with a
286 | # local_resource_id 'k8s_pod..'
287 | # which assumes the installation of the cloud-logging plug-in.
288 |
289 | @type tail
290 | path /var/log/pods/*/*.log
291 | pos_file /var/run/google-fluentd/pos-files/gcp-pods.pos
292 | # Tags at this point are in the format of:
293 | # pods.reform.var.log.pods.__..log
294 | tag pods.reform.*
295 | read_from_head true
296 |
297 | @type none
298 |
299 |
300 |
301 | @type record_reformer
302 | enable_ruby true
303 |
304 | # Extract local_resource_id from tag for 'k8s_pod' monitored
305 | # resource. The format is:
306 | # 'k8s_pod..'.
307 | "logging.googleapis.com/local_resource_id" ${"k8s_pod.#{tag_suffix[5].rpartition('.')[0].split('_')[0]}.#{tag_suffix[5].rpartition('.')[0].split('_')[1]}"}
308 |
309 | # Use the log file name as the tag. Currently only `gvisor` log is supported.
310 | tag ${"#{tag_suffix[5].rpartition('.')[0].rpartition('.')[2]}"}
311 |
312 | 7.system.input.conf: |-
313 | # Example:
314 | # Dec 21 23:17:22 gke-foo-1-1-4b5cbd14-node-4eoj startupscript: Finished running startup script /var/run/google.startup.script
315 |
316 | @type tail
317 | format syslog
318 | path /var/log/startupscript.log
319 | pos_file /var/run/google-fluentd/pos-files/gcp-startupscript.pos
320 | tag startupscript
321 |
322 |
323 | # Example:
324 | # I1118 21:26:53.975789 6 proxier.go:1096] Port "nodePort for kube-system/default-http-backend:http" (:31429/tcp) was open before and is still needed
325 |
326 | @type tail
327 | format multiline
328 | multiline_flush_interval 5s
329 | format_firstline /^\w\d{4}/
330 | format1 /^(?\w)(?