
Disaster & Zwischenfälle – Das Kubernetes Cluster DIY Pt. 3
Ein Kubernetes-Cluster ist zwar sehr resilient, aber es gibt dennoch einige Vorfälle, die potentiell schwerwiegende Auswirkungen haben können. In diesem Artikel werden wir drei potentielle
If you programmed anything with Elixir (if not, check our introductory Elixir Interview) one of the first things you encounter are modules. But what exactly is a Module and how do they work internally?
Modules are one of the key building blocks of the elixir language and also of the BEAM, which is the runtime for elixir code. Simply put, a module is a collection of functions and attributes. All code that is executed must be loaded into the runtime at first. The code loading is done on a module level, meaning the runtime can only load modules. Therefore, all elixir code has to reside in a module.
In all examples the interactive elixir shell is used. If you want to follow along start one and type the following.
At first we created a module named MyModule
and a function named myFunction
that belongs to that module by using demodule
and def
. The defmodule
command returns a tuple with four elements:
the atom :module
name of the module that was defined
a binary representation of the module called object code
the result of the last expression in the do block
Then we called the function myFunction
of the MyModule
module with the command MyModule.myFunction
and got 4711
as return value of the call.
The defmodule
command did two things.
It compiled our module definition into object code. That object code is a binary representation of the module that can be loaded by the runtime. Beside other things it contains:
The name of the module
The actual instructions that get executed by the runtime when a function is called. These instructions are called bytecode
A lookup table with all function names and a reference on where in the object code to find the function’s bytecode
It loaded the object code into the runtime.
When the MyModule.myFunction()
was called the runtime, with the help of the lookup table, found and executed the bytecode for that function. In case of myFunction
that bytecode returns the literal 4711
to the caller.
Each module in Elixir is compiled seperatly resulting in one binary e.g. object code that includes the actual instructions for the runtime as well as as metadata in the form of module variables (we cover module variables later).
The next example will show how a module can be loaded from object code. Because defmodule
will not only create the object code but will also load it into the runtime and i want you to see how the loading happens seperatly, the object code has to be written to a file. To illustrate that MyModule
is loaded there is also an additional call to my_function
.
The actual format of the object code does not matter at the moment what’s important is that each module has its own binary, which is object code.
In a newly opened iex MyModule
, as expected, is not available. After the object_code was read from the file and loaded with the :code.load_binary
function it becomes available.
In the code loading example the file in which the object code was stored was named my_module_object_code.bin
but if you rename that file to my_module.beam
it will get loaded by the iex on startup automatically. The .beam
filename makes the difference here. Every file that resides inside the directory you are in when executing the iex command and has a name that ends with .beam
is loaded on iex startup.
As you probably know elixir source code is stored in files that have names ending with .ex
or sometimes .exs
.
Let’s do the same with the MyModule
module by creating a file my_module.ex
and putting the module definition in it.
1 2 3 4 5 |
|
Next we start a iex inside the same folder where the my_module.ex
file is located. When we try to execute our function like before we just get an error that informs us that the module MyModule
is not loaded.
The command c("my_module.ex", ".")
compiles and the file and loads the module/s defined in it. Furthermore it writes a beam file to the folder provided as second parameter which is the current folder in the example.
A file with the name Elixir.MyModule.beam
was created and sure enough when the iex is restarted the module is available without the need to compile the elixir code again.
In practice all this is handled behind the scenes by mix the elixir build tool.
After considering the compile and runtime aspects of modules let’s explore (source-) code side of things next.
There are many ways you can use modules to structure your code and you can, and probably already have, read about this topic in many books, articles and so on. What i want to do is to show the basic building blocks which can be used to build more complex patterns for structuring code.
Contextualize functions with namespaces
Functions that, on an conceptual level, belong together can be put inside a module that then gives these functions context.
1 2 3 4 5 6 7 |
|
The two speek
functions are called with Greet.speek()
and Farewill.speek()
which gives them either the greet or the farewell context.
Another nice thing you can do, but that we will not discuss deeply here, is the creation of one data structure inside each module. These data structures called structs are often used to define the structure of the data on which the functions of the module operate.
Control the visibility of functions
This one is pretty simple. You can define functions to be callable from everywhere or only from functions that are part of the same module. Public functions are defined with def
and private functions are defined with defp
.
1 2 3 4 5 6 7 |
|
Inside the iex the callGreet.speek("Hans")
will return the expected result, but the call Greet.construct_message("Hans")
will result in an exception ** (UndefinedFunctionError) function Greet.construct_message/1 is undefined or private Greet.construct_message("Hans")
Annotate modules
Module attributes are the last thing you can put inside a module beside functions and structs. A module attribute is a key-value pair that attached to a module and can be set, accessed and to a degree modified, at compile time . This can be useful to define static values or pass additional data to the compiler. In this example the module attribute message
will be inlined and is available at runtime no more. The moduledoc
will be used by the compiler to add documentation to the object code. While the documentation is available at runtime the actual attribute is not.
1 2 3 4 5 6 7 8 9 10 11 |
|
To be precise there are module attributes that are also available at runtime and one can create module attributes with that property as well. This is however more cumbersome to write and only used for runtime related stuff. If you are not writing some kind of runtime or compiler you should not care about them and remember that module attributes are a compile time thing.
One thing that can be slightly confusing is that elixir provides a module with the name Module
. It provides functions and macros for working with modules. For example one can create a module with Module.create/3
Modules are one of the basic building blocks of elixir. They are not only a language feature but also a basic building block of the BEAM runtime. They are essential for compilation, code loading and execution.
With this knowledge we can dive deeper into what elixir actually is by exploring how it is implemented. But that is for another time.
Raphael arbeitet als Softwareentwickler und Berater bei Inspired. Seine Spezialität ist die IT-Sicherheit in der Software Entwicklung. Bei Konzeption und Implementierung von Software versucht er immer auch den Blick von potenziellen Angreifern einzunehmen.
Allgemein beschäftigt er sich mit funktionaler Programmierung seit über fünf Jahren. Elixir ist seit zwei Jahren auf seinem Radar und seitdem in nahezu täglichem Einsatz.
Ein Kubernetes-Cluster ist zwar sehr resilient, aber es gibt dennoch einige Vorfälle, die potentiell schwerwiegende Auswirkungen haben können. In diesem Artikel werden wir drei potentielle
Elixir’s interactive shell, known as IEx, is a powerful tool that allows Elixir developers to quickly test and evaluate code snippets, define and test functions,
Wenn es um die Verwaltung eines Kubernetes-Clusters geht, ist das passende Tooling besonders wichtig. Es hat Auswirkungen auf die Komplexität der Verwaltung generell, die Automatisierbarkeit,
Bevor wir uns in die Unendlichkeit von Kubernetes vertiefen, hier ein kurzer, aber mMn wichtiger Überblick: Hetzner Role IaaS Beschreibung/Aufgabe Servers/Virtualization Storage Cluster Volumes Networking
Cookie | Dauer | Beschreibung |
---|---|---|
cookielawinfo-checbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checbox-functional | 11 months | The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional". |
cookielawinfo-checbox-others | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other. |
cookielawinfo-checkbox-advertisement | 1 year | Set by the GDPR Cookie Consent plugin, this cookie is used to record the user consent for the cookies in the "Advertisement" category . |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
cookielawinfo-checkbox-performance | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance". |
elementor | never | This cookie is used by the website's WordPress theme. It allows the website owner to implement or change the website's content in real-time. |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |
Cookie | Dauer | Beschreibung |
---|---|---|
__cf_bm | 30 minutes | This cookie, set by Cloudflare, is used to support Cloudflare Bot Management. |
Cookie | Dauer | Beschreibung |
---|---|---|
CONSENT | 2 years | YouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data. |
Cookie | Dauer | Beschreibung |
---|---|---|
VISITOR_INFO1_LIVE | 5 months 27 days | A cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface. |
YSC | session | YSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages. |
yt-remote-connected-devices | never | YouTube sets this cookie to store the video preferences of the user using embedded YouTube video. |
yt-remote-device-id | never | YouTube sets this cookie to store the video preferences of the user using embedded YouTube video. |