How to run kubectl commands in a cron - kubernetes

I created a schedule configuration inside my Gcloud project to create snapshots of a bunch of virtual disks.
Now I want to add my schedule configuration to my disks, but I dont know how to do it in a automated way, because I have more than 1200 disks.
I tryed to use a POD with a cron inside, but I cannot execute the kubectl command to list all my persistent volumes:
kubectl describe pv | grep "Name" | awk 'NR % 2 == 1' | awk '{print $2}'
I want to use this list with the next command in a Loop to add automatically my programmed schedule to my disks:
gcloud compute disks add-resource-policies [DISK_NAME] --resource-policies [SCHEDULE_NAME] --zone [ZONE]
Thanks in advance for your help.
Edit 1: After some comments I changed my code to add a Kubernetes CronJob, but the result is the same, the code doesn't work (the pod is created, but it gives me an error: ImagePullBackOff):
resource "kubernetes_cron_job" "schedulerdemo" {
metadata {
name = "schedulerdemo"
}
spec {
concurrency_policy = "Replace"
failed_jobs_history_limit = 5
schedule = "*/5 * * * *"
starting_deadline_seconds = 10
successful_jobs_history_limit = 10
job_template {
metadata {}
spec {
backoff_limit = 2
ttl_seconds_after_finished = 10
template {
metadata {}
spec {
container {
name = "scheduler"
image = "imgscheduler"
command = ["/bin/sh", "-c", "date; kubectl describe pv | grep 'Name' | awk 'NR % 2 == 1' | awk '{print $2}'"]
}
}
}
}
}
}
}

Answering the comment:
Ok, shame on me, wrong image name. Now I have an error in the Container Log: /bin/sh: kubectl: not found
It means that the image that you are using doesn't have kubectl installed (or it's not in the PATH). You can use image: google/cloud-sdk:latest. This image already have cloud-sdk installed which includes:
gcloud
kubectl
To run a CronJob that will get the information about PV's and change the configuration of GCP storage you will need following accesses:
Kubernetes/GKE API(kubectl) - ServiceAccount with a Role and RoleBinding.
GCP API (gcloud) - Google Service account with IAM permissions for storage operations.
I found this links helpful when assigning permissions to list PV's:
Kubernetes.io: RBAC
Success.mirantis.com: Article: User unable to list persistent volumes
The recommended way to assign specific permissions for GCP access:
Workload Identity is the recommended way to access Google Cloud services from applications running within GKE due to its improved security properties and manageability.
-- Cloud.google.com: Kubernetes Engine: Workload Identity: How to
I encourage you to read documentation I linked above and check other alternatives.
As for the script used inside of a CronJob. You should look for pdName instead of Name as the pdName is representation of the gce-pd disk in GCP (assuming that we are talking about in-tree plugin).
You will have multiple options to retrieve the disk name from the API to use it in the gcloud command.
One of the options:
kubectl get pv -o yaml | grep "pdName" | cut -d " " -f 8 | xargs -n 1 gcloud compute disks add-resource-policies --zone=ZONE --resource-policies=POLICY
Disclaimer!
Please treat above command only as an example.
Above command will get the PDName attribute from the PV's and iterate with each of them in the command after xargs.
Some of the things to take into consideration when creating a script/program:
Running this command more than once on a single disk will issue an error that you cannot assign multiple policies. You could have a list of already configured disks that do not require assigning a policy.
Consider using .spec.concurrencyPolicy: Forbid instead of Replace. Replaced CronJob will start from the beginning iterating over all of those disks. Command could not complete in the desired time and CronJob will be replaced.
You will need to check for the correct kubectl version as the official support allows +1/-1 version difference between client and a server (cloud-sdk:latest uses v1.19.3).
I highly encourage you to look on other methods to backup your PVC's (like for example VolumeSnapshots).
Take a look on below links for more reference/ideas:
Stackoverflow.com: Answer: Periodic database backup in kubernetes
Stash.run: Guides: Latest: Volumesnapshot: PVC
Velero.io
It's worth to mention that:
CSI drivers are the future of storage extension in Kubernetes. Kubernetes has announced that the in-tree volume plugins are expected to be removed from Kubernetes in version 1.21. For details, see Kubernetes In-Tree to CSI Volume Migration Moves to Beta. After this change happens, existing volumes using in-tree volume plugins will communicate through CSI drivers instead.
-- Cloud.google.com: Kubernetes Engine: Persistent Volumes: GCE PD CSI Driver: Benefits of using
Switching to CSI plugin for your StorageClass will allow you to use Volume Snapshots inside of GKE:
Volume snapshots let you create a copy of your volume at a specific point in time. You can use this copy to bring a volume back to a prior state or to provision a new volume.
-- Cloud.google.com: Kubernetes Engine: Persistent Volumes: Volume snaphosts: How to
Additional resources:
Cloud.google.com: Kubernetes Engine: Persistent Volumes
Cloud.google.com: Kubernetes Engine: Cronjobs: How to
Terraform.io: Kubernetes: CronJob
Cloud.google.com: Compute: Disks: Create snapshot

