SkyWalking Helm Chart 在 Kubernetes 中的部署、配置与运维实战指南
1. 项目概述与核心价值如果你正在 Kubernetes 集群里折腾微服务的可观测性那 SkyWalking 这个名字你肯定不陌生。作为一个开源的 APM应用性能监控和分布式追踪系统它能让你的服务链路、性能指标、拓扑关系变得一目了然。但说实话在 K8s 里手动部署和配置 SkyWalking 的各个组件——OAP后端、UI前端、存储Elasticsearch/BanyanDB 等——是个挺繁琐的活儿光是 YAML 文件就能写到手软。这时候apache/skywalking-helm这个项目就派上用场了。它本质上是一个 Helm Chart 仓库把 SkyWalking 在 K8s 上的部署、配置、依赖管理都打包好了。你只需要几条helm命令就能拉起一套完整的、生产可用的 SkyWalking 环境。这不仅仅是“一键部署”那么简单它把最佳实践、资源配额、服务发现、配置模板都封装了进去让你能更专注于如何使用 SkyWalking 来解决问题而不是陷在部署的泥潭里。这个 Chart 覆盖了 SkyWalking 的核心部署场景无论是使用内置的 Elasticsearch 集群还是对接外部的存储服务无论是部署稳定的发布版本还是尝鲜最新的开发分支甚至包括集成 Satellite边车代理和 SWCKSkyWalking Cloud on Kubernetes生态组件它都提供了清晰的路径。对于运维工程师、SRE 或者任何需要在云原生环境下建立可观测性体系的团队来说掌握这个 Helm Chart 的使用能极大提升效率降低维护成本。2. 核心架构与部署方案解析在深入命令行之前我们得先搞清楚这个 Helm Chart 到底在 K8s 里部署了什么以及不同配置选项背后的逻辑。这能帮你做出更合适的选择而不是盲目复制粘贴命令。2.1 核心组件与数据流一次标准的部署主要会拉起以下几个核心工作负载OAP Server (skywalking-oap)这是 SkyWalking 的后端大脑以Deployment形式运行。它负责接收来自各种探针Java Agent、Istio、eBPF 等的遥测数据进行聚合、分析和持久化。它的伸缩性和资源消耗是你需要重点关注的。SkyWalking UI (skywalking-ui)数据展示层通常也是一个Deployment并通过Service对外暴露。它提供 Web 界面用于查询追踪链路、查看服务拓扑、分析指标告警等。Storage Backend (存储后端)这是可观测数据的“仓库”。Chart 支持多种存储每种选择都对应不同的资源模型和运维复杂度Elasticsearch (默认且推荐)通过内置的 ECK Operator 部署一个 ES 集群。适合数据量大、需要复杂查询和聚合的场景。但 ES 本身比较“重”对资源CPU、内存、磁盘要求较高。BanyanDBApache SkyWalking 社区孵化的新一代时序数据库专为可观测数据设计。相比 ES它在写入性能、存储压缩和针对 Trace/Metric 的查询上做了优化是未来的发展方向。如果你的集群资源有限或者想深度参与社区可以尝试。PostgreSQL传统关系型数据库适合数据量不大、团队对 SQL 更熟悉的场景。但在处理海量链路追踪数据时性能和扩展性可能成为瓶颈。Initialization Job (skywalking-oap-init)一个只会运行一次的Job。它的核心任务是向存储后端如 Elasticsearch创建 SkyWalking 所需的索引模板和映射Mapping确保数据能被正确写入和查询。如果这个 Job 失败OAP 将无法正常工作。数据流向大致是应用探针 - OAP Server - 存储后端。UI 则从存储后端查询数据并展示。理解这个链条对于后续的问题排查至关重要。2.2 关键配置参数深度解读Chart 的配置非常灵活但有几个参数是每次部署都必须明确指定的它们决定了部署的“基因”oap.image.tag与ui.image.tag这指定了 OAP 和 UI 的容器镜像版本。强烈建议保持两者版本一致例如都设为10.3.0。不同版本的 OAP 和 UI 可能在 API 或数据格式上不兼容导致 UI 无法正常显示数据。这个标签需要与 Apache SkyWalking 官方发布版本 对齐。oap.storageType这是最重要的决策之一。它告诉 OAP 使用哪种存储客户端。这个值必须与你实际启用的存储后端匹配。例如即使你在values.yaml里启用了elasticsearch.enabledtrue但如果oap.storageType设成了banyandbOAP 仍然会尝试连接 BanyanDB 而导致失败。elasticsearch.enabled/banyandb.enabled/postgresql.enabled这些布尔值开关控制是否由 Chart内置部署对应的存储服务。如果你已经有现成的、在集群外部的 Elasticsearch 或 PostgreSQL 服务就应该将对应的enabled设为false然后通过config字段配置连接信息。注意版本兼容性陷阱。oap.image.tag所指的 OAP 版本与 Chart 本身版本skywalking-helm的版本如4.7.0是独立的。新版本的 Chart 可能会增加新的配置项如支持新的存储类型或 Satellite 配置这些配置项在老版本的 OAP 镜像中可能不存在或不支持。因此在升级 Chart 或切换 OAP 版本时最好查阅对应版本的 Chart 文档 和 OAP 配置手册 。3. 多场景部署实操全指南纸上谈兵终觉浅我们来实战几种最常见的部署模式。我会基于 Helm 3 和 Docker Hub 的 OCI 仓库来演示这是目前最主流和推荐的方式。3.1 基础准备与环境变量设置无论哪种部署先设置好环境变量能让命令更清晰也便于复用。建议在你的部署脚本或终端中先执行# 定义 Helm Release 的名称在同一个命名空间内必须唯一 export SKYWALKING_RELEASE_NAMEmy-skywalking # 定义要安装到的 Kubernetes 命名空间建议单独创建如 observability export SKYWALKING_RELEASE_NAMESPACEobservability # 指定 skywalking-helm Chart 的版本请替换为最新的稳定版 export SKYWALKING_RELEASE_VERSION4.7.0 # 指定 SkyWalking OAP/UI 组件的镜像版本 export SKYWALKING_IMAGE_TAG10.3.0 # 创建命名空间如果不存在 kubectl create namespace ${SKYWALKING_RELEASE_NAMESPACE} --dry-runclient -o yaml | kubectl apply -f -3.2 场景一使用内置 Elasticsearch最简部署这是新手入门和快速验证的首选方案。Chart 会利用 ECK Operator 在集群内自动部署一个 Elasticsearch 实例。helm install ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version ${SKYWALKING_RELEASE_VERSION} \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ --set oap.image.tag${SKYWALKING_IMAGE_TAG} \ --set oap.storageTypeelasticsearch \ --set ui.image.tag${SKYWALKING_IMAGE_TAG}执行后发生了什么Helm 会从 Docker Hub 拉取指定版本的 Chart。由于elasticsearch.enabled默认为trueChart 会尝试部署 ECK Operator 及其所需的 Custom Resource Definitions (CRDs)。这里有一个关键坑点ECK 的 CRDs 必须在部署 Chart 之前就存在于集群中。上述命令可能会因 CRD 不存在而失败。因此更稳健的做法是预先安装 CRDs。稳健的部署步骤# 1. 添加 Elastic 的 Helm 仓库用于安装 CRDs Chart helm repo add elastic https://helm.elastic.co helm repo update # 2. 安装 ECK Operator 的 CRDs helm install eck-crds elastic/eck-operator-crds --version 3.3.1 --namespace ${SKYWALKING_RELEASE_NAMESPACE} --create-namespace # 3. 安装 SkyWalking并告知 Chart 不要重复安装 CRDs helm install ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version ${SKYWALKING_RELEASE_VERSION} \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ --set oap.image.tag${SKYWALKING_IMAGE_TAG} \ --set oap.storageTypeelasticsearch \ --set ui.image.tag${SKYWALKING_IMAGE_TAG} \ --set eck-operator.installCRDsfalse # 关键参数避免冲突部署完成后使用kubectl get pods -n observability查看你应该能看到类似以下的 Podmy-skywalking-oap-xxxxxmy-skywalking-ui-xxxxxelastic-operator-xxxxx(ECK Operator)my-skywalking-es-default-xxxxx(Elasticsearch 节点)3.3 场景二使用内置 BanyanDB面向未来BanyanDB 是 SkyWalking 社区力推的下一代存储如果你希望更紧密地跟随社区发展或对性能有更高要求可以尝试。helm install ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version ${SKYWALKING_RELEASE_VERSION} \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ --set oap.image.tag${SKYWALKING_IMAGE_TAG} \ --set oap.storageTypebanyandb \ --set ui.image.tag${SKYWALKING_IMAGE_TAG} \ --set elasticsearch.enabledfalse \ --set banyandb.enabledtrue \ --set banyandb.image.tag0.9.0注意事项版本对应banyandb.image.tag需要与 BanyanDB 的发布版本对应最新版本请查看 BanyanDB 发布页 。资源配置BanyanDB 默认的资源请求可能不适合生产环境。你需要根据数据量调整其 CPU、内存和存储配置。所有 BanyanDB 的配置参数都需要以banyandb.为前缀例如--set banyandb.persistence.size50Gi \ --set banyandb.resources.requests.memory4Gi \ --set banyandb.resources.requests.cpu2生态成熟度相比 ElasticsearchBanyanDB 的周边生态如备份工具、监控方案可能还在发展中生产环境引入前需充分测试。3.4 场景三对接外部存储生产常见生产环境中为了统一管理和维护存储服务如 Elasticsearch、PostgreSQL通常由独立的团队维护或使用云厂商的托管服务。这时就需要禁用 Chart 内置的存储转而配置外部连接。以外部 Elasticsearch 7.x 集群为例首先创建一个自定义的values-external-es.yaml文件# values-external-es.yaml oap: image: tag: 10.3.0 storageType: elasticsearch ui: image: tag: 10.3.0 # 关键禁用内置 ES 部署 elasticsearch: enabled: false config: # 你外部 ES 集群的访问地址 host: your-external-es-host.com # 例如elasticsearch.mynamespace.svc.cluster.local (集群内服务名) 或 公网域名 port: http: 9200 # 如果启用了安全认证 user: elastic password: your-strong-password # 如果使用 HTTPS 且证书是自签名的可能需要关闭证书验证仅测试环境 # protocol: https # secrets: # tls: false # 同样确保其他内置存储被禁用 banyandb: enabled: false postgresql: enabled: false然后使用这个配置文件进行安装helm install ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version ${SKYWALKING_RELEASE_VERSION} \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ -f values-external-es.yaml重要安全提示将密码明文写在 YAML 文件中不安全。在生产环境中应该将密码、证书等敏感信息存入 Kubernetes Secret然后在values.yaml中通过secretKeyRef进行引用。例如elasticsearch: config: passwordSecret: name: external-es-secret key: password3.5 场景四启用 Satellite 作为网关代理在服务网格如 Istio或大规模部署中让每个数据上报点直连 OAP 可能造成压力和单点故障。Satellite 是一个独立的网关组件可以部署为 Sidecar 或独立服务负责接收探针数据并转发给 OAP起到流量缓冲和路由的作用。helm install ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version ${SKYWALKING_RELEASE_VERSION} \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ --set oap.image.tag${SKYWALKING_IMAGE_TAG} \ --set oap.storageTypeelasticsearch \ --set ui.image.tag${SKYWALKING_IMAGE_TAG} \ --set satellite.enabledtrue \ --set satellite.image.tagv0.4.0启用后你的应用探针如 SkyWalking Java Agent或 Istio 的 Telemetry V2 需要将上报地址从 OAP Service (skywalking-oap:11800) 改为 Satellite Service (skywalking-satellite:11800)。Satellite 会透明地将数据转发给 OAP。4. 高级配置与运维管理部署成功只是第一步要让 SkyWalking 稳定高效地运行还需要进行一系列配置和调优。4.1 自定义 OAP 与 Satellite 配置SkyWalking 的 OAP 和 Satellite 有大量细粒度的配置项用于调整采样率、线程池、缓存大小、分析器开关等。Helm Chart 提供了两种方式来覆盖默认配置方式一通过环境变量优先级最高这是最灵活的方式适用于动态调整。OAP 的绝大多数配置都支持通过环境变量设置格式为SW_加配置键的大写形式点号替换为下划线。helm upgrade ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version ${SKYWALKING_RELEASE_VERSION} \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ --reuse-values \ # 保留现有配置 --set oap.env.SW_CORE_GRPC_HOST0.0.0.0 \ --set oap.env.SW_CORE_GRPC_PORT11800 \ --set oap.env.SW_RECEIVER_BUFFER_PATH/tmp/sw-rec-buffer \ # 调整缓冲区路径 --set oap.env.SW_TELEMETRY_PROMETHEUS_HOST0.0.0.0 # 暴露 Prometheus 指标方式二通过 ConfigMap 挂载配置文件更清晰对于复杂的配置直接修改配置文件更易于管理。Chart 允许你覆盖默认的application.yml。首先从运行的 OAP Pod 中导出默认配置或从源码获取kubectl exec -n ${SKYWALKING_RELEASE_NAMESPACE} deploy/${SKYWALKING_RELEASE_NAME}-oap -- cat /skywalking/config/application.yml custom-oap-config.yml修改custom-oap-config.yml例如调整 Elasticsearch 客户端线程数或启用某个分析器。创建一个 ConfigMapkubectl create configmap -n ${SKYWALKING_RELEASE_NAMESPACE} custom-oap-config --from-fileapplication.ymlcustom-oap-config.yml --dry-runclient -o yaml | kubectl apply -f -在 Helmvalues.yaml或升级命令中指定 OAP 使用这个 ConfigMap# custom-values.yaml oap: config: # 此处的键 application.yml 对应容器内的配置文件路径和名称 application.yml: | # 这里可以直接写配置内容但更推荐引用 ConfigMap # 或者使用 configMapRef extraVolumes: - name: custom-config configMap: name: custom-oap-config extraVolumeMounts: - name: custom-config mountPath: /skywalking/config/application.yml subPath: application.yml然后使用helm upgrade ... -f custom-values.yaml。注意这种方式和环境变量混用时环境变量优先级更高。4.2 资源限制与持久化配置生产环境必须设置合理的资源请求和限制并配置持久化存储否则服务可能因 OOM 被杀或数据丢失。示例values-resources.yamloap: replicaCount: 2 # 根据负载考虑部署多个副本 resources: requests: memory: 2Gi cpu: 1000m limits: memory: 4Gi cpu: 2000m # OAP 的 H2 数据库用于集群管理和缓冲区可能需要持久化 persistence: enabled: true size: 20Gi storageClassName: fast-ssd # 指定 StorageClass ui: resources: requests: memory: 512Mi cpu: 250m limits: memory: 1Gi cpu: 500m elasticsearch: # 为内置 ES 配置资源 elasticsearch: resources: requests: memory: 4Gi cpu: 2000m limits: memory: 8Gi cpu: 4000m volumeClaimTemplate: spec: storageClassName: fast-ssd accessModes: [ReadWriteOnce] resources: requests: storage: 100Gi # ES 数据盘需要较大空间4.3 初始化 Job 的重跑与问题诊断OAP 的初始化 Job (skywalking-oap-init) 如果失败整个系统将无法工作。Kubernetes 的 Job 默认不会自动重跑。如果因为网络、存储或配置问题导致初始化失败修复问题后需要手动删除并重建这个 Job。安全地重跑初始化 Job# 1. 导出当前的 Job 定义到文件 kubectl get job -n ${SKYWALKING_RELEASE_NAMESPACE} -l release${SKYWALKING_RELEASE_NAME} -o yaml oap-init-job.yaml # 2. 编辑这个 YAML 文件删除 Kubernetes 自动生成的管理字段。 # 你可以手动编辑或使用 yq 工具推荐进行清理。 # 关键是要删除 metadata.uid, metadata.resourceVersion, spec.selector, spec.template.metadata.labels 中的 controller 相关 UID。 # 一个使用 yq 的示例命令请根据你的 yq 版本调整语法 yq eval del(.metadata.creationTimestamp, .metadata.resourceVersion, .metadata.uid, .status, .spec.selector, .spec.template.metadata.labels.controller-uid) oap-init-job.yaml oap-init-job-clean.yaml # 3. 仔细检查 oap-init-job-clean.yaml确保 spec.template.spec 下的容器配置是正确的。 # 4. 删除旧的失败 Job kubectl delete job -n ${SKYWALKING_RELEASE_NAMESPACE} -l release${SKYWALKING_RELEASE_NAME} # 5. 用清理后的配置创建新的 Job kubectl apply -n ${SKYWALKING_RELEASE_NAMESPACE} -f oap-init-job-clean.yaml初始化 Job 常见失败原因存储连接失败检查oap.storageType是否与启用的存储匹配以及存储服务的地址、端口、认证信息是否正确。资源不足初始化过程可能需要较多内存确保 Job 的 Pod 有足够的资源配额。网络策略如果集群启用了 NetworkPolicy确保 initJob 的 Pod 有权限访问存储服务。版本不兼容OAP 版本与存储后端如 Elasticsearch版本不兼容。请查阅 SkyWalking 官方文档的版本兼容性矩阵。5. 故障排查与性能调优实战即使部署成功在实际运行中也可能遇到各种问题。这里记录几个我踩过的坑和对应的解决方案。5.1 OAP 启动失败或持续重启现象kubectl logs -f deploy/skywalking-oap显示错误后 Pod 重启。排查思路检查环境变量与配置首先确认oap.storageType设置正确并且对应的存储服务如elasticsearch.enabledtrue或外部 ES 配置是可用的。使用kubectl describe pod查看 Pod 的事件看是否有调度或挂卷失败。查看 OAP 日志细节OAP 启动时会打印大量日志。重点关注连接存储的阶段。典型的连接 ES 失败日志会包含Connection refused,NoNodeAvailableException或认证失败信息。验证网络连通性进入 OAP Pod 内部用curl或telnet命令测试是否能访问存储服务的主机和端口。kubectl exec -it deploy/my-skywalking-oap -n observability -- sh # 在容器内执行 curl -v http://my-skywalking-es-http:9200检查资源限制如果 OAP 因 OOM 被杀日志可能不完整。查看 Pod 的状态是否为OOMKilled。适当增加oap.resources.limits.memory。5.2 UI 无法访问或显示“无数据”现象能打开 UI 页面但拓扑图是空的或者查询不到任何追踪数据。排查思路确认 OAP 服务健康UI 通过 gRPC 和 GraphQL 从 OAP 获取数据。首先确保 OAP 的 Service (skywalking-oap) 存在且 Endpoints 正常。kubectl get svc,ep -n observability -l app.kubernetes.io/instancemy-skywalking检查 UI 到 OAP 的连接查看 UI Pod 的日志看是否有连接 OAP 失败的错误。UI 的配置中OAP 地址是通过环境变量SW_OAP_ADDRESS设置的通常由 Chart 自动配置为skywalking-oap:12800gRPC和skywalking-oap:12800GraphQL。确保网络策略允许 UI Pod 访问 OAP Service。验证数据上报链路UI 没数据根本原因可能是数据没上报到 OAP。检查你的应用探针如 SkyWalking Agent配置是否正确特别是agent.service_name和collector.backend_service应指向 OAP 或 Satellite 的地址如skywalking-oap:11800。你可以通过 OAP 的日志或/metrics端点来确认是否收到数据。检查存储数据直接查询存储后端确认是否有数据写入。例如对于 Elasticsearch可以查询相关索引# 假设 ES 服务名为 my-skywalking-es-http curl -X GET my-skywalking-es-http:9200/_cat/indices?v | grep sw_如果没有任何sw_开头的索引说明 OAP 初始化 Job 可能失败了或者 OAP 根本没能成功写入数据。5.3 性能瓶颈分析与调优建议随着监控数据量的增长SkyWalking 可能遇到性能瓶颈。以下是一些常见的调优点OAP 内存与 GCOAP 是 Java 应用对内存敏感。如果频繁 Full GC会导致处理延迟。除了增加内存可以调整 JVM 参数。通过oap.env设置oap: env: JAVA_OPTS: -Xms4g -Xmx4g -XX:UseG1GC -XX:MaxGCPauseMillis200Elasticsearch 性能分片数SkyWalking 的索引模板默认分片数可能不适合你的集群规模。对于非常大的数据集可以考虑在初始化前定制索引模板增加主分片数。刷新间隔增加索引的refresh_interval例如到30s可以提升写入吞吐但会降低数据的实时性。这需要在 Elasticsearch 的索引设置中调整。硬件确保 ES 节点有足够的堆内存通常不超过 32GB、高速 SSD 存储和充足的 CPU。采样率如果数据量实在太大可以在应用端或 OAP 端开启采样。通过环境变量SW_TRACING_SAMPLE_RATE设置例如0.5表示 50% 的采样率。这能显著降低存储和计算压力但会丢失部分追踪细节。数据保留策略SkyWalking 默认会永久保留数据。对于生产环境必须设置数据过期TTL。这需要在存储后端配置。例如在 Elasticsearch 中可以通过 ILM (Index Lifecycle Management) 策略自动滚动和删除旧索引。5.4 版本升级与回滚策略升级 SkyWalking 涉及 Chart 版本和 OAP/UI 镜像版本需要谨慎操作。备份升级前务必备份重要的配置你的自定义values.yaml和存储在 Elasticsearch/PostgreSQL 中的数据如果有。测试先在测试环境进行升级验证新版本的功能和兼容性。特别要注意 OAP 版本升级可能带来的数据格式变更。Helm Upgrade# 升级到新的 Chart 版本和 OAP 镜像版本 helm upgrade ${SKYWALKING_RELEASE_NAME} \ oci://registry-1.docker.io/apache/skywalking-helm \ --version NEW_CHART_VERSION \ --namespace ${SKYWALKING_RELEASE_NAMESPACE} \ --set oap.image.tagNEW_OAP_TAG \ --set ui.image.tagNEW_UI_TAG \ -f your-custom-values.yaml观察升级后密切监控 OAP 和 UI 的日志、Pod 状态以及核心业务指标是否正常。回滚如果升级后出现问题Helm 提供了便捷的回滚命令# 查看历史版本 helm history ${SKYWALKING_RELEASE_NAME} -n ${SKYWALKING_RELEASE_NAMESPACE} # 回滚到上一个版本 helm rollback ${SKYWALKING_RELEASE_NAME} -n ${SKYWALKING_RELEASE_NAMESPACE} # 或回滚到指定版本 helm rollback ${SKYWALKING_RELEASE_NAME} REVISION_NUMBER -n ${SKYWALKING_RELEASE_NAMESPACE}最后关于存储选择我个人的经验是对于中小规模集群和刚上手的团队使用 Chart 内置的 Elasticsearch 是最省心的虽然资源占用大些但功能全面、社区资料多。当集群规模上去对性能和成本有更高要求时再考虑迁移到 BanyanDB 或优化外部 Elasticsearch 集群。而 Satellite 的引入最好是在你明确遇到了 OAP 连接数压力或需要在网络层面做更多控制如 TLS、负载均衡的时候对于简单的部署直连 OAP 反而更简单直接。