Kubernetes - What exactly is imperative Vs Declarative - kubernetes

I am seeing multiple and different explanations for imperative Vs Declarative for Kubernetes - something like Imperative means when we use yaml files to create the resources to describe the state and declarative vice versa.
what is the real and clear difference between these two. I would really appreciate if you can put the group of commands fall under the same - like Create under imperative way etc ..

"Imperative" is a command - like "create 42 widgets".
"Declarative" is a statement of the desired end result - like "I want 42 widgets to exist".
Typically, your yaml file will be declarative in nature: it will say that you want 42 widgets to exist. You'll give that to Kubernetes, and it will execute the steps necessary to end up with having 42 widgets.
"Create" is itself an imperative command, but what you're creating is a Kubernetes cluster. What the cluster should look like is determined by the declarations in the yaml file.

Imperative
Official docs on Managing Kubernetes Objects Using Imperative Commands.
Kubernetes objects can quickly be created, updated, and deleted directly using imperative commands built into the kubectl command-line tool.
kubectl run nginx --generator=run-pod/v1 --image=nginx
kubectl create service nodeport <myservicename>
kubectl delete pod
Declarartive
Kubernetes objects can be created, updated, and deleted by storing multiple object configuration files in a directory and using kubectl apply to recursively create and update those objects as needed. This method retains writes made to live objects without merging the changes back into the object configuration files. kubectl diff also gives you a preview of what changes apply will make.
Official docs on Declarative Management of Kubernetes Objects Using Configuration Files.
Official docs on Declarative Management of Kubernetes Objects Using Kustomize
Define what you want in an yaml file and use kubectl apply
kubectl apply -f app.yaml
kubectl apply -f <directory>/
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Imperative command means::: We are not creating any yaml file and directly changing resources like pod service network anything via
Command line so that is imperative command.
Imperative object configuration::: means we are creating any resources as per our requirement in yaml file where we will remove
default value's which we don’t need everything except required things so in that case this is imperative object configuration AND that is CREATE command..
Declarative object configuration:: We don’t care about anything just we need final output so in simple words we copied
yaml from internet and created a pod where motive is to only create pod/resources So in that case we use APPLY command.

Related

Kubernetes apply to get to desired state

I feel like I have a terrible knowledge gap when it comes to managing the resource states within Kubernetes.
Suppose I have 2 deployments in my cluster, foo1 and foo2. They are both defined in separate yaml files, foo1.yaml and foo2.yaml that are both inside a my-dir directory and have been applied with kubectl apply -f my-dir/
Now I want to make a third deployment, but also delete my second deployment. I know that I can do this in 2 steps:
Make another foo3.yaml file inside the directory and then do kubectl apply -f my-dir/foo3.yaml
Run kubectl delete -f my-dir/foo2.yaml to get rid of the second deployment.
My question is, can I do this in one shot by keeping the "desired state" in my directory. i.e. Is there any way that I can delete foo2.yaml, create a new foo3.yaml and then just do kubectl apply -f my-dir/ to let kubernetes handle the deletion of the removed resource file as well? What am I missing here?
The best and easiest way is to use some DevOps tools like jenkins, ansible or terraform for managing your deployments. If you don’t want to use external tools there is a python library for managing kubernetes. You can fetch the details of your kubernetes resources, deployments, pods etc., using this library you can also manage your kubernetes cluster. Similarly if you want to remove the deployment files you just need to add a few more lines for deleting the file.

provide custom command line options for kubectl for kubernetes operator

I have one kubernetes operator (ex: kubectl get oracle_ctrl). Now I want to provide custom arguments for the kubectl command.
ex: kubectl apply oracle_ctrl --auto-discover=true --name=vcn1
I can write one more controller to do the same job. But I don't want to write one more controller and make use of existing controller.
Is it possible to use operator-sdk to provide custom args to kubectl?
No, this isn't possible.
kubernetes/kubectl#914 has a little bit further discussion of this, but its essential description is "we should start the proposal and design process to eventually write something better than kubectl create to support it". Your CRD can define additional columns to be shown in kubectl get but this is really the only kubectl-related extension point. You could potentially create a kubectl plugin or another CLI tool that does what you need.
Rather than using the kubectl imperative tools, it's often a better practice to directly write YAML artifacts and commit them to source control. You can parameterize these using tools like Helm or Kustomize. If kubectl apply -f or helm install is your primary way of loading things into the cluster, then you don't need custom CLI options to make this work.

Manually creating and editing Kubernetes objects

