I made a demo with kubernetes/go-client where i tried to list pods from my cluster.
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
fmt.Fprint(w, "There are d pods in the cluster\n", len(pods.Items))
I created serviceaccount token to assign to the pod where this code is running in.
But when code is executed pods.Items has no pods.
I deployed this pod inside minikube. When I launch some kubectl command for listing pods, this way I can get resources so it is no t permissions problems.
I wonder what is happening and how i can fix it.
Repository https://github.com/srpepperoni/inframanager.git
Image is pushed into: https://hub.docker.com/r/jaimeyh/inframanager
The endpoint I have problems with is this one :
mux.HandleFunc("/getPods", GetPodsFromNamespace)
You need to check if the err on the last line is non-nil.
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
OK, there is the problem. pods is forbidden: User "system:serviceaccount:mis-pruebas:sa-prueba-go" cannot list resource "pods" in API group "" at the cluster scope
As the error message indicates, the ServiceAccount does not have permission to list pods at cluster scope. You need to create Role and bind it to the ServiceAccount.
The article Using RBAC Authorization even has a role example for how to create such a role.
Related
Now i have Pods as Kubernetes structs wiht the help of the command
pods , err := clientset.CoreV1().Pods("namespace_String").List(context.TODO(), metav1.ListOptions{})
now i do i get it as individual yaml files
which command should i use
for i , pod := range pods.Items{
if i==0{
t := reflect.TypeOF(&pod)
for j := 0; j<t.NumMethod(); j++{
m := t.Method(j)
fmt.Println(m.Name)
}
}
}
this function will print the list of functions in the pod item which should i use
Thanks for the answer
The yaml is just a representation of the Pod object in the kubernetes internal storage in etcd. With your client-go what you have got is the Pod instance, of the type v1.Pod. So you should be able to work with this object itself and get whatever you want, for example p.Labels() etc. But if for some reason, you are insisting on getting a yaml, you can do that via:
import (
"sigs.k8s.io/yaml"
)
b, err := yaml.Marshal(pod)
if err != nil {
// handle err
}
log.Printf("Yaml of the pod is: %q", string(b))
Note that yaml library coming here is not coming from client-go library. The documentation for the yaml library can be found in: https://pkg.go.dev/sigs.k8s.io/yaml#Marshal
Instead of yaml if you want to use json, you can simply use the Marshal function https://pkg.go.dev/k8s.io/apiserver/pkg/apis/example/v1#Pod.Marshal provided by the v1.Pod struct itself, like any other Go object.
To get individual pod using client-go:
pod, err := clientset.CoreV1().Pods("pod_namespace").Get(context.TODO(),"pod_name", metav1.GetOptions{})
if err!=nil {
log.Fatalln(err)
}
// do something with pod
Is there a way to determine programatically if a pod is in crashloopbackoff?
I tried the following
pods,err := client.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return err
}
for _, item := range pods.Items {
log.Printf("found pod %v with state %v reason %v and phase %v that started at %v",
item.Name, item.Status.Message, item.Status.Reason, item.Status.Phase, item.CreationTimestamp.Time)
}
However this just prints blank for state and reason, tough it prints the phase.
To clarify I am posting a community wiki answer.
It's hiding in ContainerStateWaiting.Reason:
kubectl get po -o jsonpath='{.items[*].status.containerStatuses[*].state.waiting.reason}'
although be aware that it only intermittently shows up there, since it is an intermittent state of the container; perhaps a more programmatic approach is to examine the restartCount and the Error state
See also this repository.
Im using the following code to install chart that is bounded in my source code (eg. in my app/chart/chart1 in my go bin app), Now I need to move the chart to git repository or to artifactory,
My question is how can I install the chart from outside my program?
This is the code I use which works for bundled chart
I use the helm3 loader package which works when I have the chart bundled in my app
chart, err := loader.Load(“chart/chart1”)
https://pkg.go.dev/helm.sh/helm/v3#v3.5.4/pkg/chart/loader
Should I load it somehow with an http call or helm have some built in functionality ? we need some efficient way to handle it
It seems that helm during its upgrade/install commands checks first a couple of different locations which you can see getting called here. The content of that function is here.
And then continues here with loader.Load
You can use something like this for installing nginx chart
myChart, err := loader.Load("https://charts.bitnami.com/bitnami/nginx-8.8.4.tgz")
...
install := action.NewInstall(m.actionConfig)
install.ReleaseName = "my-release"
...
myRelease, err := install.Run(myChart, myValues)
It would be similar to:
helm install my-release https://charts.bitnami.com/bitnami/nginx-8.8.4.tgz
loader.load checks only for files and directories. If you want to use URL helm sdk provides LocateChart method in Install interface. Here is an example:
settings := cli.New()
actionConfig := new(action.Configuration)
if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), os.Getenv("HELM_DRIVER"), log.Printf); err != nil {
log.Printf("%+v", err)
os.Exit(1)
}
client := action.NewInstall(actionConfig)
chrt_path, err := client.LocateChart("https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-4.0.6/ingress-nginx-4.0.6.tgz", settings); if err != nil {
panic(err)
}
myChart, err := loader.Load(chrt_path); if err != nil {
panic(err)
}
Then you can simple setup install options and call client.Run method.
Does anyone have any examples of how to delete k8s jobs using client-go?
I've tried the following which deletes the job but leaves the pods behind:
fg := metav1.DeletePropagationBackground
deleteOptions := metav1.DeleteOptions{PropagationPolicy: &fg}
if err := clientset.BatchV1().Jobs("default").Delete("example-job", &deleteOptions); err != nil {
fmt.Printf(err)
}
I've tried using the DeletePropagationForeground option, but that resulted in nothing being deleted.
I'm following this documentation to upload files to GCS.
Setting Up Authentication for Server to Server Production Applications
It works in local but in production i get this error:
Post https://www.googleapis.com/upload/storage/v1/b/[bucket-name]/o?alt=json&prettyPrint=false&projection=full&uploadType=multipart: x509: failed to load system roots and no roots provided.
func UploadIMG(ctx *context.Context, file []byte, fileName string) error {
storageClient, err := storage.NewClient(*ctx)
if err != nil {
log.Fatal(err)
}
w := storageClient.Bucket(bucketName).Object(fileName).NewWriter(*ctx)
if _, err := w.Write(file); err != nil {return err}
if err := w.Close(); err != nil {return err}
oauthClient, err := google.DefaultClient(*ctx, cloudkms.CloudPlatformScope)
if err != nil {
log.Fatal(err)
}
kmsService, err := cloudkms.New(oauthClient)
if err != nil {
log.Fatal(err)
}
_ = kmsService
return nil
}
Did you actually continue with the tutorial you linked, making sure you have the correct credentials?
The error itself is likely certificate related. When it tries to do the request, it looks for root certificates on the underlying system but can't find them or open them. On for example Ubuntu, they should be under /usr/share/ca-certificates and/or /etc/ssl/certs . Make sure you have your certificates with correct privileges in order to be able to do the request you want.
as guys said in their answers, it's related to missing Certificate Authority in my dockerFile.
In my case, in alpine there is already a package utility called ca-certificates which comes with its preinstalled certs. Just needed to add the following command to my docker.
RUN apk --no-cache add ca-certificates
For any google api's you will need a root CA of trust.
Not sure of your production environment, but if you are using Docker add this line to your Dockerfile:
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
from, say a Linux build, you can see the order go will look to find the system root trust files:
https://golang.org/src/crypto/x509/root_linux.go
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
If you do not have any of these directories in your production (linux) build, then go will have no system root trust, and you will get the error you are seeing.