methods


weight: 92 title:访问集群 date: “2022-05-21T00:00:00+08:00” type: book

本文列举了集中访问Kubernetes集群的方式。

第一次使用kubectl访问

如果您是第一次访问Kubernetes API的话,我们建议您使用Kubernetes命令行工具:kubectl

为了访问集群,您需要知道集群的地址,并且需要有访问它的凭证。通常,如果您完成了入门指南那么这些将会自动设置,或者其他人为您部署的集群提供并给您凭证和集群地址。

使用下面的命令检查kubectl已知的集群的地址和凭证:

$ kubectl config view

直接访问REST API

Kubectl处理对apiserver的定位和认证。如果您想直接访问REST API,可以使用像curlwget或浏览器这样的http客户端,有以下几种方式来定位和认证:

  • proxy模式运行kubectl
    • 推荐方法。
    • 使用已保存的apiserver位置信息。
    • 使用自签名证书验证apiserver的身份。没有MITM(中间人攻击)的可能。
    • 认证到apiserver
    • 将来,可能会做智能的客户端负载均衡和故障转移。
  • 直接向http客户端提供位置和凭据。
    • 替代方法。
    • 适用于通过使用代理而混淆的某些类型的客户端代码。
    • 需要将根证书导入浏览器以防止MITM

使用kubectl proxy

以下命令作为反向代理的模式运行kubectl。它处理对apiserver的定位并进行认证。

像这样运行:

$ kubectl proxy --port=8080 &

然后您可以使用curlwget或者浏览器来访问API,如下所示:

$ curl http://localhost:8080/api/
{
  "versions": [
    "v1"
  ]
}

不使用kubectl proxy1.3.x以前版本)

通过将认证token直接传递给apiserver的方式,可以避免使用kubectl proxy,如下所示:

$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
$ TOKEN=$(kubectl config view | grep token | cut -f 2 -d ":" | tr -d " ")
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "versions": [
    "v1"
  ]
}

不使用kubectl proxy1.3.x以后版本)

Kubernetes 1.3或更高版本中,kubectl config view 不再显示token。使用 kubectl describe secret … 获取default service accounttoken,如下所示:

$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
$ TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t')
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

