IT

포드 컨테이너 내에서 Kubernetes API에 액세스해야합니까?

lottoking 2020. 8. 20. 19:07
반응형

포드 컨테이너 내에서 Kubernetes API에 액세스해야합니까?


나는 컬을 할 수 있었다

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

내 기본 URL은 사용하지만 kubernetes 0.18.0에서는 "승인되지 않음"을 제공합니다. 이상한 점은 API 머신 ( http://172.17.8.101:8080/api/v1beta3/namespaces/default/) 의 외부 IP 주소를 사용하면 작동한다는 것입니다.


공식 문서에서 다음을 발견했습니다.

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

분명히 이전 버전의 Kubernetes에서 필요하지 않은 보안 토큰이 없어졌습니다. 그로부터 프록시를 실행하거나 컨테이너에 golang을 설치하는 것보다 더 간단한 솔루션이라고 생각하는 것을 고안했습니다. 현재 컨테이너에 대한 정보를 API에서 가져 오는 예제를 참조하십시오.

KUBE_TOKEN=$(cat /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/ )를 사용하여 bash 펼쳐서 사용할 json을 구문 분석합니다.


모든 pod에는 apiserver에 액세스 할 수있는 서비스 계정이 자동으로 적용됩니다. 서비스 계정은 전달자 토큰 형식의 클라이언트 자격 증명과 apiserver에서 제공 한 인증서에 서명하는 데 사용하는 인증 기관 인증서를 모두 제공합니다. 이 두 가지 정보를 사용하면 curl -k(일명 curl --insecure) 을 사용하여 안전하고 apisever에 대한 인증 된 연결을 수 있습니다 .

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

Python kubernetes 클라이언트 사용 ..

from kubernetes import client, config

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

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

API 서버에 대한 가장 많이 언급 한 추가 사항은 API 서버에 할 수있는 중요한 추가 사항에 대한 수행 할 수있는 RBAC 기능이 있다는 것입니다.

k8s 시스템의 각 메모리는 서비스 계정 (예 : 사용자에게 사용되는 사용자 계정)으로 이미지됩니다. RBAC 기능에 따라 서비스 계정 토큰 (/var/run/secrets/kubernetes.io/serviceaccount/token)이 채워집니다. kube-api 바인딩 (예 : pykube)은 kube-api-servers에 강화할 때 토큰을 입력 할 수 있습니다. 포드에 올바른 RBAC 기능이있는 경우 포드는 kube-api 서버와의 연결을 수 있습니다.


포드 내부에서 kubernetes api 서버는 " https : //kubernetes.default " 에서 직접 액세스 할 수 있습니다 . 기본적으로 api 서버에 액세스하기 위해 "기본 서비스 계정"을 사용합니다.

따라서 api 서버로 인증하기 위해 "ca cert"및 "default service account token"을 전달해야합니다.

인증서 파일은 포드 내의 다음 위치에 저장됩니다. /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

및 기본 서비스 계정 토큰 : /var/run/secrets/kubernetes.io/serviceaccount/token

nodejs kubbernetes godaddy 클라이언트를 사용할 수 있습니다 .

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);
}


Google Container Engine (Kubernetes 기반)을 사용하는 모든 사용자 :

이 Java 용 kubernetes 클라이언트를https://kubernetes 사용하여 클러스터 내에서 간단한 호출 작동합니다.


Go Code를 사용하여 포드 내부에서 API에 액세스하려고 할 때이 문제가 발생했습니다. 아래는 누군가 Go를 사용하고 싶어하는이 질문을 발견하면 작동하도록 구현 한 것입니다.

이 예에서는 client-go네이티브 kubernetes 객체로 작업하는 경우 라이브러리 를 사용해야하는 포드 리소스를 사용 합니다. 이 코드는 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

RBAC를 사용하면 기본 서비스 계정에 권한이 없습니다.

필요에 따라 별도의 서비스 계정을 만들고 포드를 만드는 데 사용하는 것이 좋습니다.

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

https://developer.ibm.com/recipes/tutorials/service-accounts-and-auditing-in-kubernetes/ 여기에 잘 설명되어 있습니다.


Python 스크립트에서 갑자기 예외가 발생하는 GKE에서 유사한 인증 문제가 발생했습니다. 나를 위해 일한 해결책은 역할을 통해 포드에 권한을 부여하는 것이 었습니다.

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

자세한 내용은 여기에 링크 설명을 입력하십시오.


curl -v -cacert <path to>/ca.crt --cert <path to>/kubernetes-node.crt --key <path to>/kubernetes-node.key https://<ip:port>

내 k8s 버전은 1.2.0이고 다른 버전에서도 작동합니다 ^ ^

참고 URL : https://stackoverflow.com/questions/30690186/how-do-i-access-the-kubernetes-api-from-within-a-pod-container

반응형