资讯动态

K8S ECK 非TLS部署 ES 7.17 保留账号认证

发布时间:2026/10/26 11:48:38 来源:尧图企业网站定制
内网里跑日志平台常常会遇到这样一种组合要求对外不能暴露 HTTPS证书统一交给上游网关处理但账号密码必须保留任何人连进来之前都得先通过认证。这个需求落到 K8S 上的 ECK就是把 Elasticsearch 7.17 的 HTTP 层 TLS 关闭同时保持 xpack.security 的认证链路完整可用。听起来只是“少配一个证书”实际动手会发现坑不少只关一半会让 Pod 反复 CrashLoopBackOff全部关闭又可能把 Kibana 和采集端连接断开密码用默认生成的那套又不能直接对外使用。这篇内容就把这条链路从上到下走一遍包括 CR 怎么写、密码怎么落、客户端怎么改、出错怎么查适合正在做内网日志平台、被 TLS 和认证卡住的运维和开发同学参考。读完之后你至少能照着配置改一份可运行的 CR并且知道每一步为什么这么配。1. 非 TLS 部署的取舍与版本基线1.1 这个组合到底在解决什么问题先拆一下标题里的信息量。K8S是运行底座ECK是 Elastic Cloud on Kubernetes它用 CRD 的方式把 Elasticsearch、Kibana、Beats、APM 这些组件变成 K8S 里的一等公民你写 YAMLOperator 负责落地成 StatefulSet、Service、Secret、PVC。7.17是个特殊版本它是 7.x 系列的最后一个小版本线大量存量集群还在上面升级到 8.x 需要改的东西不少所以“继续用 7.17”本身就是一种现实选择。账号密码指的是xpack.security那套基于 file realm 的认证体系。非 TLS说的是 HTTP 层的传输加密被拿掉也就是9200端口走明文 HTTP。这四件事叠在一起就形成了一个很具体的场景一个在内网、不直接对接公网、周边有统一入口或者网关做加密、但仍然需要做身份区分的 Elasticsearch 集群。它既不是“裸奔的测试环境”也不是“合规要求拉满的生产环境”而是一个有认证、无传输加密的中间状态。理解这个定位很重要因为它直接决定了后面所有配置取舍的方向——你要保的是认证要弃的是传输层加密两者不能混着谈。很多人第一次接触这个需求时会下意识觉得“关 TLS 不就是把 ssl 设成 false 吗”然后在 ECK 里改一个字段发现 Pod 起不来。原因在于 ECK 对 TLS 的管理是分层的它既管 HTTP 层也管 transport 层还管证书的自动签发和挂载。你动的是其中一层另外两层没跟着动就会打架。所以下面我要把这几层拆开讲清楚。1.2 关掉传输加密的收益与代价在做决定之前先把账算清楚。这不是一个“技术上行不行”的问题而是“这个代价你接不接受”的问题。维度关闭 HTTP TLS 的收益需要承担的代价客户端接入不用分发 CA不用处理证书过期curl 直接敲数据在集群网络内明文传输证书运维省掉自签证书轮换、SAN 配置、告警无法抵御同网段的流量嗅探排障效率抓包可直接读错误信息直观出问题时无法用“加密了看不到”来免责性能省掉握手和加解密开销高并发写入略有改善性能收益在 SSD万兆环境下通常只有个位数百分比合规内网环境部分场景可接受跨不可信网段、跨租户场景基本不可接受我个人的判断标准是三条网络边界是否可控、数据敏感度、存在时长。如果集群只在一个 VLAN 内、只有内部服务能访问、数据是应用日志这类非敏感内容、并且这个状态是过渡期的临时方案那关掉是合理的。反过来只要有一条不满足就应该老老实实上证书或者至少在上游做加密终结。注意关闭 HTTP TLS 不等于关闭所有安全能力。xpack.security的认证、授权、审计、字段级权限这些都在只是传输层不再加密。很多人把这两件事混为一谈结果要么过度设计要么把认证也一起关掉了那是另一码事。1.3 版本与组件的对应关系7.17 这条线对 ECK 版本有要求不是随便找个 Operator 就能带起来。ECK 的兼容策略大致是“支持最近若干个 minor 版本的 Elasticsearch”7.17 作为 7.x 最后一版被支持的时间窗口比较长但越新的 Operator 对 K8S 版本的要求也越高。ECK 版本大致最低 K8S可带的 ES 版本适用场景2.6.x1.217.17.x / 8.5.x老集群、K8S 版本偏低2.9.x1.237.17.x / 8.8.x中等规模功能较全2.13.x1.257.17.x / 8.13.x主流选择2.16.x1.277.17.x / 8.17.x新集群K8S 版本跟得上具体数字请以官方兼容矩阵为准我列的是大方向。实际选型时先看你的 K8S 版本再看 ES 版本取交集。如果 K8S 版本比较老就往前找 Operator如果 K8S 比较新直接用较新的 2.x 就行。不建议跨太多版本用最新的 Operator 去带 7.17虽然理论支持但新 Operator 默认的一些行为比如更严格的 Pod 安全上下文、默认开启的某些特性在老版本 ES 上容易出兼容问题。另外7.17 的内部镜像建议锁定到具体小版本比如7.17.9、7.17.15这类别用7.17-SNAPSHOT或者浮动的 tag。一是不放心二是滚动升级时 tag 变化会导致不可预期的重启。2. 部署前的环境与前置准备2.1 集群与存储的基础门槛在写 CR 之前有几项基础条件必须先确认。K8S 集群本身要满足 Operator 的最低版本要求这个前面说过。存储方面Elasticsearch 是典型的有状态服务volumeClaimTemplates必须能绑定到实际的 StorageClass。我踩过最常见的一个坑是StorageClass 的volumeBindingMode是Immediate而节点分散在不同可用区PVC 先绑定了一个区Pod 调度到另一个区结果一直Pending。解决办法是把 StorageClass 设成WaitForFirstConsumer让调度先决定落点再绑盘。数据盘容量按你的日志量估。一个粗略的算法是每日原始日志量 × 保留天数 × 副本数 × 1.3索引开销和安全余量。比如每天 20GB 原始日志、保留 7 天、1 个副本大约是 20×7×1.3 ≈ 182GB三个节点分摊每个节点 100GB 比较稳妥。别把盘算得太紧磁盘水位到 85% 会触发分片分配限制那时候再扩盘就很被动。节点数量上三个起步是底线。单节点虽然能跑但number_of_replicas只能设 0集群状态永远是 yellow而且随便一次 Pod 重建就全站不可用。三节点可以做到一主两数据或者三合一小规模场景直接把 master 和 data 混部就行ECK 里就是node.roles: [master, data, ingest]。当然如果规模上去了还是建议拆分角色。2.2 内核参数与资源规划Elasticsearch 对操作系统参数有硬性要求最知名的是vm.max_map_count必须 ≥ 262144否则启动时直接报bootstrap checks failed。在 K8S 里这个参数有两种处理方式节点层面统一设置或者在 Pod 里用 privileged 的 initContainer 动态设置。节点层面设置最省事登录每台宿主机执行sysctl -w vm.max_map_count262144 echo vm.max_map_count262144 /etc/sysctl.d/99-elasticsearch.conf但如果是托管集群或者你没权限改宿主机就得用 initContainerinitContainers: - name: sysctl image: busybox:1.36 securityContext: privileged: true runAsUser: 0 command: [sh, -c, sysctl -w vm.max_map_count262144]顺带把fs.file-max也一起设了虽然默认值通常够用但高并发查询场景下文件句柄会吃紧。内存规划是整个部署里最容易出错的地方。ECK 有一个约定容器的 memory request 和 limit 必须相等否则 Operator 会告警并且在计算 JVM 堆的时候出现偏差。原因很简单Elasticsearch 进程需要知道自己的内存上限K8S 里唯一可靠的来源就是 cgroup 的 limit。ECK 的做法是从resources.limits.memory推导堆大小默认是 50%。比如你设memory: 4Gi那堆就是 2g。你也可以显式用ES_JAVA_OPTS覆盖但两者要协调不要让堆超过 limit 的 50%剩下的内存要留给 Lucene 的堆外缓存和文件系统缓存。堆超过物理内存一半的后果是频繁 GC 甚至 OOMKilled而且是那种“看起来内存没用满就挂了”的迷惑现场。还有一个硬限制JVM 堆不要超过 31GB。超过之后指针压缩失效同样大小的堆实际能用的内存反而变少。所以哪怕你给了 128G 的机器堆也不要超过 31g多出来的内存交给文件系统缓存那才是 Lucene 真正快的地方。2.3 命名空间与权限边界建议单独开一个命名空间比如elastic把这套东西和业务应用隔开。原因不是洁癖而是后面做 NetworkPolicy 收敛的时候你会需要按命名空间划边界。如果 ES 和一堆业务 Pod 混在default里网络策略写起来会很别扭。Operator 自己装在elastic-system命名空间这是官方 manifest 里的默认值。它需要 cluster 级别的权限来 watch 所有命名空间的 Elasticsearch 资源这部分 RBAC 在operator.yaml里已经带好了不用自己写。你要做的是决定 Operator 管理模式默认是全局模式一个 Operator 管所有命名空间也可以配成限定模式只 watch 指定的几个命名空间适合多租户场景。小规模部署直接用全局模式就行省心。3. ECK Operator 的安装与就位确认3.1 安装 CRD 与 Operator安装分两步顺序不能反。先装 CRD再装 Operator。CRD 定义了Elasticsearch、Kibana这些资源长什么样Operator 是负责把它们变成实际工作负载的控制器。# 先装 CRD kubectl apply -f https://download.elastic.co/downloads/eck/2.13.0/crds.yaml # 再装 Operator kubectl apply -f https://download.elastic.co/downloads/eck/2.13.0/operator.yaml把版本号换成你需要的那个两个文件的版本号必须一致。我见过有人 CRD 用 2.9Operator 用 2.13结果 Operator 启动后一直报“无法识别字段”因为 CRD 里没有新版本的字段定义。CRD 文件比较大如果集群的注解长度限制比较严直接 apply 会报metadata.annotations: Too long。这时候加--server-side参数就行kubectl apply --server-side -f https://download.elastic.co/downloads/eck/2.13.0/crds.yaml3.2 确认 Operator 是否真的就位装完之后别急着写 CR先确认 Operator 状态健康。这一步花不了三十秒但能省掉后面半小时的瞎猜。kubectl -n elastic-system get pods kubectl -n elastic-system logs -f statefulset.apps/elastic-operator日志里出现Starting the webhook server和manager starting之类的输出说明起来了。如果 Pod 一直ContainerCreating多半是镜像拉不下来如果CrashLoopBackOff看日志第一行的错误常见的是 webhook 证书问题或者 RBAC 权限不足。还有一个隐含条件Operator 需要能够访问镜像仓库。如果你的环境是离线或内网仓库需要提前把docker.elastic.co下的镜像同步过去然后在 CR 里用spec.image字段指定完整地址。这一点在内网环境里是必做项别等到 Pod 卡在ImagePullBackOff才想起来。4. Elasticsearch 7.17 的 CR 编写要点4.1 关闭 HTTP TLS 必须同时改两处这是整篇内容里最关键的一段。很多人失败就失败在这里以为加一个disabled: true就完事了结果 ES 启动时报找不到证书Pod 反复重启。ECK 里关闭 HTTP 层 TLS 的正确姿势是两个位置同时配第一处告诉 Operator 不要再签发和挂载自签证书spec: http: tls: selfSignedCertificate: disabled: true第二处告诉 Elasticsearch 进程本身不要启用 HTTP SSLspec: nodeSets: - name: hot config: xpack.security.http.ssl.enabled: false为什么两处都要因为这是两个不同的主体。Operator 负责“把证书文件塞进容器”Elasticsearch 负责“读配置决定要不要用证书”。你只做第一处Operator 不挂证书了但 ES 的配置文件里如果还残留xpack.security.http.ssl.enabled: true某些 Operator 版本会主动注入这个配置ES 起来找不到 keystore 文件直接拒绝启动。你只做第二处Operator 还是会挂证书只是 ES 不用虽然能跑但多了一层没必要的文件挂载而且如果 cert-manager 之类的组件参与了签发还会留下无意义的证书轮换告警。所以我的习惯是两处都写宁可多写一行也不要靠猜测 Operator 的默认行为。不同版本的 Operator 注入的默认配置不完全一致显式声明是最稳的。注意xpack.security.transport.ssl.enabled不要跟着一起关。7.x 默认要求节点间通信加密你把它关了集群根本组不起来节点会一直报“handshake failed”。transport 层的自签证书由 ECK 管理你不用管留着就行。4.2 账号密码的三种可行方式TLS 关了认证还在。密码怎么落地有三条路复杂度递增按需选择。方式一用 ECK 自动生成的 elastic 用户。集群创建完成后Operator 会自动创建一个名为集群名-es-elastic-user的 Secret里面有个elastic键值是随机密码。取密码kubectl -n elastic get secret logs-es-es-elastic-user \ -o go-template{{.data.elastic | base64decode}}这个方式最省事缺点是密码是随机串不好记也不好交给别人。想改的话直接 patch Secretkubectl -n elastic patch secret logs-es-es-elastic-user \ -p {data:{elastic:$(echo -n YourNewPassw0rd! | base64)}}改完之后ES 的 file realm 会自动感知文件变化重新加载通常几十秒内生效。如果没生效滚动重启一下 Pod 就行。这是 ECK 的一个便利特性file realm 挂的是 Secret 卷Secret 更新后 K8S 会更新卷内文件ES 检测到 mtime 变化就 reload。方式二用 fileRealm 声明自定义用户。ECK 2.6 以后支持在 CR 里直接声明 realm 用户字段是passwordHash值必须是 bcrypt 哈希不能是明文。生成方式htpasswd -bnBC 10 YourPassw0rd! | tr -d :\n会输出类似$2y$10$xxxxx的字符串。然后写进 CRspec: auth: fileRealm: - name: log_writer passwordHash: $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx roles: [ingest_admin] - name: log_reader passwordHash: $2y$10$yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy roles: [viewer]这个方式的好处是用户和角色都在 Git 里可追溯坏处是密码哈希也进了仓库得注意仓库权限。另外角色必须事先存在viewer、editor这些是内置的自定义角色要先通过 API 创建。方式三集群起来后用 API 建用户。这是最灵活的方式适合用户数量多、需要接 LDAP 或者做动态管理的场景。TLS 关了之后直接 HTTP 调 API 就行curl -X POST http://logs-es-es-http.elastic:9200/_security/user/app_user \ -H Content-Type: application/json \ -u elastic:${ES_PASSWORD} \ -d {password:AppPassw0rd!,roles:[log_writer],full_name:应用写入账号}缺点是这些用户不落在 CR 里集群重建就没了需要配合初始化脚本或者 Job 一起用。我的建议是elastic 用户用方式一保留用它做应急入口业务账号用方式二或方式三按团队习惯选。不要把业务系统直接配成 elastic那个账号权限太大出了事没有追责线索。4.3 一份可以照着改的完整 CR把前面的内容拼起来一份去掉 HTTP TLS 但保留认证的 7.17 集群配置大概长这样apiVersion: elasticsearch.k8s.elastic.co/v1 kind: Elasticsearch metadata: name: logs-es namespace: elastic spec: version: 7.17.9 http: tls: selfSignedCertificate: disabled: true nodeSets: - name: hot count: 3 config: node.roles: [master, data, ingest] xpack.security.http.ssl.enabled: false xpack.security.transport.ssl.enabled: true xpack.security.audit.enabled: true cluster.routing.allocation.awareness.attributes: k8s_node_name thread_pool.write.queue_size: 2000 podTemplate: spec: initContainers: - name: sysctl image: busybox:1.36 securityContext: privileged: true runAsUser: 0 command: [sh, -c, sysctl -w vm.max_map_count262144] containers: - name: elasticsearch resources: requests: memory: 4Gi cpu: 1 limits: memory: 4Gi cpu: 2 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: elasticsearch.k8s.elastic.co/cluster-name: logs-es topologyKey: kubernetes.io/hostname volumeClaimTemplates: - metadata: name: elasticsearch-data spec: accessModes: [ReadWriteOnce] storageClassName: standard resources: requests: storage: 100Gi几个细节值得单独说一下。podAntiAffinity用preferred而不是required是因为三节点集群如果严格要求反亲和一旦某个节点不可用剩下的 Pod 没地方调度集群直接卡住。用 preferred 是留了余地。cluster.routing.allocation.awareness.attributes: k8s_node_name这个配置配合 ECK 自动注入的节点属性使用可以让分片在节点级别做感知分配避免同一份数据的副本落在同一个宿主机上。ECK 默认会为每个 Pod 注入k8s_node_name属性这个配置是直接可用的。thread_pool.write.queue_size调到 2000 是给写入高峰留缓冲默认的 1000 在批量导入场景下容易触发EsRejectedExecutionException。代价是内存占用略增如果堆比较紧张就别调。4.4 部署后怎么验证CR 提交之后用下面几条命令跟踪状态# 看集群资源状态 kubectl -n elastic get elasticsearch logs-es # 看 Pod kubectl -n elastic get pods -l elasticsearch.k8s.elastic.co/cluster-namelogs-es # 看 PVC 是否绑定 kubectl -n elastic get pvcHEALTH字段变成green就说明起来了。yellow 通常是副本没分配三节点集群配一个副本不应该出现如果出现多半是节点角色配置有问题。然后验证 HTTP 是否真的是明文、认证是否生效kubectl -n elastic port-forward svc/logs-es-es-http 9200:9200 # 不带凭证应该返回 401 curl -i http://localhost:9200 # 带凭证应该返回集群信息 curl -s -u elastic:$(kubectl -n elastic get secret logs-es-es-elastic-user -o go-template{{.data.elastic | base64decode}}) \ http://localhost:9200 | head -20这里有个快速判断技巧返回 401 说明认证生效但没给密码返回 200 说明认证被绕过了返回Client sent an HTTP request to an HTTPS server说明 TLS 根本没关掉。三种结果对应三种完全不同的排查方向先用这一个 curl 把大方向定下来比翻日志快得多。5. Kibana 与采集端的对接调整5.1 Kibana 走 HTTP 连 ESKibana 的 CR 里有两处 TLS 需要区分一处是 Kibana 自己对外提供的 HTTP 服务另一处是它连 ES 时的客户端配置。前者可以照抄 ES 的关闭方式apiVersion: kibana.k8s.elastic.co/v1 kind: Kibana metadata: name: logs-kibana namespace: elastic spec: version: 7.17.9 count: 1 elasticsearchRef: name: logs-es http: tls: selfSignedCertificate: disabled: true config: server.host: 0.0.0.0 xpack.security.encryptionKey: 至少32位的一串随机字符用于加密会话真正麻烦的是第二处。ECK 通过elasticsearchRef建立关联时会自动往 Kibana 容器里注入ELASTICSEARCH_HOSTS环境变量正常情况下是https://logs-es-es-http.elastic:9200。ES 的 HTTP TLS 关掉之后这个 https 地址就连不上了。ECK 在新版本里会检测 ES 的 HTTP TLS 状态如果发现关了会把注入的地址自动改成 http。但这个行为跟 Operator 版本强相关不能完全指望。稳妥的做法是部署完先验证一下kubectl -n elastic get pod -l kibana.k8s.elastic.co/namelogs-kibana \ -o jsonpath{.items[0].spec.containers[0].env}看到ELASTICSEARCH_HOSTS的值如果是https://开头就得手动干预。干预方式是在config里显式覆盖spec: config: elasticsearch.hosts: [http://logs-es-es-http.elastic:9200]这里要注意一个冲突Kibana 启动时如果同时发现环境变量ELASTICSEARCH_HOSTS和kibana.yml里的elasticsearch.hosts会直接报错退出提示配置重复。所以要覆盖的话得先把elasticsearchRef去掉改成手动提供凭据spec: config: elasticsearch.hosts: [http://logs-es-es-http.elastic:9200] elasticsearch.username: kibana_system elasticsearch.password: ${KIBANA_ES_PASSWORD}密码通过 Secret 挂成环境变量。kibana_system是内置账号密码可以用 API 重置curl -X POST http://logs-es-es-http.elastic:9200/_security/user/kibana_system/_password \ -H Content-Type: application/json \ -u elastic:${ES_PASSWORD} \ -d {password:KibanaPassw0rd!}我一般倾向于保留elasticsearchRef先跑一次看 Operator 是不是自动切了 http能用就别折腾。只有确实不生效的时候才切到手动配置这条路。这样运维负担最小升级 Operator 的时候也不用担心配置漂移。5.2 采集端和客户端的改造清单ES 的地址从 https 变成 http所有下游都得跟着改。这一块很容易漏漏一个就是一个“数据断了但没人发现”的事故。客户端需要改的项常见坑Filebeatoutput.elasticsearch.hosts改 httpprotocol: http忘了改 protocol仍然按 https 拨号Logstashoutput.elasticsearch.hosts改 http证书路径还留着启动报警告Java 客户端连接串加http://前缀老版本 RestHighLevelClient 需要显式指定 schemePython 客户端Elasticsearch([http://...])默认会尝试 https 再回退慢但能通Grafana 数据源URL 改成 http保存后不测试等到出图才发现连不上自定义脚本curl 去掉-k地址改 http残留的--cacert参数导致报错Filebeat 的配置我单独说一句。7.x 版本的 Filebeat 里protocol这个字段容易被忽略因为它默认值会跟着 hosts 的 scheme 走。但如果你的 hosts 里写的是 IP 或者不带 scheme 的域名就得显式指定output.elasticsearch: hosts: [http://logs-es-es-http.elastic:9200] protocol: http username: log_writer password: ${ES_PWD} index: app-logs-%{yyyy.MM.dd}Java 客户端那边如果你用的是 7.x 的RestHighLevelClient构造的时候RestClient.builder(new HttpHost(logs-es-es-http.elastic, 9200, http))第三个参数别写成https这个是硬编码的写错了不会自动降级直接连接超时。6. 常见问题与排查实录6.1 认证与证书类报错怎么定位Pod 反复重启日志里是Cannot find certificate或者FileNotFoundException: config/http.p12。这就是典型的只关了一处。检查spec.http.tls.selfSignedCertificate.disabled和config.xpack.security.http.ssl.enabled是否都是关闭状态。还有一种可能是 CR 改了但 Operator 没重新调和用kubectl -n elastic get elasticsearch logs-es -o yaml看看status里的observedGeneration是不是落后于metadata.generation。curl 返回 401密码明明是对的。先确认 Secret 里的值有没有换行符污染。base64decode之后如果有\ncurl 传过去就是错的密码。另外要注意 elastic 用户的密码修改之后Operator 可能需要一点时间同步别改完立刻测。返回 403 而不是 401。这说明认证过了是权限不够。检查账号绑定的角色有没有对应索引的权限。7.17 里viewer角色只能读*索引但读不了.security这类系统索引这是设计如此不是 bug。Kibana 报Unable to retrieve version information from Elasticsearch nodes。九成是地址还是 https。按前面 5.1 的方法查环境变量。6.2 集群健康与调度类问题集群一直 yellow。三节点集群出现 yellow先看GET _cluster/allocation/explain输出会直接告诉你哪个分片没分配、为什么没分配。常见原因有磁盘水位到了 85%low disk watermark、节点角色不匹配数据节点数为 0、分片数超过了节点能承载的数量。Pod 一直在 Pending。大概率是 PVC 绑不上或者资源不够。kubectl describe pod看 Events 里的最后几条0/3 nodes are available: 3 Insufficient memory这种信息很直白。ES 启动了但节点组不成集群。看日志里有没有handshake failed或者failed to join。如果你不小心把xpack.security.transport.ssl.enabled也设成了 false就是这个现象。改回来就行。写入时大量EsRejectedExecutionException。这是写入队列满了不是错误而是背压信号。短期调大thread_pool.write.queue_size长期看是不是 bulk 批次太大或者分片数不合理。6.3 问题速查表现象高概率原因快速验证处理动作Pod CrashLoop日志缺证书只关了 selfSignedCertificate看 CR 里 config 段补xpack.security.http.ssl.enabled: falsecurl 报 HTTPS 相关错误TLS 没真正关闭curl -i 看返回检查两处开关 Operator 是否调和Kibana 连不上 ES注入的地址仍是 https查 Pod env覆盖 hosts 或升级 Operator集群 yellow副本无法分配_cluster/allocation/explain看磁盘水位、节点角色PVC PendingStorageClass 绑定模式kubectl describe pvc换成 WaitForFirstConsumer401 且密码正确Secret 有换行或未同步base64decode 肉眼核对重新 patch 并等待 reload分片分配失败磁盘水位超限_cat/allocation?v清理索引或扩盘7. 关掉传输加密之后的安全补强7.1 把网络边界收窄到最小TLS 没了网络层就是唯一的防线。这件事不能靠“我们内网很安全”这种口头保证得有实际配置兜底。K8S 里最直接的手段是 NetworkPolicy。apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: es-ingress-restrict namespace: elastic spec: podSelector: matchLabels: common.k8s.elastic.co/type: elasticsearch policyTypes: [Ingress] ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: elastic - namespaceSelector: matchLabels: kubernetes.io/metadata.name: logging - namespaceSelector: matchLabels: kubernetes.io/metadata.name: monitoring ports: - protocol: TCP port: 9200 - protocol: TCP port: 9300这段策略的意思是只允许elastic、logging、monitoring三个命名空间的 Pod 访问 9200 和 9300 端口其他一律拒绝。注意kubernetes.io/metadata.name这个标签是 K8S 1.21 之后自动打的如果你的版本更老需要手动给命名空间打标签。配合 Service 类型也很重要。ES 的 Service 默认是ClusterIP本来就不对外暴露这是对的别为了图方便改成NodePort或者LoadBalancer。真需要外部访问走 Ingress 或者前置网关在那一层做 TLS 终结和访问控制这样边界清晰责任也清晰。7.2 账号治理与定期轮换认证是这套方案里唯一还在起作用的安全机制所以它必须被认真对待。几个实操建议第一禁用或者限制 elastic 超级用户。如果业务不需要可以用spec.auth.disableElasticUser: true把它关掉全部走自定义账号。如果要保留至少把密码存在受控的密钥管理系统里不要放在 Wiki 或者群里。第二按用途分账号按最小权限配角色。写入端一个账号只给目标索引的create和index权限查询端一个账号只给读权限Kibana 用kibana_system不要复用。这样出问题的时候能快速定位是哪条链路。第三定期轮换。file realm 的密码改起来不复杂改 Secret 或者改 CR 里的 hash 都行改完 ES 会自动 reload。轮换周期看你们的规范我一般建议至少季度一次人员变动时立即执行。第四打开审计日志。xpack.security.audit.enabled: true这个配置开销不大但能在出问题时提供“谁在什么时候用什么账号访问了什么”的记录。配合xpack.security.audit.logfile.events.include可以只记关键事件避免日志爆炸。提醒审计日志同样会写进索引别忘了给它配上 ILM 策略否则它会成为磁盘占用的隐形大户。我见过一个集群磁盘莫名其妙涨满最后查出来是审计日志没有清理策略。最后说一个我自己的习惯在每个非 TLS 的集群 CR 里加一行注释写清楚为什么关、什么时候关的、计划什么时候恢复。半年后接手的人看到这行注释能少走很多弯路。这条建议听起来不像技术方案但在实际运维里价值很高——技术债最难还的部分从来不是技术而是没人记得当初为什么这么干。我在实际使用中发现这类“半安全”状态的集群最容易出问题的不是部署当天而是三个月后的一次人员交接或者一次 Operator 升级。所以配置能显式写清楚的地方就别依赖默认值能加注释的地方就别省那几行。至于 7.17 这条线还能撑多久取决于你们什么时候有动力做 8.x 的迁移在那之前把现有的东西跑稳、跑清楚比追新版本实在得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