Skip to content Skip to sidebar Skip to footer

Gcp Cloud Function - Could Not Find Kubectl On The Path

i'm writing this Google Cloud Function (Python) def create_kubeconfig(request): subprocess.check_output('curl https://sdk.cloud.google.com | bash | echo '' ',stdin=subprocess.P

Solution 1:

You have to reach programmatically the K8S API. You have the description of the API in the documentation

But it's not easy and simple to perform. However, here some inputs for achieving what you want.

First, get the GKE master IP enter image description here

Then you can access to the cluster easily. Here for reading the deployment

import google.auth
    from google.auth.transport import requests
    credentials, project_id = google.auth.default()
    session = requests.AuthorizedSession(credentials)
    response = session.get('https://34.76.28.194/apis/apps/v1/namespaces/default/deployments', verify=False)
    response.raise_for_status()
    print(response.json())

For creating one, you can do this

import google.auth
    from google.auth.transport import requests
    credentials, project_id = google.auth.default()
    session = requests.AuthorizedSession(credentials)
    withopen("deployment.yaml", "r") as f:
        data = f.read()
    response = session.post('https://34.76.28.194/apis/apps/v1/namespaces/default/deployments', data=data,
                            headers={'content-type': 'application/yaml'}, verify=False)
    response.raise_for_status()
    print(response.json())

According with the object that you want to build, you have to use the correct file definition and the correct API endpoint. I don't know a way to apply a whole yaml with several definition in only one API call.

Last things, be sure to provide the correct GKE roles to the Cloud Function service Account

UPDATE

Another solution is to use Cloud Run. Indeed, with Cloud Run and thanks to the Container capability, you have the ability to install and to call system process (it's totally open because your container runs into a GVisor sandbox, but most of common usages are allowed)

The idea is the following: use a gcloud SDK base image and deploy your application on it. Then, code your app to perform system calls.

Here a working example in Go

Docker file

FROM golang:1.13 as builder

# Copy local code to the container image.
WORKDIR /app/
COPY go.mod .
ENV GO111MODULE=on
RUN go mod download

COPY . .

# Perform test for building a clean package
RUN go test -v ./...
RUN CGO_ENABLED=0 GOOS=linux go build -v -o server

# Gcloud capable image
FROM google/cloud-sdk

COPY --from=builder /app/server /server
CMD ["/server"]

Note: The image cloud-sdk image is heavy: 700Mb

The content example (only the happy path. I remove error management, and the stderr/stdout feedback for simplifying the code)

    .......
// Example here: recover the yaml file into a bucket
    client,_ := storage.NewClient(ctx)
    reader,_ := client.Bucket("my_bucket").Object("deployment.yaml").NewReader(ctx)
    content,_:= ioutil.ReadAll(reader)
// You can store locally the file into /tmp directory. It's an in-memory file system. Don't forget to purge it to avoid any out of memory crash
    ioutil.WriteFile("/tmp/file.yaml",content, 0644)
// Execute external command// 1st Recover the kube authentication
    exec.Command("gcloud","container","clusters","get-credentials","cluster-1","--zone=us-central1-c").Run()
// Then interact with the cluster with kubectl tools and simply apply your description file
    exec.Command("kubectl","apply", "-f","/tmp/file.yaml").Run()
    .......

Solution 2:

Instead of using gcloud inside the Cloud Function (and attempting to install it on every request, which will significantly increase the runtime of your function), you should use the google-cloud-container client library to make the same API calls directly from Python, for example:

from google.cloud import container_v1

client = container_v1.ClusterManagerClient()

project_id = 'YOUR_PROJECT_ID'
zone = 'YOUR_PROJECT_ZONE'

response = client.list_clusters(project_id, zone)

Post a Comment for "Gcp Cloud Function - Could Not Find Kubectl On The Path"