मैं एक पॉड कंटेनर के भीतर से कुबेरनेट्स एपि का उपयोग कैसे करूं?


118

मैं कर्ल करने में सक्षम था

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

मेरे आधार URL के रूप में, लेकिन कुबेरनेट्स 0.18.0 में यह मुझे "अनधिकृत" देता है। अजीब बात यह है कि अगर मैंने एपीआई मशीन ( http://172.17.8.101:8080/api/v1beta3/namespaces/default/) के बाहरी आईपी पते का उपयोग किया है , तो यह ठीक काम करता है।


आप अपना क्लस्टर (GCE, AWS, आदि) कहां चला रहे हैं और किस बेस OS (डेबियन, कोरओएस आदि) का उपयोग कर रहे हैं?
रॉबर्ट बेली

Vagrant / CoreOS ... मैं अंततः इसे AWS / CoreOS में ले जाऊंगा
tslater

चर $KUBERNETES_SERVICE_HOSTऔर $KUBERNETES_PORT_443_TCP_PORTचर कहाँ से आते हैं?
ruediste

मुझे यह मार्गदर्शिका 101 के लिए सेवा खातों, भूमिकाओं और भूमिका निर्धारक डेवलपर . ibm.com/recipes/tutorial// पर आश्चर्यजनक लगी । अंतिम खंड में बताया गया है कि हम पॉड्स के भीतर k8 एपीआई फॉर्म कैसे एक्सेस कर सकते हैं।
viv

जवाबों:


132

आधिकारिक दस्तावेज में मुझे यह मिला:

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

जाहिरा तौर पर मैं एक सुरक्षा टोकन को याद नहीं कर रहा था, जिसे मुझे कुबेरनेट्स के पिछले संस्करण में ज़रूरत नहीं थी। उस से, मैंने सोचा कि मुझे क्या लगता है एक प्रॉक्सी चलाने या मेरे कंटेनर पर गोलंग स्थापित करने की तुलना में एक सरल समाधान है। इस उदाहरण को देखें, जो जानकारी प्राप्त करता है, एपी से, वर्तमान कंटेनर के लिए:

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/ ) का उपयोग करता हूं, बैश लिपियों में उपयोग के लिए जेंस को पार्स करने के लिए।


5
हाल ही में तैनात किए गए समूहों के लिए आप बदलना चाहते हो सकता है v1beta3के लिएv1
ईयाल लेविन

6
ध्यान दें कि यह कर्ल कमांड असुरक्षित रूप से एपसेवर से जुड़ जाएगा (यह वाहक के बीच अवरोधक को रोकने के लिए एक आदमी के लिए संभव है), इसलिए आपको केवल इसका उपयोग करना चाहिए यदि फली और एपेस्वर के बीच नेटवर्क पूरी तरह से विश्वसनीय है। अन्यथा, आपको --cacertध्वज को कर्ल करने के लिए पास करना चाहिए ताकि कर्ल एपर्वर द्वारा प्रस्तुत प्रमाण पत्र को मान्य कर सके।
रॉबर्ट बेली