以上示例使用--insecure 标志。这使得它容易受到MITM攻击。当kubectl访问集群时,它使用存储的根证书和客户端证书来访问服务器(这些安装在~/.kube目录中。由于集群证书通常是自签名的,因此可能需要特殊配置才能让您的http客户端使用根证书。

对于某些集群,apiserver可能不需要身份验证;可以选择在本地主机上服务,或者使用防火墙保护。对此还没有一个标准。配置对API的访问 描述了集群管理员如何配置此操作。这种方法可能与未来的高可用性支持相冲突。

编程访问API

Kubernetes支持 GoPython 客户端库。

Go客户端

  • 要获取该库,请运行以下命令:go get k8s.io/client-go/<version number>/kubernetes 请参阅 https://github.com/kubernetes/client-go 以查看支持哪些版本。
  • 使用client-go客户端编程。请注意,client-go定义了自己的API对象,因此如果需要,请从client-go而不是从主存储库导入API定义,例如导入 k8s.io/client-go/1.4/pkg/api/v1 是正确的。

Go客户端可以使用与kubectl命令行工具相同的 kubeconfig文件 来定位和验证apiserver。参考官方 示例client-go示例

如果应用程序在集群中以Pod的形式部署,请参考 下一节

Python客户端

要使用 Python client,请运行以下命令:pip install kubernetes。查看 Python客户端库页面 获取更多的安装选择。

Python客户端可以使用与kubectl命令行工具相同的 kubeconfig文件 来定位和验证apiserver

其他语言

还有更多的客户端库可以用来访问API。有关其他库的验证方式,请参阅文档。

Pod中访问API

Pod中访问API时,定位和认证到API server的方式有所不同。在Pod中找到apiserver地址的推荐方法是使用kubernetes DNS名称,将它解析为服务IP,后者又将被路由到apiserver

apiserver认证的推荐方法是使用 service account 凭据。通过kube-systempodservice account相关联,并且将该service account的凭据(token)放入该pod中每个容器的文件系统树中,位于 /var/run/secrets/kubernetes.io/serviceaccount/token

如果可用,证书包将位于每个容器的文件系统树的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 位置,并用于验证apiserver的服务证书。

最后,用于namespace API操作的默认namespace放在每个容器中的 /var/run/secrets/kubernetes.io/serviceaccount/namespace 中。

pod中,连接到API的推荐方法是:

  • kubectl proxy作为pod中的一个容器来运行,或作为在容器内运行的后台进程。它将Kubernetes API代理到pod的本地主机接口,以便其他任何pod中的容器内的进程都可以访问它。

  • 使用Go客户端库,并使用 rest.InClusterConfig()kubernetes.NewForConfig() 函数创建一个客户端。

    他们处理对apiserver的定位和认证。示例

在以上的几种情况下,都需要使用pod的凭据与apiserver进行安全通信。

访问集群中运行的service

上一节是关于连接到kubernetes API server。这一节是关于连接到kubernetes集群中运行的service。在Kubernetes中,nodepodservices 都有它们自己的IP。很多情况下,集群中nodeIPPodIPserviceIP都是不可路由的,因此在集群外面的机器就无法访问到它们,例如从您自己的笔记本电脑。

连接的方式

您可以选择以下几种方式从集群外部连接到nodepodservice

  • 通过public IP访问service
    • 使用 NodePortLoadBalancer 类型的service,以使service能够在集群外部被访问到。
    • 根据您的集群环境,这可能会将服务暴露给您的公司网络,或者可能会将其暴露在互联网上。想想暴露的服务是否安全。它是否自己进行身份验证?
    • pod放在服务后面。要从一组副本(例如为了调试)访问一个特定的pod,请在pod上放置一个唯一的label,并创建一个选择该label的新服务。
    • 在大多数情况下,应用程序开发人员不需要通过node IP直接访问节点。
  • 通过Proxy规则访问service、node、pod。
    • 在访问远程服务之前,请执行apiserver认证和授权。如果服务不够安全,无法暴露给互联网,或者为了访问节点IP上的端口或进行调试,请使用这种方式。
    • 代理可能会导致某些Web应用程序出现问题。
    • 仅适用于HTTP/HTTPS
    • 见此描述
  • 在集群内访问nodepod
    • 运行一个pod,然后使用kubectl exec命令连接到shell。从该shell中连接到其他nodepodservice
    • 有些集群可能允许ssh到集群上的某个节点。从那个节点您可以访问到集群中的服务。这是一个非标准的方法,它可能将在某些集群上奏效,而在某些集群不行。这些节点上可能安装了浏览器和其他工具也可能没有。集群DNS可能无法正常工作。

访问内置服务

通常集群内会有几个在kube-system中启动的服务。使用 kubectl cluster-info 命令获取该列表:

$ kubectl cluster-info

  Kubernetes master is running at https://104.197.5.247
  elasticsearch-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy
  kibana-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kibana-logging/proxy
  kube-dns is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kube-dns/proxy
  grafana is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
  heapster is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy

这显示了访问每个服务的代理URL

例如,此集群启用了集群级日志记录(使用Elasticsearch,如果传入合适的凭据,可以在该地址 https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/ 访问到,或通过kubectl代理,例如:http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/

(有关如何传递凭据和使用kubectl代理,请 参阅上文

手动构建apiserver代理URL

如上所述,您可以使用 kubectl cluster-info 命令来检索服务的代理URL。要创建包含服务端点、后缀和参数的代理URL,您只需附加到服务的代理URL

http://kubernetes_master_address/api/v1/namespaces/namespace_name/services/service_name[:port_name]/proxy

如果您没有指定port的名字,那么您不必在URL里指定port_name

示例

  • 要想访问Elasticsearch的服务端点 _search?q=user:kimchy,您需要使用:http://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy
  • 要想访问Elasticsearch的集群健康信息 _cluster/health?pretty=true,您需要使用:https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true
{
  "cluster_name": "kubernetes_logging",
  "status": "yellow",
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 5,
  "active_shards": 5,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 5
}

使用web浏览器来访问集群中运行的服务

您可以将apiserver代理网址放在浏览器的地址栏中。然而:

  • Web浏览器通常不能传递token,因此您可能需要使用基本(密码)认证。Apiserver可以配置为接受基本认证,但您的集群可能未配置为接受基本认证。
  • 某些网络应用程序可能无法正常工作,特别是那些在不知道代理路径前缀的情况下构造URL的客户端JavaScript

请求重定向

重定向功能已被弃用和删除。请改用代理(见下文

多种代理

在使用kubernetes的时候您可能会遇到许多种不同的代理:

  1. kubectl代理
    • 在用户桌面或pod中运行
    • localhost地址到Kubernetes apiserver的代理
    • 客户端到代理使用HTTP
    • apiserver的代理使用HTTPS
    • 定位apiserver
    • 添加身份验证header
  2. apiserver代理
    • 将一个堡垒机作为apiserver
    • 将集群之外的用户连接到集群IP,否则可能无法访问
    • apiserver进程中运行
    • 客户端到代理使用HTTPS(或http,如果apiserver如此配置)
    • 根据代理目标的可用信息由代理选择使用HTTPHTTPS
    • 可用于访问nodepodservice
    • 用于访问service时进行负载均衡
  3. kube代理
    • 在每个节点上运行
    • 代理UDPTCP
    • 不支持HTTP
    • 提供负载均衡
    • 只是用来访问service
  4. apiserver前面的代理/负载均衡器:
    • 存在和实现因集群而异(例如nginx
    • 位于所有客户端和一个或多个apiserver之间
    • 作为负载均衡器,如果有多个apiserver
  5. 外部服务的云负载均衡器:
    • 由一些云提供商提供(例如AWS ELB,Google Cloud Load Balancer)
    • Kubernetes service类型为LoadBalancer时,会自动创建
    • 仅使用UDP/TCP
    • 实施方式因云提供商而异
上一页
下一页