如何从pod容器中访问Kubernetes api?

时间:2015-06-07 04:55:17

标签: kubernetes

我曾经能够卷曲

https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1beta3/namespaces/default/

作为我的基本网址,但在kubernetes 0.18.0中,它给了我"未经授权的#34;。奇怪的是,如果我使用API​​机器的外部IP地址(http://172.17.8.101:8080/api/v1beta3/namespaces/default/),它就可以正常工作。

12 个答案:

答案 0 :(得分:95)

在官方文档中我发现了这个:

https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/#accessing-the-api-from-a-pod

显然我错过了一个安全令牌,我在之前版本的Kubernetes中并不需要。从那时起,我设计了一个比运行代理或在容器上安装golang更简单的解决方案。请参阅此示例,该示例从api获取当前容器的信息:

KUBE_TOKEN=$(</var/run/secrets/kubernetes.io/serviceaccount/token)
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" \
      https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME

我还使用包含一个简单的二进制文件jq(http://stedolan.github.io/jq/download/)来解析json以便在bash脚本中使用。

答案 1 :(得分:53)

每个pod都有一个自动应用的服务帐户,允许它访问apiserver。服务帐户以持有者令牌的形式提供客户端凭证,以及用于签署由许可者提供的证书的证书颁发机构证书。使用这两条信息,您可以创建与apisever的安全,经过身份验证的连接,而无需使用curl -k(又名curl --insecure):

curl -v --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes/

答案 2 :(得分:9)

使用Python kubernetes客户端..

from kubernetes import client, config

config.load_incluster_config()
v1_core = client.CoreV1Api()

答案 3 :(得分:6)

wget版本:

KUBE_TOKEN=$(</var/run/secrets/kubernetes.io/serviceaccount/token)    
wget -vO- --ca-certificate /var/run/secrets/kubernetes.io/serviceaccount/ca.crt  --header "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME

答案 4 :(得分:4)

上面已经提到的详细信息中最重要的附录是,您尝试从其访问API服务器的容器应该具有RBAC功能。

k8s系统中的每个实体都由一个服务帐户(例如用户使用的用户帐户)标识。基于RBAC功能,将填充服务帐户令牌(/var/run/secrets/kubernetes.io/serviceaccount/token)。创建与kube-api-server的连接时,kube-api绑定(例如pykube)可以将此令牌作为输入。如果Pod具有正确的RBAC功能,则Pod将能够与kube-api服务器建立连接。

答案 5 :(得分:3)

从pod内部可以直接访问kubernetes api服务器&#34; https://kubernetes.default&#34;。默认情况下,它使用&#34;默认服务帐户&#34;用于访问api服务器。

所以,我们还需要通过一个&#34; ca cert&#34;和#34;默认服务帐户令牌&#34;使用api服务器进行身份验证。

证书文件存储在pod中的以下位置: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

和默认服务帐户令牌位于: /var/run/secrets/kubernetes.io/serviceaccount/token

您可以使用nodejs kubbernetes godaddy client

&#13;
&#13;
let getRequestInfo = () => {
    return {
        url: "https://kubernetes.default",
        ca:   fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/ca.crt').toString(),
        auth: {
            bearer: fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/token').toString(),
        },
        timeout: 1500
    };
}

let initK8objs = () =>{
    k8obj = getRequestInfo();
    k8score = new Api.Core(k8obj),
    k8s = new Api.Api(k8obj);
}
&#13;
&#13;
&#13;

答案 6 :(得分:2)

对于使用Google容器引擎的任何人(由Kubernetes提供支持):

使用this kubernetes client for Java从群集中简单调用localhost即可。

答案 7 :(得分:2)

尝试使用Go Code从pod内部访问API时遇到此问题。下面是我实现的工作,如果有人遇到这个想要使用Go的问题。

该示例使用pod资源,如果您正在使用本机kubernetes对象,则应使用client-go库。该代码对于使用CustomResourceDefintions的人更有帮助。

serviceHost := os.GetEnv("KUBERNETES_SERVICE_HOST")
servicePort := os.GetEnv("KUBERNETES_SERVICE_PORT")
apiVersion := "v1" // For example
namespace := default // For example
resource := "pod" // For example
httpMethod := http.MethodGet // For Example

url := fmt.Sprintf("https://%s:%s/apis/%s/namespaces/%s/%s", serviceHost, servicePort, apiVersion, namespace, resource)

u, err := url.Parse(url)
if err != nil {
  panic(err)
}
req, err := http.NewRequest(httpMethod, u.String(), bytes.NewBuffer(payload))
if err != nil {
    return err
}

caToken, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
if err != nil {
    panic(err) // cannot find token file
}

req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(caToken)))

caCertPool := x509.NewCertPool()
caCert, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")
if err != nil {
    return panic(err) // Can't find cert file
}
caCertPool.AppendCertsFromPEM(caCert)

client := &http.Client{
  Transport: &http.Transport{
    TLSClientConfig: &tls.Config{
        RootCAs: caCertPool,
    },
  },
}

resp, err := client.Do(req)
if err != nil {
    log.Printf("sending helm deploy payload failed: %s", err.Error())
    return err
}
defer resp.Body.Close()

// Check resp.StatusCode
// Check resp.Status

答案 8 :(得分:1)

我在GKE上遇到类似的auth问题,其中python脚本突然抛出异常。对我有用的解决方案是通过角色

授予pods权限
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: fabric8-rbac
subjects:
  - kind: ServiceAccount
  # Reference to upper's `metadata.name`
  name: default
  # Reference to upper's `metadata.namespace`
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

了解更多信息enter link description here

答案 9 :(得分:1)

This is from the Kubernetes In Action book.

您需要注意身份验证。 API服务器本身说您无权访问它,因为它不知道您是谁

要进行身份验证,您需要一个身份验证令牌。。幸运的是,令牌是通过前面提到的 default-token密钥提供的,并存储在令牌文件中。秘密卷。

您将使用令牌访问API服务器。首先,将令牌加载到环境变量中:

root@myhome:/# TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

令牌现在存储在令牌 环境 变量中。您可以在向API服务器发送请求时使用它:

root@curl:/# curl -H "Authorization: Bearer $TOKEN"  https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME
   {  "paths": 
      [    
        "/api",    
        "/api/v1",   
        "/apis",    
        "/apis/apps",    
        "/apis/apps/v1beta1",    
        "/apis/authorization.k8s.io",        
         ...    
        "/ui/",    
        "/version"  
      ]
  }

答案 10 :(得分:0)

display:inline-block

我的k8s版本是1.2.0,而在其他版本中它也应该可以工作^ ^

答案 11 :(得分:0)

启用RBAC后,默认服务帐户没有任何权限。

最好根据您的需求创建单独的服务帐户,并使用它来创建您的帐户。

spec:
  serviceAccountName: secret-access-sa
  containers:
    ...

这里很好地解释了https://developer.ibm.com/recipes/tutorials/service-accounts-and-auditing-in-kubernetes/