Related

Error while installing mongodb in AWS EKS cluster - "running PreBind plugin VolumeBinding: binding volumes: timed out > waiting for the condition"

I tried to install mongodb in EKS cluster by following the given links.
(using mongodb-kubernetes-operator)
https://www.youtube.com/watch?v=VqeTT0NvRR4&t=1s
https://github.com/mongodb/mongodb-kubernetes-operator
kubectl apply -f config/crd/bases/mongodbcommunity.mongodb.com_mongodbcommunity.yaml
kubectl get crd/mongodbcommunity.mongodbcommunity.mongodb.com
kubectl create ns mongo
kubectl apply -k config/rbac/ --namespace mongo
kubectl get role mongodb-kubernetes-operator --namespace mongo
kubectl get rolebinding mongodb-kubernetes-operator --namespace mongo
kubectl get serviceaccount mongodb-kubernetes-operator --namespace mongo
kubectl create -f config/manager/manager.yaml --namespace mongo
kubectl get pods --namespace mongo
kubectl apply -f config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml --namespace mongo
kubectl get pods -n mongo
When checked
kubectl get pods -n mongo
example-mongodb-0 pod is in pending state for very long time.
Upon describing the pod got the following error,
"running PreBind plugin "VolumeBinding": binding volumes: timed out
waiting for the condition".
When contacted with AWS support team, got the following response.
From your correspondence, I understand that you are facing issues
while creating the mongodb pods in your EKS cluster, and after
creating the pod, your pod is going to pending status.
Please let me know if I misunderstood your query. Thanks for sharing
the GitHub repository URL using the same. I put some effort into
replicating the same issue on my side, and thankfully I was able to
replicate the issue.
Further investigation into my pending pod problem I ran the following
describe command on my cluster,
"kubectl describe pod <pending_pod_name>"
After several minutes, I found the following line in the "event"
part of my output.
"running PreBind plugin "VolumeBinding": binding volumes: timed out
waiting for the condition".
On further investigation, I found that the mongodb pod module that you
are trying to deploy on your cluster is trying to create an EBS volume
as a persistent volume, which is why I got the aforementioned error.
We need the EBS CSI driver add-on installed in your cluster to create
an EBS volume using EKS, and the above error usually occurs if the EBS
CSI driver add-on is not present. Since this add-on is not installed
by default while creating the cluster you need to install it via EKS
console add-on tab.
Or another possibility is that, even though the add-on is present, it
won't have the required permission to create the EBS volume. So,
before we even install the EBS CSI driver add-on to the cluster, we
need to make sure that we have created the IAM role for attaching to
the add-on. The same is referred to over here[1].
In your case, you can check whether the EBS CSI driver is present by
running the following command:
"kubectl get pods -n kube-system"
And look for pods with names like "ebs-csi-controller-xxxxxxx." If
you find one, it means you've already installed the EBS CSI driver,
and the problem could be with permissions.
For that, you need to run the following command.
"kubectl describe pod ebs-csi-controller-xxxxxxx -c csi-provisioner
-n kube-system"
This will give an output of the configuration of the driver pod. In
that output, you need to check for an environment called
"AWS_ROLE_ARN:" If that wasn't present in your output, this implies
that you haven't provided the IAM OIDC provider role for the add-on.
So you need to create that role in the IAM console, then remove the
existing EBS CSI driver add-on from the EKS cluster console, and then
again add the EBS CSI driver add-on with that role as "Service
account role". More details for adding the EBS CSI driver add-on to
the cluster are referred to here[3].
If you already have the value for "AWS_ROLE_ARN" then you need to
check for the configuration of the role by using this
documentation[2].
So, keeping the above things in mind, I have created the IAM OIDC
provider role for the add-on. For that, you need to follow all the
steps regarding how to create an IAM role for the add-on as referred
to here[2].
After creating the IAM OIDC provider role, I have installed the add-on
via console by following the steps in this documentation[3] and for
the service account role, I have selected the OIDC provider role that
was created in the above step.
After installing the add-on, I tried to delete the mogodb database pod
by running the following command.
"kubectl delete -f
config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml"
Then run the following apply command to redeploy the pods.
"kubectl apply -f
config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml"
After I checked the pods, I could see that the mongodb database pod
had come to running status.
The above is the most common issue that might happen, if none of the
above is your problem then please share a convenient time along with
the timezone you're working in as well as contact number with country
code so that we can connect over a call and have a screen sharing
troubleshooting session.
reference links:
[1] Amazon EBS CSI driver add-on : https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html
[2] How to create IAM OIDC provider for EBS CSI driver add-on : https://docs.aws.amazon.com/eks/latest/userguide/csi-iam-role.html
[3] Managing the EBS CSI driver add-on : https://docs.aws.amazon.com/eks/latest/userguide/managing-ebs-csi.html
Working commands/steps
(Steps mentioned by support team)
Creation of EKS cluster
Go to the newly created EKS cluster in AWS console. In the Overview tab, copy the value of OpenID Connect provider URL and save the value in some place for future reference.
Go to IAM -> Identity providers -> Add Provider. Select OpenID Connect as the provider type.
Paste the copied url from step 2, in the Provider URL textbox and click ‘Get thumbprint’. Set Audience - sts.amazonaws.com in the corresponding text box.
Click the ‘Add Provider’ button.
Create the required iam role. IAM -> Roles -> Create Role. In the ‘Select trusted entity’ section, choose ‘Web Identity’ . In Identity provider drop down, select the OIDC option that is created in step 5. Choose Audience - sts.amazonaws.com in the drop down. Click ‘Next’
Search for AmazonEBSCSIDriverPolicy policy in the next window and click ‘Next’ and give name,description,tags for the role and click create role.
In the Roles section, search for the newly created role in step 7 and go inside that role. Trust relationships -> Edit trust policy.
"oidc.eks.eu-west-1.amazonaws.com/id/385AA11111111116116:sub":
"system:serviceaccount:kube-system:ebs-csi-controller-sa"
Update the above text with current oidc id and add it as new key-value in the Statement[0] -> Condition -> StringEquals. Refer the full json structure of this trusted relationship json data in the last.
After updating the text, click ‘Update Policy’
Go to EKS -> Clusters -> Newly created cluster in step 1. Click Add-ons tab, Add new.
In the pop up choose Name as Amazon EBS CSI Driver. Version as latest. Choose Role as the role created in step 7. If the above role is not listed in drop down, reload the section using the reload button and click Add.
After some time, the new Add on will become active. Then run this kubectl get pods -n kube-system command and we should see csi pods as shown.
ebs-csi-controller-68d49f84c8-sl7w6 6/6 Running 0 109s
ebs-csi-controller-68d49f84c8-w2k6r 6/6 Running 0 2m19s
ebs-csi-node-ldmsm 3/3 Running 0 2m20s
Then run the commands given in the question.
Following dictionary is the Trusted relationships json for role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::112345678900:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/Axxxxxxxxxxxxx"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.eu-west-1.amazonaws.com/id/Axxxxxxxxxxxxx:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa",
"oidc.eks.eu-west-1.amazonaws.com/id/Axxxxxxxxxxxxx:aud": "sts.amazonaws.com"
}
}
}
]
}