1
मैं का इस्तेमाल किया था KUBERNETES_SERVICE_HOST=kubernetes.default, $KUBERNETES_443_TCP_PORT=443, NAMESPACE == $ (</ var / रन / रहस्य / kubernetes.io / serviceaccount / नाम स्थान) . The URL was kubernetes.default: 443 / API / v1 / नामस्थान / $ NAMESPACE / फली / ... `। ध्यान दें कि एपीआई संस्करण v1beta3 के बजाय v1 पर सेट है और डिफ़ॉल्ट नाम स्थान को $ NAMESPACE के साथ बदल दिया गया था।
ruediste

74

प्रत्येक पॉड में एक स्वचालित खाता होता है जो स्वचालित रूप से लागू होता है जो इसे एपेसेवर तक पहुंचने देता है। सेवा खाता दोनों क्लाइंट क्रेडेंशियल्स प्रदान करता है, एक वाहक टोकन के रूप में, और प्रमाणपत्र प्राधिकारी प्रमाण पत्र जो एपर्चर द्वारा प्रस्तुत प्रमाण पत्र पर हस्ताक्षर करने के लिए उपयोग किया जाता था। जानकारी के इन दो टुकड़ों के साथ, आप 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.default.svc/

2
यह ध्यान दिया जाना चाहिए कि सेवा खाते में दोनों के कैचर और टोकन के लिए, प्रतिकृति-नियंत्रक को एक --root-ca-file=तर्क दिया जाना चाहिए जब शुरू हो। (यह अधिकांश कुबेरनेट इंस्टॉलर में स्वचालित रूप से नियंत्रित किया जाता है)। अधिक जानकारी के लिए यहां चर्चा देखें: github.com/kubernetes/kubernetes/issues/10265
JKnight

7
मैं एक अलग नामस्थान के साथ पॉड से एपीआई सर्वर को एक्सेस कर रहा था। इस प्रकार मैं इस्तेमाल किया था https://kubernetes.default/के रूप में मेजबान
ruediste


17

पायथन कुबेरनेट्स क्लाइंट का उपयोग करना ।।

from kubernetes import client, config

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

1
धन्यवाद! यहां आपके जवाब के आधार पर एक उदाहरण के साथ एक छोटा रेपो है , जिससे इस कोड के साथ खेलना सरल हो जाता है।
ओमर लेवी हेवरोनी

10

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

6

ऊपर बताए गए विवरणों में सबसे महत्वपूर्ण परिशिष्ट यह है कि जिस पॉड से आप एपीआई सर्वर तक पहुंचने का प्रयास कर रहे हैं, उसके पास ऐसा करने के लिए आरबीएसी क्षमताएं होनी चाहिए।

K8s सिस्टम की प्रत्येक इकाई को एक सेवा-खाते (जैसे उपयोगकर्ता खाता उपयोगकर्ताओं के लिए उपयोग किया जाता है) द्वारा पहचाना जाता है। RBAC क्षमताओं के आधार पर, सेवा खाता टोकन (/var/run/secrets/kubernetes.io/serviceaccount/token) आबाद है। क्यूब-एपी-सर्वर से कनेक्शन बनाते समय क्यूब-एपी बाइंडिंग (जैसे प्यूब्यूब) इस टोकन को इनपुट के रूप में ले सकते हैं। यदि पॉड में सही RBAC क्षमताएं हैं, तो पॉड kube-api सर्वर के साथ कनेक्शन स्थापित करने में सक्षम होगा।


5

गो कोड का उपयोग करके पॉड के अंदर से एपीआई तक पहुंचने की कोशिश करते समय मैं इस मुद्दे पर भाग गया। नीचे मैंने उस कार्य को करने के लिए लागू किया है, क्या किसी को इस प्रश्न के बारे में पता होना चाहिए कि वह भी गो का उपयोग करना चाहता है।

उदाहरण पॉड संसाधन का उपयोग करता है, जिसके लिए आपको 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

4

फली के अंदर से, कुबेरनेट्स एपीआई सर्वर " https: //kubernetes.default " पर सीधे पहुँचा जा सकता है । डिफ़ॉल्ट रूप से यह एपीआई सर्वर तक पहुँचने के लिए "डिफ़ॉल्ट सेवा खाता" का उपयोग करता है।

इसलिए, हमें एपीआई सर्वर के साथ प्रमाणित करने के लिए "सीए सर्टिफिकेट" और "डिफॉल्ट सर्विस अकाउंट टोकन" भी पास करना होगा।

प्रमाणपत्र फ़ाइल पॉड के अंदर निम्न स्थान पर संग्रहीत है: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

और डिफ़ॉल्ट सेवा खाता टोकन यहां: /var/run/secrets/kubernetes.io/serviceaccount/token

आप नोडज क्बरनेट्स गोडैडी क्लाइंट का उपयोग कर सकते हैं ।

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


3

मुझे 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

अधिक जानकारी के लिए लिंक विवरण यहां दर्ज करें



2

RBAC सक्षम होने के साथ, डिफ़ॉल्ट सेवा खाते में कोई अनुमति नहीं है।

अपनी आवश्यकताओं के लिए बेहतर सेवा खाता बनाएं और अपनी पॉड बनाने के लिए इसका उपयोग करें।

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

यह यहाँ अच्छी तरह से समझाया गया है https://developer.ibm.com/recipes/tutorials/service-accounts-and-auditing-in-kubernetes/


0
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 है, और अन्य संस्करणों में यह ^ ^ भी काम करने वाला है


यदि आपके पास webhooks या कुछ अन्य RBAC सक्षम हैं, तो उपरोक्त सही है। यह विशेष रूप से सच है> 1.2 k8s की
doktoroblivion

0

This is from the एक्शन में कुबेरनेट्स book.

आपको प्रमाणीकरण का ध्यान रखने की आवश्यकता है । एपीआई सर्वर खुद कहता है कि आप इसे एक्सेस करने के लिए अधिकृत नहीं हैं, क्योंकि यह नहीं जानता कि आप कौन हैं

प्रमाणित करने के लिए, आपको एक प्रमाणीकरण टोकन की आवश्यकता है सौभाग्य से, टोकन को डिफ़ॉल्ट-टोकन सीक्रेट के माध्यम से प्रदान किया जाता है पहले बताए किया जाता है, और गुप्त वॉल्यूम में टोकन फ़ाइल में संग्रहीत किया जाता है।

आप API सर्वर तक पहुंचने के लिए टोकन का उपयोग करने जा रहे हैं । सबसे पहले, एक टोकन को एक पर्यावरण चर में लोड करें:

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

टोकन अब 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"  
      ]
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.