refactor: install ansible with Python venv (#863)

This commit is contained in:
Devin Buhl authored and GitHub committed 2023-07-19 11:03:59 -04:00
1 parent e4d1fa15d6
commit 571a7454c0
15 files changed
+85 -153

No files matched your search

+8 -3
View File
@@ -1,4 +1,9 @@
#shellcheck disable=SC2148,SC2155 #shellcheck disable=SC2148,SC2155
export KUBECONFIG=$(expand_path ./kubeconfig) export KUBECONFIG="$(expand_path ./kubeconfig)"
export K8S_AUTH_KUBECONFIG=$(expand_path ./kubeconfig) export SOPS_AGE_KEY_FILE="$(expand_path ./age.key)"
export SOPS_AGE_KEY_FILE=$(expand_path ~/.config/sops/age/keys.txt) # ansible
PATH_add "$(expand_path ./.venv/bin)"
export VIRTUAL_ENV="$(expand_path ./.venv)"
export ANSIBLE_COLLECTIONS_PATH=$(expand_path ./.venv/galaxy)
export ANSIBLE_ROLES_PATH=$(expand_path ./.venv/galaxy/ansible_roles)
export K8S_AUTH_KUBECONFIG="$(expand_path ./kubeconfig)"
-11
View File
@@ -20,12 +20,6 @@
"suppressNotifications": ["prIgnoreNotification"], "suppressNotifications": ["prIgnoreNotification"],
"rebaseWhen": "conflicted", "rebaseWhen": "conflicted",
"schedule": ["on saturday"], "schedule": ["on saturday"],
"ansible-galaxy": {
"fileMatch": [
"(^|/)requirements\\.ya?ml(\\.j2)?$",
"(^|/)galaxy\\.ya?ml(\\.j2)?$"
]
},
"flux": { "flux": {
"fileMatch": [ "fileMatch": [
"(^|/)kubernetes/.+\\.ya?ml(\\.j2)?$", "(^|/)kubernetes/.+\\.ya?ml(\\.j2)?$",
@@ -50,11 +44,6 @@
"(^|/)kustomization\\.ya?ml(\\.j2)?$" "(^|/)kustomization\\.ya?ml(\\.j2)?$"
] ]
}, },
"pip_requirements": {
"fileMatch": [
"(^|/)[\\w-]*requirements(-\\w+)?\\.(txt|pip)(\\.j2)?$"
]
},
"regexManagers": [ "regexManagers": [
{ {
"description": "Process various other dependencies", "description": "Process various other dependencies",
+1 -2
View File
@@ -3,11 +3,10 @@
Thumbs.db Thumbs.db
# k8s # k8s
kubeconfig kubeconfig
# vscode-sops
.decrypted~*.yaml .decrypted~*.yaml
.config.env .config.env
*.agekey *.agekey
*.pub *.pub
*.key *.key
# Ansible # Ansible
xanmanning.k3s* .venv*
+15 -56
View File
@@ -1,95 +1,54 @@
--- ---
version: "3" version: "3"
env:
K8S_AUTH_KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig"
vars: vars:
ANSIBLE_PLAYBOOK_DIR: "{{.ANSIBLE_DIR}}/playbooks" ANSIBLE_PLAYBOOK_DIR: "{{.ANSIBLE_DIR}}/playbooks"
ANSIBLE_INVENTORY_DIR: "{{.ANSIBLE_DIR}}/inventory" ANSIBLE_INVENTORY_DIR: "{{.ANSIBLE_DIR}}/inventory"
tasks: tasks:
deps:
desc: Install / Upgrade Ansible galaxy deps
dir: "{{.ANSIBLE_DIR}}"
cmds:
- pip3 install --user --requirement requirements.txt
- ansible-galaxy install -r requirements.yaml --roles-path ~/.ansible/roles --force
- ansible-galaxy collection install -r requirements.yaml --collections-path ~/.ansible/collections --force
preconditions:
- test -f "{{.ANSIBLE_DIR}}/requirements.txt"
- test -f "{{.ANSIBLE_DIR}}/requirements.yaml"
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
list:
desc: List all the hosts
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --list-hosts
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
prepare: prepare:
desc: Prepare all the k8s nodes for running k3s desc: Prepare all the k8s nodes for running k3s
dir: "{{.ANSIBLE_DIR}}" dir: "{{.ANSIBLE_DIR}}"
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-prepare.yaml cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-prepare.yaml
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
install: install:
desc: Install Kubernetes on the nodes desc: Install Kubernetes on the nodes
dir: "{{.ANSIBLE_DIR}}" dir: "{{.ANSIBLE_DIR}}"
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-installation.yaml cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-installation.yaml
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
rollout-update: rollout-update:
desc: Preform operating system updates and rollout restart the cluster desc: Preform operating system updates and rollout restart the cluster
dir: "{{.ANSIBLE_DIR}}" dir: "{{.ANSIBLE_DIR}}"
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-rollout-update.yaml cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-rollout-update.yaml
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
kube-vip:
desc: Apply new kube-vip configuration to the cluster
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-kube-vip.yaml
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
nuke: nuke:
desc: Uninstall Kubernetes on the nodes desc: Uninstall Kubernetes on the nodes
dir: "{{.ANSIBLE_DIR}}" dir: "{{.ANSIBLE_DIR}}"
interactive: true interactive: true
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-nuke.yaml cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-nuke.yaml
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" reboot:
desc: Reboot all the k8s nodes
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-reboot.yaml
poweroff:
desc: Shutdown all the k8s nodes
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible kubernetes -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml -a '/usr/bin/systemctl poweroff' --become
list:
desc: List all the hosts
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --list-hosts
ping: ping:
desc: Ping all the hosts desc: Ping all the hosts
dir: "{{.ANSIBLE_DIR}}" dir: "{{.ANSIBLE_DIR}}"
cmd: ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --one-line -m 'ping' cmd: ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --one-line -m 'ping'
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
uptime: uptime:
desc: Uptime of all the hosts desc: Uptime of all the hosts
dir: "{{.ANSIBLE_DIR}}" dir: "{{.ANSIBLE_DIR}}"
cmd: ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --one-line -a 'uptime' cmd: ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --one-line -a 'uptime'
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
force-reboot:
desc: Reboot all the k8s nodes
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-reboot.yaml
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
force-poweroff:
desc: Shutdown all the k8s nodes
dir: "{{.ANSIBLE_DIR}}"
cmd: ansible kubernetes -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml -a '/usr/bin/systemctl poweroff' --become
env:
ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg"
-4
View File
@@ -14,16 +14,12 @@ tasks:
vars: vars:
DEPS: >- DEPS: >-
age age
ansible
cilium-cli cilium-cli
cloudflared cloudflared
direnv
fluxcd/tap/flux fluxcd/tap/flux
go-task/tap/go-task
helm helm
kubernetes-cli kubernetes-cli
kustomize kustomize
python
sops sops
stern stern
yq yq
+1 -1
View File
@@ -20,7 +20,7 @@ tasks:
msg: | msg: |
Age key file is not found. Did you forget to create it? Age key file is not found. Did you forget to create it?
vars: vars:
SOPS_AGE_KEY_FILE: ~/.config/sops/age/keys.txt SOPS_AGE_KEY_FILE: "{{.ROOT_DIR}}/age.key"
reconcile: reconcile:
desc: Force update Flux to pull in changes from your Git repository desc: Force update Flux to pull in changes from your Git repository
+33 -32
View File
@@ -99,33 +99,47 @@ According to the documentation [here](https://raspi.debian.net/defaults-and-sett
The very first step will be to create a new **public** repository by clicking the big green **Use this template** button on this page. Next clone **your new repo** to you local workstation and `cd` into it. The very first step will be to create a new **public** repository by clicking the big green **Use this template** button on this page. Next clone **your new repo** to you local workstation and `cd` into it.
📍 _**All of the below commands** are run on your **local** workstation, **not** on any of your cluster nodes._ 📍 _**All commands** are run on your **local** workstation within your repository directory_
## 🔧 Workstation Tools ## 🔧 Workstation Tools
📍 _Install the **most recent version** of the CLI tools below. If you are **having trouble with future steps**, it is very likely you **don't have the most recent version** of these CLI tools. The most troublesome are `ansible`, `go-task`, and `sops`._ Lets get the required workstation tools installed and configured.
1. Install the following CLI tools on your workstation, if you are using [Homebrew](https://brew.sh/) skip this step and move onto 2 & 3. 1. Install the most recent version of [task](https://taskfile.dev/)
- **Required**: [age](https://github.com/FiloSottile/age), [ansible](https://www.ansible.com), [flux](https://toolkit.fluxcd.io/), [cloudflared](https://github.com/cloudflare/cloudflared), [go-task](https://github.com/go-task/task), [direnv](https://github.com/direnv/direnv), [kubectl](https://kubernetes.io/docs/tasks/tools/), [python3](https://www.python.org/), [python-pip3](https://pypi.org/project/pip/), [sops](https://github.com/getsops/sops) 📍 _See the task [installation docs](https://taskfile.dev/installation/) for other platforms_
- **Recommended**: [helm](https://helm.sh/), [kustomize](https://github.com/kubernetes-sigs/kustomize), [stern](https://github.com/stern/stern)
2. [Homebrew] Install [go-task](https://github.com/go-task/task)
```sh ```sh
brew install go-task/tap/go-task # Brew
brew install go-task
``` ```
3. [Homebrew] Install the other workstation dependencies 2. Install the most recent version of [direnv](https://direnv.net/)
📍 _See the direnv [installation docs](https://direnv.net/docs/installation.html) for other platforms_
📍 _After installing `direnv` be sure to [hook it into your shell](https://direnv.net/docs/hook.html) and after that is done run `direnv allow` while in your repos directory._
```sh ```sh
task brew:deps # Brew
brew install direnv
``` ```
## 🌱 Environment 3. Setup a Python virual env and install Ansible by running the following task command.
Next take a moment and configure [direnv](https://direnv.net/). This tool will make it so anytime you `cd` to your repo's directory it export the required environment variables (e.g. `KUBECONFIG`). To set this up make sure you [hook it into your shell](https://direnv.net/docs/hook.html) and after that is done, run `direnv allow` while in your repos directory. 📍 _This commands requires Python 3.8+ to be installed_
```sh
# Platform agnostic
task deps
```
4. Install the required tools: [age](https://github.com/FiloSottile/age), [flux](https://toolkit.fluxcd.io/), [cloudflared](https://github.com/cloudflare/cloudflared), [kubectl](https://kubernetes.io/docs/tasks/tools/), [sops](https://github.com/getsops/sops)
```sh
# Brew
task brew:deps
```
## 📄 Configuration ## 📄 Configuration
@@ -141,20 +155,13 @@ Next take a moment and configure [direnv](https://direnv.net/). This tool will m
📍 _Using [SOPS](https://github.com/getsops/sops) with [Age](https://github.com/FiloSottile/age) allows us to encrypt secrets and use them in Ansible and Flux._ 📍 _Using [SOPS](https://github.com/getsops/sops) with [Age](https://github.com/FiloSottile/age) allows us to encrypt secrets and use them in Ansible and Flux._
2a. Create a Age private / public key 2a. Create a Age private / public key (this file is gitignored)
```sh ```sh
age-keygen -o age.agekey age-keygen -o age.key
``` ```
2b. Create the directory for the Age key and move the Age file to it 2b. Fill out the appropriate vars in `bootstrap/vars/config.yaml`
```sh
mkdir -p ~/.config/sops/age
mv age.agekey ~/.config/sops/age/keys.txt
```
2c. Fill out the appropriate vars in `bootstrap/vars/config.yaml`
3. Create Cloudflare API Token 3. Create Cloudflare API Token
@@ -224,25 +231,19 @@ Next take a moment and configure [direnv](https://direnv.net/). This tool will m
1. Ensure you are able to SSH into your nodes from your workstation using a private SSH key **without a passphrase**. For example using a SSH agent. This is how Ansible is able to connect to your remote nodes. 1. Ensure you are able to SSH into your nodes from your workstation using a private SSH key **without a passphrase**. For example using a SSH agent. This is how Ansible is able to connect to your remote nodes.
2. Install the Ansible deps 2. Verify Ansible can view your config
```sh
task ansible:deps
```
3. Verify Ansible can view your config
```sh ```sh
task ansible:list task ansible:list
``` ```
4. Verify Ansible can ping your nodes 3. Verify Ansible can ping your nodes
```sh ```sh
task ansible:ping task ansible:ping
``` ```
5. Run the Ansible prepare playbook (nodes wil reboot when done) 4. Run the Ansible prepare playbook (nodes wil reboot when done)
```sh ```sh
task ansible:prepare task ansible:prepare
+15 -1
View File
@@ -2,13 +2,19 @@
version: "3" version: "3"
vars: vars:
PYTHON_BIN: python3
BOOTSTRAP_DIR: "{{.ROOT_DIR}}/bootstrap" BOOTSTRAP_DIR: "{{.ROOT_DIR}}/bootstrap"
ANSIBLE_DIR: "{{.ROOT_DIR}}/ansible" ANSIBLE_DIR: "{{.ROOT_DIR}}/ansible"
KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes" KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes"
env: env:
KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig" KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig"
SOPS_AGE_KEY_FILE: ~/.config/sops/age/keys.txt SOPS_AGE_KEY_FILE: "{{.ROOT_DIR}}/age.key"
PATH: "{{.ROOT_DIR}}/.venv/bin:$PATH"
VIRTUAL_ENV: "{{.ROOT_DIR}}/.venv"
ANSIBLE_COLLECTIONS_PATH: "{{.ROOT_DIR}}/.venv/galaxy"
ANSIBLE_ROLES_PATH: "{{.ROOT_DIR}}/.venv/galaxy/ansible_roles"
K8S_AUTH_KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig"
includes: includes:
ansible: .taskfiles/AnsibleTasks.yaml ansible: .taskfiles/AnsibleTasks.yaml
@@ -19,6 +25,14 @@ tasks:
default: task -l default: task -l
deps:
desc: Create a Python virtual env and install required packages
cmds:
- "{{.PYTHON_BIN}} -m venv {{.ROOT_DIR}}/.venv"
- .venv/bin/python3 -m pip install --upgrade pip setuptools wheel
- .venv/bin/python3 -m pip install --upgrade --requirement "{{.ROOT_DIR}}/requirements.txt"
- .venv/bin/ansible-galaxy install --role-file "{{.ROOT_DIR}}/requirements.yaml" --force
init: init:
desc: Initialize configuration files desc: Initialize configuration files
dir: "{{.BOOTSTRAP_DIR}}" dir: "{{.BOOTSTRAP_DIR}}"
+4 -4
View File
@@ -1,18 +1,18 @@
--- ---
- name: Query age key file - name: Query age key file
ansible.builtin.stat: ansible.builtin.stat:
path: ~/.config/sops/age/keys.txt path: "{{ repository_path }}/age.key"
register: result register: result
- name: Check if age key file exists - name: Check if age key file exists
ansible.builtin.assert: ansible.builtin.assert:
that: result.stat.exists that: result.stat.exists
success_msg: Age file ~/.config/sops/age/keys.txt exists success_msg: Age file {{ repository_path }}/age.key exists
fail_msg: Age file ~/.config/sops/age/keys.txt does not exist fail_msg: Age file {{ repository_path }}/age.key does not exist
- name: Query age key file contents - name: Query age key file contents
ansible.builtin.set_fact: ansible.builtin.set_fact:
age_contents: "{{ lookup('file', '~/.config/sops/age/keys.txt') }}" age_contents: "{{ lookup('file', repository_path + '/age.key') }}"
- name: Check if age public keys match - name: Check if age public keys match
ansible.builtin.assert: ansible.builtin.assert:
+1 -1
View File
@@ -2,7 +2,7 @@
- name: Check for required CLI tools - name: Check for required CLI tools
ansible.builtin.shell: | ansible.builtin.shell: |
command -v {{ item }} >/dev/null 2>&1 command -v {{ item }} >/dev/null 2>&1
loop: [age, cloudflared, flux, git, pip3, sops, task] loop: [age, cloudflared, flux, sops]
changed_when: false changed_when: false
check_mode: false check_mode: false
register: result register: result
@@ -1,35 +0,0 @@
[defaults]
# General settings
nocows = True
executable = /bin/bash
stdout_callback = yaml
force_valid_group_names = ignore
# File/Directory settings
log_path = ~/.ansible/ansible.log
inventory = ./inventory
roles_path = ~/.ansible/roles:./roles
collections_path = ~/.ansible/collections
remote_tmp = ~/.ansible/tmp
local_tmp = ~/.ansible/tmp
# Fact Caching settings
fact_caching = jsonfile
fact_caching_connection = ~/.ansible/facts_cache
# SSH settings
remote_port = 22
timeout = 60
host_key_checking = False
# Plugin settings
vars_plugins_enabled = host_group_vars,community.sops.sops
[inventory]
unparsed_is_failed = True
[privilege_escalation]
become = True
[ssh_connection]
scp_if_ssh = smart
retries = 3
ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o Compression=yes -o ServerAliveInterval=15s
pipelining = True
control_path = %(directory)s/%%h-%%r
@@ -41,7 +41,7 @@
- name: Drain - name: Drain
ansible.builtin.command: "kubectl drain --ignore-daemonsets --delete-emptydir-data --force {% raw %}{{ inventory_hostname }}{% endraw %}" ansible.builtin.command: "kubectl drain --ignore-daemonsets --delete-emptydir-data --force {% raw %}{{ inventory_hostname }}{% endraw %}"
delegate_to: "{{ groups['master'][0] }}" delegate_to: "{% raw %}{{ groups['master'][0] }}{% endraw %}"
changed_when: false changed_when: false
- name: Update - name: Update
@@ -1 +0,0 @@
openshift==0.13.1
+6
View File
@@ -0,0 +1,6 @@
ansible==8.2.0
ansible-lint==6.17.2
bcrypt==4.0.1
netaddr==0.8.0
openshift==0.13.1
passlib==1.7.4
@@ -12,5 +12,4 @@ collections:
version: 2.4.0 version: 2.4.0
roles: roles:
- name: xanmanning.k3s - name: xanmanning.k3s
src: https://github.com/PyratLabs/ansible-role-k3s.git
version: v3.4.2 version: v3.4.2