From 7a33a394abcb39dce9e0e78fd705de09d602c926 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Wed, 8 Apr 2026 19:39:31 +0300 Subject: [PATCH 1/8] add terraform definitions of k8s nodes --- .gitignore | 6 +++++- .terraform.lock.hcl | 46 +++++++++++++++++++++++++++++++++++++++ main.tf | 47 ++++++++++++++++++++++++++++++++++++++++ modules/vm/main.tf | 48 +++++++++++++++++++++++++++++++++++++++++ modules/vm/terraform.tf | 13 +++++++++++ modules/vm/variables.tf | 27 +++++++++++++++++++++++ terraform.tf | 13 +++++++++++ 7 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 .terraform.lock.hcl create mode 100644 main.tf create mode 100644 modules/vm/main.tf create mode 100644 modules/vm/terraform.tf create mode 100644 modules/vm/variables.tf create mode 100644 terraform.tf diff --git a/.gitignore b/.gitignore index f04484f..4977619 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,8 @@ .venv/ .ansible/ .ansible_vault.pass -.secrets/ \ No newline at end of file +.secrets/ +.terraform/ +secrets.tfvars +*.tfstate +*.tfstate.* diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..ee2203e --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,46 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/bpg/proxmox" { + version = "0.100.0" + constraints = "0.100.0" + hashes = [ + "h1:ubWt5DGEISEVYd1xWrNBS6BmNHOj5nlUcBqxd0Fo2Dg=", + "zh:1a00788132ce14f97131c3e606a6bbbb9f656cf3aabd919380dde2e02d7c849d", + "zh:1a07e0cb29983d5dc7ed77d86816caf567a2b3fd63e900473e15f31107b82780", + "zh:1b02d824b13a4cc1cc404c29dd904d2ea9019c341461462e790b8e81e3a25345", + "zh:2100de25322ed027792cf9a0fdb4d43285d6d829bf48adf1846b4af7eb2c408f", + "zh:30a37beaf6a7d2438413d5a37c2937ab2961f2d514892d6e4f7acb71c4919683", + "zh:30bc3cd9a3402f6b20f92f8bb01928a44dc2ea20ce78ef52c79e5cf2ca727758", + "zh:68ee24eff994318d0b018000d0ae63d851daf51462682c692b84bff0aaa4d468", + "zh:6a202d7cf9c4511846084126f2b56111744354009dc89c9fc0c7a79062e8a5da", + "zh:7417bb2f1d7a96e2f6feb1f8d02c6443ba6833be325b90f742fe0635ff2230bd", + "zh:77c9559016c444df8972ca5f0947d45ef0b67abff25f4b98dec67ab8c42793aa", + "zh:b3ac0fc97c80e13039e6cb1df0878caf6a578febde2db740720486fb8cfaa1d0", + "zh:c8c85043c2a9e30c8f9a2318ce84f871962a72a32e2726e5df0ccd0e3d51e7c4", + "zh:cc2626d95ef69c09602ad526bfda9045f36fac296248fb3fd482b72ed4a984b7", + "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", + ] +} + +provider "registry.terraform.io/orfops/openwrt" { + version = "0.1.29" + constraints = "0.1.29" + hashes = [ + "h1:oD2tV3XSfNb0pOiYZX6kCshhGu1f7V+NYlVkPOr/Efo=", + "zh:1aa757c6907ccbdc7987d830191be2b643a85456112b8fa1724ae0e64ba40d7c", + "zh:4b895cfd6d8fc4af9949cbff93cbb3f467765b61221479f1673e65e4f9ef797a", + "zh:50532fc3730f0a9eeb3d761967ae026f75b0a50d360b197d6f871bbb917b4361", + "zh:512dd28fe0f9bd05d7bab47aded49fed5b92af020f1714fd8df768323685adf3", + "zh:71aff3cea677379e882b366bf56338f491aa44b9bf5a3d8dfde24e42eb140797", + "zh:74ce6cb5fececdddbc2b8d5d3c5fcf73ac14d1d6dd7c9d1eef5a9ac6c48b2919", + "zh:77b0e1bb0db33dd02b3856500be10c8377331fb1ee49687d452fc3c62283f58e", + "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", + "zh:90af344a3d00d07d8b9190b007de27e967ae83fc81ab315cdb776dd0642f4146", + "zh:97a20485582712b597b6de2081f2b2d7aba6be149f9af0cff88e0d50f36f5fd3", + "zh:b62ff3269d164c55ff3cd7c440a77280b82103a48182573bd0c93831084b6562", + "zh:dff396fd2dc25d01e11b4d75bb315c6e127d65795cc3a3852d14b30ffbd73f64", + "zh:f484b6c64201b93053175dae5a9e8e27948a9a87020d82047f81183d44df11e6", + "zh:fa7bc64f0515424e18b51a97e6c316d9ccc227bcf9ee0987ac4ac928ba06f55d", + ] +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..a91a6f3 --- /dev/null +++ b/main.tf @@ -0,0 +1,47 @@ +variable "pve_token" { + type = string + sensitive = true + ephemeral = true +} + +variable "openwrt_password" { + type = string + sensitive = true + ephemeral = true +} + +provider "proxmox" { + endpoint = "https://nas.home.shduo.ru:8006/api2/json" + insecure = true + api_token = var.pve_token +} + +provider "openwrt" { + hostname = "gw.home.shduo.ru" + username = "root" + password = var.openwrt_password +} + +module "kube_master1" { + source = "./modules/vm" + + name = "kube-master1" + node = "nas" + vm_id = 101 + template_id = 9001 + cpu_cores = 2 + memory = 2048 + ip_cidr = "10.19.1.21/24" +} + +module "kube_node1" { + source = "./modules/vm" + + name = "kube-node1" + node = "nas" + vm_id = 201 + template_id = 9001 + cpu_cores = 2 + memory = 2048 + ip_cidr = "10.19.1.31/24" +} diff --git a/modules/vm/main.tf b/modules/vm/main.tf new file mode 100644 index 0000000..17257ae --- /dev/null +++ b/modules/vm/main.tf @@ -0,0 +1,48 @@ +resource "openwrt_dhcp_domain" "dns" { + name = var.name + ip = split("/", var.ip_cidr)[0] +} + +resource "proxmox_virtual_environment_vm" "vm" { + name = var.name + node_name = var.node + vm_id = var.vm_id + + clone { + vm_id = var.template_id + full = false + } + + cpu { + cores = var.cpu_cores + type = "x86-64-v2-AES" + } + + memory { + dedicated = var.memory + floating = var.memory + } + + network_device { + bridge = "vmbr0" + } + + initialization { + dns { + domain = "home.shduo.ru" + servers = ["10.19.1.1"] + } + + ip_config { + ipv4 { + address = var.ip_cidr + gateway = "10.19.1.1" + } + } + + user_account { + username = "deploy" + keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIZak62dHFoQL3Co/XYs8SC6Lc/FnCT8xOiHu2SJAWO"] + } + } +} diff --git a/modules/vm/terraform.tf b/modules/vm/terraform.tf new file mode 100644 index 0000000..6de14a4 --- /dev/null +++ b/modules/vm/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.100.0" + } + + openwrt = { + source = "ORFops/openwrt" + version = "0.1.29" + } + } +} diff --git a/modules/vm/variables.tf b/modules/vm/variables.tf new file mode 100644 index 0000000..b4347f0 --- /dev/null +++ b/modules/vm/variables.tf @@ -0,0 +1,27 @@ +variable "name" { + type = string +} + +variable "node" { + type = string +} + +variable "vm_id" { + type = number +} + +variable "template_id" { + type = number +} + +variable "cpu_cores" { + type = number +} + +variable "memory" { + type = number +} + +variable "ip_cidr" { + type = string +} diff --git a/terraform.tf b/terraform.tf new file mode 100644 index 0000000..2772696 --- /dev/null +++ b/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.100.0" + } + + openwrt = { + source = "ORFops/openwrt" + version = "0.1.29" + } + } +} \ No newline at end of file From d04698dbb5ba8bd2797deb6282e0936f729dca47 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Sun, 12 Apr 2026 17:03:40 +0300 Subject: [PATCH 2/8] add bareboned k8d cluster provisioning --- ansible.cfg | 2 +- group_vars/k8s.yaml | 4 + inventory.yaml | 9 ++ main.tf | 9 +- playbooks/k8s.yaml | 5 + roles/k8s/defaults/main.yaml | 9 ++ roles/k8s/handlers/main.yaml | 14 ++ roles/k8s/tasks/main.yaml | 219 +++++++++++++++++++++++++++ roles/k8s/templates/kube-vip.yaml.j2 | 72 +++++++++ roles/pve/defaults/main.yaml | 6 +- roles/pve/tasks/main.yaml | 20 +-- 11 files changed, 344 insertions(+), 25 deletions(-) create mode 100644 group_vars/k8s.yaml create mode 100644 playbooks/k8s.yaml create mode 100644 roles/k8s/defaults/main.yaml create mode 100644 roles/k8s/handlers/main.yaml create mode 100644 roles/k8s/tasks/main.yaml create mode 100644 roles/k8s/templates/kube-vip.yaml.j2 diff --git a/ansible.cfg b/ansible.cfg index a5b825d..d7d65ea 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -328,7 +328,7 @@ vault_password_file=.ansible_vault.pass # (boolean) Set this to "False" if you want to avoid host key checking by the underlying connection plugin Ansible uses to connect to the host. # Please read the documentation of the specific connection plugin used for details. -;host_key_checking=True +host_key_checking=False # (boolean) Facts are available inside the `ansible_facts` variable, this setting also pushes them as their own vars in the main namespace. # Unlike inside the `ansible_facts` dictionary where the prefix `ansible_` is removed from fact names, these will have the exact names that are returned by the module. diff --git a/group_vars/k8s.yaml b/group_vars/k8s.yaml new file mode 100644 index 0000000..a664707 --- /dev/null +++ b/group_vars/k8s.yaml @@ -0,0 +1,4 @@ +--- +k8s_endpoint: kube-master +k8s_vip_interface: eth0 +k8s_vip_address: 10.19.1.20 diff --git a/inventory.yaml b/inventory.yaml index 7a49416..0490f26 100644 --- a/inventory.yaml +++ b/inventory.yaml @@ -1,3 +1,12 @@ pve: hosts: nas: + +k8s: + children: + k8s_master: + hosts: + kube-master1: + k8s_worker: + hosts: + kube-node1: diff --git a/main.tf b/main.tf index a91a6f3..49e4b8c 100644 --- a/main.tf +++ b/main.tf @@ -22,6 +22,11 @@ provider "openwrt" { password = var.openwrt_password } +resource "openwrt_dhcp_domain" "kube_master" { + name = "kube-master" + ip = "10.19.1.20" +} + module "kube_master1" { source = "./modules/vm" @@ -41,7 +46,7 @@ module "kube_node1" { node = "nas" vm_id = 201 template_id = 9001 - cpu_cores = 2 - memory = 2048 + cpu_cores = 8 + memory = 8192 ip_cidr = "10.19.1.31/24" } diff --git a/playbooks/k8s.yaml b/playbooks/k8s.yaml new file mode 100644 index 0000000..6740c64 --- /dev/null +++ b/playbooks/k8s.yaml @@ -0,0 +1,5 @@ +--- +- name: Apply Kubernetes nodes + hosts: k8s + roles: + - k8s diff --git a/roles/k8s/defaults/main.yaml b/roles/k8s/defaults/main.yaml new file mode 100644 index 0000000..72c0da9 --- /dev/null +++ b/roles/k8s/defaults/main.yaml @@ -0,0 +1,9 @@ +--- +k8s_master_group: k8s_master +k8s_worker_group: k8s_worker +k8s_endpoint: "" +k8s_pre_init: false +k8s_master_node_ready: false +k8s_any_master_ready: false +k8s_first_master: "" +k8s_node_joined: false diff --git a/roles/k8s/handlers/main.yaml b/roles/k8s/handlers/main.yaml new file mode 100644 index 0000000..f94ac67 --- /dev/null +++ b/roles/k8s/handlers/main.yaml @@ -0,0 +1,14 @@ +--- +- name: Restart containerd + become: true + ansible.builtin.systemd_service: + name: containerd + state: restarted + +- name: Rebalance coredns + become: true + ansible.builtin.command: + cmd: kubectl --kubeconfig /etc/kubernetes/admin.conf -n kube-system rollout restart deployment coredns + changed_when: true + delegate_to: "{{ k8s_first_master }}" + run_once: true diff --git a/roles/k8s/tasks/main.yaml b/roles/k8s/tasks/main.yaml new file mode 100644 index 0000000..7e72d33 --- /dev/null +++ b/roles/k8s/tasks/main.yaml @@ -0,0 +1,219 @@ +--- +- name: Enable IP forwarding + become: true + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: "1" + sysctl_set: true + state: present + reload: true + +- name: Install containerd + become: true + block: + - name: Add Docker repository + ansible.builtin.yum_repository: + name: docker-ce-stable + description: Docker CE Stable - $basearch + baseurl: https://download.docker.com/linux/rhel/$releasever/$basearch/stable + gpgcheck: true + gpgkey: https://download.docker.com/linux/rhel/gpg + state: present + + - name: Install contrainerd package + ansible.builtin.dnf: + name: containerd.io + state: present + + - name: Remove cri from disabled plugins + ansible.builtin.lineinfile: + path: /etc/containerd/config.toml + regexp: "^disabled_plugins" + state: absent + notify: Restart containerd + + - name: Enable and start containerd service + ansible.builtin.systemd_service: + name: containerd + state: started + enabled: true + + - name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Install Kubernetes packages + become: true + block: + - name: Set SELinux to permissive mode + ansible.posix.selinux: + policy: targeted + state: permissive + + - name: Add Kubernetes repository + ansible.builtin.yum_repository: + name: kubernetes + description: Kubernetes + baseurl: https://pkgs.k8s.io/core:/stable:/v1.35/rpm/ + gpgcheck: true + gpgkey: https://pkgs.k8s.io/core:/stable:/v1.35/rpm/repodata/repomd.xml.key + exclude: + - kubelet + - kubeadm + - kubectl + - cri-tools + - kubernetes-cni + state: present + + - name: Install Kubernetes packages + ansible.builtin.dnf: + name: + - kubelet + - kubeadm + - kubectl + disable_excludes: kubernetes + state: present + +- name: Install additional packages + become: true + block: + - name: Install EPEL repository + ansible.builtin.dnf: + name: + - epel-release + state: present + + - name: Install packages + ansible.builtin.dnf: + name: + - helm3 + - python3-kubernetes + - python3-cryptography + state: present + +- name: Check Kubernetes status + become: true + any_errors_fatal: true + block: + - name: Check kubeconfig presence + when: k8s_master_group in group_names + ansible.builtin.stat: + path: /etc/kubernetes/admin.conf + register: k8s_kubeconfig + + - name: Set node configured + when: k8s_master_group in group_names + ansible.builtin.set_fact: + k8s_master_node_ready: "{{ k8s_kubeconfig.stat.exists }}" + + - name: Check if any master is configured + ansible.builtin.set_fact: + k8s_any_master_ready: "{{ groups[k8s_master_group] | map('extract', hostvars, 'k8s_master_node_ready') is any }}" + + - name: Choose first master + ansible.builtin.set_fact: + k8s_first_master: >- + {{ k8s_any_master_ready | ternary( + groups[k8s_master_group] | map('extract', hostvars) | selectattr('k8s_master_node_ready') | map(attribute='inventory_hostname') | first, + groups[k8s_master_group] | first + ) }} + +- name: Provision first master node + become: true + when: inventory_hostname == k8s_first_master and not k8s_any_master_ready + any_errors_fatal: true + block: + - name: Prepare initial kube-vip manifest + vars: + k8s_pre_init: true + ansible.builtin.template: + src: kube-vip.yaml.j2 + dest: /etc/kubernetes/manifests/kube-vip.yaml + mode: "0644" + + - name: Init Kubernetes first master + ansible.builtin.command: + cmd: kubeadm init --control-plane-endpoint {{ k8s_endpoint }}:6443 + creates: /etc/kubernetes/admin.conf + +- name: Wait for API to be up + ansible.builtin.wait_for: + host: "{{ k8s_endpoint }}" + port: 6443 + state: started + +- name: Install initial addons + become: true + when: k8s_master_group in group_names + any_errors_fatal: true + block: + - name: Prepare kube-vip manifest + ansible.builtin.template: + src: kube-vip.yaml.j2 + dest: /etc/kubernetes/manifests/kube-vip.yaml + mode: "0644" + + - name: Install Cilium + when: inventory_hostname == k8s_first_master + kubernetes.core.helm: + binary_path: helm3 + kubeconfig: /etc/kubernetes/admin.conf + name: cilium + chart_ref: oci://quay.io/cilium/charts/cilium + chart_version: "1.19.2" + namespace: kube-system + +- name: Get node status + become: true + any_errors_fatal: true + block: + - name: Get node list + when: inventory_hostname == k8s_first_master + kubernetes.core.k8s_info: + kubeconfig: /etc/kubernetes/admin.conf + kind: Node + register: k8s_node + + - name: Set node vars + ansible.builtin.set_fact: + k8s_node_joined: "{{ hostvars[k8s_first_master].k8s_node.resources | map(attribute='metadata.name') is contains(ansible_facts['fqdn']) }}" + + - name: Set any not joined + ansible.builtin.set_fact: + k8s_any_node_not_joined: "{{ not ansible_play_hosts | map('extract', hostvars, 'k8s_node_joined') is all }}" + + - name: Debug + ansible.builtin.debug: + msg: "joined={{ k8s_node_joined }} anyleft={{ k8s_any_node_not_joined }}" + +- name: Get join credentials + become: true + when: k8s_any_node_not_joined + any_errors_fatal: true + block: + - name: Get join token + when: inventory_hostname == k8s_first_master + ansible.builtin.command: + cmd: kubeadm token list -o jsonpath={.token} + changed_when: false + register: k8s_join_token_result + + - name: Get discovery token CA cert + when: inventory_hostname == k8s_first_master + community.crypto.x509_certificate_info: + path: /etc/kubernetes/pki/ca.crt + register: k8s_ca_cert_result + + - name: Save tokens + ansible.builtin.set_fact: + k8s_join_token: "{{ hostvars[k8s_first_master].k8s_join_token_result.stdout }}" + k8s_discovery_token_ca_cert_hash: "{{ hostvars[k8s_first_master].k8s_ca_cert_result.public_key_fingerprints.sha256 | replace(':', '') }}" + +- name: Provision Kubernetes worker nodes + become: true + when: not k8s_node_joined + block: + - name: Join cluster + ansible.builtin.command: + cmd: kubeadm join --token {{ k8s_join_token }} {{ k8s_endpoint }}:6443 --discovery-token-ca-cert-hash sha256:{{ k8s_discovery_token_ca_cert_hash }} + changed_when: true + notify: Rebalance coredns diff --git a/roles/k8s/templates/kube-vip.yaml.j2 b/roles/k8s/templates/kube-vip.yaml.j2 new file mode 100644 index 0000000..6b66baa --- /dev/null +++ b/roles/k8s/templates/kube-vip.yaml.j2 @@ -0,0 +1,72 @@ +apiVersion: v1 +kind: Pod +metadata: + name: kube-vip + namespace: kube-system +spec: + containers: + - args: + - manager + env: + - name: vip_arp + value: "true" + - name: port + value: "6443" + - name: vip_nodename + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: vip_interface + value: {{ k8s_vip_interface }} + - name: vip_subnet + value: "32" + - name: dns_mode + value: first + - name: dhcp_mode + value: ipv4 + - name: cp_enable + value: "true" + - name: cp_namespace + value: kube-system + - name: svc_enable + value: "true" + - name: svc_leasename + value: plndr-svcs-lock + - name: vip_leaderelection + value: "true" + - name: vip_leasename + value: plndr-cp-lock + - name: vip_leaseduration + value: "15" + - name: vip_renewdeadline + value: "10" + - name: vip_retryperiod + value: "2" + - name: address + value: {{ k8s_vip_address }} + - name: prometheus_server + value: :2112 + image: ghcr.io/kube-vip/kube-vip:v1.1.2 + imagePullPolicy: IfNotPresent + name: kube-vip + resources: {} + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + drop: + - ALL + volumeMounts: + - mountPath: /etc/kubernetes/admin.conf + name: kubeconfig + hostAliases: + - hostnames: + - kubernetes + ip: 127.0.0.1 + hostNetwork: true + volumes: + - hostPath: + path: {{ '/etc/kubernetes/super-admin.conf' if k8s_pre_init else '/etc/kubernetes/admin.conf' }} + name: kubeconfig +status: {} diff --git a/roles/pve/defaults/main.yaml b/roles/pve/defaults/main.yaml index b1185db..0ed145e 100644 --- a/roles/pve/defaults/main.yaml +++ b/roles/pve/defaults/main.yaml @@ -1,7 +1,7 @@ --- pve_vm_images: - - name: almalinux-10 + - name: almalinux-9 vmid: 9001 - template: AlmaLinux-10-GenericCloud-latest.x86_64_v2.qcow2 - url: https://repo.almalinux.org/almalinux/10/cloud/x86_64_v2/images/AlmaLinux-10-GenericCloud-latest.x86_64_v2.qcow2 + template: AlmaLinux-9-GenericCloud-latest.x86_64.qcow2 + url: https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2 diff --git a/roles/pve/tasks/main.yaml b/roles/pve/tasks/main.yaml index fdf0b1b..74a5b04 100644 --- a/roles/pve/tasks/main.yaml +++ b/roles/pve/tasks/main.yaml @@ -170,27 +170,9 @@ url: "{{ item.url }}" state: present delegate_to: localhost + timeout: 300 loop: "{{ pve_vm_images }}" - # - name: Get current template VM status - # community.proxmox.proxmox_kvm: - # api_host: "{{ inventory_hostname }}" - # api_user: "{{ deploy_user }}@pve" - # api_token_id: deploy - # api_token_secret: "{{ pve_deploy_token }}" - # validate_certs: false - # node: "{{ inventory_hostname }}" - # vmid: "{{ item.vmid }}" - # state: current - # delegate_to: localhost - # loop: "{{ pve_vm_images }}" - # ignore_errors: true - # register: pve_template_vm_status - - # - name: Print result - # ansible.builtin.debug: - # var: pve_template_vm_status - - name: Create QEMU template VM community.proxmox.proxmox_kvm: api_host: "{{ inventory_hostname }}" From f11ba68355e295ab70ddb15a8845b3a9d78fca01 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Tue, 14 Apr 2026 15:55:58 +0300 Subject: [PATCH 3/8] add flux cd test config --- .sourceignore | 3 +++ clusters/staging/test.yaml | 25 +++++++++++++++++++++++ group_vars/k8s.yaml | 3 +++ roles/k8s/defaults/main.yaml | 3 +++ roles/k8s/tasks/main.yaml | 24 ++++++++++++++++++++++ roles/k8s/templates/flux-instance.yaml.j2 | 18 ++++++++++++++++ 6 files changed, 76 insertions(+) create mode 100644 .sourceignore create mode 100644 clusters/staging/test.yaml create mode 100644 roles/k8s/templates/flux-instance.yaml.j2 diff --git a/.sourceignore b/.sourceignore new file mode 100644 index 0000000..c82b36e --- /dev/null +++ b/.sourceignore @@ -0,0 +1,3 @@ +/* + +!/clusters/ \ No newline at end of file diff --git a/clusters/staging/test.yaml b/clusters/staging/test.yaml new file mode 100644 index 0000000..4f9fd0f --- /dev/null +++ b/clusters/staging/test.yaml @@ -0,0 +1,25 @@ +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: podinfo + namespace: default +spec: + interval: 5m + url: https://github.com/stefanprodan/podinfo + ref: + branch: master +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: podinfo + namespace: default +spec: + interval: 10m + targetNamespace: default + sourceRef: + kind: GitRepository + name: podinfo + path: "./kustomize" + prune: true + timeout: 1m diff --git a/group_vars/k8s.yaml b/group_vars/k8s.yaml index a664707..16cb4ad 100644 --- a/group_vars/k8s.yaml +++ b/group_vars/k8s.yaml @@ -2,3 +2,6 @@ k8s_endpoint: kube-master k8s_vip_interface: eth0 k8s_vip_address: 10.19.1.20 +k8s_flux_sync_repo: "https://github.com/MilkyCode13/infra.git" +k8s_flux_sync_ref: refs/heads/k8s-cluster +k8s_flux_sync_path: clusters/staging diff --git a/roles/k8s/defaults/main.yaml b/roles/k8s/defaults/main.yaml index 72c0da9..1522225 100644 --- a/roles/k8s/defaults/main.yaml +++ b/roles/k8s/defaults/main.yaml @@ -7,3 +7,6 @@ k8s_master_node_ready: false k8s_any_master_ready: false k8s_first_master: "" k8s_node_joined: false +k8s_flux_sync_repo: "https://github.com/MilkyCode13/infra.git" +k8s_flux_sync_ref: refs/heads/main +k8s_flux_sync_path: clusters/default diff --git a/roles/k8s/tasks/main.yaml b/roles/k8s/tasks/main.yaml index 7e72d33..e40d2e3 100644 --- a/roles/k8s/tasks/main.yaml +++ b/roles/k8s/tasks/main.yaml @@ -217,3 +217,27 @@ cmd: kubeadm join --token {{ k8s_join_token }} {{ k8s_endpoint }}:6443 --discovery-token-ca-cert-hash sha256:{{ k8s_discovery_token_ca_cert_hash }} changed_when: true notify: Rebalance coredns + +- name: Install Flux CD + become: true + block: + - name: Install Flux Operator + when: inventory_hostname == k8s_first_master + kubernetes.core.helm: + binary_path: helm3 + kubeconfig: /etc/kubernetes/admin.conf + name: flux-operator + chart_ref: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator + chart_version: "0.46.0" + namespace: flux-system + create_namespace: true + values: + web: + enabled: false + + - name: Add Flux Instance + when: inventory_hostname == k8s_first_master + kubernetes.core.k8s: + kubeconfig: /etc/kubernetes/admin.conf + template: flux-instance.yaml.j2 + state: present diff --git a/roles/k8s/templates/flux-instance.yaml.j2 b/roles/k8s/templates/flux-instance.yaml.j2 new file mode 100644 index 0000000..4dd3cb1 --- /dev/null +++ b/roles/k8s/templates/flux-instance.yaml.j2 @@ -0,0 +1,18 @@ +apiVersion: fluxcd.controlplane.io/v1 +kind: FluxInstance +metadata: + name: flux + namespace: flux-system +spec: + distribution: + version: "2.8.x" + registry: "ghcr.io/fluxcd" + artifact: "oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests" + cluster: + type: kubernetes + size: small + sync: + kind: GitRepository + url: "{{ k8s_flux_sync_repo }}" + ref: {{ k8s_flux_sync_ref }} + path: {{ k8s_flux_sync_path }} From 560ad9349fa62fb83123c520b78087290ab12fe7 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Thu, 16 Apr 2026 22:46:32 +0300 Subject: [PATCH 4/8] add flux artifact publishing --- .github/workflows/test.yaml | 22 ++++++++++++++++++++++ main.tf | 4 ++-- roles/k8s/tasks/main.yaml | 7 +++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index bf7daef..b086867 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -16,3 +16,25 @@ jobs: env: ANSIBLE_VAULT_PASSWORD: ${{ secrets.ANSIBLE_VAULT_PASSWORD }} - run: ansible-lint + + publish-flux-artifact: + name: Publish Flux Artifact + runs-on: ubuntu-latest + needs: lint + steps: + - uses: actions/checkout@v5 + - uses: fluxcd/flux2/action@main + - name: Log in to registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + - name: Push artifact + run: | + flux push artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) \ + --path="." \ + --source="$(git config --get remote.origin.url)" \ + --revision="$(git branch --show-current)@sha1:$(git rev-parse HEAD)" + - name: Tag staging + run: flux tag artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) --tag staging + - name: Tag latest + if: github.ref_name == 'main' + run: flux tag artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) --tag latest + diff --git a/main.tf b/main.tf index 49e4b8c..12ee389 100644 --- a/main.tf +++ b/main.tf @@ -34,8 +34,8 @@ module "kube_master1" { node = "nas" vm_id = 101 template_id = 9001 - cpu_cores = 2 - memory = 2048 + cpu_cores = 4 + memory = 4096 ip_cidr = "10.19.1.21/24" } diff --git a/roles/k8s/tasks/main.yaml b/roles/k8s/tasks/main.yaml index e40d2e3..17e70bc 100644 --- a/roles/k8s/tasks/main.yaml +++ b/roles/k8s/tasks/main.yaml @@ -152,6 +152,13 @@ dest: /etc/kubernetes/manifests/kube-vip.yaml mode: "0644" + - name: Wait for API to be up + ansible.builtin.wait_for: + host: "{{ k8s_endpoint }}" + port: 6443 + state: started + delay: 5 + - name: Install Cilium when: inventory_hostname == k8s_first_master kubernetes.core.helm: From a2917a0e40ef4dbfdb24f2ec9b1a2b82f768e529 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Thu, 16 Apr 2026 22:52:04 +0300 Subject: [PATCH 5/8] fix workflow file --- .github/workflows/test.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b086867..15decac 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -37,4 +37,3 @@ jobs: - name: Tag latest if: github.ref_name == 'main' run: flux tag artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) --tag latest - From ed6f250ab02b96e4974574d28033f9732ea960b4 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Thu, 16 Apr 2026 23:14:04 +0300 Subject: [PATCH 6/8] fix oci url --- .github/workflows/test.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 15decac..6a0d991 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -28,12 +28,12 @@ jobs: run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - name: Push artifact run: | - flux push artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) \ + flux push artifact oci://ghcr.io/milkycode13/manifests/infra:$(git rev-parse --short HEAD) \ --path="." \ --source="$(git config --get remote.origin.url)" \ --revision="$(git branch --show-current)@sha1:$(git rev-parse HEAD)" - name: Tag staging - run: flux tag artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) --tag staging + run: flux tag artifact oci://ghcr.io/milkycode13/manifests/infra:$(git rev-parse --short HEAD) --tag staging - name: Tag latest if: github.ref_name == 'main' - run: flux tag artifact oci://ghcr.io/MilkyCode13/manifests/infra:$(git rev-parse --short HEAD) --tag latest + run: flux tag artifact oci://ghcr.io/milkycode13/manifests/infra:$(git rev-parse --short HEAD) --tag latest From 0cd22be0ffe6fe1688c49f566aa4adc3e80f0d34 Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Thu, 16 Apr 2026 23:17:23 +0300 Subject: [PATCH 7/8] fix job token permissions --- .github/workflows/test.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 6a0d991..d9b1050 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,6 +21,9 @@ jobs: name: Publish Flux Artifact runs-on: ubuntu-latest needs: lint + permissions: + contents: read + packages: write steps: - uses: actions/checkout@v5 - uses: fluxcd/flux2/action@main From c1164da1005aec52c0f8d10420c683ce9ce76c8b Mon Sep 17 00:00:00 2001 From: MilkyCode13 Date: Thu, 16 Apr 2026 23:38:57 +0300 Subject: [PATCH 8/8] switch to oci repository & fix kubernetes playbook --- group_vars/k8s.yaml | 5 +++-- roles/k8s/defaults/main.yaml | 1 + roles/k8s/tasks/main.yaml | 7 +++++++ roles/k8s/templates/flux-instance.yaml.j2 | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/group_vars/k8s.yaml b/group_vars/k8s.yaml index 16cb4ad..61c038b 100644 --- a/group_vars/k8s.yaml +++ b/group_vars/k8s.yaml @@ -2,6 +2,7 @@ k8s_endpoint: kube-master k8s_vip_interface: eth0 k8s_vip_address: 10.19.1.20 -k8s_flux_sync_repo: "https://github.com/MilkyCode13/infra.git" -k8s_flux_sync_ref: refs/heads/k8s-cluster +k8s_flux_sync_kind: OCIRepository +k8s_flux_sync_repo: "oci://ghcr.io/milkycode13/manifests/infra" +k8s_flux_sync_ref: staging k8s_flux_sync_path: clusters/staging diff --git a/roles/k8s/defaults/main.yaml b/roles/k8s/defaults/main.yaml index 1522225..9a9eb4f 100644 --- a/roles/k8s/defaults/main.yaml +++ b/roles/k8s/defaults/main.yaml @@ -7,6 +7,7 @@ k8s_master_node_ready: false k8s_any_master_ready: false k8s_first_master: "" k8s_node_joined: false +k8s_flux_sync_kind: GitRepository k8s_flux_sync_repo: "https://github.com/MilkyCode13/infra.git" k8s_flux_sync_ref: refs/heads/main k8s_flux_sync_path: clusters/default diff --git a/roles/k8s/tasks/main.yaml b/roles/k8s/tasks/main.yaml index 17e70bc..c2ec60a 100644 --- a/roles/k8s/tasks/main.yaml +++ b/roles/k8s/tasks/main.yaml @@ -73,6 +73,13 @@ disable_excludes: kubernetes state: present + - name: Enable kubelet + become: true + ansible.builtin.systemd_service: + name: kubelet + state: started + enabled: true + - name: Install additional packages become: true block: diff --git a/roles/k8s/templates/flux-instance.yaml.j2 b/roles/k8s/templates/flux-instance.yaml.j2 index 4dd3cb1..d7f8007 100644 --- a/roles/k8s/templates/flux-instance.yaml.j2 +++ b/roles/k8s/templates/flux-instance.yaml.j2 @@ -12,7 +12,7 @@ spec: type: kubernetes size: small sync: - kind: GitRepository + kind: {{ k8s_flux_sync_kind }} url: "{{ k8s_flux_sync_repo }}" ref: {{ k8s_flux_sync_ref }} path: {{ k8s_flux_sync_path }}