Kustomize 生产实战-注入监控 APM Agent
Kustomize 简介
Kubernetes 原生配置管理工具, 它自定义引入了一种无需模板的方式来定制应用程序配置,从而简化了对现成应用程序的使用。目前,在kubectl
中内置了,通过 apply -k
即可使用。
Kustomize 遍历 Kubernetes 清单以添加、删除或更新配置选项,而无需分叉。它既可以作为独立的二进制文件使用,也可以作为kubectl
的原生特性使用。
Kustomize 优势
- 完全声明式的配置定制方法
- 原生构建进
kubectl
中 - 管理任意数量的独特定制的 Kubernetes 配置
- ☸ 作为独立的二进制文件提供,用于扩展和集成到其他服务
- 定制使用的每个工件都是纯 YAML,并且可以被验证和处理
- Kustomize 支持 fork/modify/rebase 工作流
- GitOps 工具(如 ArgoCD) 对其的完美支持
Kustomize 可以做什么
️ Reference:
️URL: https://mp.weixin.qq.com/s/gmwkoqZpKbq1hM0B8XxQNw
在 Kubernetes 中我们使用 YAML 文件来声明我们的应用应该如何部署到底层的集群中,这些 YAML 文件中包含应用定义、治理需要的标签、日志、安全上下文定义、资源依赖关系等,当我们应用扩展到成百上千个 Pod 以后,管理这些 YAML 文件就会成为一场噩梦了。
最典型的就是,有很多项目要管理,同时又有多套不同的部署环境:开发环境、测试环境、UAT 环境、生产环境。甚至可能有不同的公有云 Kubernetes 发行版。那么每一套环境都需要一套各种各样的 YAML 文件, 但是它们直接只有部分细节有差异。比如:镜像 Tag,服务 Name,Label,有没有存储等。
如果全是手动,维护工作量非常巨大,同时也容易出错。
Kustomize 相比 Helm, 更适合解决这种场景的痛点:有一个基础(base)的模板管理一个项目的所有基础 YAML,更多高级的需求通过 overlay 来实现叠加覆盖。
另外还有一类典型场景,就是融合来自不同用户的配置数据(例如来自 devops/SRE 和 developers).
同时也可以结合 helm, 进行一些更高级的配置。
今天就以一个典型场景为例:生产环境 Deployment 自动注入商业(如:AppDynamics) 或开源 (SkyWalking/pinpoint) 的开箱即用的 Java Agent.
实战 - 通过 Kustomize 注入监控 APM Agent
背景概述
以 Java 为例,这里的 APM Agent 包是商业(如:AppDynamics) 或开源 (SkyWalking/pinpoint) 产品提供的开箱即用的 Agent jar 包。
在 Kubernetes 场景中,出于以下几点考虑:
- 和应用镜像分离;
- 复用
Agent jar 包做成了一个通用镜像,通过 init container 方式拷贝到运行中的应用容器中,并通过配置环境变量进行参数的自动设置。
✍️ 笔者注:
其实商业 APM 都有 Helm 或 Operator 实现自动化安装配置的功能,但是实际使用中体验不佳,不太适合我们的实际场景。
通过 Kustomize 注入监控 APM Agent 步骤
步骤简述如下:(以 AppDynamics Java Agent 为例)
- 获取原始的 Deployment yaml 文件(通过
kubectl
和kubectl neat
插件) - 通过 Kustomize 对每个 Deployment 通过
patches
实现以下步骤:- 注入
initContainers
:appd-agent-attach-java
, 该initContainers
有:volumeMounts
: 把 java agent jar 包挂载到 volume 实现共享;
- 在 Deployment -> 应用自己的 container 中,加入以下参数:
volumeMounts
: 把 java agent jar 包挂载到 volume 实现共享;- 加入各种 AppD Java agent 需要的 env 信息;
volumes
通过 tmpdir 实现共享。
- 注入
Kustomize 目录结构
目录结构如下:
inject-appd-agent/
├── base
│ └── kustomization.yaml
├── overlays
└── prod
├── appd_agent.yaml
└── kustomization.yaml
其中,后续所有需要注入 APM Agent 的应用的 Deployment, 都放在 base
目录中。
base/kustomization.yaml
resources:
- ./foo-deployment.yml
注意:
这里提一句,目前的 resources
是不支持文件通配符 (file glob) 匹配的,具体 issue 可以见这里:
但是有个临时解决方案,就是通过执行命令:kustomize edit add resource base/*.yml
运行后会遍历 file blob, 将结果一个个加到 kustomization.yaml
中。
运行后的文件可能是这样:
resources:
- ./foo-deployment.yml
- ./bar-deployment.yml
- ./a-deployment.yml
- ./b-deployment.yml
- ./c-deployment.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
overlays/prod/kustomization.yaml
bases:
- ../../base
# patchesStrategicMerge:
# - appd_agent.yaml
patches:
- path: appd_agent.yaml
target:
kind: Deployment
注意:
这里没用 patchesStrategicMerge
, 而是用了patches
. 目的就是为了批量 patch. 上面 YAML 的意思是,将appd_agent.yaml
应用于所有的 Deployment manifests 中。
overlays/prod/appd_agent.yaml
具体内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: not-important
spec:
template:
spec:
containers:
- name: app
volumeMounts:
- mountPath: /opt/appdynamics-java
name: appd-agent-repo-java
env:
- name: APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY
value: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: APPDYNAMICS_CONTROLLER_HOST_NAME
value: 192.168.1.10
- name: APPDYNAMICS_CONTROLLER_PORT
value: '8090'
- name: APPDYNAMICS_CONTROLLER_SSL_ENABLED
value: 'false'
- name: APPDYNAMICS_AGENT_ACCOUNT_NAME
value: my_account
- name: APPDYNAMICS_AGENT_APPLICATION_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: APPDYNAMICS_AGENT_TIER_NAME
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: JAVA_TOOL_OPTIONS
value:
' -Dappdynamics.agent.accountAccessKey=$(APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY)
-Dappdynamics.agent.reuse.nodeName=true -Dappdynamics.socket.collection.bci.enable=true
-javaagent:/opt/appdynamics-java/javaagent.jar'
- name: APPDYNAMICS_NETVIZ_AGENT_HOST
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: APPDYNAMICS_NETVIZ_AGENT_PORT
value: '3892'
initContainers:
- command:
- cp
- -r
- /opt/appdynamics/.
- /opt/appdynamics-java
image: appdynamics/appdynamics-java-agent:1.8-21.11.3.33314
imagePullPolicy: IfNotPresent
name: appd-agent-attach-java
resources:
limits:
cpu: 200m
memory: 75M
requests:
cpu: 100m
memory: 50M
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt/appdynamics-java
name: appd-agent-repo-java
volumes:
- name: appd-agent-repo-java
上面内容就不详细说明了,具体可以参考这篇文章,了解 APM Agent 注入的几种思路:
注意:
实践中,上面内容有几点需要注意的:
spec/template/spec/containers/name
这里往往是应用的名字,如foo
, 如果appd_agent.yaml
的内容要正确地 patch, 也需要写上同样的 container name; 这对于一个应用来说不是什么问题,但是对于批量自动化/GitOps 来说,就非常不方便。- 我之前想用 Kustomize 中的
nameReference
来实现,但是没搞出来,有知道的可以教教我 - ️20220706 11:00 update: Kustomize 出于安全考虑, 是严格按照
metadata.name
进行 merge 的, 所以通过 Kustomize 无法解决; 但是可以通过yq
(类似jq, 但是针对 yaml)来解决, 示例命令为:i=foo yq -i '.spec.template.spec.containers[0].name="strenv(i)"' appd_agent.yaml
- 我之前想用 Kustomize 中的
之前的环境变量,手动部署的时候如这个:
- name: APPDYNAMICS_AGENT_APPLICATION_NAME
value: foo
直接写死,这样不便于批量自动化/GitOps. 解决办法就是利用 Kubernetes env 的
valueFrom
能力。改为如下就可以了。valueFrom:
fieldRef:
fieldPath: metadata.name
appd_agent.yaml
的 Deployment name 是无所谓的,因为仍会是被 patch 清单的名字;另外appd_agent.yaml
也不要带namespace
, 方便批量自动化/GitOps, 可以适应所有 NameSpace.
自动化脚本
最后,自动化脚本 demo 如下:(假设脚本位于 /inject-appd-agent/scripts/
目录下)
#!/bin/bash
# USAGE:
# bash inject-appd-agent.sh default
# NAMESPACE=default
NAMESPACE=$1
# only get deploy name
deployments=$(kubectl get deploy --no-headers=true -o custom-columns=:.metadata.name -n "${NAMESPACE}")
for i in ${deployments}; do
# get deploy yaml
cd ../base && kubectl get deploy -n "${NAMESPACE}" "${i}" -o yaml | kubectl neat >./"${i}.yml"
# add the deploy yaml to base
kustomize edit add resource ./"${i}.yml"
# change appd_agent.yaml .spec.template.spec.containers[0].name
# = <the deploy name>
cd ../overlays/prod && DEPLOY="${i}" yq -i '.spec.template.spec.containers[0].name = strenv(DEPLOY)' ./appd_agent.yaml
# dry run
# kustomize build . >../../examples/output/"${i}.yml"
# deploy rollout
kubectl apply -k .
# remove the deploy yaml resource from base
cd ../../base && kustomize edit remove resource ./"${i}.yml"
done
# clean up
kustomize edit remove resource ./*.yml
cd ../overlays/prod && yq -i '.spec.template.spec.containers[0].name = "app"' ./appd_agent.yaml
运行上面脚本,即可实现对所有 Deployment 自动注入 AppD Java Agent, 并 Rollout 生效。
️ Reference
- Kustomize - Kubernetes native configuration management
- K8S 实用工具之四 - kubectl 实用插件 - 东风微鸣技术博客 (ewhisper.cn)
三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.
Kustomize 生产实战-注入监控 APM Agent的更多相关文章
- Zabbix WebUI 配置监控Zabbix Agent
Zabbix WebUI 配置监控Zabbix Agent 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.部署zabbix服务 1>.部署zabbix server 和z ...
- shell脚本编程——生产实战案例
生产实战案例 在日常的生产环境中,可能会遇到需要批量检查内网目前在线的主机IP地址有哪些,还可能需要检查这些在线的主机哪些端口是开放状态,因此依靠手工来检查是可以实现,但比较费时费力,所以需要 ...
- JSR310-新日期APIJSR310新日期API(完结篇)-生产实战
前提 前面通过五篇文章基本介绍完JSR-310常用的日期时间API以及一些工具类,这篇博文主要说说笔者在生产实战中使用JSR-310日期时间API的一些经验. 系列文章: JSR310新日期API(一 ...
- 开源一个监控数据采集Agent:OpenFalcon-SuitAgent
OpenFalcon-SuitAgent 项目地址:github 版本说明 本系统版本划分如下 alpha:内部测试版(不建议使用于生产环境) beta:公开测试版(不建议使用于生产环境) final ...
- zabbix监控windows agent安装配置
下载Windows的zabbix客户端 下载地址:http://www.zabbix.com/download.php 从官方下载Zabbix Agent后,压缩包里面有2个目录,bin和conf,c ...
- 利用ELK分析Nginx日志生产实战(高清多图)
本文以api.mingongge.com.cn域名为测试对象进行统计,日志为crm.mingongge.com.cn和risk.mingongge.com.cn请求之和(此二者域名不具生产换环境统计意 ...
- Zabbix监控 windows agent安装配置
下载Windows的zabbix客户端 载地址:http://www.zabbix.com/download.php 选择windows版本的agent下载 从官方下载Zabbix Agent后,压缩 ...
- 【zabbix】自动注册,实现自动发现agent并添加监控(agent不需要任何配置)
更新: 后来在实际使用中发现,与其使用zabbix自动注册,不如直接调用zabbix的api主动发起添加服务器的请求,这样就不需要在zabbixserver上配置host信息了.实现全自动.具体调用方 ...
- 【Stack Overflow -- 原创加工、原创整理、生产实战】-- 深度复制
一.说明 1.本程序的核心代码不是我原创的,是我在Stack Overflow上搜集后加工出来的,原作者已忘记了~ 2.这段程序是我在上海携程(2014年左右)上班时整理并在生产环境应用的,先后经历了 ...
- consul生产实战
pwd:/home/appadmin wget https://releases.hashicorp.com/consul/1.6.1/consul_1.6.1_linux_amd64.zip unz ...
随机推荐
- Pytest Fixture(三)
name: name参数表示可以对fixture的名称进行重命名: 注意:通过name重命名后,继续使用以前的名字调用会报错. import pytest @pytest.fixture(name=' ...
- 端口被占用 for mac
启用项目提示端口被占用 解决方案: lsof -i : 3010 杀死占用的进程 kill -9 4804 重新启动
- Docker部署网心云-挣点电费
网心云 是CDN业务的一种,容器魔方 是网心云的容器安装产品,其安装也很简单. 1.启动容器--一行命令 docker run -d --name watchtower --restart alway ...
- python菜鸟学习: 8. 集合基础知识
# -*- coding: utf-8 -*-# 列表的特性:1,去重:2.关系测试list1 = [1, 4, 6, 8, 7, 8, 9]# 集合去重list2 = set(list1)print ...
- Typora怎么让左边的标题折叠
点击文件选择偏好设置->在选择外观->选中侧边栏的大纲视图允许折叠和展开 效果
- SQL IIF函数的使用 判断为空数据不显示的问题
先说说IIF函数 IIF函数 需要一个条件 两个值 当条件满足的时候 执行第一个值 条件不满足的时候 执行第二个值 IIF(判断条件,值1,值2) 今天判断数据的时候 发现当值为NULL或者为' ...
- SQL教程
SQL教程 SQL简介 SQL (Structured Query Language:结构化查询语言) 是用于管理关系数据库管理系统(RDBMS). SQL 的范围包括数据插入.查询.更新和删除,数据 ...
- python Elementtree 生成带缩进格式的xml文件
示例 之前拿ET写xml,直接对root节点调用write函数,会出现产生的xml字符串没有缩进,是干巴巴的一行,可读性比较差,就像下面这样: <annotation><filena ...
- zxb2022习题班16
(1) 原则:合同中包含多项履约义务的,企业应当按照各单项履约义务所承诺的商品的单独售价的比例,将交易价格分摊至各单项履约义务. 方法:按照A和B商品单独售价的相对比例, 2x22年4月16日 借:合 ...
- vue项目安装淘宝镜像一直失败,解决办法
这个问题纠缠了我好几天,刚开始把npm,node卸载了重装,发现还是一样的问题,最后发现是权限不够,下面这个方法完美解决 失败原因:没有用管理员权限执行, 解决办法:找到安装nodejs安装的路径,再 ...