initial commit
This commit is contained in:
96
README.md
Normal file
96
README.md
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# Kubernetes on Raspberry Pi with Ansible - Usage Guide
|
||||||
|
|
||||||
|
This guide details how to use the generated Ansible playbook to install Kubernetes on your Raspberry Pi cluster.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **Ansible Installed**: You need Ansible installed on your control machine (your laptop/desktop).
|
||||||
|
* **Debian/Ubuntu**:
|
||||||
|
```bash
|
||||||
|
sudo apt update && sudo apt install ansible sshpass -y
|
||||||
|
```
|
||||||
|
* **Arch Linux**:
|
||||||
|
```bash
|
||||||
|
sudo pacman -S ansible sshpass
|
||||||
|
```
|
||||||
|
* **Fedora**:
|
||||||
|
```bash
|
||||||
|
sudo dnf install ansible sshpass
|
||||||
|
```
|
||||||
|
2. **SSH Access**: Ensure you have SSH access to all Raspberry Pi nodes.
|
||||||
|
3. **Hardware**: 4 Raspberry Pi nodes (1 Master, 3 Workers) with Raspberry Pi OS installed.
|
||||||
|
|
||||||
|
## Configuration Steps
|
||||||
|
|
||||||
|
### 1. Configure Inventory
|
||||||
|
Edit `inventory/hosts.ini` and replace the placeholder IP addresses with the actual IPs of your Raspberry Pis.
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[masters]
|
||||||
|
pi1 ansible_host=192.168.1.10 <-- Change to Master IP
|
||||||
|
|
||||||
|
[workers]
|
||||||
|
pi2 ansible_host=192.168.1.11 <-- Change to Worker 1 IP
|
||||||
|
pi3 ansible_host=192.168.1.12 <-- Change to Worker 2 IP
|
||||||
|
pi4 ansible_host=192.168.1.13 <-- Change to Worker 3 IP
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configure Credentials
|
||||||
|
You need to set the SSH password for the `pi` user. We use Ansible Vault for security.
|
||||||
|
|
||||||
|
1. Generate an encrypted password string:
|
||||||
|
```bash
|
||||||
|
ansible-vault encrypt_string 'YOUR_ACTUAL_PASSWORD' --name 'vault_ssh_password'
|
||||||
|
```
|
||||||
|
*Replace `YOUR_ACTUAL_PASSWORD` with the real password.*
|
||||||
|
|
||||||
|
2. Copy the output block and paste it into `group_vars/all.yml`, replacing the commented out section or just adding it.
|
||||||
|
|
||||||
|
Example in `group_vars/all.yml`:
|
||||||
|
```yaml
|
||||||
|
ansible_password: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
... (encrypted string) ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Do the same for `vault_become_password` if your sudo password is different. If sudo password is same as ssh password, you can just set:
|
||||||
|
```yaml
|
||||||
|
ansible_become_password: "{{ vault_ssh_password }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Run the Playbook
|
||||||
|
|
||||||
|
To start the installation, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook site.yml --ask-vault-pass
|
||||||
|
```
|
||||||
|
|
||||||
|
*Note: Since you used `encrypt_string` without a password file, it might ask for a vault password if you set one. If you just used `encrypt_string`, you might need to provide the vault password you used to encrypt it.*
|
||||||
|
|
||||||
|
**Alternative (Simpler for testing):**
|
||||||
|
If you don't want to use Vault yet, you can pass the password as an extra var (INSECURE - be careful with history):
|
||||||
|
```bash
|
||||||
|
ansible-playbook site.yml -e "ansible_password=yourpassword ansible_become_password=yourpassword"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
After the playbook completes:
|
||||||
|
|
||||||
|
1. **SSH into the Master Node**:
|
||||||
|
```bash
|
||||||
|
ssh pi@<master-ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check Nodes**:
|
||||||
|
```bash
|
||||||
|
kubectl get nodes
|
||||||
|
```
|
||||||
|
You should see 4 nodes with status `Ready`.
|
||||||
|
|
||||||
|
3. **Check Pods**:
|
||||||
|
```bash
|
||||||
|
kubectl get pods -A
|
||||||
|
```
|
||||||
|
Ensure `coredns` and `kube-flannel` are running.
|
||||||
7
ansible.cfg
Normal file
7
ansible.cfg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = ./inventory/hosts.ini
|
||||||
|
host_key_checking = False
|
||||||
|
retry_files_enabled = False
|
||||||
|
interpreter_python = auto_silent
|
||||||
|
stdout_callback = yaml
|
||||||
|
bin_ansible_callbacks = True
|
||||||
11
group_vars/all.yml
Normal file
11
group_vars/all.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
ansible_user: pi
|
||||||
|
# Use ansible-vault to encrypt the password:
|
||||||
|
# ansible-vault encrypt_string 'your_password' --name 'vault_ssh_password'
|
||||||
|
# then put the result here.
|
||||||
|
# For now, we expect these variables to be defined, e.g. in a vault file or extra vars.
|
||||||
|
# ansible_password: "{{ vault_ssh_password }}"
|
||||||
|
# ansible_become_password: "{{ vault_become_password }}"
|
||||||
|
|
||||||
|
# Kubernetes Version
|
||||||
|
k8s_version: "1.28.0-00"
|
||||||
10
inventory/hosts.ini
Normal file
10
inventory/hosts.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[masters]
|
||||||
|
pi1 ansible_host=192.168.1.10
|
||||||
|
|
||||||
|
[workers]
|
||||||
|
pi2 ansible_host=192.168.1.11
|
||||||
|
pi3 ansible_host=192.168.1.12
|
||||||
|
pi4 ansible_host=192.168.1.13
|
||||||
|
|
||||||
|
[all:vars]
|
||||||
|
# These are placeholders, update with real IPs
|
||||||
10
roles/common/handlers/main.yml
Normal file
10
roles/common/handlers/main.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: restart containerd
|
||||||
|
service:
|
||||||
|
name: containerd
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
- name: restart kubelet
|
||||||
|
service:
|
||||||
|
name: kubelet
|
||||||
|
state: restarted
|
||||||
129
roles/common/tasks/main.yml
Normal file
129
roles/common/tasks/main.yml
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
---
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Upgrade all packages
|
||||||
|
apt:
|
||||||
|
upgrade: dist
|
||||||
|
|
||||||
|
- name: Install required system packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- software-properties-common
|
||||||
|
- gnupg
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Disable swap
|
||||||
|
command: swapoff -a
|
||||||
|
when: ansible_swaptotal_mb > 0
|
||||||
|
|
||||||
|
- name: Disable swap in dphys-swapfile
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/dphys-swapfile
|
||||||
|
regexp: '^CONF_SWAPSIZE='
|
||||||
|
line: 'CONF_SWAPSIZE=0'
|
||||||
|
notify: restart kubelet
|
||||||
|
|
||||||
|
- name: Enable cgroup features in cmdline.txt
|
||||||
|
replace:
|
||||||
|
path: /boot/cmdline.txt
|
||||||
|
regexp: '^((?!.*\bcgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1\b).*)$'
|
||||||
|
replace: '\1 cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1'
|
||||||
|
register: cgroup_update
|
||||||
|
|
||||||
|
- name: Reboot if cgroup features updated
|
||||||
|
reboot:
|
||||||
|
when: cgroup_update.changed
|
||||||
|
|
||||||
|
- name: Load kernel modules for containerd
|
||||||
|
copy:
|
||||||
|
dest: /etc/modules-load.d/containerd.conf
|
||||||
|
content: |
|
||||||
|
overlay
|
||||||
|
br_netfilter
|
||||||
|
|
||||||
|
- name: Load overlay module
|
||||||
|
modprobe:
|
||||||
|
name: overlay
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Load br_netfilter module
|
||||||
|
modprobe:
|
||||||
|
name: br_netfilter
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Configure sysctl params for Kubernetes
|
||||||
|
copy:
|
||||||
|
dest: /etc/sysctl.d/99-kubernetes-cri.conf
|
||||||
|
content: |
|
||||||
|
net.bridge.bridge-nf-call-iptables = 1
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
net.bridge.bridge-nf-call-ip6tables = 1
|
||||||
|
register: sysctl_config
|
||||||
|
|
||||||
|
- name: Apply sysctl params
|
||||||
|
command: sysctl --system
|
||||||
|
when: sysctl_config.changed
|
||||||
|
|
||||||
|
- name: Install containerd
|
||||||
|
apt:
|
||||||
|
name: containerd
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create containerd config directory
|
||||||
|
file:
|
||||||
|
path: /etc/containerd
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Generate default containerd config
|
||||||
|
shell: containerd config default > /etc/containerd/config.toml
|
||||||
|
args:
|
||||||
|
creates: /etc/containerd/config.toml
|
||||||
|
|
||||||
|
- name: Configure SystemdCgroup in containerd config
|
||||||
|
replace:
|
||||||
|
path: /etc/containerd/config.toml
|
||||||
|
regexp: 'SystemdCgroup = false'
|
||||||
|
replace: 'SystemdCgroup = true'
|
||||||
|
notify: restart containerd
|
||||||
|
|
||||||
|
- name: Create keyrings directory
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Download Kubernetes GPG key
|
||||||
|
get_url:
|
||||||
|
url: https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key
|
||||||
|
dest: /etc/apt/keyrings/kubernetes-apt-keyring.asc
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Add Kubernetes apt repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.asc] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /"
|
||||||
|
state: present
|
||||||
|
filename: kubernetes
|
||||||
|
|
||||||
|
- name: Install Kubernetes binaries
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- kubelet
|
||||||
|
- kubeadm
|
||||||
|
- kubectl
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Hold Kubernetes packages
|
||||||
|
dpkg_selections:
|
||||||
|
name: "{{ item }}"
|
||||||
|
selection: hold
|
||||||
|
loop:
|
||||||
|
- kubelet
|
||||||
|
- kubeadm
|
||||||
|
- kubectl
|
||||||
37
roles/master/tasks/main.yml
Normal file
37
roles/master/tasks/main.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
- name: Initialize Kubernetes Control Plane
|
||||||
|
command: kubeadm init --pod-network-cidr=10.244.0.0/16
|
||||||
|
args:
|
||||||
|
creates: /etc/kubernetes/admin.conf
|
||||||
|
register: kubeadm_init
|
||||||
|
|
||||||
|
- name: Create .kube directory
|
||||||
|
file:
|
||||||
|
path: /home/{{ ansible_user }}/.kube
|
||||||
|
state: directory
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "{{ ansible_user }}"
|
||||||
|
mode: 0755
|
||||||
|
|
||||||
|
- name: Copy admin.conf to user's kube config
|
||||||
|
copy:
|
||||||
|
src: /etc/kubernetes/admin.conf
|
||||||
|
dest: /home/{{ ansible_user }}/.kube/config
|
||||||
|
remote_src: yes
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "{{ ansible_user }}"
|
||||||
|
|
||||||
|
- name: Install Flannel Pod Network
|
||||||
|
command: kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ ansible_user }}"
|
||||||
|
when: kubeadm_init.changed
|
||||||
|
|
||||||
|
- name: Get join command
|
||||||
|
command: kubeadm token create --print-join-command
|
||||||
|
register: join_command_raw
|
||||||
|
|
||||||
|
- name: Add dummy host with variable
|
||||||
|
add_host:
|
||||||
|
name: "K8S_TOKEN_HOLDER"
|
||||||
|
join_command: "{{ join_command_raw.stdout_lines[0] }}"
|
||||||
5
roles/worker/tasks/main.yml
Normal file
5
roles/worker/tasks/main.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
- name: Join worker to cluster
|
||||||
|
command: "{{ hostvars['K8S_TOKEN_HOLDER']['join_command'] }}"
|
||||||
|
args:
|
||||||
|
creates: /etc/kubernetes/kubelet.conf
|
||||||
Reference in New Issue
Block a user