DEV Community

Cover image for Kubernetes homelab - Learning by doing, Part 6: Automation
Sacha Thommet
Sacha Thommet

Posted on

Kubernetes homelab - Learning by doing, Part 6: Automation

In this section, I'll dive into how I automated my Kubernetes cluster, using two tools: Ansible for machine configuration and ArgoCD for application deployments.

Why automate ?

1. Reducing Human Error

In IT operations, even small mistakes can lead to service outages or security vulnerabilities. Human errors like typos may happen, that's why automation is important — it ensures that each task is executed consistently.

2. Minimizing Repetitive Tasks

Automation reduces repetitive, time-consuming tasks like updates and patching, this let teams to work on more strategic tasks.

3. Scalability and Reproducibility

Automating infrastructure setup enables large-scale deployments with consistent configurations, regardless of the size of the environment.

4. Version Control

Tools like Ansible use declarative files that can be tracked in Git, allowing quick rollbacks and maintaining an accessible record of changes.

5. Documentation

Declaratives files are easy to understand — they describe WHAT the infrastructure should look like rather than HOW, like in the imperative way. Being versioned in Git, these files are accessible to the team, allowing them to quickly review the current state of the infrastructure.

Infrastructure as Code (IaS) with Ansible

Ansible is an open-source tool that excels in infrastructure configuration. With an agentless architecture (no services need to be installed on the managed machines), it communicates with machines over SSH.

Image description

The inventory file is where you list the machines that Ansible will manage. It contains the IP addresses or hostnames of each machine. Here's mine:

inventory.yaml

k8s:
  hosts:
    server1:
    server2:
Enter fullscreen mode Exit fullscreen mode

Then, the tasks performed by Ansible are defined in files called playbooks.

playbook.yaml

- name: Ensure useful packages are present
  hosts: k8s
  gather_facts: false # don't gather information on nodes as I don't use them
  become: true
  tasks:
    - name: Ensure all apt packages are updated to their latest version
      ansible.builtin.apt:
        update_cache: true      # run the equivalent of apt-get update
        cache_valid_time: 86400 # in seconds: one day
        upgrade: yes            # run apt-get upgrade

    - name: TLP - Optimize Linux Laptop Battery Life - https://linrunner.de/tlp/
      ansible.builtin.apt:
        name: tlp
        state: present

- name: Enforce security
  hosts: k8s
  gather_facts: false
  become: true
  tasks:
    - name: Ensure firewall is configured and running
      block:
        - name: Ensure firewall package is installed
          ansible.builtin.apt:
            name: ufw
            state: present

        - name: Allow incoming HTTPS traffic
          community.general.ufw:
            rule: allow
            comment: Allow incoming HTTPS traffic
            protocol: tcp
            port: 443

        - name: Allow everything from LAN
          community.general.ufw:
            rule: allow
            comment: Allow everything from LAN
            protocol: any
            from_ip: 192.168.1.0/24

        ...

        - name: Ensure firewall is up and running
          community.general.ufw:
            state: enabled

- name: Ensure microk8s is up and running
  hosts: k8s
  roles:
    - role: 'istvano.microk8s'
      vars:
        microk8s_version: 1.29/stable
        ...
Enter fullscreen mode Exit fullscreen mode

With that, I only need to run the following command to configure my nodes:

# run only once to install the required role used by the playbook
ansible-galaxy role install istvano.microk8s

ansible-playbook playbook.yaml -i inventory.yaml
Enter fullscreen mode Exit fullscreen mode

Ansible is idempotent

Idempotence is originally a concept from Mathematics. As defined by Wikipedia,

Idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application.

In Ansible, idempotence is offered as a built-in feature of many of the Ansible modules (be careful, some modules like shell or command don't support this feature). This means that re-running a playbook will produce the same final state without any unwanted side effects.

See this blog post for more explanation.

GitOps with ArgoCD

While Ansible manages the infrastructure, ArgoCD focuses on deploying and updating applications in a Kubernetes environment.
ArgoCD automatically synchronizes applications with their configurations defined in a Git repository. When the repository is updated, ArgoCD adjusts the state of the applications in the Kubernetes cluster to match the repository's configuration. This provides a declarative and versioned approach for deploying and managing Kubernetes applications.

Image description

Note that this diagram explains the pull-based approach, where ArgoCD regularly pulls the latest changes from the Git repository. You can also use the push-based approach with ArgoCD, where Git notifies ArgoCD via a webhook that there is a change.

Additionally, ArgoCD comes with a web interface that provides a clear view of deployment statuses. The screenshot below illustrates this interface.

Image description

With these tools, almost everything stays in my Git repository (which I plan to make public soon, once I’ve cleared the repo of hard-coded secrets!). Git is the single source of truth.

Top comments (0)