In this lecture, we will discuss about imperative and declarative approaches in communities towards
the end of this lecture.
We will talk about some tips that you can use in the exam.
So far, we have seen different ways of creating and managing objects in communities.
We created objects directly by running commands, as well as using object configuration files.
Now, in the infrastructure as code world, there are different approaches in managing the infrastructure
and they are classified into imperative and declarative approaches.
Let's understand this with an analogy, let's say you want to visit a friend's house located at St.
B and the past you would hire a taxi and give Step-By-Step instructions to the driver on how to reach
the destination, like take right to Street B, then take left to go to Street C, and then take another
left and then right to go to Street D and stop at the house specifying what to do and how to do.
More importantly is the imperative approach.
On the other hand, today when you book a cab, say through Uber, you just specify the final destination,
like drive to Tom's house.
And this is the declarative approach.
In this case, we are not giving Step-By-Step instructions.
Instead, we're just specifying the final destination.
We're declaring the final destination.
And the system figures out the right path to reach the destination, specifying what to do, not how
to do, is the declarative approach.
So what's that got to do with what we are learning in the infrastructure as code world?
An example of an imperative approach of provisioning infrastructure would be a set of instructions right
step by step, such as provisioning a VM named a Web server, installing the Ingenix software on it,
editing configuration file to use Port AT&T and setting the path to Web files, downloading source code
of repositories from GIT and finally starting the engine server.
So here we are saying what is required and also how to get things done.
In the declarative approach we declare our requirements.
For instance, all we say is that we need a VM by the name Web server with the Internet software on
it with a port said to eighty eight and the path to the web files defined and where the source code
of the application is is stored.
And everything that's needed to be done to get this infrastructure in place is done by the system or
the software.
You don't have to provide step by step instructions, orchestration, tools like Ansible Puppet or chef
or terraform fall into this category.
And the imperative approach, what happens if the first time only half of the steps were executed?
What happens if you provide the same set of instructions again to complete the remaining steps to handle
such situations?
There will be many additional steps involved, such as checks to see if something already exists and
taking an action based on the results of that check.
For instance, while provisioning EVM, what would happen if a m by the name Web server already exists?
The same goes with creating a database or importing data should it fail or should it continue since
the VM is already there?
What if we decide to upgrade the version of software to say in the next one or one eight in the future,
it should be as simple as updating the version of Engine X in the configuration file and the system
should take care of the rest.
Ideally, the system should be intelligent enough to know what has already been done and apply the necessary
changes.
Only that's the declarative way of doing things.
In the corporate world, the imperative way of managing infrastructure is using commands like the cattle
run command to create a pod that you've got to create a deployment command to create a deployment,
the expose command to create a service to expose the deployment.
And the added command may be used to edit an existing object for scaling a deployment or replicates
it.
Use the scale command and updating the image on a deployment.
We use the whole set image command.
We have also used object configuration files to manage objects such as creating an object, using the
character to create that command with the option to specify the object configuration file and editing
an object using the cube to replace command and deleting an object using the cubicle delete command.
All of these are imperative approaches to managing objects and capabilities.
We are saying exactly how to bring the infrastructure to our needs by creating, updating or deleting
objects.
The declarative approach would be to create a set of files that defines the expected state of the applications
and services on a continuous cluster.
And with a single API, command coordinators should be able to read the configuration files and decide
by itself what needs to be done to bring the infrastructure to the expected state.
So in the declarative approach, you will run the code to apply command for creating, updating or deleting
an object.
The API command will look at the existing configuration and figure out what changes need to be made
to the system.
So let's look at these in a bit more detail now within the imperative approach.
There are two ways.
The first is using imperative commands such as the run, create or expose commands to create new objects
and the added scale and said commands to update existing objects.
Now, these commands help in quickly creating or modifying objects as we don't have to deal with YAML
files and these are helpful during the certification exams.
However, they are limited in functionality and will require forming long and complex commands for advanced
use cases such as creating a multi container pod or deployment.
Secondly, these commands are run once and forgotten.
They are only available in the history of the user who ran these commands.
So it's hard for another person to figure out how these objects were created.
So it is hard to keep track of.
And so it's difficult to work with these commands in large or complex environments.
And that's where managing objects with the object configuration files can help.
Creating object definition files or configuration files or manifesto files, as it's also called, can
help us write down exactly what we need the object to look like in a Yamal format and use the kicker
to create command to create the object.
We now have the YAML file with us always, and it can be saved in a code repository like it.
We can put together a change review and approval process around these files so that a change made is
reviewed and approved before it is applied to a production environment in the future.
If it changes to be made, for instance, editing the image name to another version, there are different
ways to go about it.
One way is to use the cubicle to edit command and specify the object name.
So when this command is run, it opens a Yamal definition file similar to the one you used to create
the object.
But with some additional fields, such as the status fields that you see here, which are used to store
the status of the pod.
This is not the file you used to create the object.
This is a similar pod definition file within the coronets memory.
You can make changes to this file and save and quit and those changes will be applied to the life object.
However, note that there is a difference between the live object and the definition file that you have
locally.
The change you made using the to edit command is not really recorded anywhere.
After the change is applied, you're only left with your local definition file, which in fact has the
old image name in it.
In the future, say, you or a team may decide to make a change to this object, unaware that a change
was made using the edit command when the new change is applied, the previous change to the image is
lost.
So you can use the edit command.
If you are making a change and you're sure that you're not going to rely on the object configuration
file in the future.
But a better approach to that is to first edit the local version of the object configuration file with
the required changes, and that is by updating the image name here and then running the cubicle to replace
command to update the object.
This way going forward, the changes made are recorded and can be tracked as part of the change review
process.
So at times you may want to completely delete and recreate objects in such cases, you may run the same
command but with the force option like this.
Now, this is still the imperative approach because you're still instructed is how to create or update
these objects first, you're only to create command, to create the object, and then you run the replace
command to replace the object or delete command or delete the object.
And what if you run the create command?
If the object already exists now, then it would fail with an error that says the part already exists.
When you update an object, you should always make sure that the object exists first before running
the replace command.
If an object does not exist, the replace command failed with an error message.
So the imperative approach is very taxing for you as an administrator, as you must always be aware
of the current configurations and perform checks to make sure that things are in place before making
a change.
The declarative approach is where you used the same object configuration files that that we've been
working on, but instead of the creator, every place commands, we used to apply command to manage
objects.
The cubicle apply command is intelligent enough to create an object if it doesn't already exist.
If there are multiple object configuration files, as you would usually, then you may specify a directory
as the path instead of a single file.
That way all the objects are created at once.
Now, when changes are to be made, we simply update the object configuration file and run the apply
command again.
And this time it knows that the object exists and so it only updates the object with the new changes.
So it never really throws an error that says the object already exists or the updates cannot be applied
and will always figure out and the right approach to updating the object.
So going forward, any changes made on the application, whether they're updating images or fields of
existing configuration files or adding new configuration files altogether for new objects, all they
do is simply update our local directory with the changes and then apply command, take care of the rest.
So we will discuss more about how the command works exactly in the backend in the next lecture.
For now, let me give you some tips as part of the exam.
So from an exam perspective, you could use the imperative approach to save time as much as possible.
For example, if the question is to just create a path or a deployment with a given image, then one
of these imperative commands can help you achieve that quickly.
So it's important to practice the imperative commands.
If you need to edit a property of an existing object, then using the edit command, um, maybe the
quickest way.
Right.
If you have a complex requirement for, say, for example, that requires multiple container's environment
variables, commands in containers, etc., then using an object configuration file to create object
would be preferred.
This way.
If you see that you made a mistake, you can easily update the file and apply it again.
And using the high command in that case would be a better option.
So for more details on the different approaches to managing a cluster, get yourself familiarized with
the community's documentation pages and in the upcoming lab exercises, try to use imperative approach
in solving questions.
Well, I will see you in the next lecture.