Statefulset - How automatically setting labels to pods after creation and restarting?

I have statefulset mongo-replica, It creates Two replica, I want to set a new label ( COMPANY ) foreach pod (replica) it's value should be the pod's name .e.g.:
in POD mongo-replica-0 -> COMPANY: mongo-replica-0
in POD mongo-replica-1 -> COMPANY: mongo-replica-1
So, Is there away to do it, automatically in Creating/Restarting pod ?
I know we can do it via kubectl label, but it manual
At the time of writing this, there is not such a dedicated tool for this purpose. There are two things that comes to my mind here:
Use an initContainer for the Statefulset Pods that uses service
account created upon it with appropriate permissions. initContainer
will then run a command like kubectl label pod $hostname company=$HOSTNAME"
This article shows how run kubectl from within a
pod with image build, service account and roles creation.
Creating some sort of bash script that will run in pod/job and automate this process for you:
a=$(kubectl get pods -o jsonpath='{.items[*].[metadata.name](http://metadata.name/)}' -l app=$stsname) for n in $a ; do kubectl label pod $n company="$n" --overwrite ; done
Create custom mutating webhook/controller that will modify those objects.
Here is good article that describes how to write basic kubernetes mutating admission webhook. Kubernetes official documentaion shares a very good section about dynamic admission control that is worth checking out.

