Kubernetes

基于 Kubernetes 的服务发现

Kubernetes 服务发现模块以 List-Watch 方式监听 Kubernetes 集群 Endpoints 资源的实时变化, 并将其值存储到 ngx.shared.kubernetes 中 \ 模块同时遵循 APISIX Discovery 规范 提供了节点查询接口

Kubernetes 服务发现模块的配置

Kubernetes 服务发现模块的完整配置如下:

  1. discovery:
  2. kubernetes:
  3. service:
  4. # apiserver schema, options [http, https]
  5. schema: https #default https
  6. # apiserver host, options [ipv4, ipv6, domain, environment variable]
  7. host: ${KUBERNETES_SERVICE_HOST} #default ${KUBERNETES_SERVICE_HOST}
  8. # apiserver port, options [port number, environment variable]
  9. port: ${KUBERNETES_SERVICE_PORT} #default ${KUBERNETES_SERVICE_PORT}
  10. client:
  11. # serviceaccount token or token_file
  12. token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  13. #token: |-
  14. # eyJhbGciOiJSUzI1NiIsImtpZCI6Ikx5ME1DNWdnbmhQNkZCNlZYMXBsT3pYU3BBS2swYzBPSkN3ZnBESGpkUEEif
  15. # 6Ikx5ME1DNWdnbmhQNkZCNlZYMXBsT3pYU3BBS2swYzBPSkN3ZnBESGpkUEEifeyJhbGciOiJSUzI1NiIsImtpZCI
  16. # kubernetes discovery plugin support use namespace_selector
  17. # you can use one of [equal, not_equal, match, not_match] filter namespace
  18. namespace_selector:
  19. # only save endpoints with namespace equal default
  20. equal: default
  21. # only save endpoints with namespace not equal default
  22. #not_equal: default
  23. # only save endpoints with namespace match one of [default, ^my-[a-z]+$]
  24. #match:
  25. #- default
  26. #- ^my-[a-z]+$
  27. # only save endpoints with namespace not match one of [default, ^my-[a-z]+$]
  28. #not_match:
  29. #- default
  30. #- ^my-[a-z]+$
  31. # kubernetes discovery plugin support use label_selector
  32. # for the expression of label_selector, please refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
  33. label_selector: |-
  34. first="a",second="b"

如果 Kubernetes 服务发现模块运行在 Pod 内, 你可以使用最简配置:

  1. discovery:
  2. kubernetes: { }

如果 Kubernetes 服务发现模块运行在 Pod 外, 你需要新建或选取指定的 ServiceAccount, 获取其 Token 值, 然后使用如下配置:

  1. discovery:
  2. kubernetes:
  3. service:
  4. schema: https
  5. host: # enter apiserver host value here
  6. port: # enter apiServer port value here
  7. client:
  8. token: # enter serviceaccount token value here
  9. #token_file: # enter file path here

Kubernetes 服务发现模块的查询接口

Kubernetes 服务发现模块遵循 APISIX Discovery 规范 提供查询接口

函数: nodes(service_name)

说明: service_name 必须满足格式: [namespace]/[name]:[portName]

  • namespace: Endpoints 所在的命名空间

  • name: Endpoints 的资源名

  • portName: Endpoints 定义包含的 portName, 如果 Endpoints 没有定义 portName, 请使用 targetPort,Port 代替

返回值: 以如下 Endpoints 为例:

  1. apiVersion: v1
  2. kind: Endpoints
  3. metadata:
  4. name: plat-dev
  5. namespace: default
  6. subsets:
  7. - addresses:
  8. - ip: "10.5.10.109"
  9. - ip: "10.5.10.110"
  10. ports:
  11. - port: 3306

nodes(“default/plat-dev:3306”) 调用会得到如下的返回值:

  1. {
  2. {
  3. host="10.5.10.109",
  4. port= 3306,
  5. weight= 50,
  6. },
  7. {
  8. host="10.5.10.110",
  9. port= 3306,
  10. weight= 50,
  11. },
  12. }

Q&A

Q: 为什么只支持配置 token 来访问 Kubernetes APIServer \ A: 一般情况下,我们有三种方式可以完成与 Kubernetes APIServer 的认证:

  • mTLS
  • token
  • basic authentication

因为 lua-resty-http 目前不支持 mTLS, basic authentication 不被推荐使用,\ 所以当前只实现了 token 认证方式


Q: APISIX 继承了 Nginx 的多进程模型, 是否意味着每个 APISIX 工作进程都会监听 Kubernetes Endpoints \ A: Kubernetes 服务发现模块只使用特权进程监听 Kubernetes Endpoints, 然后将其值存储\ 到 ngx.shared.kubernetes, 工作进程通过查询 ngx.shared.kubernetes 来获取结果


Q: 怎样获取指定 ServiceAccount 的 Token 值 \ A: 假定你指定的 ServiceAccount 资源名为 “kubernetes-discovery“, 命名空间为 “apisix”, 请按如下步骤获取其 Token 值

  1. 获取 Secret 资源名: \ 执行以下命令, 输出的第一列内容就是目标 Secret 资源名
  1. kubectl -n apisix get secrets | grep kubernetes-discovery
  1. 获取 Token 值: \ 假定你获取到的 Secret 资源名为 “kubernetes-discovery-token-c64cv”, 执行以下命令, 输出内容就是目标 Token 值
  1. kubectl -n apisix get secret kubernetes-discovery-token-c64cv -o jsonpath={.data.token} | base64 -d