最近公司需要在 k8s 环境接入 SkyWalking,要让应用无感知接入。
开始打算的是把agent文件放到基础镜像中,这样应用只需要引用包含agent的基础镜像即可。但是这样会有几个问题,首先不好管理agent,升级需要应用重新打镜像部署,动静太大。第二,不是所有应用都需要接入,要按需引入不同基础镜像,这样就多个一个步骤,应用会有感知。
最终我们使用的是通过initContainers的方式集成,跟helm搭配起来,只需要修改参数配置,就可以控制集成、移除agent。完整方案如下:
把agent文件放进镜像中,并进行配置。升级agent只需要更换agent.zip然后重新打镜像即可。
FROM alpine:3.9.4
# 设置变量
ENV APP_HOME=/home \
VERSION=8.3.0
# 增加用户和用户组
ARG USER=appl
ARG USER_GROUP=appl
RUN addgroup -g 1500 $USER_GROUP && \
adduser -D -u 1500 $USER -G $USER_GROUP
# 切换用户安装
USER root
# 切换到应用目录
WORKDIR ${APP_HOME}
# 复制探针文件和可选插件到镜像
COPY agent.zip apm-aliyun-ons-1.x-plugin-2.1.0.jar apm-oracle-10.x-plugin-2.1.0.jar ./
# 安装探针
RUN unzip agent.zip && \
rm agent.zip && \
mv apm-aliyun-ons-1.x-plugin-2.1.0.jar apm-oracle-10.x-plugin-2.1.0.jar agent/plugins && \
echo -e "\nplugin.springmvc.collect_http_params=true\nplugin.tomcat.collect_http_params=true\nplugin.http.http_params_length_threshold=2048\nplugin.mysql.trace_sql_parameters=true\n" >> agent/config/agent.config && \
cp agent/optional-plugins/apm-trace-ignore-plugin-${VERSION}.jar agent/plugins && \
touch agent/config/apm-trace-ignore-plugin.config && \
echo "trace.ignore_path=\${SW_AGENT_TRACE_IGNORE_PATH:com.alibaba.dubbo.monitor.MonitorService.collect(URL),/healthCheck,/**/healthCheck,/**/actuator/**,/sba/**}" >> agent/config/apm-trace-ignore-plugin.config && \
chown -R appl:appl ${APP_HOME}
USER appl
复制代码
可以通过配置 skywalking.enabled
参数来启用和停用。
skywalking:
enabled: true
backendService: "sw-oap.dev:11800"
init:
pullPolicy: IfNotPresent
repository: harbor-dev.k8s.com/skywalking-agent-init
tag: 1.0.0
resources:
limits:
cpu: 250m
memory: 500Mi
requests:
cpu: 200m
memory: 200Mi
复制代码
agent需要jvm参数中配置javaagent才能生效,根据自己charts模板添加到合适的位置。
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "application.name" . }}-jvm-configmap
namespace: {{ .Values.namespace }}
labels:
{{ include "application.labels" . | indent 4 }}
data:
{{- (.Files.Glob "files/jvm.conf").AsConfig| nindent 2 }}
# 把探针配置加到 JAVA_OPTS 中
{{- if .Values.skywalking.enabled }}
{{ printf "JAVA_OPTS=\"$JAVA_OPTS -javaagent:%s/agent/skywalking-agent.jar\"" .Values.appHome | indent 4 }}
{{- end }}
复制代码
使用initContainers将agent文件复制到主容器中
{{- $appHome := .Values.appHome -}}
{{- $appName := .Values.appName -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "application.name" . }}
namespace: {{ .Values.namespace }}
labels:
{{ include "application.labels" . | indent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "application.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app: {{ include "application.name" . }}
template:
metadata:
labels:
{{ include "application.labels" . | indent 8 }}
spec:
# 初始化容器,复制探针文件到共享目录
{{- if .Values.skywalking.enabled }}
initContainers:
- name: init-agent
image: "{{ .Values.skywalking.init.repository }}:{{ .Values.skywalking.init.tag }}"
imagePullPolicy: {{ .Values.skywalking.init.pullPolicy }}
command: [ 'sh', '-c', "mkdir -p {{ printf "%s/%s" .Values.appHome "agent" }} && cp -r /home/agent/* {{ printf "%s/%s" .Values.appHome "agent" }}" ]
resources:
{{- toYaml .Values.skywalking.init.resources | nindent 12 }}
volumeMounts:
- name: agent-dir
mountPath: {{ printf "%s/%s" .Values.appHome "agent" }}
{{- end }}
containers:
- name: {{ include "application.name" . }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}/{{ .Values.appName }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
resources:
{{- if .Values.resources.requests }}
requests:
memory: {{ .Values.resources.requests.memory | quote }}
cpu: {{ .Values.resources.requests.cpu | quote }}
{{- end }}
limits:
memory: {{ .Values.resources.limits.memory | quote }}
cpu: {{ .Values.resources.limits.cpu | quote }}
ports:
{{- range $index, $service := .Values.service }}
- name: {{ $service.name }}
containerPort: {{ $service.port }}
protocol: TCP
{{- end }}
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.appUri }}{{ .Values.livenessProbe.path }}
{{- range $index, $service := .Values.service }}
{{- if eq $service.name "http" }}
port: {{ $service.port }}
{{- end }}
{{- end }}
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
successThreshold: {{ .Values.livenessProbe.successThreshold }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
{{- end }}
{{- if .Values.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: {{ .Values.appUri }}{{ .Values.readinessProbe.path }}
{{- range $index, $service := .Values.service }}
{{- if eq $service.name "http" }}
port: {{ $service.port }}
{{- end }}
{{- end }}
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
successThreshold: {{ .Values.readinessProbe.successThreshold }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
{{- end }}
volumeMounts:
- name: {{ include "application.name" . }}-log
mountPath: "{{ .Values.appHome }}/log"
- name: {{ include "application.name" . }}-jvm-configmap
mountPath: "{{ .Values.appHome }}/jvm .conf"
subPath: jvm.conf
# 挂载卷,引入探针文件
{{- if .Values.skywalking.enabled }}
- name: agent-dir
mountPath: {{ printf "%s/%s" .Values.appHome "agent" }}
{{- end }}
# 环境变量,用来设置探针所需参数
{{- if .Values.skywalking.enabled }}
env:
- name: SW_AGENT_NAME
value: {{ include "application.name" . }}
- name: SW_LOGGING_DIR
value: {{ printf "%s/%s" .Values.appHome "log" }}
- name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
value: {{ .Values.skywalking.backendService }}
{{- end }}
volumes:
- name: {{ include "application.name" . }}-log
persistentVolumeClaim:
claimName: {{ include "application.name" . }}-pvc-log
{{- if (.Files.Glob "files/app.conf") }}
- name: {{ include "application.name" . }}-jvm-configmap
configMap:
name: {{ include "application.name" . }}-jvm-configmap
items:
- key: jvm.conf
path: jvm.conf
{{- end }}
# 声明卷
{{- if .Values.skywalking.enabled }}
- name: agent-dir
emptyDir: {}
{{- end }}
securityContext:
runAsUser: {{ .Values.storage.securityContext.runAsUser }}
fsGroup: {{ .Values.storage.securityContext.fsGroup }}
复制代码