Most Kubernetes objects can be created with kubectl create, but if you need e.g. a DaemonSet — you're out of luck.
On top of that, the objects being created through kubectl can only be customized minimally (e.g. kubectl create deployment allows you to only specify the image to run and nothing else).
So, considering that Kubernetes actually expects you to either edit a minimally configured object with kubectl edit to suit your needs or write a spec from scratch and then use kubectl apply to apply it, how does one figure out all possible keywords and their meanings to properly describe the object they need?
I expected to find something similar to Docker Compose file reference, but when looking at DaemonSet docs, I found only a single example spec that doesn't even explain most of it's keys.
The spec of the resources in .yaml file that you can run kubectl apply -f on is described in Kubernetes API reference.
Considering DeamonSet, its spec is described here. It's template is actually the same as in Pod resource.

Using full Declarative approach in Kubernetes

We can use a declarative approach for creating and updating kubernetes resources using kubectl apply -f , how can we do the same for recyclying the resources that are no longer needed.
I have used kubectl delete , but that looks like imperative , and sometimes we will need to delete things in proper order.
Is there a way to always use kubectl apply and it figures out itself which resources to keep and which to delete. Just like in Terraform.
Or we should conclude that currently the declarative approach works for resource creation and update only.
Use case:
For example , we have decided not to provide the K8S API to end users and instead provide them a repository where they keep and update thier yaml files that a bot can apply to the cluster on each update when the pull request is merged. So we need this declarative delete as well so that we don't have to clean up things after users. Terraform provider maybe the solution but in that case things will lock to terraform and users will need to learn one more tool instead of using the native k8s format.
Truns out that they have added a declarative approach for pruning the resources that are no longer present in the yaml manifests:
kubectl apply -f <directory/> --prune -l your=label
With too many cautions though.
As an alternative to kubectl delete, you can use kubectl apply to
identify objects to be deleted after their configuration files have
been removed from the directory. Apply with --prune queries the API
server for all objects matching a set of labels, and attempts to match
the returned live object configurations against the object
configuration files. If an object matches the query, and it does not
have a configuration file in the directory, and it has a
last-applied-configuration annotation, it is deleted.

kubernetes - kubectl run vs create and apply

I'm just getting started with kubernetes and setting up a cluster on AWS using kops. In many of the examples I read (and try), there will be commands like:
kubectl run my-app --image=mycompany/myapp:latest --replicas=1 --port=8080
kubectl expose deployment my=app --port=80 --type=LoadBalancer
This seems to do several things behind the scenes, and I can view the manifest files created using kubectl edit deployment, and so forth However, i see many examples where people are creating the manifest files by hand, and using commands like kubectl create -f or kubectl apply -f
Am I correct in assuming that both approaches accomplish the same goals, but that by creating the manifest files yourself, you have a finer grain of control?
Would I then have to be creating Service, ReplicationController, and Pod specs myself?
Lastly, if you create the manifest files yourself, how do people generally structure their projects as far as storing these files? Are they simply in a directory alongside the project they are deploying?
The fundamental question is how to apply all of the K8s objects into the k8s cluster. There are several ways to do this job.
Using Generators (Run, Expose)
Using Imperative way (Create)
Using Declarative way (Apply)
All of the above ways have a different purpose and simplicity. For instance, If you want to check quickly whether the container is working as you desired then you might use Generators .
If you want to version control the k8s object then it's better to use declarative way which helps us to determine the accuracy of data in k8s objects.
Deployment, ReplicaSet and Pods are different layers which solve different problems.All of these concepts provide flexibility to k8s.
Pods: It makes sure that related containers are together and provide efficiency.
ReplicaSet: It makes sure that k8s cluster has desirable replicas of the pods
Deployment: It makes sure that you can have different version of Pods and provide the capability to rollback to the previous version
Lastly, It depends on use case how you want to use these concepts or methodology. It's not about which is good or which is bad.
There is a little more nuance to the difference between apply and create than what is already mentioned here. Kubectl create can be used imperatively on the command line or declaratively against a manifest file.
Kubectl apply is used declaratively against a manifest file. You can't use kubectl apply imperatively.
One key difference is when you already have an object and you want to update something. Even if you used a manifest file with kubectl create, you will get an error when you use kubectl create again to update the same resource. But, if you use kubectl apply, you will not get an error. It will update the resource without any issues.
So, the convention is to use kubectl apply to create AND update resources, kubectl create is used to create resources, and kubectl run is used to create a pod with a specific image, namespace, etc. for experimentation and testing with the --dry-run=client option.