Migrate PV and change CPU limits on Kubernetes

I have a small kubernetes cluster with AWX running.
I would like to make some changes, the PV is a filesystem on one of the nodes.
Is it possible to migrate it to a different PV, like NFS?
Also, I would like to change the CPU and memory limits. But I guess I will have to redeploy it.
Should I try to migrate the PV or delete everything and recreate it?
Thanks
Assuming that you have dynamic provisioning enabled I advice you to use pv-migrate.
This is a cli tool/kubectl plugin to easily migrate the contents of one Kubernetes PersistentVolume to another.
Common use cases:
You have a database with a bound 30 GB PersistentVolumeClaim. It occurred 30 GB was not enough and you filled all the disk space rather quickly. And sadly your StorageClass/provisioner doesn't support volume expansion. Now you need to create a new PVC of 100 GB and somehow copy all the data to the new volume, as-is, with its permissions and so on.
You need to move a PersistentVolumeClaim from one namespace to another.
To migrate contents of PersistentVolumeClaim pvc-a in namespace name-space-a to the PersistentVolumeClaim pvc-b in namespace name-space-b, use the following command:
$ kubectl pv-migrate \
--source-namespace name-space-a \
--source pvc-a \
--dest-namespace name-space-b \
--dest pvc-b
Take also a look at: change-pv-reclaim-policy, resizing-persistent-volumes-using-kubernetes.

What is the architecture for recover logs from a storage account to a Elasticsearch deployed on KUBERNETES?

I am working on the evolution of a siem soc, and my actual issue is to recover my logs from my storage account on Azure to a Elasticsearch-data deployed on a pod on KUBERNETES. So I would like to know the the right approach for that.
With filebeat there is no input for azureblod, only output
Logstash seems don't work without agent.
Thanks !
There is an approach you could consider for accomplishing your task. Kubernetes in Azure allows you to deploy Azure File Shares with your containers. If you move your logs to a file share, you should be able to accomplish your project.
I'd recommend checking Diego's post here, it shows how to access logs from a storage account, specifically FileShare.
here's a blurb from the tutorial:
1- *Create an Azure Storage account with your own parameters (deployment model: resource manager; type: general purpose). You will need the Azure Storage account name in the next step.
2- Modify the storageAccount parameter in this .yaml file with your Azure Storage account name and deploy it to your Kubernetes cluster: kubectl apply -f sidecar-storageclass.yaml. It will create a Kubernetes volume using your Azure File Storage account.
3- Deploy this .yaml file to your Kubernetes cluster: kubectl apply -f sidecar-pvc.yaml. It will create a volume claim for your volume in order to use it in your pod.
4- Modify your application deployment .yaml file by adding (modify the logFileDirectory parameter) this content and deploy it to your Kubernetes cluster. It will add the volume to your pod and store on it the logFilesDirectory.
5- Modify the logReaderName (you will filter the logs using this parameter), logFileDirectory (x2) and the logFileName with your data in this .yaml file and deploy it to your Kubernetes cluster: kubectl apply -f sidecar-logreaderpod.yaml. It will create the Log Reader pod and write the logFile content to the STDOUT.
The Log Reader pod uses tail command to write in the STDOUT. You can modify the tail command, for example, to write different files (extension .log) in the same STDOUT: tail -n+1 -f //*.log
Once you deploy the Log Reader, you can start to check the logs filtered by the pod name (you selected it when you deployed the last .yaml file):
kubectl get pods
kubectl logs <podname>

Kubernetes nfs volumes

I'm referring to this [1] document about creating nfs mounts on kubernetes. But I have couple of issues to be clarified.
What is meant by privileged containers?
How can I set allow-privileged true of a kubernetes setup installed on bare metal ubuntu machine? I setup it using kebe-up.sh script.
[1] http://kubernetes.io/v1.1/examples/nfs/index.html
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/user-guide/pods.md#privileged-mode-for-pod-containers
That refers to the corresponding field in the yaml: https://github.com/kubernetes/kubernetes/blob/master/pkg/api/types.go#L2089
And it should be on per the document in 1.1 (https://github.com/kubernetes/kubernetes/blob/b9cfab87e33ea649bdd13a1bd243c502d76e5d22/cluster/saltbase/pillar/privilege.sls#L2, you can confirm by creating the pod and running kubectl describe like the docs says).