diff --git a/.ansible-lint b/.ansible-lint index 85ecfa1..95e5f2b 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,6 +1,10 @@ skip_list: - risky-file-permissions - var-naming[no-role-prefix] + - yaml[indentation] + - run-once[task] + - no-changed-when + - partial-become[task] exclude_paths: - ansible/roles/haproxy_static_pods/files/haproxy.yaml diff --git a/ansible/inventory.yml b/ansible/inventory.yml index dfa6176..e855288 100644 --- a/ansible/inventory.yml +++ b/ansible/inventory.yml @@ -3,27 +3,19 @@ kubeadm: kubeadm_control_plane: hosts: kubeadm-cp-01: - ansible_host: 10.0.70.70 + ansible_host: 10.0.75.81 kubeadm-cp-02: - ansible_host: 10.0.70.78 + ansible_host: 10.0.75.82 kubeadm-cp-03: - ansible_host: 10.0.70.79 + ansible_host: 10.0.75.83 kubeadm_nodes: hosts: kubeadm-node-01: - ansible_host: 10.0.70.71 + ansible_host: 10.0.75.84 kubeadm-node-02: - ansible_host: 10.0.70.77 + ansible_host: 10.0.75.85 kubeadm-node-03: - ansible_host: 10.0.70.74 - vars: - ansible_user: infra - ansible_port: 22 - -test_hosts: - hosts: - kubeadm-cp-01: - ansible_host: 10.0.75.203 + ansible_host: 10.0.75.86 vars: ansible_user: infra ansible_port: 22 diff --git a/ansible/kubeadm.yml b/ansible/kubeadm.yml index 4e42e0a..70faf45 100644 --- a/ansible/kubeadm.yml +++ b/ansible/kubeadm.yml @@ -1,44 +1,29 @@ -# Запустите сервисы как статические подсистемы -# https://github.com/kubernetes/kubeadm/blob/main/docs/ha-considerations.md#option-2-run-the-services-as-static-pods -- name: Настраиваю keepalived + haproxy - become: true - hosts: - - kubeadm_control_plane - roles: - - haproxy_static_pods - -- name: Разворачиваю kubernetes кластер +# Подготовка к запуску Kubernetes кластера +- name: Подготоваливаю узлы для kubernetes кластера become: true hosts: - kubeadm - handlers: - - name: Перезагружаю виртуальные машины - ansible.builtin.reboot: tasks: - name: Добавляю модули br_netfilter и overlay community.general.modprobe: - name: '{{ item }}' + name: "{{ item }}" state: present with_items: - br_netfilter - overlay - # notify: - # - Перезагружаю виртуальные машины - name: Добавляю модули br_netfilter и overlay в /etc/modules ansible.builtin.lineinfile: path: /etc/modules - line: '{{ item }}' + line: "{{ item }}" create: true with_items: - br_netfilter - overlay - # notify: - # - Перезагружаю виртуальные машины - name: Включаю маршрутизацию IP и iptables для моста ansible.posix.sysctl: - name: '{{ item }}' + name: "{{ item }}" value: 1 state: present with_items: @@ -54,6 +39,9 @@ - gpg - software-properties-common update_cache: true + register: apt_res + retries: 5 + until: apt_res is success - name: Добавляю gpg ключ для репозиториев Kubernetes и cri-o ansible.builtin.apt_key: @@ -61,15 +49,21 @@ state: present keyring: '{{ item["keyring"] }}' with_items: - - {url: "https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key", keyring: "/etc/apt/keyrings/kubernetes-apt-keyring.gpg"} - - {url: "https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/Release.key", keyring: "/etc/apt/keyrings/cri-o-apt-keyring.gpg"} + - { + url: "https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key", + keyring: "/etc/apt/keyrings/kubernetes-apt-keyring.gpg", + } + - { + url: "https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/Release.key", + keyring: "/etc/apt/keyrings/cri-o-apt-keyring.gpg", + } - name: Добавляю репозитории Kubernetes и cri-o ansible.builtin.apt_repository: - repo: '{{ item }}' + repo: "{{ item }}" state: present with_items: - - deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/ / + - deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/stable:/v1.30/deb/ / - deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ / - name: Устанавливаю пакеты kubelet, kubeadm, kubectl и cri-o @@ -84,7 +78,7 @@ - name: Предотвращаю обновление kubelet, kubeadm и kubectl ansible.builtin.dpkg_selections: - name: '{{ item }}' + name: "{{ item }}" selection: hold with_items: - kubelet @@ -93,33 +87,88 @@ - name: Включаю и запускаю службы kubelet и cri-o ansible.builtin.systemd: - name: '{{ item }}' + name: "{{ item }}" enabled: true state: started with_items: - kubelet - crio -- name: Устанавливаю пакеты для Longhorn +# Запуск сервисов keepalived и haproxy как статических подсистем +# https://github.com/kubernetes/kubeadm/blob/main/docs/ha-considerations.md#option-2-run-the-services-as-static-pods +- name: Настраиваю keepalived + haproxy и инициализирую кластер become: true hosts: - - kubeadm_nodes + - kubeadm_control_plane + roles: + - haproxy_static_pods tasks: - - name: Устанавливаю нужные пакеты - ansible.builtin.apt: - name: - - open-iscsi - - nfs-common - - bash - - curl - - grep - state: present - update_cache: true + - name: Инициализирую высокодоступный кластер + run_once: true + ansible.builtin.command: | + kubeadm init \ + --pod-network-cidr=10.244.0.0/16 \ + --control-plane-endpoint=10.0.75.80:8888 \ + --upload-certs \ + --skip-phases=addon/kube-proxy + args: + creates: /etc/kubernetes/kubelet.conf + notify: + - Создаю token для control-plane + - Создаю token для node + - Добавляю control-plane узлы в кластер + - Добавляю node узлы в кластер + handlers: + - name: Создаю token для control-plane + ansible.builtin.shell: + cmd: | + set -o pipefail + echo $(kubeadm token create --print-join-command) \ + --control-plane \ + --certificate-key \ + $(kubeadm init phase upload-certs --upload-certs | grep -vw -e certificate -e Namespace) + executable: /bin/bash + register: join_control_plane_raw + - name: Создаю token для node + ansible.builtin.command: kubeadm token create --print-join-command + register: join_node_raw + - name: Добавляю control-plane узлы в кластер + ansible.builtin.command: "{{ join_control_plane_raw.stdout }}" + args: + creates: /etc/kubernetes/kubelet.conf + delegate_to: "{{ item }}" + loop: "{{ groups['kubeadm_control_plane'] }}" + - name: Добавляю node узлы в кластер + ansible.builtin.command: "{{ join_node_raw.stdout }}" + args: + creates: /etc/kubernetes/kubelet.conf + delegate_to: "{{ item }}" + loop: "{{ groups['kubeadm_nodes'] }}" - - name: Включаю и запускаю службы - ansible.builtin.systemd: - name: '{{ item }}' - enabled: true - state: started - with_items: - - iscsid +# Подготовка control-plane узлов +- name: Подготовка control-plane узлов для работы с kubectl + become: true + gather_facts: false + hosts: + - kubeadm_control_plane + tasks: + - name: Создаю директорию .kube + become_user: infra + ansible.builtin.file: + path: $HOME/.kube + state: directory + mode: "755" + - name: Копирую admin.conf в директорию .kube + ansible.builtin.copy: + src: /etc/kubernetes/admin.conf + dest: /home/infra/.kube/config + remote_src: true + owner: infra + group: infra + mode: "600" + - name: Копирую kube/config + run_once: true + ansible.posix.synchronize: + src: "~/.kube/config" # remote host + dest: "~/.kube/config" # localhost + mode: pull diff --git a/ansible/roles/haproxy_static_pods/files/check_apiserver.sh b/ansible/roles/haproxy_static_pods/files/check_apiserver.sh index 487d43e..866ee37 100755 --- a/ansible/roles/haproxy_static_pods/files/check_apiserver.sh +++ b/ansible/roles/haproxy_static_pods/files/check_apiserver.sh @@ -5,7 +5,7 @@ errorExit() { exit 1 } -curl --silent --max-time 2 --insecure https://localhost:7443/ -o /dev/null || errorExit "Error GET https://localhost:7443/" -if ip addr | grep -q 10.0.70.85; then - curl --silent --max-time 2 --insecure https://10.0.70.85:7443/ -o /dev/null || errorExit "Error GET https://10.0.70.85:7443/" +curl --silent --max-time 2 --insecure https://localhost:8888/ -o /dev/null || errorExit "Error GET https://localhost:8888/" +if ip addr | grep -q 10.0.75.80; then + curl --silent --max-time 2 --insecure https://10.0.75.80:8888/ -o /dev/null || errorExit "Error GET https://10.0.75.80:8888/" fi diff --git a/ansible/roles/haproxy_static_pods/files/haproxy.cfg b/ansible/roles/haproxy_static_pods/files/haproxy.cfg index 9369876..4d62014 100644 --- a/ansible/roles/haproxy_static_pods/files/haproxy.cfg +++ b/ansible/roles/haproxy_static_pods/files/haproxy.cfg @@ -32,7 +32,7 @@ defaults # apiserver frontend which proxys to the control plane nodes #--------------------------------------------------------------------- frontend apiserver - bind *:7443 + bind *:8888 mode tcp option tcplog default_backend apiserverbackend @@ -46,7 +46,7 @@ backend apiserverbackend mode tcp option ssl-hello-chk balance roundrobin - server 10.0.70.70 10.0.70.70:6443 check - server 10.0.70.78 10.0.70.78:6443 check - server 10.0.70.79 10.0.70.79:6443 check + server 10.0.75.81 10.0.75.81:6443 check + server 10.0.75.82 10.0.75.82:6443 check + server 10.0.75.83 10.0.75.83:6443 check # [...] diff --git a/ansible/roles/haproxy_static_pods/files/haproxy.yaml b/ansible/roles/haproxy_static_pods/files/haproxy.yaml index 5c8f679..83159c1 100644 --- a/ansible/roles/haproxy_static_pods/files/haproxy.yaml +++ b/ansible/roles/haproxy_static_pods/files/haproxy.yaml @@ -5,23 +5,23 @@ metadata: namespace: kube-system spec: containers: - - image: haproxy:2.9.7 - name: haproxy - livenessProbe: - failureThreshold: 8 - httpGet: - host: localhost - path: /healthz - port: 7443 - scheme: HTTPS - volumeMounts: - - mountPath: /usr/local/etc/haproxy/haproxy.cfg - name: haproxyconf - readOnly: true + - image: haproxy:3.0.2 + name: haproxy + livenessProbe: + failureThreshold: 8 + httpGet: + host: localhost + path: /healthz + port: 8888 + scheme: HTTPS + volumeMounts: + - mountPath: /usr/local/etc/haproxy/haproxy.cfg + name: haproxyconf + readOnly: true hostNetwork: true volumes: - - hostPath: - path: /etc/haproxy/haproxy.cfg - type: FileOrCreate - name: haproxyconf + - hostPath: + path: /etc/haproxy/haproxy.cfg + type: FileOrCreate + name: haproxyconf status: {} diff --git a/ansible/roles/haproxy_static_pods/files/keepalived.yaml b/ansible/roles/haproxy_static_pods/files/keepalived.yaml index e70c60b..42e5ce7 100644 --- a/ansible/roles/haproxy_static_pods/files/keepalived.yaml +++ b/ansible/roles/haproxy_static_pods/files/keepalived.yaml @@ -6,26 +6,26 @@ metadata: namespace: kube-system spec: containers: - - image: osixia/keepalived:2.0.20 - name: keepalived - resources: {} - securityContext: - capabilities: - add: - - NET_ADMIN - - NET_BROADCAST - - NET_RAW - volumeMounts: - - mountPath: /usr/local/etc/keepalived/keepalived.conf - name: config - - mountPath: /etc/keepalived/check_apiserver.sh - name: check + - image: ghcr.io/batonogov/docker-keepalived:2.0.20 + name: keepalived + resources: {} + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_BROADCAST + - NET_RAW + volumeMounts: + - mountPath: /usr/local/etc/keepalived/keepalived.conf + name: config + - mountPath: /etc/keepalived/check_apiserver.sh + name: check hostNetwork: true volumes: - - hostPath: - path: /etc/keepalived/keepalived.conf - name: config - - hostPath: - path: /etc/keepalived/check_apiserver.sh - name: check + - hostPath: + path: /etc/keepalived/keepalived.conf + name: config + - hostPath: + path: /etc/keepalived/check_apiserver.sh + name: check status: {} diff --git a/ansible/roles/haproxy_static_pods/tasks/main.yml b/ansible/roles/haproxy_static_pods/tasks/main.yml index d9cc95f..d861e1f 100644 --- a/ansible/roles/haproxy_static_pods/tasks/main.yml +++ b/ansible/roles/haproxy_static_pods/tasks/main.yml @@ -1,9 +1,9 @@ # tasks file for haproxy_static_pods - name: Создать директории /etc/kubernetes/manifests и /etc/keepalived ansible.builtin.file: - path: '{{ item }}' + path: "{{ item }}" state: directory - mode: '755' + mode: "755" with_items: - /etc/kubernetes/manifests - /etc/keepalived @@ -19,22 +19,22 @@ ansible.builtin.copy: src: check_apiserver.sh dest: /etc/keepalived/check_apiserver.sh - mode: '644' + mode: "644" - name: Наливаю haproxy.cfg ansible.builtin.copy: src: haproxy.cfg dest: /etc/haproxy/haproxy.cfg - mode: '644' + mode: "644" - name: Наливаю keepalived static pods manifest ansible.builtin.copy: src: keepalived.yaml dest: /etc/kubernetes/manifests/keepalived.yaml - mode: '644' + mode: "644" - name: Наливаю haproxy static pods manifest ansible.builtin.copy: src: haproxy.yaml dest: /etc/kubernetes/manifests/haproxy.yaml - mode: '644' + mode: "644" diff --git a/ansible/roles/haproxy_static_pods/templates/keepalived.conf.j2 b/ansible/roles/haproxy_static_pods/templates/keepalived.conf.j2 index b853b0a..a377c2d 100644 --- a/ansible/roles/haproxy_static_pods/templates/keepalived.conf.j2 +++ b/ansible/roles/haproxy_static_pods/templates/keepalived.conf.j2 @@ -21,7 +21,7 @@ vrrp_instance VI_1 { auth_pass {{ lookup('password', 'secrets/kubeadm/keepalived/auth_pass length=64') }} } virtual_ipaddress { - 10.0.70.85/24 + 10.0.75.80/24 } track_script { check_apiserver diff --git a/kubeadm/README.md b/kubeadm/README.md index 13fea84..6ecc3bd 100644 --- a/kubeadm/README.md +++ b/kubeadm/README.md @@ -1,13 +1,18 @@ # Настройка kubernetes кластера после чистой установки при помощи **kubeadm** +## Создание ВМ + +Наш кластер работает на 6 виртуальных машинах (3 control-plane и 3 node) и разворачивается с помощью [OpenTofu](../opentofu/kubeadm). + ## Подготовка ВМ -Тестирование проводилось на **Ubuntu 22.04** +Тестирование проводилось на **Ubuntu 24.04** Подготавливаем ВМ при помощи [плейбука](../ansible/kubeadm.yml) -Плейбук настроит все что нудно для работы **Kubernetes**. +Плейбук настроит все что нужно для работы **Kubernetes**. Добавит необходимые **модули ядра**, установит **kubelet**, **kubeadm**, **kubectl**, **cri-o**... и перезапустит машинки если это необходимо. +Также произойдет инициализация кластера в HA режиме без **kube-proxy**. Запускаем плейбук @@ -19,40 +24,46 @@ ansible-playbook kubeadm.yml ```output PLAY RECAP ******************************************************************************************************* -kubeadm-cp-01 : ok=19 changed=16 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -kubeadm-cp-02 : ok=19 changed=16 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -kubeadm-cp-03 : ok=19 changed=16 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -kubeadm-node-01 : ok=12 changed=10 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -kubeadm-node-02 : ok=12 changed=10 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -kubeadm-node-03 : ok=12 changed=10 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +kubeadm-cp-01 : ok=28 changed=23 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +kubeadm-cp-02 : ok=22 changed=17 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +kubeadm-cp-03 : ok=22 changed=17 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +kubeadm-node-01 : ok=13 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +kubeadm-node-02 : ok=13 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +kubeadm-node-03 : ok=13 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -вторник 23 апреля 2024 09:29:22 +0300 (0:00:41.104) 0:02:19.111 ******** +четверг 02 мая 2024 19:33:56 +0500 (0:00:02.841) 0:04:44.638 *********** =============================================================================== -Устанавливаю пакеты kubelet, kubeadm, kubectl и cri-o ---------------------------------------------------- 51.97s -Перезагружаю виртуальные машины -------------------------------------------------------------------------- 41.10s -Добавляю репозитории Kubernetes и cri-o ------------------------------------------------------------------ 12.58s -Устанавливаю пакеты --------------------------------------------------------------------------------------- 6.54s -upgrade_packages : Обновляю все пакеты до актуальных версий ----------------------------------------------- 3.54s -Добавляю gpg ключ для репозиториев Kubernetes и cri-o ----------------------------------------------------- 2.61s -Gathering Facts ------------------------------------------------------------------------------------------- 2.53s -Gathering Facts ------------------------------------------------------------------------------------------- 2.53s -Включаю маршрутизацию IP и iptables для моста ------------------------------------------------------------- 2.19s -Включаю и запускаю службы kubelet и cri-o ----------------------------------------------------------------- 2.09s -Предотвращаю обновление kubelet, kubeadm и kubectl -------------------------------------------------------- 1.87s -haproxy_static_pods : Создать директории /etc/kubernetes/manifests и /etc/keepalived ---------------------- 1.64s -Добавляю модули br_netfilter и overlay -------------------------------------------------------------------- 1.21s -Добавляю модули br_netfilter и overlay в /etc/modules ----------------------------------------------------- 1.20s -haproxy_static_pods : Наливаю keepalived.conf ------------------------------------------------------------- 1.19s -haproxy_static_pods : Наливаю haproxy.cfg ----------------------------------------------------------------- 1.11s -haproxy_static_pods : Наливаю haproxy static pods manifest ------------------------------------------------ 1.09s -haproxy_static_pods : Наливаю check_apiserver.sh ---------------------------------------------------------- 1.07s -haproxy_static_pods : Наливаю keepalived static pods manifest --------------------------------------------- 1.03s +Добавляю control-plane узлы в кластер ------------------------------------------------ 67.74s +Инициализирую высокодоступный кластер ------------------------------------------------ 50.23s +Устанавливаю пакеты kubelet, kubeadm, kubectl и cri-o -------------------------------- 44.44s +Добавляю репозитории Kubernetes и cri-o ---------------------------------------------- 14.60s +Устанавливаю нужные пакеты ----------------------------------------------------------- 13.38s +Добавляю node узлы в кластер --------------------------------------------------------- 11.06s +Устанавливаю пакеты ------------------------------------------------------------------- 7.83s +Предотвращаю обновление kubelet, kubeadm и kubectl ------------------------------------ 4.89s +Добавляю gpg ключ для репозиториев Kubernetes и cri-o --------------------------------- 4.74s +haproxy_static_pods : Наливаю конфигурацию keepalived --------------------------------- 4.62s +haproxy_static_pods : Создать директории /etc/kubernetes/manifests и /etc/keepalived -- 4.48s +Gathering Facts ----------------------------------------------------------------------- 4.44s +Включаю и запускаю службы kubelet и cri-o --------------------------------------------- 4.30s +upgrade_packages : Обновляю все пакеты до актуальных версий --------------------------- 4.20s +Gathering Facts ----------------------------------------------------------------------- 3.70s +haproxy_static_pods : Наливаю check_apiserver.sh -------------------------------------- 3.52s +haproxy_static_pods : Наливаю haproxy.cfg --------------------------------------------- 3.31s +haproxy_static_pods : Наливаю haproxy static pods manifest ---------------------------- 3.31s +haproxy_static_pods : Наливаю keepalived static pods manifest ------------------------- 3.23s +Добавляю модули br_netfilter и overlay ------------------------------------------------ 3.21s ``` +Если все прошло успешно, то можно перейти к [настройке CNI](README.md#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-cni). + ## Инициализация кластера Первый вариант подходит для тестирования, или создания не отказоустоичивого кластера, Второй вариант создаст отказоустойчивый кластер готовый для прода. +Ansible Playbook создает второй вариант. + +Дальше описаны варианты для понимания работы. ### Non HA (Подходит для тестирования, не рекомендуется для прода) @@ -81,10 +92,19 @@ kubeadm-node-02 Ready 13s v1.30.0 10.0.70.77 ### HA (Production Ready решение, рекомендуется) Мы разместим **haproxy** и **keepalived** на **control-plane** узлах. Конфигурации налиты при помощи Ansible на этапе подготовки. -Наш виртуальный IP: **10.0.70.85:7443** для взаимодействия с **Kube Api Server** +Наш виртуальный IP: **10.0.70.85:8888** для взаимодействия с **Kube Api Server** + +Обратите внимание, что мы не устанавливаем **kube-proxy**, для этого мы указали ключ **--skip-phases=addon/kube-proxy**, +этот вариант подходит при использовании **Kubernetes** без **kube-proxy** и позволяет использовать **Cilium** для его полной замены. + +Если вы планируете использовать **Flannel**, нужно оставить **kube-proxy**. ```sh -sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint=10.0.70.85:7443 --upload-certs +sudo kubeadm init \ + --pod-network-cidr=10.244.0.0/16 \ + --control-plane-endpoint=10.0.70.85:8888 \ + --upload-certs \ + --skip-phases=addon/kube-proxy ``` При успешном выполнении мы увидим примерно следующее @@ -108,7 +128,7 @@ Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: You can now join any number of the control-plane node running the following command on each as root: - kubeadm join 10.0.70.85:7443 --token r120zn.za3vq0au6kzgoepu \ + kubeadm join 10.0.70.85:8888 --token r120zn.za3vq0au6kzgoepu \ --discovery-token-ca-cert-hash sha256:cacb3c674f63d7f261c4fed403f59ce6e7d4c869c3748e301c98b2b9f17f7786 \ --control-plane --certificate-key 31ba08487b6899c2ebe43dd3857e168840a98d1077a7998c79f6f4838b4c08f7 @@ -118,7 +138,7 @@ As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you c Then you can join any number of worker nodes by running the following on each as root: -kubeadm join 10.0.70.85:7443 --token r120zn.za3vq0au6kzgoepu \ +kubeadm join 10.0.70.85:8888 --token r120zn.za3vq0au6kzgoepu \ --discovery-token-ca-cert-hash sha256:cacb3c674f63d7f261c4fed403f59ce6e7d4c869c3748e301c98b2b9f17f7786 ``` @@ -131,13 +151,13 @@ kubectl get nodes -o wide ``` ```output -NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME -kubeadm-cp-01 Ready control-plane 2m26s v1.30.0 10.0.70.70 Ubuntu 22.04.4 LTS 5.15.0-105-generic cri-o://1.30.0 -kubeadm-cp-02 Ready control-plane 68s v1.30.0 10.0.70.78 Ubuntu 22.04.4 LTS 5.15.0-105-generic cri-o://1.30.0 -kubeadm-cp-03 Ready control-plane 64s v1.30.0 10.0.70.79 Ubuntu 22.04.4 LTS 5.15.0-105-generic cri-o://1.30.0 -kubeadm-node-01 Ready 53s v1.30.0 10.0.70.71 Ubuntu 22.04.4 LTS 5.15.0-105-generic cri-o://1.30.0 -kubeadm-node-02 Ready 27s v1.30.0 10.0.70.77 Ubuntu 22.04.4 LTS 5.15.0-105-generic cri-o://1.30.0 -kubeadm-node-03 Ready 37s v1.30.0 10.0.70.74 Ubuntu 22.04.4 LTS 5.15.0-105-generic cri-o://1.30.0 +NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME +kubeadm-cp-01 Ready control-plane 46m v1.30.0 10.0.70.70 Ubuntu 24.04 LTS 6.8.0-31-generic cri-o://1.31.0 +kubeadm-cp-02 Ready control-plane 45m v1.30.0 10.0.70.78 Ubuntu 24.04 LTS 6.8.0-31-generic cri-o://1.31.0 +kubeadm-cp-03 Ready control-plane 45m v1.30.0 10.0.70.79 Ubuntu 24.04 LTS 6.8.0-31-generic cri-o://1.31.0 +kubeadm-node-01 Ready 45m v1.30.0 10.0.70.71 Ubuntu 24.04 LTS 6.8.0-31-generic cri-o://1.31.0 +kubeadm-node-02 Ready 45m v1.30.0 10.0.70.77 Ubuntu 24.04 LTS 6.8.0-31-generic cri-o://1.31.0 +kubeadm-node-03 Ready 45m v1.30.0 10.0.70.74 Ubuntu 24.04 LTS 6.8.0-31-generic cri-o://1.31.0 ``` ## Настройка CNI @@ -145,33 +165,121 @@ kubeadm-node-03 Ready 37s v1.30.0 10.0.70.74 -kube-flannel-ds-8fzzw 1/1 Running 0 26s 10.0.70.74 kubeadm-node-03 -kube-flannel-ds-9hrcj 1/1 Running 0 26s 10.0.70.78 kubeadm-cp-02 -kube-flannel-ds-gm24r 1/1 Running 0 26s 10.0.70.70 kubeadm-cp-01 -kube-flannel-ds-rd7jr 1/1 Running 0 26s 10.0.70.77 kubeadm-node-02 -kube-flannel-ds-rjsl9 1/1 Running 0 26s 10.0.70.79 kubeadm-cp-03 +KubeProxyReplacement Details: + Status: True + Socket LB: Enabled + Socket LB Tracing: Enabled + Socket LB Coverage: Full + Devices: eth0 10.0.75.83 fe80::be24:11ff:fee9:819e (Direct Routing) + Mode: SNAT + Backend Selection: Random + Session Affinity: Enabled + Graceful Termination: Enabled + NAT46/64 Support: Disabled + XDP Acceleration: Disabled + Services: + - ClusterIP: Enabled + - NodePort: Enabled (Range: 30000-32767) + - LoadBalancer: Enabled + - externalIPs: Enabled + - HostPort: Enabled +``` + +Больше информации о работе без **kube-proxy** в [официальной документации](https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/). + +Проверяем статус установки + +```sh +cilium status --wait +``` + +Мы должны увидеть что-то подобное + +```output + /¯¯\ + /¯¯\__/¯¯\ Cilium: OK + \__/¯¯\__/ Operator: OK + /¯¯\__/¯¯\ Envoy DaemonSet: disabled (using embedded mode) + \__/¯¯\__/ Hubble Relay: disabled + \__/ ClusterMesh: disabled + +DaemonSet cilium Desired: 6, Ready: 6/6, Available: 6/6 +Deployment cilium-operator Desired: 2, Ready: 2/2, Available: 2/2 +Containers: cilium Running: 6 + cilium-operator Running: 2 +Cluster Pods: 2/2 managed by Cilium +Helm chart version: +Image versions cilium quay.io/cilium/cilium:v1.15.6@sha256:6aa840986a3a9722cd967ef63248d675a87add7e1704740902d5d3162f0c0def: 6 + cilium-operator quay.io/cilium/operator-generic:v1.15.6@sha256:5789f0935eef96ad571e4f5565a8800d3a8fbb05265cf6909300cd82fd513c3d: 2 +``` + +Выполните следующую команду, чтобы убедиться, что ваш кластер имеет правильное сетевое подключение (опционально): + +```sh +cilium connectivity test +``` + +Пример вывода + +```output +✅ [cilium-test] All 52 tests (600 actions) successful, 28 tests skipped, 0 scenarios skipped. +``` + +Можно удалить неймспейс **cilium-test** + +```sh +kubectl delete namespaces cilium-test ``` ## Установка тестового приложения @@ -185,7 +293,8 @@ helm upgrade \ --create-namespace \ kube-prometheus-stack \ prometheus-community/kube-prometheus-stack \ - --version 58.2.2 + --values ./kube-prometheus-stack/values.yaml \ + --version 61.3.2 ``` Проверяем, что все запустилось @@ -226,6 +335,8 @@ kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 8000:80 **CSI (Container Storage Interface)** - это спецификация, которая позволяет контейнерам в **Kubernetes** взаимодействовать с различными хранилищами данных, такими как блочные и файловые системы, через стандартизированный интерфейс. Это позволяет управлять хранилищем данных более гибко и эффективно в среде контейнеров. +### **Longhorn** + Для организации системы хранения в кластере, мы будем использовать **[Longhorn](https://longhorn.io/)**. **Longhorn** - это легкая, надежная и мощная система хранения распределенных блоков для **Kubernetes**. @@ -234,7 +345,7 @@ kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 8000:80 **Longhorn** создает выделенный контроллер хранения для каждого тома блочного устройства и синхронно реплицирует том на несколько реплик, хранящихся на нескольких узлах. Контроллер хранилища и реплики сами оркеструются с помощью **Kubernetes**. -### Характеристики +#### Характеристики - **Распределенное блочное хранилище** корпоративного класса без единой точки отказа - **Инкрементный снимок** блочного хранилища @@ -243,32 +354,32 @@ kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 8000:80 - **Автоматизированное обновление без сбоев**. Вы можете обновить весь стек программного обеспечения **Longhorn**, не нарушая работу томов хранения. - Интуитивно понятная приборная панель с **графическим интерфейсом** -### Пререквизиты +#### Пререквизиты - Кластер Kubernetes: Убедитесь, что каждый узел соответствует требованиям к установке. - Ваша рабочая станция: Установите Helm версии 3.0 или более поздней. -### Установка Longhorn +#### Установка Longhorn Примечание: - Начальные настройки для **Longhorn** можно найти в пользовательских опциях **Helm** или отредактировав файл конфигурации развертывания. -- Для **Kubernetes** < v1.25, если в вашем кластере все еще используется контроллер допуска Pod Security Policy, установите значение helm enablePSP в true, -чтобы установить ресурс longhorn-psp PodSecurityPolicy, который позволит запускать привилегированные поды **Longhorn**. +- Для **Kubernetes** \< v1.25, если в вашем кластере все еще используется контроллер допуска Pod Security Policy, установите значение helm enablePSP в true, + чтобы установить ресурс longhorn-psp PodSecurityPolicy, который позволит запускать привилегированные поды **Longhorn**. -### Требования к установке +#### Требования к установке Каждый узел в кластере **Kubernetes**, на котором установлен **Longhorn**, должен отвечать следующим требованиям: - Контейнерная среда выполнения, совместимая с Kubernetes (Docker v1.13+, containerd v1.3.7+ и т. д.) - Kubernetes >= v1.21 - Установлен open-iscsi, и на всех узлах запущен демон iscsid. -Это необходимо, поскольку Longhorn полагается на iscsiadm на узле для предоставления постоянных томов Kubernetes. Помощь в установке open-iscsi см. в [этом разделе](https://longhorn.io/docs/1.6.1/deploy/install/#installing-open-iscsi). + Это необходимо, поскольку Longhorn полагается на iscsiadm на узле для предоставления постоянных томов Kubernetes. Помощь в установке open-iscsi см. в [этом разделе](https://longhorn.io/docs/1.6.2/deploy/install/#installing-open-iscsi). - Поддержка RWX требует, чтобы на каждом узле был установлен клиент NFSv4. - Об установке клиента NFSv4 читайте в [этом разделе](https://longhorn.io/docs/1.6.1/deploy/install/#installing-nfsv4-client). + Об установке клиента NFSv4 читайте в [этом разделе](https://longhorn.io/docs/1.6.2/deploy/install/#installing-nfsv4-client). - Файловая система узла поддерживает функцию расширения файлов для хранения данных. В настоящее время мы поддерживаем: - ext4 - XFS + ext4 + XFS - Должны быть установлены bash, curl, findmnt, grep, awk, blkid, lsblk. - Распространение монтирования должно быть включено. @@ -280,72 +391,72 @@ kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 8000:80 1. Добавьте репозиторий Longhorn Helm: - ```sh - helm repo add longhorn https://charts.longhorn.io - ``` + ```sh + helm repo add longhorn https://charts.longhorn.io + ``` -2. Получите список последних чартов из репозитория: +1. Получите список последних чартов из репозитория: - ```sh - helm repo update - ``` + ```sh + helm repo update + ``` -3. Установите Longhorn в пространстве имен longhorn-system. +1. Установите Longhorn в пространстве имен longhorn-system. - ```sh - helm upgrade \ - --install \ - longhorn longhorn/longhorn \ - --namespace longhorn-system \ - --create-namespace \ - --version 1.6.1 - ``` + ```sh + helm upgrade \ + --install \ + longhorn longhorn/longhorn \ + --namespace longhorn-system \ + --create-namespace \ + --version 1.6.2 + ``` -4. Чтобы убедиться, что развертывание прошло успешно, выполните команду: +1. Чтобы убедиться, что развертывание прошло успешно, выполните команду: - ```sh - kubectl -n longhorn-system get pod - ``` + ```sh + kubectl -n longhorn-system get pod + ``` - Результат должен выглядеть следующим образом: + Результат должен выглядеть следующим образом: - ```output - NAME READY STATUS RESTARTS AGE - csi-attacher-799967d9c-nx4f9 1/1 Running 0 3m10s - csi-attacher-799967d9c-vsz7g 1/1 Running 0 3m10s - csi-attacher-799967d9c-zh6vq 1/1 Running 0 3m10s - csi-provisioner-58f97759c-676jf 1/1 Running 0 3m10s - csi-provisioner-58f97759c-fxsb5 1/1 Running 0 3m10s - csi-provisioner-58f97759c-krfs2 1/1 Running 0 3m10s - csi-resizer-6c9b8598f4-dzxwp 1/1 Running 0 3m10s - csi-resizer-6c9b8598f4-kkfn4 1/1 Running 0 3m10s - csi-resizer-6c9b8598f4-wq47f 1/1 Running 0 3m10s - csi-snapshotter-5c5f9b754d-4pdbg 1/1 Running 0 3m10s - csi-snapshotter-5c5f9b754d-7n7wf 1/1 Running 0 3m10s - csi-snapshotter-5c5f9b754d-q4rzx 1/1 Running 0 3m10s - engine-image-ei-5cefaf2b-8j4j9 1/1 Running 0 3m14s - engine-image-ei-5cefaf2b-94g2f 1/1 Running 0 3m14s - engine-image-ei-5cefaf2b-g5bg5 1/1 Running 0 3m14s - instance-manager-3af1ba7167264c2020df4d36d77d3905 1/1 Running 0 3m14s - instance-manager-8452580cb8e2bc9ad134bb6a1c2806cc 1/1 Running 0 3m12s - instance-manager-a006e8fdef719ff0b5aee753abbe1dd8 1/1 Running 0 3m14s - longhorn-csi-plugin-bswvc 3/3 Running 0 3m10s - longhorn-csi-plugin-fmlrd 3/3 Running 0 3m10s - longhorn-csi-plugin-tpnqm 3/3 Running 0 3m10s - longhorn-driver-deployer-68b5879955-7tkrs 1/1 Running 0 3m31s - longhorn-manager-5psrc 1/1 Running 0 3m31s - longhorn-manager-5qjbd 1/1 Running 0 3m31s - longhorn-manager-rwzbb 1/1 Running 0 3m31s - longhorn-ui-9ccf5c989-bxdv2 1/1 Running 0 3m31s - longhorn-ui-9ccf5c989-dsvz6 1/1 Running 0 3m31s - ``` + ```output + NAME READY STATUS RESTARTS AGE + csi-attacher-799967d9c-nx4f9 1/1 Running 0 3m10s + csi-attacher-799967d9c-vsz7g 1/1 Running 0 3m10s + csi-attacher-799967d9c-zh6vq 1/1 Running 0 3m10s + csi-provisioner-58f97759c-676jf 1/1 Running 0 3m10s + csi-provisioner-58f97759c-fxsb5 1/1 Running 0 3m10s + csi-provisioner-58f97759c-krfs2 1/1 Running 0 3m10s + csi-resizer-6c9b8598f4-dzxwp 1/1 Running 0 3m10s + csi-resizer-6c9b8598f4-kkfn4 1/1 Running 0 3m10s + csi-resizer-6c9b8598f4-wq47f 1/1 Running 0 3m10s + csi-snapshotter-5c5f9b754d-4pdbg 1/1 Running 0 3m10s + csi-snapshotter-5c5f9b754d-7n7wf 1/1 Running 0 3m10s + csi-snapshotter-5c5f9b754d-q4rzx 1/1 Running 0 3m10s + engine-image-ei-5cefaf2b-8j4j9 1/1 Running 0 3m14s + engine-image-ei-5cefaf2b-94g2f 1/1 Running 0 3m14s + engine-image-ei-5cefaf2b-g5bg5 1/1 Running 0 3m14s + instance-manager-3af1ba7167264c2020df4d36d77d3905 1/1 Running 0 3m14s + instance-manager-8452580cb8e2bc9ad134bb6a1c2806cc 1/1 Running 0 3m12s + instance-manager-a006e8fdef719ff0b5aee753abbe1dd8 1/1 Running 0 3m14s + longhorn-csi-plugin-bswvc 3/3 Running 0 3m10s + longhorn-csi-plugin-fmlrd 3/3 Running 0 3m10s + longhorn-csi-plugin-tpnqm 3/3 Running 0 3m10s + longhorn-driver-deployer-68b5879955-7tkrs 1/1 Running 0 3m31s + longhorn-manager-5psrc 1/1 Running 0 3m31s + longhorn-manager-5qjbd 1/1 Running 0 3m31s + longhorn-manager-rwzbb 1/1 Running 0 3m31s + longhorn-ui-9ccf5c989-bxdv2 1/1 Running 0 3m31s + longhorn-ui-9ccf5c989-dsvz6 1/1 Running 0 3m31s + ``` -5. Чтобы включить доступ к пользовательскому интерфейсу Longhorn, необходимо настроить контроллер Ingress. +1. Чтобы включить доступ к пользовательскому интерфейсу Longhorn, необходимо настроить контроллер Ingress. - По умолчанию аутентификация в пользовательском интерфейсе Longhorn не включена. - Информацию о создании контроллера NGINX Ingress с базовой аутентификацией см. в [этом разделе](https://longhorn.io/docs/1.6.1/deploy/accessing-the-ui/longhorn-ingress). + По умолчанию аутентификация в пользовательском интерфейсе Longhorn не включена. + Информацию о создании контроллера NGINX Ingress с базовой аутентификацией см. в [этом разделе](https://longhorn.io/docs/1.6.2/deploy/accessing-the-ui/longhorn-ingress). -6. Войдите в пользовательский интерфейс Longhorn, выполнив [следующие действия](https://longhorn.io/docs/1.6.1/deploy/accessing-the-ui). +1. Войдите в пользовательский интерфейс Longhorn, выполнив [следующие действия](https://longhorn.io/docs/1.6.2/deploy/accessing-the-ui). Посмотреть на веб интерфейс можно так: @@ -382,7 +493,20 @@ helm upgrade \ --install \ --namespace traefik \ --create-namespace \ - traefik traefik/traefik + traefik traefik/traefik \ + --values traefik/values.yaml +``` + +```sh +helm upgrade \ + --install ingress-nginx ingress-nginx \ + --repo https://kubernetes.github.io/ingress-nginx \ + --namespace ingress-nginx \ + --create-namespace \ + --set controller.kind=DaemonSet \ + --set controller.hostNetwork=false \ + --set controller.hostPort.enabled=false \ + --set controller.service.loadBalancerIP=10.0.70.199 ``` ### Проброс дашборда Traefik @@ -404,16 +528,16 @@ kubectl get nodes -o wide Эти команды выполняют следующие действия: - kubectl drain - этот шаг убеждается, что все поды, которые могут быть перезапущены в другом месте, были перезапущены. -Он также удаляет все пустые директории, которые были созданы подами на узле, -и удаляет все поды, которые не могут быть перезапущены в другом месте (например, поды, которые имеют локальные данные). + Он также удаляет все пустые директории, которые были созданы подами на узле, + и удаляет все поды, которые не могут быть перезапущены в другом месте (например, поды, которые имеют локальные данные). ```sh kubectl drain kubeadm-node-01 --delete-local-data --force --ignore-daemonsets ``` - kubectl delete node - этот шаг удаляет узел из кластера. -Обратите внимание, что эти команды могут привести к потере данных, -поэтому убедитесь, что вы понимаете, что делаете, и что у вас есть резервное копирование данных, если это необходимо. + Обратите внимание, что эти команды могут привести к потере данных, + поэтому убедитесь, что вы понимаете, что делаете, и что у вас есть резервное копирование данных, если это необходимо. ```sh kubectl delete node kubeadm-node-01 @@ -438,69 +562,3 @@ kubeadm token list ```sh kubeadm token create --print-join-command ``` - -## Тестирование кластера - -Отчет **sonobuoy** - -```txt -Plugin: e2e -Status: failed -Total: 7201 -Passed: 384 -Failed: 20 -Skipped: 6797 - -Failed tests: - [sig-network] DNS should provide DNS for pods for Subdomain [Conformance] - [sig-network] Services should be able to change the type from ExternalName to ClusterIP [Conformance] - [sig-network] Services should be able to switch session affinity for service with type clusterIP [LinuxOnly] [Conformance] - [sig-cli] Kubectl client Guestbook application should create and stop a working application [Conformance] - [sig-network] Services should be able to switch session affinity for NodePort service [LinuxOnly] [Conformance] - [sig-network] Services should serve multiport endpoints from pods [Conformance] - [sig-network] Services should have session affinity work for NodePort service [LinuxOnly] [Conformance] - [sig-architecture] Conformance Tests should have at least two untainted nodes [Conformance] - [sig-network] DNS should provide DNS for services [Conformance] - [sig-network] Services should be able to change the type from NodePort to ExternalName [Conformance] - [sig-network] DNS should resolve DNS of partial qualified names for services [LinuxOnly] [Conformance] - [sig-network] Services should be able to change the type from ExternalName to NodePort [Conformance] - [sig-network] Services should serve a basic endpoint from pods [Conformance] - [sig-apps] Daemon set [Serial] should rollback without unnecessary restarts [Conformance] - [sig-network] DNS should provide DNS for ExternalName services [Conformance] - [sig-network] DNS should provide DNS for the cluster [Conformance] - [sig-network] Services should be able to create a functioning NodePort service [Conformance] - [sig-network] Services should be able to change the type from ClusterIP to ExternalName [Conformance] - [sig-auth] ServiceAccounts ServiceAccountIssuerDiscovery should support OIDC discovery of service account issuer [Conformance] - [sig-network] Services should have session affinity work for service with type clusterIP [LinuxOnly] [Conformance] - -Plugin: systemd-logs -Status: passed -Total: 2 -Passed: 2 -Failed: 0 -Skipped: 0 - -Run Details: -API Server version: v1.30.0 -Node health: 2/2 (100%) -Pods health: 13/14 (92%) -Details for failed pods: -sonobuoy/sonobuoy-e2e-job-c23b74c9b2004efd Ready:False: : -Errors detected in files: -Warnings: -754 podlogs/kube-system/kube-controller-manager-kubeadm-cp-01/logs/kube-controller-manager.txt - 90 podlogs/kube-system/kube-apiserver-kubeadm-cp-01/logs/kube-apiserver.txt - 29 podlogs/kube-system/kube-scheduler-kubeadm-cp-01/logs/kube-scheduler.txt - 7 podlogs/sonobuoy/sonobuoy-e2e-job-c23b74c9b2004efd/logs/e2e.txt - 3 podlogs/kube-system/etcd-kubeadm-cp-01/logs/etcd.txt - 1 podlogs/sonobuoy/sonobuoy/logs/kube-sonobuoy.txt -Errors: -6268 podlogs/sonobuoy/sonobuoy-e2e-job-c23b74c9b2004efd/logs/e2e.txt -1742 podlogs/kube-system/kube-controller-manager-kubeadm-cp-01/logs/kube-controller-manager.txt - 350 podlogs/kube-system/kube-apiserver-kubeadm-cp-01/logs/kube-apiserver.txt - 63 podlogs/kube-system/kube-scheduler-kubeadm-cp-01/logs/kube-scheduler.txt - 9 podlogs/kube-system/coredns-7db6d8ff4d-lkwk9/logs/coredns.txt - 9 podlogs/kube-system/coredns-7db6d8ff4d-bdvht/logs/coredns.txt - 8 podlogs/kube-system/kube-proxy-4g6fl/logs/kube-proxy.txt - 8 podlogs/kube-system/kube-proxy-p5vr5/logs/kube-proxy.txt -``` diff --git a/kubeadm/cilium/ippool.yaml b/kubeadm/cilium/ippool.yaml new file mode 100644 index 0000000..cab93c8 --- /dev/null +++ b/kubeadm/cilium/ippool.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: "cilium.io/v2alpha1" +kind: CiliumLoadBalancerIPPool +metadata: + name: "pool" +spec: + blocks: + - cidr: "10.0.75.199/32" diff --git a/kubeadm/cilium/l2-announcement-policy.yaml b/kubeadm/cilium/l2-announcement-policy.yaml new file mode 100644 index 0000000..9080646 --- /dev/null +++ b/kubeadm/cilium/l2-announcement-policy.yaml @@ -0,0 +1,16 @@ +apiVersion: "cilium.io/v2alpha1" +kind: CiliumL2AnnouncementPolicy +metadata: + name: policy1 +spec: + serviceSelector: + matchLabels: + color: blue + nodeSelector: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + interfaces: + - ^eth[0-9]+ + externalIPs: true + loadBalancerIPs: true diff --git a/kubeadm/cilium/values.yaml b/kubeadm/cilium/values.yaml new file mode 100644 index 0000000..b315070 --- /dev/null +++ b/kubeadm/cilium/values.yaml @@ -0,0 +1,6 @@ +kubeProxyReplacement: true +k8sServiceHost: 10.0.75.80 +k8sServicePort: 8888 +l2announcements: + enabled: true +devices: eth+ diff --git a/kubeadm/kube-prometheus-stack/values.yaml b/kubeadm/kube-prometheus-stack/values.yaml new file mode 100644 index 0000000..6b5dd49 --- /dev/null +++ b/kubeadm/kube-prometheus-stack/values.yaml @@ -0,0 +1,9 @@ +grafana: + ingress: + enabled: true + hosts: + - grafana.example.local + tls: + - secretName: grafana-general-tls + hosts: + - grafana.example.local diff --git a/kubeadm/test-app/deployment.yaml b/kubeadm/test-app/deployment.yaml new file mode 100644 index 0000000..3b876f9 --- /dev/null +++ b/kubeadm/test-app/deployment.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend + namespace: development + labels: + app: frontend +spec: + revisionHistoryLimit: 10 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + replicas: 3 + selector: + matchLabels: + app: frontend + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + image: python:3.12.4-alpine + command: ["python3", "-m", "http.server", "80"] + imagePullPolicy: IfNotPresent + resources: + requests: + memory: "16Mi" + cpu: "10m" + limits: + memory: "1Gi" + cpu: "1000m" diff --git a/kubeadm/test-app/ingress.yaml b/kubeadm/test-app/ingress.yaml new file mode 100644 index 0000000..40738e5 --- /dev/null +++ b/kubeadm/test-app/ingress.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: frontend + namespace: development +spec: + # В кластере может быть несколько Ingress Controllers, мы используем NGINX + ingressClassName: "traefik" + tls: + - hosts: + - "frontend.example.local" + rules: + # Хост определяет правило направления траффика по доменному имени + - host: "frontend.example.local" + http: + # Для различных путей в URL можно указать различные бэкенд-сервисы + paths: + - path: / + pathType: Prefix + backend: + service: + # Заранее создан сервис типа ClusterIP + # Он выступает в качестве бэкенда нашего Ingress + name: frontend + port: + # У сервиса может быть несколько портов, указываем нужный нам + number: 80 diff --git a/kubeadm/test-app/namespace.yaml b/kubeadm/test-app/namespace.yaml new file mode 100644 index 0000000..919e4f8 --- /dev/null +++ b/kubeadm/test-app/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: development + labels: + name: development diff --git a/kubeadm/test-app/service.yaml b/kubeadm/test-app/service.yaml new file mode 100644 index 0000000..f8f38cf --- /dev/null +++ b/kubeadm/test-app/service.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend + namespace: development + labels: + app: frontend +spec: + type: ClusterIP + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: frontend diff --git a/kubeadm/traefik/values.yaml b/kubeadm/traefik/values.yaml new file mode 100644 index 0000000..09772e7 --- /dev/null +++ b/kubeadm/traefik/values.yaml @@ -0,0 +1,8 @@ +deployment: + kind: DaemonSet + +service: + labels: + color: blue + spec: + externalTrafficPolicy: Local diff --git a/opentofu/kubeadm/.terraform.lock.hcl b/opentofu/kubeadm/.terraform.lock.hcl index b67ed60..bb3663c 100644 --- a/opentofu/kubeadm/.terraform.lock.hcl +++ b/opentofu/kubeadm/.terraform.lock.hcl @@ -2,24 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/bpg/proxmox" { - version = "0.54.0" - constraints = ">= 0.51.0" + version = "0.61.1" + constraints = ">= 0.61.1" hashes = [ - "h1:xgDrDol/cYu93YOPTL0UVpURchPzdxPXaHjcoieoXXI=", - "zh:4521f8893b4645c93e75ffc3545ea59d3f31aed7cea4c26dcd0fbd7c0cce6ca8", - "zh:520e56abd10d888935047ef07a7577c2a1cce5bc54e25b03a0dbdc4356997ca9", - "zh:53469dd058ef8b2ea29577f69a2681f8ffb9f79494b8c1d1594dd42ad314d7bd", - "zh:6948adb6e088fe652b7273906a5c11032528f84eb5a5ca797534ab3b6076a8c6", - "zh:72655e9765b7791e3e37508c70a847172561bff348c7d5f916794e5823a84efe", - "zh:7faa281319d90026ad9b2dce00ac059896f451cb9305ed11bb90fcfda7c5d143", - "zh:8fe20fa893e9545aa30672392f76948ed56a93a2decb1d3bd8693c5e1d2dd85a", - "zh:b175411aa820c1a47473ef691c743670eeb900999576c6cdcb113d14a7c499aa", - "zh:b59205ad7981f263ff287d3eb0a93296f8cd6b166a01ddd3b16606fc39d456ec", + "h1:SQSHTHj2ThcF08cON2gHYcnkS/XLmoF8E4cRIgpagtE=", + "zh:27d8b589a2dc1e0a5b0f8ab299b9f3704a2f0b69799d1d4d8845c68056986d1f", + "zh:46dfa6b33ddd7007a2144f38090457604eb56a59a303b37bb0ad1be5c84ddaca", + "zh:47a1b14a759393c5ecc76f2feb950677c418c910b8c677fde0dd3e4675c41579", + "zh:582e49d109d1c2b1f3b1268a7cbc43548f3c6d96a87c92a5428767097a5e383e", + "zh:5e98ad6afae5969a4c3ffb14c0484936550c66c8313d7686551c29b633ff32f2", + "zh:7b9e24b76f947ab8f1e571cf61beefc983b7d2aa1b85df35c4f015728fe37a38", + "zh:8255ca210f279a0f7b8ca2762df26d2ea1a01704298c5e3d5cf601bd39a743f0", + "zh:85d7655fdc95dedced9cf8105a0beeb0d7bc8f668c55f62019a7215a76d60300", + "zh:8aeea5a1d001b06baaf923b754e1a14d06c75eb8c8b87a7f65a3c8205fc8b079", + "zh:a9cfab6c06f613658c5fdd83742cd22c0eb7563778924b1407965ef8c36c1ce0", + "zh:ceaab67801d49a92eb5858b1ddae6df2569462e5ffbe31f9dbd79dcb684ea142", + "zh:dc25b506d5c55d1d78a335d3ebd03213c99b4b2a5859812349a955c2f746ff7e", + "zh:e04b477fd77a0d37a0bdb76a7cf69184dad9e7fbba9b4f3a378a8901b82b75e5", + "zh:f1e6838d9141557f73340df9b21fce5a82b41cc16ae36f063a920ccc36bc0758", "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", - "zh:f3524bc67d995e98ad9d7e17f3be91f7a975608180fad6b227fc42087b5facc1", - "zh:f4bf087717e1b0f5f3ee7d3b6b47fb66e5f821097f15ec0cf6714a39c7d80959", - "zh:fc14a29b1aef50872d60f338af89f7cbbac307c630f973c07a7951bdde8be2a5", - "zh:fc72da3d651bf0f0e20a0860e9217a94797b4c1d5cae1742f1b8e15d28f8ceeb", - "zh:fff2299a427e1590775611bf186220686795af966772e61e44234f0df44b6c22", ] } diff --git a/opentofu/kubeadm/control-plane-01.tf b/opentofu/kubeadm/control-plane-01.tf deleted file mode 100644 index bf52ebf..0000000 --- a/opentofu/kubeadm/control-plane-01.tf +++ /dev/null @@ -1,70 +0,0 @@ -# Машинка -resource "proxmox_virtual_environment_vm" "kubeadm-cp-01" { - name = "kubeadm-cp-01" - migrate = true - description = "Managed by OpenTofu" - tags = ["kubeadm", "test"] - on_boot = true - - # Указываем целевой узел, на котором будет запущена ВМ - node_name = "pve-01" - - # Шоблон из которого будет создавать ВМ - clone { - vm_id = "2204" - node_name = "pve-01" - retries = 2 - } - - # Активируем QEMU для этов ВМ - agent { - enabled = true - } - - operating_system { - type = "l26" - } - - cpu { - cores = 4 - type = "host" - numa = true - } - - memory { - dedicated = 4096 - } - - disk { - size = "50" - interface = "virtio0" - datastore_id = "k8s-data-01" - file_format = "raw" - } - - network_device { - bridge = "vmbr0" - model = "virtio" - } - - initialization { - datastore_id = "k8s-data-01" - ip_config { - ipv4 { - address = "10.0.70.70/24" - gateway = "10.0.70.101" - } - } - dns { - servers = [ - "77.88.8.8" - ] - } - user_account { - username = "infra" - keys = [ - "ssh-rsa..." - ] - } - } -} diff --git a/opentofu/kubeadm/control-plane-02.tf b/opentofu/kubeadm/control-plane-02.tf deleted file mode 100644 index af4c73e..0000000 --- a/opentofu/kubeadm/control-plane-02.tf +++ /dev/null @@ -1,70 +0,0 @@ -# Машинка -resource "proxmox_virtual_environment_vm" "kubeadm-cp-02" { - name = "kubeadm-cp-02" - migrate = true - description = "Managed by OpenTofu" - tags = ["kubeadm", "test"] - on_boot = true - - # Указываем целевой узел, на котором будет запущена ВМ - node_name = "pve-02" - - # Шоблон из которого будет создавать ВМ - clone { - vm_id = "2204" - node_name = "pve-01" - retries = 2 - } - - # Активируем QEMU для этов ВМ - agent { - enabled = true - } - - operating_system { - type = "l26" - } - - cpu { - cores = 4 - type = "host" - numa = true - } - - memory { - dedicated = 4096 - } - - disk { - size = "50" - interface = "virtio0" - datastore_id = "k8s-data-01" - file_format = "raw" - } - - network_device { - bridge = "vmbr0" - model = "virtio" - } - - initialization { - datastore_id = "k8s-data-01" - ip_config { - ipv4 { - address = "10.0.70.78/24" - gateway = "10.0.70.101" - } - } - dns { - servers = [ - "77.88.8.8" - ] - } - user_account { - username = "infra" - keys = [ - "ssh-rsa..." - ] - } - } -} diff --git a/opentofu/kubeadm/control-plane-03.tf b/opentofu/kubeadm/control-plane-03.tf deleted file mode 100644 index cd6809c..0000000 --- a/opentofu/kubeadm/control-plane-03.tf +++ /dev/null @@ -1,70 +0,0 @@ -# Машинка -resource "proxmox_virtual_environment_vm" "kubeadm-cp-03" { - name = "kubeadm-cp-03" - migrate = true - description = "Managed by OpenTofu" - tags = ["kubeadm", "test"] - on_boot = true - - # Указываем целевой узел, на котором будет запущена ВМ - node_name = "pve-03" - - # Шоблон из которого будет создавать ВМ - clone { - vm_id = "2204" - node_name = "pve-01" - retries = 2 - } - - # Активируем QEMU для этов ВМ - agent { - enabled = true - } - - operating_system { - type = "l26" - } - - cpu { - cores = 4 - type = "host" - numa = true - } - - memory { - dedicated = 4096 - } - - disk { - size = "50" - interface = "virtio0" - datastore_id = "k8s-data-01" - file_format = "raw" - } - - network_device { - bridge = "vmbr0" - model = "virtio" - } - - initialization { - datastore_id = "k8s-data-01" - ip_config { - ipv4 { - address = "10.0.70.79/24" - gateway = "10.0.70.101" - } - } - dns { - servers = [ - "77.88.8.8" - ] - } - user_account { - username = "infra" - keys = [ - "ssh-rsa..." - ] - } - } -} diff --git a/opentofu/kubeadm/control-plane.tf b/opentofu/kubeadm/control-plane.tf new file mode 100644 index 0000000..76d610f --- /dev/null +++ b/opentofu/kubeadm/control-plane.tf @@ -0,0 +1,110 @@ +variable "cp_vms" { + type = list(object({ + name = string + address = string + node_name = string + })) + default = [ + { + name = "kubeadm-cp-01" + address = "10.0.75.81/24" + node_name = "pve-01" + }, + { + name = "kubeadm-cp-02" + address = "10.0.75.82/24" + node_name = "pve-02" + }, + { + name = "kubeadm-cp-03" + address = "10.0.75.83/24" + node_name = "pve-02" + } + ] +} + +# Создание виртуальных машин +resource "proxmox_virtual_environment_vm" "control-plane" { + for_each = { for vm in var.cp_vms : vm.name => vm } + + name = each.value.name + migrate = true + # protection = true + description = "Managed by OpenTofu" + tags = ["kubeadm", "kubernetes"] + on_boot = true + node_name = each.value.node_name + + clone { + vm_id = "2404" + node_name = "pve-01" + retries = 3 + } + + agent { + enabled = true + } + + operating_system { + type = "l26" + } + + cpu { + cores = 4 + type = "host" + numa = true + } + + memory { + dedicated = 4096 + } + + vga { + memory = 4 + type = "serial0" + } + + disk { + size = "20" + interface = "virtio0" + datastore_id = "proxmox-data-01" + file_format = "raw" + } + + network_device { + bridge = "vmbr0" + model = "virtio" + } + + initialization { + datastore_id = "proxmox-data-01" + ip_config { + ipv4 { + address = each.value.address + gateway = "10.0.75.1" + } + } + dns { + servers = [ + "10.0.75.65", + "10.0.75.66" + ] + } + user_account { + username = "infra" + keys = [ + var.ssh_public_key + ] + } + } +} + +# Создание ресурсов высокой доступности +# resource "proxmox_virtual_environment_haresource" "patroni" { +# for_each = { for vm in var.cp_vms : vm.name => vm } + +# resource_id = "vm:${proxmox_virtual_environment_vm.patroni[each.key].vm_id}" +# state = "started" +# group = "prod" +# comment = "Managed by OpenTofu" +# } diff --git a/opentofu/kubeadm/node-01.tf b/opentofu/kubeadm/node-01.tf deleted file mode 100644 index 8e3304d..0000000 --- a/opentofu/kubeadm/node-01.tf +++ /dev/null @@ -1,70 +0,0 @@ -# Машинка -resource "proxmox_virtual_environment_vm" "kubeadm-node-01" { - name = "kubeadm-node-01" - migrate = true - description = "Managed by OpenTofu" - tags = ["kubeadm", "test"] - on_boot = true - - # Указываем целевой узел, на котором будет запущена ВМ - node_name = "pve-01" - - # Шоблон из которого будет создавать ВМ - clone { - vm_id = "2204" - node_name = "pve-01" - retries = 2 - } - - # Активируем QEMU для этов ВМ - agent { - enabled = true - } - - operating_system { - type = "l26" - } - - cpu { - cores = 4 - type = "host" - numa = true - } - - memory { - dedicated = 32768 - } - - disk { - size = "500" - interface = "virtio0" - datastore_id = "k8s-data-01" - file_format = "raw" - } - - network_device { - bridge = "vmbr0" - model = "virtio" - } - - initialization { - datastore_id = "k8s-data-01" - ip_config { - ipv4 { - address = "10.0.70.71/24" - gateway = "10.0.70.101" - } - } - dns { - servers = [ - "77.88.8.8" - ] - } - user_account { - username = "infra" - keys = [ - "ssh-rsa..." - ] - } - } -} diff --git a/opentofu/kubeadm/node-02.tf b/opentofu/kubeadm/node-02.tf deleted file mode 100644 index 806e1c4..0000000 --- a/opentofu/kubeadm/node-02.tf +++ /dev/null @@ -1,70 +0,0 @@ -# Машинка -resource "proxmox_virtual_environment_vm" "kubeadm-node-02" { - name = "kubeadm-node-02" - migrate = true - description = "Managed by OpenTofu" - tags = ["kubeadm", "test"] - on_boot = true - - # Указываем целевой узел, на котором будет запущена ВМ - node_name = "pve-02" - - # Шоблон из которого будет создавать ВМ - clone { - vm_id = "2204" - node_name = "pve-01" - retries = 2 - } - - # Активируем QEMU для этов ВМ - agent { - enabled = true - } - - operating_system { - type = "l26" - } - - cpu { - cores = 4 - type = "host" - numa = true - } - - memory { - dedicated = 32768 - } - - disk { - size = "500" - interface = "virtio0" - datastore_id = "k8s-data-01" - file_format = "raw" - } - - network_device { - bridge = "vmbr0" - model = "virtio" - } - - initialization { - datastore_id = "k8s-data-01" - ip_config { - ipv4 { - address = "10.0.70.77/24" - gateway = "10.0.70.101" - } - } - dns { - servers = [ - "77.88.8.8" - ] - } - user_account { - username = "infra" - keys = [ - "ssh-rsa..." - ] - } - } -} diff --git a/opentofu/kubeadm/node-03.tf b/opentofu/kubeadm/node-03.tf deleted file mode 100644 index 5011423..0000000 --- a/opentofu/kubeadm/node-03.tf +++ /dev/null @@ -1,70 +0,0 @@ -# Машинка -resource "proxmox_virtual_environment_vm" "kubeadm-node-03" { - name = "kubeadm-node-03" - migrate = true - description = "Managed by OpenTofu" - tags = ["kubeadm", "test"] - on_boot = true - - # Указываем целевой узел, на котором будет запущена ВМ - node_name = "pve-03" - - # Шоблон из которого будет создавать ВМ - clone { - vm_id = "2204" - node_name = "pve-01" - retries = 2 - } - - # Активируем QEMU для этов ВМ - agent { - enabled = true - } - - operating_system { - type = "l26" - } - - cpu { - cores = 4 - type = "host" - numa = true - } - - memory { - dedicated = 32768 - } - - disk { - size = "500" - interface = "virtio0" - datastore_id = "k8s-data-01" - file_format = "raw" - } - - network_device { - bridge = "vmbr0" - model = "virtio" - } - - initialization { - datastore_id = "k8s-data-01" - ip_config { - ipv4 { - address = "10.0.70.74/24" - gateway = "10.0.70.101" - } - } - dns { - servers = [ - "77.88.8.8" - ] - } - user_account { - username = "infra" - keys = [ - "ssh-rsa..." - ] - } - } -} diff --git a/opentofu/kubeadm/node.tf b/opentofu/kubeadm/node.tf new file mode 100644 index 0000000..3fe0198 --- /dev/null +++ b/opentofu/kubeadm/node.tf @@ -0,0 +1,110 @@ +variable "node_vms" { + type = list(object({ + name = string + address = string + node_name = string + })) + default = [ + { + name = "kubeadm-node-01" + address = "10.0.75.84/24" + node_name = "pve-01" + }, + { + name = "kubeadm-node-02" + address = "10.0.75.85/24" + node_name = "pve-02" + }, + { + name = "kubeadm-node-03" + address = "10.0.75.86/24" + node_name = "pve-02" + } + ] +} + +# Создание виртуальных машин +resource "proxmox_virtual_environment_vm" "node" { + for_each = { for vm in var.node_vms : vm.name => vm } + + name = each.value.name + migrate = true + # protection = true + description = "Managed by OpenTofu" + tags = ["kubeadm", "kubernetes"] + on_boot = true + node_name = each.value.node_name + + clone { + vm_id = "2404" + node_name = "pve-01" + retries = 3 + } + + agent { + enabled = true + } + + operating_system { + type = "l26" + } + + cpu { + cores = 16 + type = "host" + numa = true + } + + memory { + dedicated = 32768 + } + + vga { + memory = 4 + type = "serial0" + } + + disk { + size = "20" + interface = "virtio0" + datastore_id = "proxmox-data-01" + file_format = "raw" + } + + network_device { + bridge = "vmbr0" + model = "virtio" + } + + initialization { + datastore_id = "proxmox-data-01" + ip_config { + ipv4 { + address = each.value.address + gateway = "10.0.75.1" + } + } + dns { + servers = [ + "10.0.75.65", + "10.0.75.66" + ] + } + user_account { + username = "infra" + keys = [ + var.ssh_public_key + ] + } + } +} + +# Создание ресурсов высокой доступности +# resource "proxmox_virtual_environment_haresource" "patroni" { +# for_each = { for vm in var.node_vms : vm.name => vm } + +# resource_id = "vm:${proxmox_virtual_environment_vm.patroni[each.key].vm_id}" +# state = "started" +# group = "prod" +# comment = "Managed by OpenTofu" +# } diff --git a/opentofu/kubeadm/provider.tf b/opentofu/kubeadm/provider.tf index 912ac71..e8a7099 100644 --- a/opentofu/kubeadm/provider.tf +++ b/opentofu/kubeadm/provider.tf @@ -2,7 +2,7 @@ terraform { required_providers { proxmox = { source = "bpg/proxmox" - version = ">= 0.51.0" + version = ">= 0.61.1" } } } diff --git a/opentofu/kubeadm/terraform.tfvars.example b/opentofu/kubeadm/terraform.tfvars.example index c5306f0..e046f62 100644 --- a/opentofu/kubeadm/terraform.tfvars.example +++ b/opentofu/kubeadm/terraform.tfvars.example @@ -1,2 +1,3 @@ virtual_environment_api_token = "root@pam!for-terraform-provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" virtual_environment_endpoint = "https://x.x.x.x:8006/" +ssh_public_key = "ssh-rsa ..." diff --git a/opentofu/kubeadm/variables.tf b/opentofu/kubeadm/variables.tf index 4508554..4d3e347 100644 --- a/opentofu/kubeadm/variables.tf +++ b/opentofu/kubeadm/variables.tf @@ -7,3 +7,8 @@ variable "virtual_environment_api_token" { type = string description = "The api roken the Proxmox Virtual Environment API (example: root@pam!for-terraform-provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)" } + +variable "ssh_public_key" { + type = string + description = "SSH Puclic key for VMs (example: ssh-rsa ...)" +}