forked from tim/k3s-ansible
docs(agent): improve repository guidance [skip ci] (#685)
- Add canonical agent and contributor documentation. - Modernize issue and pull request templates. - Skip CI for documentation and issue-template-only changes.
This commit is contained in:
@@ -1,85 +0,0 @@
|
|||||||
|
|
||||||
<!-- It's a good idea to check this post first for general troubleshooting https://github.com/timothystewart6/k3s-ansible/discussions/19 -->
|
|
||||||
|
|
||||||
<!--- Provide a general summary of the issue in the Title above -->
|
|
||||||
|
|
||||||
## Expected Behavior
|
|
||||||
|
|
||||||
<!--- Tell us what should happen -->
|
|
||||||
|
|
||||||
## Current Behavior
|
|
||||||
<!--- Tell us what happens instead of the expected behavior -->
|
|
||||||
|
|
||||||
## Steps to Reproduce
|
|
||||||
|
|
||||||
<!--- reproduce this bug. Include code to reproduce, if relevant -->
|
|
||||||
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
4.
|
|
||||||
|
|
||||||
## Context (variables)
|
|
||||||
<!--- please include which OS, along with the variables used when running the playbook -->
|
|
||||||
|
|
||||||
Operating system:
|
|
||||||
|
|
||||||
Hardware:
|
|
||||||
|
|
||||||
### Variables Used
|
|
||||||
|
|
||||||
`all.yml`
|
|
||||||
|
|
||||||
```yml
|
|
||||||
k3s_version: ""
|
|
||||||
ansible_user: NA
|
|
||||||
systemd_dir: ""
|
|
||||||
|
|
||||||
flannel_iface: ""
|
|
||||||
|
|
||||||
#calico_iface: ""
|
|
||||||
calico_ebpf: ""
|
|
||||||
calico_cidr: ""
|
|
||||||
calico_tag: ""
|
|
||||||
|
|
||||||
apiserver_endpoint: ""
|
|
||||||
|
|
||||||
k3s_token: "NA"
|
|
||||||
|
|
||||||
extra_server_args: ""
|
|
||||||
extra_agent_args: ""
|
|
||||||
|
|
||||||
kube_vip_tag_version: ""
|
|
||||||
|
|
||||||
kube_vip_cloud_provider_tag_version: ""
|
|
||||||
kube_vip_lb_ip_range: ""
|
|
||||||
|
|
||||||
metal_lb_speaker_tag_version: ""
|
|
||||||
metal_lb_controller_tag_version: ""
|
|
||||||
|
|
||||||
metal_lb_ip_range: ""
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hosts
|
|
||||||
|
|
||||||
`host.ini`
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[master]
|
|
||||||
IP.ADDRESS.ONE
|
|
||||||
IP.ADDRESS.TWO
|
|
||||||
IP.ADDRESS.THREE
|
|
||||||
|
|
||||||
[node]
|
|
||||||
IP.ADDRESS.FOUR
|
|
||||||
IP.ADDRESS.FIVE
|
|
||||||
|
|
||||||
[k3s_cluster:children]
|
|
||||||
master
|
|
||||||
node
|
|
||||||
```
|
|
||||||
|
|
||||||
## Possible Solution
|
|
||||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
|
||||||
|
|
||||||
- [ ] I've checked the [General Troubleshooting Guide](https://github.com/timothystewart6/k3s-ansible/discussions/20)
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
description: Report a reproducible problem with the playbooks, roles, or generated resources.
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels:
|
||||||
|
- bug
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for reporting a problem. Search existing issues and review the troubleshooting link first.
|
||||||
|
Remove credentials, tokens, public IP addresses, and private hostnames from all fields and logs.
|
||||||
|
|
||||||
|
- type: checkboxes
|
||||||
|
id: prerequisites
|
||||||
|
attributes:
|
||||||
|
label: Prerequisites
|
||||||
|
options:
|
||||||
|
- label: I searched existing issues and discussions for this problem.
|
||||||
|
required: true
|
||||||
|
- label: I reviewed the troubleshooting guidance linked from the issue chooser.
|
||||||
|
required: true
|
||||||
|
- label: I removed secrets and identifying infrastructure details from this report.
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: summary
|
||||||
|
attributes:
|
||||||
|
label: Problem summary
|
||||||
|
description: Describe what failed and its impact.
|
||||||
|
placeholder: A concise description of the problem and affected nodes or components.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: What should have happened?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: Provide the smallest reliable sequence that reproduces the issue.
|
||||||
|
placeholder: |
|
||||||
|
1. Configure ...
|
||||||
|
2. Run ...
|
||||||
|
3. Observe ...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: revision
|
||||||
|
attributes:
|
||||||
|
label: Repository revision
|
||||||
|
description: Release, tag, branch, or commit SHA used.
|
||||||
|
placeholder: v1.36.2+k3s1+tt1 or a commit SHA
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: ansible-version
|
||||||
|
attributes:
|
||||||
|
label: Ansible version
|
||||||
|
description: Output of `ansible --version`, shortened to version and Python details.
|
||||||
|
placeholder: ansible-core 2.18.0, Python 3.12
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: environment
|
||||||
|
attributes:
|
||||||
|
label: Environment
|
||||||
|
description: Include target OS and version, architecture, node counts, platform, and network provider.
|
||||||
|
placeholder: Debian 13, amd64, 3 control nodes and 2 agents, bare metal, Cilium
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: configuration
|
||||||
|
attributes:
|
||||||
|
label: Relevant sanitized configuration
|
||||||
|
description: Include only variables and inventory groups needed to reproduce the problem.
|
||||||
|
render: yaml
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant logs or task output
|
||||||
|
description: Include the failing task and surrounding output. Redact sensitive or identifying values.
|
||||||
|
render: shell
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add attempted fixes, suspected causes, regressions, or other useful context.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Troubleshooting and support
|
||||||
|
url: https://github.com/timothystewart6/k3s-ansible/discussions/20
|
||||||
|
about: Review common troubleshooting guidance and ask configuration or usage questions.
|
||||||
|
- name: General discussions
|
||||||
|
url: https://github.com/timothystewart6/k3s-ansible/discussions
|
||||||
|
about: Discuss ideas and questions that are not confirmed bugs or concrete feature requests.
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
description: Propose a focused improvement to supported repository behavior.
|
||||||
|
title: "[Feature]: "
|
||||||
|
labels:
|
||||||
|
- enhancement
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Describe the use case before proposing an implementation. Search existing issues and discussions first.
|
||||||
|
|
||||||
|
- type: checkboxes
|
||||||
|
id: prerequisites
|
||||||
|
attributes:
|
||||||
|
label: Prerequisites
|
||||||
|
options:
|
||||||
|
- label: I searched existing issues and discussions for this request.
|
||||||
|
required: true
|
||||||
|
- label: This request is about reusable project behavior, not support for one private environment.
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: Problem or use case
|
||||||
|
description: What limitation exists, who encounters it, and why does it matter?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: proposal
|
||||||
|
attributes:
|
||||||
|
label: Proposed behavior
|
||||||
|
description: Describe the desired user-visible result. Include example variables or commands when useful.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: alternatives
|
||||||
|
attributes:
|
||||||
|
label: Alternatives considered
|
||||||
|
description: Describe workarounds or other designs and their tradeoffs.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: compatibility
|
||||||
|
attributes:
|
||||||
|
label: Compatibility and operational impact
|
||||||
|
description: Note affected operating systems, architectures, CNIs, existing clusters, or reset behavior.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add relevant upstream documentation, examples, or prior discussion.
|
||||||
@@ -1,15 +1,46 @@
|
|||||||
# Proposed Changes
|
## Summary
|
||||||
<!--- Provide a general summary of your changes -->
|
|
||||||
|
<!-- Explain the problem and the resulting behavior. Keep implementation details in the sections below. -->
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
-
|
||||||
|
|
||||||
## Checklist
|
## Related issues
|
||||||
|
|
||||||
- [ ] Tested locally
|
<!-- Use "Fixes #123" when this pull request should close an issue. Write "None" when not applicable. -->
|
||||||
- [ ] Ran `site.yml` playbook
|
|
||||||
- [ ] Ran `reset.yml` playbook
|
## Testing
|
||||||
- [ ] Did not add any unnecessary changes
|
|
||||||
- [ ] Ran pre-commit install at least once before committing
|
<!-- List exact commands, scenarios, and relevant manual checks. Do not check a box for a test that was not run. -->
|
||||||
- [ ] 🚀
|
|
||||||
|
- [ ] `pre-commit run --all-files`
|
||||||
|
- [ ] Relevant Ansible syntax checks
|
||||||
|
- [ ] Relevant focused regression tests
|
||||||
|
- [ ] Relevant Molecule scenario
|
||||||
|
- [ ] Provisioning tested against a non-production cluster
|
||||||
|
- [ ] Reset behavior tested against a non-production cluster
|
||||||
|
|
||||||
|
Not run, with reason:
|
||||||
|
|
||||||
|
## Risk and compatibility
|
||||||
|
|
||||||
|
<!-- Cover existing clusters, upgrades, networking, supported platforms, security, and rollback. Write "None" when a
|
||||||
|
category is not affected. -->
|
||||||
|
|
||||||
|
- Existing cluster or upgrade impact:
|
||||||
|
- Networking or CNI impact:
|
||||||
|
- Security impact:
|
||||||
|
- Rollback plan:
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
<!-- Identify updated docs and sample configuration, or explain why no documentation change is needed. -->
|
||||||
|
|
||||||
|
## Final checklist
|
||||||
|
|
||||||
|
- [ ] The change is focused and contains no unrelated edits.
|
||||||
|
- [ ] Tests cover new behavior or a regression, where applicable.
|
||||||
|
- [ ] User-facing variables are documented in role defaults, sample inventory, and the README.
|
||||||
|
- [ ] Logs, examples, and configuration contain no secrets or identifying infrastructure details.
|
||||||
|
- [ ] Generated files and local environment files are not included.
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# GitHub Copilot instructions
|
||||||
|
|
||||||
|
Read and follow the repository's root-level `AGENTS.md` before proposing or making changes. It is the canonical guide
|
||||||
|
for architecture, safety, implementation, validation, and documentation expectations.
|
||||||
|
|
||||||
|
Do not duplicate repository guidance here. If instructions need to change, update `AGENTS.md`.
|
||||||
@@ -14,6 +14,7 @@ on:
|
|||||||
- '**/FUNDING.yml'
|
- '**/FUNDING.yml'
|
||||||
- '**/host.ini'
|
- '**/host.ini'
|
||||||
- '**/*.md'
|
- '**/*.md'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
- '**/.editorconfig'
|
- '**/.editorconfig'
|
||||||
- '**/ansible.example.cfg'
|
- '**/ansible.example.cfg'
|
||||||
- '**/deploy.sh'
|
- '**/deploy.sh'
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
# Agent Guide
|
||||||
|
|
||||||
|
This file is the canonical repository guide for coding agents and automated contributors. Read it before making
|
||||||
|
changes. Human contributors should also review [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## Project overview
|
||||||
|
|
||||||
|
This repository is an Ansible collection that provisions and resets highly available k3s clusters. It supports
|
||||||
|
multiple networking choices, including Flannel, Calico, Cilium, kube-vip, and MetalLB.
|
||||||
|
|
||||||
|
The main entry points are:
|
||||||
|
|
||||||
|
- `site.yml`: provision or update a cluster.
|
||||||
|
- `reset.yml`: remove k3s from a cluster.
|
||||||
|
- `reboot.yml`: reboot cluster nodes.
|
||||||
|
- `inventory/sample/`: example inventory and variables.
|
||||||
|
- `roles/`: reusable Ansible roles used by the playbooks.
|
||||||
|
- `molecule/`: integration scenarios run by CI.
|
||||||
|
- `.github/scripts/`: CI support scripts and focused regression tests.
|
||||||
|
|
||||||
|
## Source of truth
|
||||||
|
|
||||||
|
- Role defaults belong in `roles/<role>/defaults/main.yml`.
|
||||||
|
- Tasks belong in `roles/<role>/tasks/` and handlers in `roles/<role>/handlers/`.
|
||||||
|
- Example user configuration belongs in `inventory/sample/`.
|
||||||
|
- User-facing setup and variable documentation belongs in `README.md`.
|
||||||
|
- Contributor workflows and review expectations belong in `CONTRIBUTING.md`.
|
||||||
|
- Agent-specific repository instructions belong in this file.
|
||||||
|
|
||||||
|
Keep `CLAUDE.md` and `.github/copilot-instructions.md` as small pointers to this file. Do not duplicate these
|
||||||
|
instructions in tool-specific files.
|
||||||
|
|
||||||
|
## Development setup
|
||||||
|
|
||||||
|
Use a Python virtual environment. Do not commit the environment, generated logs, inventories, kubeconfigs, or
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .env
|
||||||
|
source .env/bin/activate
|
||||||
|
python3 -m pip install -r requirements.txt
|
||||||
|
ansible-galaxy collection install -r collections/requirements.yml
|
||||||
|
pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
|
`ansible.cfg` is intentionally ignored. Copy `ansible.example.cfg` when local configuration is needed.
|
||||||
|
|
||||||
|
## Working rules
|
||||||
|
|
||||||
|
1. Inspect the current branch and worktree before editing. Preserve unrelated user changes.
|
||||||
|
2. Keep changes focused. Avoid drive-by formatting or dependency updates.
|
||||||
|
3. Never add real IP addresses, hostnames, tokens, private keys, kubeconfigs, or inventory secrets.
|
||||||
|
4. Use placeholders in examples and redact sensitive values from logs and issue reports.
|
||||||
|
5. Preserve idempotence. An already-converged host should not report changes without a real state transition.
|
||||||
|
6. Prefer Ansible modules over `ansible.builtin.command` or `ansible.builtin.shell`. When a command is required,
|
||||||
|
define accurate `changed_when` and `failed_when` behavior.
|
||||||
|
7. Use fully qualified collection names, such as `ansible.builtin.copy`.
|
||||||
|
8. Put configurable values in role defaults or inventory variables. Avoid embedding environment-specific values in
|
||||||
|
tasks and templates.
|
||||||
|
9. Maintain compatibility with the operating systems and architectures listed in `README.md`.
|
||||||
|
10. Do not weaken lint rules, tests, or CI checks to make a change pass.
|
||||||
|
|
||||||
|
## Change guidance
|
||||||
|
|
||||||
|
### Ansible tasks and roles
|
||||||
|
|
||||||
|
- Use descriptive task names in sentence case.
|
||||||
|
- Use YAML booleans (`true` and `false`) rather than aliases.
|
||||||
|
- Quote file modes, for example `mode: "0644"`.
|
||||||
|
- Notify handlers only when the managed resource changes.
|
||||||
|
- Use `become: true` only where privilege escalation is needed.
|
||||||
|
- Update role defaults, sample inventory, and the README together when adding or renaming user-facing variables.
|
||||||
|
- Check reset behavior when provisioning introduces persistent services, files, mounts, or network state.
|
||||||
|
|
||||||
|
### Templates and manifests
|
||||||
|
|
||||||
|
- Keep Jinja logic small and readable. Move complicated decisions into task variables where practical.
|
||||||
|
- Render valid YAML after Jinja evaluation.
|
||||||
|
- Preserve explicit handling for optional and undefined variables.
|
||||||
|
- Add or update a focused test under `.github/scripts/` when changing generated Kubernetes manifests or bootstrap
|
||||||
|
behavior.
|
||||||
|
|
||||||
|
### Molecule scenarios
|
||||||
|
|
||||||
|
- Reuse `molecule/resources/` for shared behavior.
|
||||||
|
- Put scenario-specific inputs in `molecule/<scenario>/overrides.yml` and `verify-vars.yml`.
|
||||||
|
- Update `molecule/README.md` when adding, removing, or materially changing a scenario.
|
||||||
|
- Clean up resources created by tests, including failure paths.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
Run the smallest relevant checks while iterating, then run the complete local validation before considering a change
|
||||||
|
ready:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pre-commit run --all-files
|
||||||
|
```
|
||||||
|
|
||||||
|
For playbook or role changes, also run syntax checks with a non-sensitive inventory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook site.yml --syntax-check -i inventory/sample/hosts.ini
|
||||||
|
ansible-playbook reset.yml --syntax-check -i inventory/sample/hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
Run focused regression scripts when their related files change. The mapping is defined in
|
||||||
|
`.pre-commit-config.yaml`.
|
||||||
|
|
||||||
|
Molecule tests require Vagrant, VirtualBox, host-only networking, and substantial local resources. Run the most
|
||||||
|
relevant scenario when that environment is available:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
molecule test --scenario-name <scenario>
|
||||||
|
```
|
||||||
|
|
||||||
|
If a required test can't be run locally, state exactly which check was skipped and why. Never claim a check passed
|
||||||
|
unless it was executed.
|
||||||
|
|
||||||
|
## Documentation and review
|
||||||
|
|
||||||
|
- Keep commands copyable and examples free of secrets.
|
||||||
|
- Update documentation in the same change as user-visible behavior.
|
||||||
|
- Explain behavior changes, compatibility concerns, operational risks, and rollback steps in the pull request.
|
||||||
|
- Use conventional commit messages with a scope, for example `fix(k3s-server): handle an existing token safely`.
|
||||||
|
- Do not commit, push, open a pull request, or modify remote resources unless the user explicitly requests it.
|
||||||
|
|
||||||
|
## Definition of done
|
||||||
|
|
||||||
|
A change is ready for review when it is focused, documented, linted, tested in proportion to its risk, and shown in a
|
||||||
|
clean diff with no secrets or generated artifacts.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@AGENTS.md
|
||||||
|
|
||||||
|
`AGENTS.md` is the canonical repository guide. Follow it for all work in this repository.
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# Contributing to k3s-ansible
|
||||||
|
|
||||||
|
Thank you for improving k3s-ansible. Contributions should be focused, safe to apply to existing clusters, and tested
|
||||||
|
in proportion to their operational impact.
|
||||||
|
|
||||||
|
## Before opening an issue
|
||||||
|
|
||||||
|
- Search existing issues and discussions for the same behavior.
|
||||||
|
- Review the [troubleshooting discussion](https://github.com/timothystewart6/k3s-ansible/discussions/20).
|
||||||
|
- Remove tokens, credentials, public IP addresses, private hostnames, and other sensitive values from logs and
|
||||||
|
configuration.
|
||||||
|
- For support requests, include the k3s-ansible revision, Ansible version, target operating system, architecture,
|
||||||
|
network provider, relevant sanitized variables, and a minimal reproduction.
|
||||||
|
|
||||||
|
Use the bug report template for reproducible defects and the feature request template for proposed behavior.
|
||||||
|
|
||||||
|
## Development environment
|
||||||
|
|
||||||
|
Fork and clone the repository, then create a branch from the latest `master`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git switch master
|
||||||
|
git pull --ff-only
|
||||||
|
git switch -c <type>/<short-description>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a Python environment and install the pinned development dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .env
|
||||||
|
source .env/bin/activate
|
||||||
|
python3 -m pip install -r requirements.txt
|
||||||
|
ansible-galaxy collection install -r collections/requirements.yml
|
||||||
|
pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy `ansible.example.cfg` to the ignored `ansible.cfg` file if local Ansible configuration is needed. Start custom
|
||||||
|
inventories from `inventory/sample/`, keep them out of Git, and never use production credentials in tests.
|
||||||
|
|
||||||
|
## Making changes
|
||||||
|
|
||||||
|
- Keep each pull request focused on one problem or feature.
|
||||||
|
- Follow [AGENTS.md](AGENTS.md) for repository structure, implementation conventions, and safety requirements.
|
||||||
|
- Preserve idempotence and existing-cluster compatibility.
|
||||||
|
- Add or update tests for behavior changes and regressions.
|
||||||
|
- Update role defaults, sample inventory, and documentation when user-facing variables change.
|
||||||
|
- Consider both provisioning and reset behavior for persistent resources.
|
||||||
|
- Avoid unrelated reformatting and generated files.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
Run all pre-commit checks before submitting a pull request:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pre-commit run --all-files
|
||||||
|
```
|
||||||
|
|
||||||
|
For playbook or role changes, run syntax checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook site.yml --syntax-check -i inventory/sample/hosts.ini
|
||||||
|
ansible-playbook reset.yml --syntax-check -i inventory/sample/hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the most relevant Molecule scenario when Vagrant, VirtualBox, and the required host networking are available:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
molecule test --scenario-name <scenario>
|
||||||
|
```
|
||||||
|
|
||||||
|
See [molecule/README.md](molecule/README.md) for scenario details and local requirements. Pull requests should list
|
||||||
|
every check that was run and clearly identify checks that could not be run locally.
|
||||||
|
|
||||||
|
## Commits and pull requests
|
||||||
|
|
||||||
|
Use a conventional commit subject with a scope:
|
||||||
|
|
||||||
|
```text
|
||||||
|
type(scope): short description
|
||||||
|
```
|
||||||
|
|
||||||
|
Common types are `feat`, `fix`, `refactor`, `test`, `docs`, and `chore`. Write subjects in the imperative mood and
|
||||||
|
keep commits logically focused.
|
||||||
|
|
||||||
|
Pull requests should:
|
||||||
|
|
||||||
|
- Describe the problem and the resulting behavior.
|
||||||
|
- Identify compatibility, security, networking, and upgrade risks.
|
||||||
|
- Include testing evidence without sensitive data.
|
||||||
|
- Call out documentation and sample configuration changes.
|
||||||
|
- Link related issues with `Fixes #<issue>` when applicable.
|
||||||
|
- Avoid checking boxes for tests that were not run.
|
||||||
|
|
||||||
|
Maintainers may ask for a change to be split when unrelated work makes it difficult to review or roll back.
|
||||||
@@ -2,51 +2,66 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
This playbook will build an HA Kubernetes cluster with `k3s`, `kube-vip` and MetalLB via `ansible`.
|
This Ansible collection builds a highly available Kubernetes cluster with k3s. It supports kube-vip for the control
|
||||||
|
plane virtual IP, multiple CNI options, and either MetalLB or kube-vip for service load balancing.
|
||||||
|
|
||||||
This is based on the work from [this fork](https://github.com/212850a/k3s-ansible) which is based on the work from [k3s-io/k3s-ansible](https://github.com/k3s-io/k3s-ansible). It uses [kube-vip](https://kube-vip.io/) to create a load balancer for control plane, and [metal-lb](https://metallb.universe.tf/installation/) for its service `LoadBalancer`.
|
This is based on the work from [this fork](https://github.com/212850a/k3s-ansible) which is based on the work from [k3s-io/k3s-ansible](https://github.com/k3s-io/k3s-ansible). It uses [kube-vip](https://kube-vip.io/) to create a load balancer for control plane, and [metal-lb](https://metallb.universe.tf/installation/) for its service `LoadBalancer`.
|
||||||
|
|
||||||
If you want more context on how this works, see:
|
For more context on how it works, see:
|
||||||
|
|
||||||
📄 [Documentation](https://technotim.com/posts/k3s-etcd-ansible/) (including example commands)
|
📄 [Documentation](https://technotim.com/posts/k3s-etcd-ansible/) (including example commands)
|
||||||
|
|
||||||
📺 [Watch the Video](https://www.youtube.com/watch?v=CbkEWcUZ7zM)
|
📺 [Watch the Video](https://www.youtube.com/watch?v=CbkEWcUZ7zM)
|
||||||
|
|
||||||
|
## Project guides
|
||||||
|
|
||||||
|
- [Getting started](#-getting-started)
|
||||||
|
- [Configuration variables](#variables)
|
||||||
|
- [Upgrading an existing cluster](#-upgrading-an-existing-cluster)
|
||||||
|
- [Local Molecule testing](molecule/README.md)
|
||||||
|
- [Contributing guidelines](CONTRIBUTING.md)
|
||||||
|
- [Repository guide for coding agents](AGENTS.md)
|
||||||
|
|
||||||
## 📖 k3s Ansible Playbook
|
## 📖 k3s Ansible Playbook
|
||||||
|
|
||||||
Build a Kubernetes cluster using Ansible with k3s. The goal is easily install a HA Kubernetes cluster on machines running:
|
Build a Kubernetes cluster using Ansible and k3s. The goal is to make a highly available cluster straightforward to
|
||||||
|
install on machines running:
|
||||||
|
|
||||||
- [x] Debian (tested on version 13)
|
- [x] Debian (tested on version 13)
|
||||||
- [x] Ubuntu (tested on version 26.04 LTS)
|
- [x] Ubuntu (tested on version 26.04 LTS)
|
||||||
- [x] Rocky (tested on version 10)
|
- [x] Rocky (tested on version 10)
|
||||||
|
|
||||||
on processor architecture:
|
Supported processor architectures are:
|
||||||
|
|
||||||
- [X] x64
|
- [x] x64
|
||||||
- [X] arm64
|
- [x] arm64
|
||||||
- [X] armhf
|
- [x] armhf
|
||||||
|
|
||||||
## ✅ System requirements
|
## ✅ System requirements
|
||||||
|
|
||||||
- Control Node (the machine you are running `ansible` commands) must have Ansible 2.11+ If you need a quick primer on Ansible [you can check out my docs and setting up Ansible](https://technotim.com/posts/ansible-automation/).
|
- The control node, which runs the Ansible commands, must have Ansible 2.11 or newer. For a quick primer, see
|
||||||
|
[setting up Ansible](https://technotim.com/posts/ansible-automation/).
|
||||||
|
|
||||||
- You will also need to install collections that this playbook uses by running `ansible-galaxy collection install -r ./collections/requirements.yml` (important❗)
|
- Install the required collections with
|
||||||
|
`ansible-galaxy collection install -r ./collections/requirements.yml`.
|
||||||
|
|
||||||
- [`netaddr` package](https://pypi.org/project/netaddr/) must be available to Ansible. If you have installed Ansible via apt, this is already taken care of. If you have installed Ansible via `pip`, make sure to install `netaddr` into the respective virtual environment.
|
- [`netaddr` package](https://pypi.org/project/netaddr/) must be available to Ansible. If you have installed Ansible via apt, this is already taken care of. If you have installed Ansible via `pip`, make sure to install `netaddr` into the respective virtual environment.
|
||||||
|
|
||||||
- `server` and `agent` nodes should have passwordless SSH access, if not you can supply arguments to provide credentials `--ask-pass --ask-become-pass` to each command.
|
- Server and agent nodes should support passwordless SSH access. Otherwise, pass `--ask-pass --ask-become-pass` to
|
||||||
|
each playbook command.
|
||||||
|
|
||||||
## 🚀 Getting Started
|
## 🚀 Getting Started
|
||||||
|
|
||||||
### 🍴 Preparation
|
### 🍴 Preparation
|
||||||
|
|
||||||
First create a new directory based on the `sample` directory within the `inventory` directory:
|
Create a cluster-specific inventory from the sample. The `inventory/` directory ignores custom inventory content so
|
||||||
|
credentials and environment details aren't committed accidentally.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp -R inventory/sample inventory/my-cluster
|
cp -R inventory/sample inventory/my-cluster
|
||||||
```
|
```
|
||||||
|
|
||||||
Second, edit `inventory/my-cluster/hosts.ini` to match the system information gathered above
|
Edit `inventory/my-cluster/hosts.ini` to match the target hosts.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
@@ -67,9 +82,10 @@ node
|
|||||||
|
|
||||||
If multiple hosts are in the master group, the playbook will automatically set up k3s in [HA mode with etcd](https://rancher.com/docs/k3s/latest/en/installation/ha-embedded/).
|
If multiple hosts are in the master group, the playbook will automatically set up k3s in [HA mode with etcd](https://rancher.com/docs/k3s/latest/en/installation/ha-embedded/).
|
||||||
|
|
||||||
Finally, copy `ansible.example.cfg` to `ansible.cfg` and adapt the inventory path to match the files that you just created.
|
Copy `ansible.example.cfg` to `ansible.cfg`, then update its inventory path. The local `ansible.cfg` file is ignored by
|
||||||
|
Git.
|
||||||
|
|
||||||
This requires at least k3s version `1.19.1` however the version is configurable by using the `k3s_version` variable.
|
The minimum k3s version is `1.19.1`. Select the desired version with the `k3s_version` variable.
|
||||||
|
|
||||||
If needed, you can also edit `inventory/my-cluster/group_vars/all.yml` to match your environment.
|
If needed, you can also edit `inventory/my-cluster/group_vars/all.yml` to match your environment.
|
||||||
|
|
||||||
@@ -81,7 +97,8 @@ Start provisioning of the cluster using the following command:
|
|||||||
ansible-playbook site.yml -i inventory/my-cluster/hosts.ini
|
ansible-playbook site.yml -i inventory/my-cluster/hosts.ini
|
||||||
```
|
```
|
||||||
|
|
||||||
After deployment control plane will be accessible via virtual ip-address which is defined in inventory/group_vars/all.yml as `apiserver_endpoint`
|
After deployment, the control plane is accessible through the virtual IP defined by `apiserver_endpoint` in the
|
||||||
|
inventory variables.
|
||||||
|
|
||||||
### 🔥 Remove k3s cluster
|
### 🔥 Remove k3s cluster
|
||||||
|
|
||||||
@@ -89,7 +106,7 @@ After deployment control plane will be accessible via virtual ip-address which i
|
|||||||
ansible-playbook reset.yml -i inventory/my-cluster/hosts.ini
|
ansible-playbook reset.yml -i inventory/my-cluster/hosts.ini
|
||||||
```
|
```
|
||||||
|
|
||||||
>You should also reboot these nodes due to the VIP not being destroyed
|
> Reboot the nodes after reset because the virtual IP may remain configured.
|
||||||
|
|
||||||
## 🔁 Upgrading an existing cluster
|
## 🔁 Upgrading an existing cluster
|
||||||
|
|
||||||
@@ -124,13 +141,21 @@ To copy your `kube config` locally so that you can access your **Kubernetes** cl
|
|||||||
```bash
|
```bash
|
||||||
scp debian@master_ip:/etc/rancher/k3s/k3s.yaml ~/.kube/config
|
scp debian@master_ip:/etc/rancher/k3s/k3s.yaml ~/.kube/config
|
||||||
```
|
```
|
||||||
If you get file Permission denied, go into the node and temporarly run:
|
If the copy fails with a permission error, grant the SSH user temporary read access using the least permissive method
|
||||||
|
available for the target system. Restore the original ownership and permissions immediately after copying. Avoid
|
||||||
|
world-writable permissions on the kubeconfig because it contains cluster credentials.
|
||||||
|
|
||||||
|
For example, copy the file to a temporary user-readable path from the control node:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo chmod 777 /etc/rancher/k3s/k3s.yaml
|
ssh debian@master_ip 'sudo install -o "$(id -un)" -m 0600 /etc/rancher/k3s/k3s.yaml /tmp/k3s.yaml'
|
||||||
```
|
```
|
||||||
Then copy with the scp command and reset the permissions back to:
|
|
||||||
|
Copy `/tmp/k3s.yaml`, then remove the temporary remote copy:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo chmod 600 /etc/rancher/k3s/k3s.yaml
|
scp debian@master_ip:/tmp/k3s.yaml ~/.kube/config
|
||||||
|
ssh debian@master_ip rm -f /tmp/k3s.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
You'll then want to modify the config to point to master IP by running:
|
You'll then want to modify the config to point to master IP by running:
|
||||||
@@ -150,7 +175,7 @@ See the commands [here](https://technotim.com/posts/k3s-etcd-ansible/#testing-yo
|
|||||||
| `download` | `k3s_version` | string | ❌ | Required | K3s binaries version |
|
| `download` | `k3s_version` | string | ❌ | Required | K3s binaries version |
|
||||||
| `k3s_agent`, `k3s_server`, `k3s_server_post` | `apiserver_endpoint` | string | ❌ | Required | Virtual ip-address configured on each master |
|
| `k3s_agent`, `k3s_server`, `k3s_server_post` | `apiserver_endpoint` | string | ❌ | Required | Virtual ip-address configured on each master |
|
||||||
| `k3s_agent` | `extra_agent_args` | string | `null` | Not required | Extra arguments for agents nodes |
|
| `k3s_agent` | `extra_agent_args` | string | `null` | Not required | Extra arguments for agents nodes |
|
||||||
| `k3s_agent`, `k3s_server` | `group_name_master` | string | `null` | Not required | Name othe master group |
|
| `k3s_agent`, `k3s_server` | `group_name_master` | string | `null` | Not required | Name of the master group |
|
||||||
| `k3s_agent` | `k3s_token` | string | `null` | Not required | Token used to communicate between masters |
|
| `k3s_agent` | `k3s_token` | string | `null` | Not required | Token used to communicate between masters |
|
||||||
| `k3s_agent`, `k3s_server` | `proxy_env` | dict | `null` | Not required | Internet proxy configurations |
|
| `k3s_agent`, `k3s_server` | `proxy_env` | dict | `null` | Not required | Internet proxy configurations |
|
||||||
| `k3s_agent`, `k3s_server` | `proxy_env.HTTP_PROXY` | string | ❌ | Required | HTTP internet proxy |
|
| `k3s_agent`, `k3s_server` | `proxy_env.HTTP_PROXY` | string | ❌ | Required | HTTP internet proxy |
|
||||||
@@ -227,9 +252,11 @@ It is run automatically in CI, but you can also run the tests locally.
|
|||||||
This might be helpful for quick feedback in a few cases.
|
This might be helpful for quick feedback in a few cases.
|
||||||
You can find more information about it [here](molecule/README.md).
|
You can find more information about it [here](molecule/README.md).
|
||||||
|
|
||||||
### Pre-commit Hooks
|
### Pre-commit hooks
|
||||||
|
|
||||||
This repo uses `pre-commit` and `pre-commit-hooks` to lint and fix common style and syntax errors. Be sure to install python packages and then run `pre-commit install`. For more information, see [pre-commit](https://pre-commit.com/)
|
This repository uses `pre-commit` to check style, syntax, Ansible content, and shell scripts. Install the Python
|
||||||
|
dependencies, run `pre-commit install` once, and run `pre-commit run --all-files` before submitting a change. See
|
||||||
|
[CONTRIBUTING.md](CONTRIBUTING.md) for the complete development workflow.
|
||||||
|
|
||||||
## 🌌 Ansible Galaxy
|
## 🌌 Ansible Galaxy
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user