Ansible Playbook for K3s and Argo CD Installation

This Ansible playbook automates the installation and configuration of a Kubernetes cluster using K3s (a lightweight Kubernetes distribution) and sets up Argo CD for GitOps-based application deployment. The playbook is designed to perform the following key actions:

  • Install K3s: Deploys K3s on target hosts, with Traefik disabled to allow for a custom ingress controller (e.g., via Helm).
  • Configure kubectl access: Ensures a non-root user can execute kubectl commands without sudo.
  • Install Argo CD: Deploys Argo CD and configures a root application (App-of-Apps pattern) to manage other applications.

Main Playbook: tasks.yml

This is the main entry point of the Ansible playbook, orchestrating the execution of other task files.

---
- hosts: all
  vars:
    github_user: "example-user"
    github_token: "YOUR_GITHUB_TOKEN_HERE" # IMPORTANT: Replace with a secure token (e.g., Ansible Vault)
    repo_url: "https://github.com/example-org/k3s.git"
    root_app_folder: "/home/deploy/argocd-init"
    ansible_python_interpreter: /usr/bin/python3
  ignore_errors: yes # WARNING: Use with caution in production. This allows the playbook to continue even if some tasks fail.
  become: true       # Run tasks with privilege escalation
  become_user: root  # Execute tasks as the root user
 
  tasks:
    - name: Include system apps installation
      include_tasks: system.yml
 
    - name: Include K3s installation tasks
      include_tasks: installk3s.yml
 
    - name: Include Argo CD setup tasks
      include_tasks: argo.yml

System Dependencies: system.yml

This task file installs essential system packages required for the K3s and Argo CD setup.

- name: Install default apps
  become: yes
  become_user: root
  apt:
    state: present
    update_cache: true
    name: '{{ item }}'
  loop:
    - nfs-common # Required for NFS volume support
    - rsync      # Utility for file synchronization
    - unzip      # Archive extraction utility
    - git        # Version control system, used for cloning repositories

K3s Installation and Configuration: installk3s.yml

This section handles the deployment of K3s and configures kubectl access for a non-root user.

- name: Download and install K3s
  shell: |
    curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik" sh -
  args:
    # `INSTALL_K3S_EXEC="--disable=traefik"` disables the default Traefik Ingress Controller
    # included with K3s, allowing for a custom ingress solution.
 
- name: Ensure .kube directory exists for user deploy
  file:
    path: /home/deploy/.kube
    state: directory
    owner: deploy
    group: deploy
    mode: '0755'
 
- name: Copy kubeconfig to non-root user
  ansible.builtin.copy:
    src: /etc/rancher/k3s/k3s.yaml # Source path on the remote machine
    dest: /home/deploy/.kube/config # Destination path for the user's kubeconfig
    owner: deploy
    group: deploy
    mode: 0600
    remote_src: true # IMPORTANT: This tells Ansible that 'src' refers to a path on the remote host, not the Ansible controller.
 
- name: Export KUBECONFIG in user's .bashrc
  lineinfile:
    path: /home/deploy/.bashrc
    line: 'export KUBECONFIG=$HOME/.kube/config'
    state: present
    owner: deploy
    group: deploy
    mode: '0644'
 
- name: Reboot
  ansible.builtin.reboot:
    reboot_timeout: 60
    post_reboot_delay: 60

Argo CD Setup: argo.yml

This task file installs Argo CD and deploys an initial “root” Application resource, often used in the App-of-Apps GitOps pattern.

- name: Ensure ArgoCD namespace exists
  ansible.builtin.command: kubectl create namespace argocd --kubeconfig /home/deploy/.kube/config
  register: ns_result
  failed_when: false # Allow this task to fail if the namespace already exists
 
- name: Install Argo CD
  ansible.builtin.shell: |
    kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml \
      --kubeconfig /home/deploy/.kube/config
 
- name: Ensure argocd-init folder exists
  ansible.builtin.file:
    path: /home/deploy/argocd-init
    state: directory
    mode: '0755'
 
- name: Render repo secret
  ansible.builtin.template:
    src: ../../templates/repo-secret.yaml.j2 # Assumes a Jinja2 template for repository credentials
    dest: /home/deploy/argocd-init/repo-secret.yaml
 
- name: Render root app shared
  ansible.builtin.template:
    src: ../../templates/root-app-shared.yaml.j2 # Assumes a Jinja2 template for the root application definition
    dest: /home/deploy/argocd-init/root-app-shared.yaml
 
- name: Apply repo secret
  ansible.builtin.command: kubectl apply -f /home/deploy/argocd-init/repo-secret.yaml --kubeconfig /home/deploy/.kube/config
 
- name: Apply root app shared
  ansible.builtin.command: kubectl apply -f /home/deploy/argocd-init/root-app-shared.yaml --kubeconfig /home/deploy/.kube/config
 
- name: Wait for ArgoCD server to be ready
  ansible.builtin.command: kubectl rollout status deployment/argocd-server -n argocd --timeout=300s --kubeconfig /home/deploy/.kube/config

Root Application Template Example

This is an example of an Argo CD Application resource, which points to a Git repository containing other Argo CD applications. This is a common pattern for managing multiple applications from a central Git repository (App-of-Apps).

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app-shared
  namespace: argocd
spec:
  destination:
    namespace: argocd
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: {{ repo_url }}  # Fetches the repository URL from Ansible variables
    targetRevision: main
    path: k3s/argo-apps      # Path within the repository where child applications are defined
    directory:
      recurse: true          # This enables App-of-Apps management by recursively scanning the path
  syncPolicy:
    automated:
      prune: true
      selfHeal: true