Установка k8s со всей обвязкой

Thank you for reading this post, don't forget to subscribe!

рас­смот­рим как на bare metal под­нять кубер со всей обвяз­кой - ста­тья будет масштабной.

что нуж­но под­го­то­вить: несколь­ко сер­ве­ров на debian

уста­нав­ли­ва­е­те себе ansible выка­чи­ва­е­те сле­ду­ю­щую репку:
git clone https://github.com/midnight47/ansible-playbook.ginerdctlt

я её раз­ме­стил в /etc/ansible

cd /etc/ansible/

cat hosts

пер­вым делом я про­го­няю роль   по уста­нов­ке базо­вых паке­тов / пользователей

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/new_server.yml --ask-pass

1.Уста­нов­ка Freeipa
2.Уста­нов­ка Nexus
3.Уста­нов­ка Vault
4. Уста­нов­ка gitlab / gitlab-runner(host)
5. Уста­нов­ка NFS
6. Уста­нов­ка Glusterfs
7. Уста­нов­ка s3-minio
9.Инте­гра­ция Freeipa
9.1 Freeipa -> Nexus
9.2 Freeipa -> Gitlab
9.3 Freeipa -> Vault
9.4 Freeipa -> S3-Minio
10. Уста­нов­ка kubernetes (kubespray - official)
10.1 Доступ с локаль­но­го PC до кластера
11  Уста­нов­ка допол­ни­тель­ных компонентов
11.1 Ingress
11.1.1 ingress helm installation (пред­по­чти­тель­ный вариант)
11.2 Metallb
11.2.1 Metallb helm-installation  (пред­по­чти­тель­ный вариант)
11.3 NFS provisioner
11.4 GlusterFS provisioner
11.5 Seaweedfs provisioner (есть про­бле­мы с fuse chown, sync victoria-metrics не поднялась)
11.6 monitoring - Prometheus, grafana, alertmanager
11.7 monitoring - Victoria-metrics, grafana, alertmanager (пред­по­чти­тель­ный вариант)
11.7.1 Exporter on node not in the k8s
11.7.2 VMServiceScrape - for ingress controller
11.8 Metrics servers
11.9 Пра­вим COREDNS и LOCALDNS что­бы рабо­тал resolv.
11.10 Log - elk
11.11 Log - loki
11.11.1 Log - loki (backend s3-minio без Freeipa - LDAP)
11.11.2 Log - loki (backend s3-minio c Freeipa - LDAP)
11.11.3 Log - Loki - s3 bucket (seaweedfs)
11.11.4 Promail (сбор­щик логов)
11.11.5 Инте­гра­ция grafana с loki
12 Vault - auto unseal
12.1.1 Уста­нов­ка vault в k8s
12.1.2 Уста­нов­ка autounseal для vault в k8s через cronjob
12.1.3 Настрой­ка tranzit autounseal vault на физи­че­ских серверах
12.1.4 обно­вить токен для рас­пе­ча­ты­вая основ­но­го vault
12.2 Инте­гра­ция vault и k8s "Vault Secrets Operator"
12.3 При­мер с autoreloader после изме­не­ния сек­ре­та в vault
13 Аутен­ти­фи­ка­ция, авто­ри­за­ция в k8s (SSO в kubernetes через Freeipa)
13.1 Loft (мне не очень понра­ви­лось, не рекомендую)
13.2 Dex - dexK8sAuthenticator  (нор­маль­но рабо­та­ет - дёше­во и сердито)
13.3 Rancher (луч­ше ста­вить на отдель­ной вир­ту­ал­ке а не в кла­сте­ре, мно­го функционала)
13.3.1 Rancher инте­гра­ция с Freeipa
13.3.2 Rancher под­клю­че­ние к k8s кластеру
13.3.3 Rancher про­вер­ка авто­ри­за­ции для поль­зо­ва­те­лей k8s
13.4 Keycloak (слож­ная шту­ка, у меня тол­ком с ней ниче­го не завелось)
13.4.1 Инте­гра­ция keycloak c Freeipa
13.4.2 Настрой­ка под­клю­че­ния к k8s
13.5 Teleport
13.5.1 уста­нов­ка teleport
13.5.2 Под­клю­че­ние кла­сте­ра Kubernetes к Teleport
13.5.3 инте­гра­ция teleport - keycloak
14.0.0 Обнов­ле­ние кла­сте­ра k8s
14.0.1 update 1.24->1.25
14.0.2 update 1.25->1.26
14.0.3 update 1.26->1.27
14.0.4 update 1.27->1.28
14.0.5 update 1.28->1.29
14.0.6 update 1.29->1.30
14.0.6 update 1.30->1.31
14.0.7 update 1.31->1.32
14.0.8 update 1.32.5 - > 1.32.9 (пока писал ста­тью новые вер­сии вышли)
14.0.9 update 1.32.9 - > 1.33.5 (install PLUTO)
14.0.10 update 1.33.5 -> 1.34.1
15.1 Gitlab in k8s (helm chart)
15.2 Gitlab runner in k8s
15.3 Gitlab helm chart с Freeipa
16.1 Резерв­ное копи­ро­ва­ние etcd в hostPath
16.2 Резерв­ное копи­ро­ва­ние etcd в s3-minio
16.3 Резерв­ное копи­ро­ва­ние etcd в s3-minio (LDAP enabled)
17 Cert-manager (self-signed - самоподписанный)
18 Argocd
18.1 Argocd add user
18.2 Argocd инте­гра­ция с Freeipa
18.3.1 Argocd созда­ние про­ек­та, настрой­ка деплоя
18.3.2 Argocd созда­ние про­ек­та, настрой­ка деп­лоя Helm
18.3.3 Argocd созда­ние про­ек­та из кон­фиг файла
18.3.4 Argocd созда­ние про­ек­та. настрой­ка деп­лоя Helm когда values и chart в раз­ных репозиториях
19 Keda
20 Patrony (кла­стер для postgresql)
21 Helm-chart
21.1 Созда­ние дефолт­но­го чарта
21.2 Добав­ле­ние сек­ре­тов из vault
21.3 Добав­ле­ние Topology Spread Constraints
21.4 Добав­ле­ние RollingUpdate
21.5 При­ме­ры исполь­зо­ва­ния affinity/anti-affinity, nodeSelector, taint/tolerations
21.6 Добав­ле­ние PodDisruptionBudget
21.7 Ingress+ cert-manager+resources
21.8 Про­ве­рим HPA (HorizontalPodAutoscaler)
21.9 Доба­вим Keda (есть при­ме­ры с логи­кой скей­лин­га ИЛИ / И)
21.9.1 Скей­линг с логи­кой ИЛИ
21.9.2 Скей­линг с логи­кой И
21.10 Кон­тей­не­ры в POD
21.10.1 обыч­ные кон­тей­не­ры (sidecar)
21.10.2 init кон­тей­не­ры
21.10.3 ephemeral Containers (debug) контейнеры
21.11 Configmap (дела­ем связ­ку nginx->php-fpm)
21.12 volume/ephemeral volume/emptyDir
21.13 job и cronjob
21.14 probe grpc tcp http
21.15 network policy
21.16 Canary/Blue-green deployment
21.16.1 Blue-Green
21.16.2 Canary
22 Pod priority class
22.1 add priorityClassName promtail
22.2 add priorityClassName vault-csi-provider
22.3 add priorityClassName ingress-nginx-controller
23 про­ве­рим VPA vertical-pod-autoscaler
23.1 изме­ним дефолт­ное зна­че­ние реплик 2 на 1 для VPA updater
24 namespace limitrange (огра­ни­че­ния для ресур­сов на уровне namespace)
25 istio+kiali (service mesh)
25.1 уста­нов­ка istio - исполь­зу­ем sidecar
25.2 уста­нов­ка kiali
26.0.1 Заме­на nginx ingress controller(Envoy Gateway)
26.0.2 Уста­нов­ка Envoy Gateway
26.1 Helm chart - gateway вме­сто ingress
27 Пере­езд на новую опе­ра­ци­он­ку debian 13
27.1 про­бле­ма с пере­ез­дом kub-master1  etcd
27.2 про­бле­ма с пере­ез­дом kub-master1  сертификаты
27.3 про­бле­мы с пере­ез­дом kub-master1 локаль­ный kubctl
27.4 про­бле­мы с пере­ез­дом kub-master1 scheduller
27.5 про­бле­мы с пере­ез­дом - worker node  а имен­но - cluster-info
27.6 быст­рая диа­гно­сти­ка проблем
27.7 пере­езд worker-node
28.1 Резерв­ное копи­ро­ва­ние etcd в hostPath (без bitnami)
28.2 Резерв­ное копи­ро­ва­ние etcd в s3-minio (без bitnami)
29.0 Обнов­ле­ние кла­сте­ра k8s после пере­ез­да на debian 13
29.1 update v1.34.1 -> 1.34.6
29.2 update v1.34.6 -> 1.35.4
29.3 update v1.35.4 -> 1.36.2

 

 

 

 

Установка Freeipa

У меня 2 сер­ве­ра CENTOS 7 с параметрами
2 ядра 4 гб опе­ра­тив­ки - это­го хва­та­ет на про­цесс уста­нов­ки - мень­ше опе­ра­тив­ки я бы не ста­вил так как может прий­ти OOMkill после того как вся уста­нов­ка прой­дёт мож­но и пони­зить ресур­сы до 1 ядра и 2гб оперативки

Под­го­тав­ли­ва­ем для freeipa inventory файл

cd /etc/ansible/

cat hosts

у нас будет 2 сер­ве­ра freeipa для отка­зо­устой­чи­во­сти на них будет dns сер­вер отве­ча­ю­щий за зону test.local

cat /etc/ansible/playbooks/roles_play/freeipa.yaml

в дан­ном фай­ле мы обя­за­тель­но зада­ём домен test.local  и пароль Secret123

запус­ка­ем установку:

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/freeipa.yaml --ask-pass

дожи­да­ем­ся окон­ча­ния и про­ве­ря­ем работу:

https://freeipa-1.test.local/

после можем сни­зить пара­мет­ры сер­ве­ра до 1 ядра и 2гб оперативки

 

Установка Nexus

для ноды с nexus нуж­но мини­мум 1 ядро и 2гб оперативки

на сер­ве­ре ansible ставим:

ansible-galaxy collection install community.general

пере­хо­дим в директорию:

/etc/ansible/roles/nexus/files
cd /etc/ansible/roles/nexus/files
объ­еди­ня­ем архив
cat jdk-8u371-linux-x64.tar.gz.part_* > jdk-8u371-linux-x64.tar.gz

cd /etc/ansible/

cat hosts

 

ука­зы­ва­ем пароль и домен:
- domain: nexus.test.local
- password: Secret123

cat /etc/ansible/playbooks/roles_play/nexus.yml

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/nexus.yml --ask-pass

дожи­да­ем­ся окон­ча­ния уста­нов­ки и про­ве­ря­ем работу:

http://nexus.test.local:8081/

 

Установка vault

cd /etc/ansible/
cat hosts

в фай­ле
/etc/ansible/roles/vault/defaults/main.yaml

выстав­ля­ем пара­мет­ры для сер­ти­фи­ка­та кото­рый будет сге­не­рен и какие там будут домены

если у вас уже есть сер­ти­фи­кат (куп­лен­ный или сам­под­пи­ан­ный) то поло­жи­те его в дирек­то­рию /etc/ansible/roles/vault/ssl/  назо­ви­те его my_crt_file.crt так же нуж­но поло­жить в эту дирек­то­рию pem файл  my_crt_file.pem   имя фай­лов как и дирек­то­рию мож­но задать в пере­мен­ных  localhost_ssl_dir   vault_certificate_file_name в фай­ле /etc/ansible/roles/vault/defaults/main.yaml   если это­го не сде­лать то будет сге­не­рен само­под­пи­сан­ный сертификат
после уста­нов­ки и рас­пе­чат­ки вол­та  в дирек­то­рии /etc/ansible/roles/vault/unseal_tmp  появит­ся рут токен и клю­чи для распечатки.

 

запус­ка­ем установку:

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/vault.yml --ask-pass

как и писал выше клю­чи вот тут:

 

Установка gitlab / gitlab-runner(host)

по ресур­сам нуж­но для установки

4 ядра 4 оперативки
20 гб диска

/etc/ansible/hosts

 

/etc/ansible/playbooks/roles_play/gitlab.yml

если хотим ран­нер  хосто­вой  то ста­вим пере­мен­ную в true

запус­ка­ем установку:

ansible-playbook -u root /etc/ansible/playbooks/roles_play/gitlab.yml --ask-pass

дожи­да­ем­ся кон­ца установки.
в самом кон­це анси­бл пока­жет пароль:

про­ве­ря­ем:

http://gitlab.test.local/
логин: root
пароль:  Ukhr+Al9mi9SutCfItn05Q+MtsYLM9HZ7OkoxpUBxk8=

захо­дим и меня­ем пароль. я меняю на Secret123

гото­во, после уста­нов­ки можем отка­тить ресур­сы на 2 ядра и 3,5 гб оперативки

 

Установка NFS

по ресур­сам хва­тит 1 ядро и 512 оперативки

можем поме­нять дирек­то­рию в кото­рой будут хра­нит­ся дан­ные на nfs сер­ве­ре, а на кли­ен­те к какой дирек­то­рии будет под­клю­че­но хра­ни­ли­ще, или вооб­ще не созда­вать, если хотим исполь­зо­вать как про­ви­жи­нер на k8s:

/etc/ansible/playbooks/roles_play/nfs.yml

в моём при­ме­ре на кли­ен­тах я буду созда­вать дирек­то­рии к кото­рым под­клю­че­но хранилище.

/etc/ansible/hosts

ansible-playbook -u root /etc/ansible/playbooks/roles_play/nfs.yml --ask-pass

дожи­да­ем­ся окон­ча­ния и проверяем:

 

Установка GLUSTERFS

можем задать дирек­то­рии для сер­ве­ра и кли­ен­тов и имя для glusterfs tom:

/etc/ansible/playbooks/roles_play/glusterfs.yml

/etc/ansible/hosts

если нуж­но доба­вить боль­ше сер­ве­ров то про­сто доки­ды­вай­те в glustermaster. Репли­ка­фак­тор равен 2 все­гда. Изме­нить мож­но тут:
/etc/ansible/roles/glusterfs/tasks/add-tom.yml

запус­ка­ем установку:

ansible-playbook -u root /etc/ansible/playbooks/roles_play/glusterfs.yml --ask-pass

после пер­во­го про­хож­де­ния запу­сти­те ещё раз, - воз­мож­ны про­бле­мы при пер­вом проходе

Даль­ше проверяем:

 

 

и на сервере

любой из сер­ве­ров мож­но спо­кой­но выклю­чать, доступ настро­ен через fstab

 

Установка S3-minio

Уста­но­вим хра­ни­ли­ще S3 minio в виде кла­сте­ра что­бы была репли­ка­ция как баке­тов так и поль­зо­ва­те­лей с роля­ми, + у нас будет вир­ту­аль­ный IP что­бы мы ходи­ли по одно­му и тому же адресу.
Приступим:

под­го­то­вим 2 сер­ве­ра debian 12  1CPU 1RAM и нуж­но будет доба­вить туда по выде­лен­ную раз­де­лу , т.е. про­сто ука­зать дирек­то­рию не прокатит.

ip будут

192.168.1.118 # s3-minio1

192.168.1.119 # s3-minio2

192.168.1.120 # s3-minio это вир­ту­аль­ный IP
про­го­ня­ем плей­бук на уста­нов­ку всех поль­зо­ва­те­лей доп паке­тов и т.д.
пра­вим
/etc/ansible/hosts

 
[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/new_server.yml --ask-pass

 

после это­го настра­и­ва­ем на этих сер­ве­рах доп диск у меня он будет на LVM

Этой коман­дой

созда­ём PV pvcreate /dev/sdb
рас­ши­ря­ем груп­пу vgextend debian-vg /dev/sdb
созда­ём том на 10GB lvcreate --name minio -L 10g debian-vg
фор­мат­ри­уем том в нуж­ную фай­ло­вую систе­му mkfs.ext4 /dev/mapper/debian--vg-minio
созда­ём дирек­то­рию в кото­рую будем мон­ти­ро­вать том mkdir /minio
мон­ти­ру­ем том mount /dev/debian-vg/minio /minio

далее доба­вим в fstab это

про­ве­ря­ем

root@debian:~# echo "/dev/mapper/debian--vg-minio /minio ext4 errors=remount-ro 0 1" >> /etc/fstab
root@debian:~# reboot

на вто­ром сер­ве­ре дела­ем тоже самое:

ок сер­ве­ра под­го­то­ви­ли теперь настро­им роль:

/etc/ansible/hosts

/etc/ansible/roles/minio/defaults/main.yml

ука­зы­ва­ем что мы будем исполь­зо­вать вир­ту­аль­ный IP  keepalived: true
ука­зы­ва­ем наш LVM том minio_server_datadirs
ука­зы­ва­ем име­на наших s3 нод minio_server_cluster_nodes  отме­чу что эти име­на долж­ны сов­па­дать с теми что ука­за­ны в /etc/ansible/hosts
ука­зы­ва­ем руто­вый логин minio_root_user
ука­зы­ва­ем руто­вый пароль minio_root_password

гото­во­го мож­но запус­кать установку:

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/s3-minio.yml --ask-pass

ждём окон­ча­ния и проверяем:

сна­ча­ла пер­вый сервер:

http://s3-minio-1.test.local:9001

вво­дим наши
admin
Secret123

Созда­ём бакет

созда­ём пользователя:

про­ве­ря­ем на вто­ром сервере:

http://s3-minio-2.test.local:9001/login

как видим на вто­ром сер­ве­ре и бакет и поль­зо­ва­тель доступ­ны - репли­ка­ция рабо­та­ет, всё ок

 

Интеграция FREEIPA

Для нача­ла созда­дим груп­пу сер­ве­ров груп­пы поль­зо­ва­те­лей для сервисов

созда­ём сле­ду­ю­щие груп­пы пользователей:

доба­вим 2 пользователя
user1 - будет админом
user2 - будет обыч­ным пользователем

теперь доба­вим их по соот­вет­ству­ю­щим группам

так же рас­ки­ды­ва­ем по осталь­ным группам

gitlab, nexus-admins, vault-admins - user1
gitlab. nexus-ro-users, vault-ro-users - user2

 

Freeipa -> Nexus

[root@freeipa-1 ~]# ipa cert-show 1 --out=/tmp/ipa-ca.crt
[root@freeipa-1 ~]# scp /tmp/ipa-ca.crt root@192.168.1.102:/tmp/
root@nexus:~# find / -name jre
/usr/lib/jvm/jdk1.8.0_371/jre/bin
root@nexus:/usr/lib/jvm/jdk1.8.0_371/jre/bin# ./keytool -import -trustcacerts -alias freeipa-ca -file /tmp/ipa-ca.crt -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Trust this certificate? [no]: yes
Certificate was added to keystore

Далее нам нуж­но создать систем­но­го поль­зо­ва­те­ля во freeipa с помо­щью кото­ро­го nexus смо­жет ходить в api и читать име­на поль­зо­ва­те­лей, но у него не будет прав что то выпол­нить. для это­го на сер­ве­ре freeipa или его репли­ке захо­дим в дирек­то­рию /etc/ipa  и запус­ка­ем скрипт. или выка­чи­ва­ем тут:
https://github.com/noahbliss/freeipa-sam

[root@freeipa-1 ipa]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

нажи­ма­ем 1 и зада­ём имя наше­го сервера:

нажи­ма­ем enter и полу­ча­ем результат:

как видим далее мы нажа­ли
выби­ра­ем любо­го поль­зо­ва­те­ля с админ­ски­ми пра­ва­ми - я выбрал admin

Далее выби­ра­ем 4 и нуж­но будет вве­сти пароль

после выби­ра­ем 5 чтоб отклю­чить SSL

как видим ssl=true поме­ня­лось на ssl=false

жмём enter и после можем созда­вать систем­но­го поль­зо­ва­те­ля nexus для это­го наби­ра­ем коман­ду add

далее вво­дим пароль и нас попро­сят ука­зать дату окон­ча­ния рабо­ты это­го паро­ля, там ниче­го не ука­зы­ва­ем - про­сто жмём ENTER

коман­дой ls можем про­ве­рить создан­но­го пользователя

пароль я кста­ти задал Secret123

 

логи­ним­ся в nexus и пере­хо­дим в настрой­ки LDAP

для запол­не­ния исполь­зу­ем данные
uid=nexus,cn=sysaccounts,cn=etc,dc=test,dc=local

про­ве­ря­ем и нажи­ма­ем NEXT

далее настра­и­ва­ем

 

User relative DN: cn=users,cn=accounts
User subtree: уста­нав­ли­ва­ем галку.
Object class: inetOrgPerson
User filter: (memberOf=cn=nexus-admins,cn=groups,cn=accounts,dc=test,dc=local)
User ID attribute: uid
Real name attribute: cn
Email attribute: mail
Password attribute: остав­ля­ем пустым.
Map LDAP groups as roles: уста­нав­ли­ва­ем галку.
Group type: Static Groups
Group relative DN: cn=groups,cn=accounts
Group subtree: уста­нав­ли­ва­ем галку.
Group object class: groupOfNames
Group ID attribute: cn
Group member attribute: member
Group member format: uid=${username},cn=users,cn=accounts,dc=example,dc=org

всё нажи­ма­ем create

идём про­ве­рять:

Настра­и­ва­ем тоже самое для вто­ро­го сер­ве­ра - для отказоустойчивости:

 

Созда­ём админ­скую роль чтоб поль­зо­ва­те­ли под­тя­ги­ва­лись и ста­но­ви­лись сра­зу админами:

всё, теперь мота­ем в самый низ и сохра­ня­ем роль

вот наша роль:

про­ве­ря­ем, для это­го идём во freeipa и добав­ля­ем ново­го пользователя:

добав­ля­ем его в груп­пу nexus-admins

про­ве­ря­ем в nexus

поль­зо­ва­тель есть:

и он в нуж­ны­ми пра­ва­ми правами

 

read only группа

тут пока в настрой­ках остав­ля­ем всё так же

а вот при настройке

User filter мы меня­ем груп­пу с nexus-admins на nexus-ro-users

(memberOf=cn=nexus-ro-users,cn=groups,cn=accounts,dc=test,dc=local)

и созда­ём роль с при­ви­ле­ги­я­ми - тут я ука­зал при­ве­ле­гии пер­вые попав­ши­е­ся, вы може­те зада­вать какие нуж­ны имен­но вам.

про­ве­ря­ем пра­ва у поль­зо­ва­те­ля user2

как видим всё ок

 

Freeipa -> Gitlab

сде­ла­ем инте­гра­цию меж­ду freeipa и gitlab

к сожа­ле­нию в бес­плат­ной вер­сии гит­ла­ба нель­зя при­вя­зы­вать поль­зо­ва­те­лей к опре­де­лён­ным груп­пам в гитла­бе, вот дока:
https://docs.gitlab.com/ee/administration/auth/ldap/ldap_synchronization.html

поэто­му созда­дим 1 груп­пу в FreeIPA:

gitlab

созда­дим систем­но­го поль­зо­ва­те­ля gitlab у кото­ро­го будет доступ на чте­ние групп и пользователей.

для это­го на сер­ве­ре freeipa или его репли­ке захо­дим в дирек­то­рию /etc/ipa  и запус­ка­ем скрипт. или выка­чи­ва­ем тут:
https://github.com/noahbliss/freeipa-sam

[root@freeipa-1 ipa]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

нажи­ма­ем 1 и зада­ём имя наше­го сер­ве­ра freeipa-1.test.local :

вот резуль­тат:

выбра­ли 3 ука­зы­ва­ем поль­зо­ва­те­ля admin (любой поль­зо­ва­тель с пра­ва­ми админа)в нашем freeipa далее выбе­рем 4 и зада­дим пароль от это­го поль­зо­ва­те­ля, после выби­ра­ем 5 чтоб отклю­чить SSL

после можем созда­вать систем­но­го поль­зо­ва­те­ля gitlab для это­го наби­ра­ем коман­ду add

нас попро­сят вве­сти имя поль­зо­ва­те­ля мы вво­дим gitlab после нас попро­сят вве­сти пароль я ука­зал Secret123  далее нас попро­сят ука­зать дату исте­че­ния это­го пароль - ниче­го не ука­зы­ва­ем, нажи­ма­ем ENTER

про­ве­ря­ем что поль­зо­ва­тель создан для это­го наби­ра­ем ls

как видим поль­зо­ва­тель создан:

dn: uid=gitlab,cn=sysaccounts,cn=etc,dc=test,dc=local

 

теперь идём на сер­вер gitlab

[root@ansible ansible]# ssh 192.168.1.106
root@192.168.1.106's password:

редак­ти­ру­ем файл:
root@gitlab:~# nano /etc/gitlab/gitlab.rb

вклю­ча­ем LDAP
gitlab_rails['ldap_enabled'] = true

Затем ука­жи­те путь к фай­лу с настрой­ка­ми LDAP для FreeIPA.

gitlab_rails['ldap_servers'] = YAML.load_file('/etc/gitlab/freeipa_settings.yml')
Нако­нец, создай­те файл YAML для хра­не­ния настро­ек под­клю­че­ния IPA.

cat /etc/gitlab/freeipa_settings.yml

вот тут:
user_filter: 'memberOf=cn=gitlab,cn=groups,cn=accounts,dc=test,dc=local'
мы огра­ни­чи­ва­ем поль­зо­ва­те­лей груп­пой gitlab

bind_dn: 'uid=gitlab,cn=sysaccounts,cn=etc,dc=test,dc=local'
а тут мы исполь­зу­ем систем­ный акка­унт кото­рый созда­ли ранее

и запус­ка­ем реконфигурацию:

root@gitlab:~# gitlab-ctl reconfigure

про­ве­ря­ем:

http://gitlab.test.local/users/sign_in

как видим всё ок.

даль­ше можем настра­и­вать груп­пы и добав­лять поль­зо­ва­те­лей внут­ри гитлаба

 

Freeipa -> Vault

созда­дим систем­но­го поль­зо­ва­те­ля vault у кото­ро­го будет доступ на чте­ние групп и пользователей.

для это­го на сер­ве­ре freeipa или его репли­ке захо­дим в дирек­то­рию /etc/ipa  и запус­ка­ем скрипт. или выка­чи­ва­ем тут:
https://github.com/noahbliss/freeipa-sam

[root@freeipa-1 ipa]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

нажи­ма­ем 1 и зада­ём имя наше­го сер­ве­ра freeipa-1.test.local 
нажи­ма­ем 3 и вво­дим имя поль­зо­ва­те­ля admin
нажи­ма­ем 4 и вво­дим пароль Secret123
нажи­ма­ем 5 - выклю­ча­ем ssl

далее нажи­ма­ем add пред­ло­жат вве­сти имя систем­но­го поль­зо­ва­те­ля, вво­дим vault пред­ло­жат вве­сти пароль для него, я исполь­зую Secret123 далее попро­сят вве­сти дату исте­че­ния паро­ля, ниче­го не вво­дим, нажи­ма­ем Enter

поль­зо­ва­тель создан, про­ве­ря­ем, нажи­ма­ем ls
вот результат:

со сто­ро­ны freeipa всё,

теперь настра­и­ва­ем vault:

на всех тач­ках добавляем:

echo "192.168.1.100 freeipa-1.test.local" >> /etc/hosts

если DNS не настроен.

захо­дим в vault

https://vault.test.local:8200/

напом­ню что root_token hvs.UuG0QJvRRfwUHUTGxDTjFaAd

пере­хо­дим:
Access -> Enable new Method -> LDAP -> Enable Method

теперь настра­и­ва­ем
URL = ldap://freeipa-1.test.local:389

в раз­де­ле LDAP options:  рас­кры­ва­ем и меня­ем User atrribut на  uid

Сле­ду­ю­щий раз­дел customize user search — тут мы как раз и настра­и­ва­ем адрес кем бин­дим­ся, а так же где искать поль­зо­ва­те­лей, для freeipa это будут такие параметры

Name of Object to bind (binddn) =        uid=vault,cn=sysaccounts,cn=etc,dc=test,dc=local
User DN =    cn=users,cn=accounts,dc=test,dc=local
Bindpass  =    Secret123

Так же настро­им поиск по группам

Group Filter  =  (|(member={{.UserDN}})(uniqueMember={{.UserDN}}))
Group Attribute  = cn
Group DN  = cn=groups,cn=accounts,dc=test,dc=local

теперь созда­дим policy для адми­нов и пользователей

и ещё одну

вот сами policy:
vault-admins

vault-ro-users

 

теперь  груп­пы в LDAP

груп­па vault-admins
policy vault-admins

добав­ля­ем вто­рую группу
груп­па vault-ro-users
policy vault-ro-users

про­ве­ря­ем:

как видим KV успеш­но создан

теперь зай­дём под user2 кото­рый напом­ним что нахо­дит­ся в груп­пе vault-ro-users

как видим нам не хва­та­ет прав на созда­ние ново­го KV

настрой­ка закон­че­на, далее мож­но изме­нять policy как нам требуется.

ниже ука­за­но как про­из­ве­сти всё тоже самое но  кон­соль­ны­ми командами

захо­дим на vault и логинимся

vault login

вво­дим рут токен

вклю­ча­ем LDAP

vault auth enable ldap

настра­и­ва­ем подключение

vault write auth/ldap/config \
url="ldap://freeipa-1.test.local:389" \
binddn="uid=vault,cn=sysaccounts,cn=etc,dc=test,dc=local" \
bindpass='Secret123' \
userdn="cn=users,cn=accounts,dc=test,dc=local" \
userattr="uid" \
groupdn="cn=groups,cn=accounts,dc=test,dc=local" \
groupfilter="(|(member={{.UserDN}})(uniqueMember={{.UserDN}}))" \
groupattr="cn"

созда­ём policy
vault-admins

vault policy write vault-admins - <<EOF path "*" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] } EOF

и vault-ro-users

vault policy write vault-ro-users - <<EOF path "*" { capabilities = ["read", "list"] } EOF

созда­ём груп­пы в ldap и при­вя­зы­ва­ем к ним policy

vault write auth/ldap/groups/vault-admins policies=vault-admins
vault write auth/ldap/groups/vault-ro-users policies=vault-ro-users

 

Freeipa -> S3-Minio

Настра­и­ва­ем инте­гра­цию Freeipa с S3-Minio

/etc/ansible/hosts

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/freeipa.yaml --ask-pass

идём в freeipa

https://freeipa-1.test.local/

созда­ём груп­пу узлов:

Добав­ля­ем туда наши сервера

созда­ём груп­пы поль­зо­ва­те­лей  admin и read only

user1 у нас будет в груп­пе админов
user2 у нас будет в груп­пе read only пользователей

Далее нам нуж­но создать систем­но­го поль­зо­ва­те­ля во freeipa с помо­щью кото­ро­го s3-minio смо­жет ходить в api и читать име­на поль­зо­ва­те­лей, но у него не будет прав что то выпол­нить. для это­го на сер­ве­ре freeipa или его репли­ке захо­дим в дирек­то­рию /etc/ipa  и запус­ка­ем скрипт. или выка­чи­ва­ем тут:
https://github.com/noahbliss/freeipa-sam

[root@freeipa-1 ipa]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

нажи­ма­ем 1 и зада­ём имя наше­го сер­ве­ра freeipa-1.test.local :

вот резуль­тат:

выбра­ли 3 ука­зы­ва­ем поль­зо­ва­те­ля admin (любой поль­зо­ва­тель с пра­ва­ми админа)в нашем freeipa далее выбе­рем 4 и зада­дим пароль от это­го поль­зо­ва­те­ля, после выби­ра­ем 5 чтоб отклю­чить SSL

после можем созда­вать систем­но­го поль­зо­ва­те­ля s3minio для это­го наби­ра­ем коман­ду add

нас попро­сят вве­сти имя поль­зо­ва­те­ля мы вво­дим s3minio  после нас попро­сят вве­сти пароль я ука­зал Secret123 далее нас попро­сят ука­зать дату исте­че­ния это­го пароль - ниче­го не ука­зы­ва­ем, нажи­ма­ем ENTER

про­ве­ря­ем что поль­зо­ва­тель создан для это­го наби­ра­ем ls

как видим поль­зо­ва­тель создан:

dn: uid=s3minio,cn=sysaccounts,cn=etc,dc=test,dc=local

даль­ше настрой­ка из консоли:

1 созда­ём подключение:

2. про­ве­ря­ем какие баке­ты есть

3. настра­и­ва­ем под­клю­че­ние к ldap

рестар­ту­ем

под­вя­зы­ва­ем поли­ти­ку consoleAdmin к роли адми­нов s3-minio-admins

под­вя­зы­ва­ем поли­ти­ки readwrite и diagnostics к роли поль­зо­ва­те­лей s3-minio-ro-users я вижу что роль назы­ва­ет­ся RO но мне лень сей­час и скри­ны пере­де­лы­вать и роль переименовывать.

 

про­ве­ря­ем в админ пане­ли minio что досту­пы есть:

про­ве­ря­ем авто­ри­за­цию напом­ню что user1 у нас в груп­пе адми­нов а user2 в груп­пе поль­зо­ва­те­лей, + логин пароль исполь­зу­ем из freeipa

y user1  админ­ка не отли­ча­ет­ся от поль­зо­ва­те­ля admin

вот админ­ка поль­зо­ва­те­ля user2

ну всё ок. логин проверили.

инте­гра­ция успеш­но настроена.

 

Install kubernetes (kubespray official)

 

Под­го­то­вим 6 сер­ве­ров 3 под масте­ров 3 под воркеры

опе­ра­ци­он­ка debian 12

192.168.1.112 # kub-master1
192.168.1.113 # kub-master2
192.168.1.114 # kub-master3
192.168.1.115 # kub-worker1
192.168.1.116 # kub-worker2
192.168.1.117 # kub-worker3

для масте­ров 2 ядра 4 оперативки
для вор­ке­ров 4 ядра 4 оперативки

так же под­го­то­вим дис­ки мини­мум 30 гб

pvcreate /dev/sdb && vgextend debian-vg /dev/sdb && lvextend -L +15G /dev/debian-vg/root  &&  resize2fs /dev/debian-vg/root

обно­вим и доуста­но­вим все необ­хо­ди­мые пакеты:

/etc/ansible/hosts

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/new_server.yml --ask-pass

ЭТО ОПЦИОНАЛЬНО доба­вим эти сер­ве­ра сра­зу к freeipa. nexus

(мож­но и не добав­лять если в вашем вари­ан­те это не требуется)

/etc/ansible/hosts

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/freeipa.yaml --ask-pass

теперь можно приступать к установке k8s

нам нужен будет python3.8 у меня на ansible исполь­зу­ет­ся опе­ра­ци­он­ка centos7 с python3.6 поэто­му я став­лю так:

yum install -y gcc openssl-devel bzip2-devel libffi-devel zlib-devel
cd /usr/src
wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz
tar xzf Python-3.8.10.tgz
cd Python-3.8.10
./configure --enable-optimizations
make altinstall
python3.8 -m venv ~/venv
source ~/venv/bin/activate

 

вот тут офи­ци­аль­ный чарт kubespray

https://github.com/kubernetes-incubator/kubespray.git

в моём репо­зи­то­рии тоже исполь­зу­ет­ся офи­ци­аль­ный kubespray но так в моём репо­зи­то­рии исполь­зу­ет­ся ста­рый kubespray

Ста­вим все нуж­ные зави­си­мо­сти в ansible:

root@ansible:/etc/ansible# cd /etc/ansible/kubespray-official/kubespray
root@ansible:/etc/ansible/kubespray-official/kubespray# apt install python3-pip -y
root@ansible:/etc/ansible/kubespray-official/kubespray# pip install -r requirements.txt
root@ansible:/etc/ansible/kubespray-official/kubespray# pip install -U jinja2

запол­ня­ем inventory

/etc/ansible/kubespray-official/kubespray/inventory/sample/inventory.ini

допол­ни­тель­ные аддо­ны мы можем вклю­чить тут:

inventory/sample/group_vars/k8s_cluster/addons.yml

я выклю­чаю всё кро­ме helm_enabled и local_volume_provisioner_enabled

Далее пра­вим
vim inventory/sample/group_vars/all/all.yml

#тут ука­зы­ва­ем наши днс сер­ве­ра, я исполь­зую гуг­ло­вые, мож­но оста­вить по умол­ча­нию. ниже ука­зы­ва­ем наш прок­си если он исполь­зу­ет­ся http_proxy: "http://proxy_ip:3128" https_proxy: "http://proxy_ip:3128"

я добав­ляю ещё мои 2 dns сер­ве­ра с freeipa это 192,168,1,100 и 192,168,1,101

vim inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
вклю­чим все вари­ан­ты аутен­ти­фи­ка­ции (обра­ти­те вни­ма­ние на отсту­пы в yml фай­лах, моду­ли долж­ны быть без отступов)

kube_oidc_auth: true
kube_token_auth: true

в фай­ле
/etc/ansible/kubespray-official/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
настраиваем:

вер­сию кластера:
kube_version: v1.24.0
пла­гин сети
kube_network_plugin: calico
под­сеть для service
kube_service_addresses: 10.233.0.0/18
под­сеть для pod
kube_pods_subnet: 10.233.64.0/18
под­сеть node
kube_network_node_prefix: 24
выклю­чим под­держ­ку IPv6
enable_dual_stack_networks: false
имя кластера
cluster_name: cluster.local
мож­но настро­ить авто обнов­ле­ние сер­ти­фи­ка­тов controlplane, но я это буду делать в руч­ном режиме.
auto_renew_certificates: false

на debian я запус­кал так:

 

запус­ка­ем установку:

ansible-playbook -u root -i inventory/sample/inventory.ini cluster.yml -b --ask-pass

ждём минут 30-40 зави­сит от сети и системы

про­ве­ря­ем:

[root@ansible ansible]# ssh 192.168.1.112
root@kub-master1:~# kubectl get nodes

 

Доступ с локального PC до кластера

допу­стим у нас PC с опе­ра­ци­он­кой debian и ip адре­сом 192.168.1.120

root@debian:~# curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

root@debian:~# chmod +x kubectl

root@debian:~# cp ./kubectl /usr/bin/

копи­ру­ем кон­фиг на наш клиент

root@kub-master1:~# scp /etc/kubernetes/admin.conf root@192.168.1.120:~/

root@debian:~# mkdir -p ~/.kube
root@debian:~# mv admin.conf ~/.kube/config

так как в этом кон­фи­ге ука­зан 127.0.0.1 в каче­стве сер­ве­ра, заме­ним на наш ip 192.168.1.112

root@debian:~# sed -i 's/127.0.0.1/192.168.1.112/' ~/.kube/config

можем про­ве­рять

настро­им ещё автодополнения
root@debian:~# apt-get install bash-completion -y
root@debian:~# echo 'source <(kubectl completion bash)' >>~/.bashrc

уста­но­вим на наш локаль­ный PC HELM

root@debian:~# apt-get install gpg -y
root@debian:~# curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | tee /usr/share/keyrings/helm.gpg > /dev/null
root@debian:~# apt-get install apt-transport-https --yes
root@debian:~# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | tee /etc/apt/sources.list.d/helm-stable-debian.list
root@debian:~# apt-get update
root@debian:~# apt-get install helm -y

доба­вим ещё пла­гин diff - пригодится
helm plugin install https://github.com/databus23/helm-diff

Установка дополнительных компонентов

Ставим ingress controller

сра­зу вклю­чим и мет­ри­ки и snippet-annotations

curl -sL https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.3/deploy/static/provider/cloud/deploy.yaml \
| sed 's/--enable-metrics=false/--enable-metrics=true/g; s/allow-snippet-annotations: "false"/allow-snippet-annotations: "true"/g' \
| kubectl apply -f -

про­ве­ря­ем:

 

Ingress controller helm install

 

или можем поста­вить через helm вот оф values

https://github.com/kubernetes/ingress-nginx/blob/helm-chart-4.12.2/charts/ingress-nginx/values.yaml

вот values
cat values.yaml

ста­вим командой:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

 

 

Metalllb

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml

пра­вим конфигмапу

kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply -f - -n kube-system

воз­вра­ща­ем­ся на ansible и идём в дирек­то­рию:  /etc/ansible/kubespray-official/

так как нам нуж­но отре­дак­ти­ро­вать фай­лы и при­ме­нить их а доступ на анси­бл мы давать не хотим то ско­пи­ру­ем эту дирек­то­рию на наш master и уже отту­да применим.

rsync -avh --progress metallb root@192.168.1.112:/tmp/

пере­хо­дим в мастер и захо­дим в дирек­то­рию  /tmp/metallb и редак­ти­ру­ем файл ip-pool.yaml

root@kub-master1:~# cd /tmp/metallb/
root@kub-master1:/tmp/metallb# vim ip-pool.yaml

В файл ip-pool.yaml добав­ля­ем или диа­па­зон IP адре­сов, или 1 IP ука­зав его под­сеть /32 (по это­му адре­су будет досту­пен кластер)
я доба­вил - 192.168.1.191/32  и  192.168.1.192/32

при­ме­ня­ем

kubectl apply -f ip-pool.yaml

Добав­ля­ем сер­вис для ingres-controller типа LoadBalancer

kubectl apply -f lb-ingress-controller-svc.yaml

про­ве­ря­ем:

как видим IP 192.168.1.191 и  192.168.1.192  явля­ют­ся EXTERNAL-IP

 

Metallb helm-installation

оффи­ци­аль­ный репозиторий

https://github.com/metallb/metallb/tree/main/charts/metallb

helm repo add metallb https://metallb.github.io/metallb
cat values.yaml

helm install metallb metallb/metallb -n metallb-system --create-namespace -f values.yaml
cat ip-pool.yaml

kubectl apply -f ip-pool.yaml

так же вклю­ча­ем strictArp

 

про­ве­рить можем так

cat 1.yaml

kubectl apply -f 1.yaml

 

NFS provisioner

добав­ля­ем доступ для сер­ве­ров k8s к nfs серверу

/etc/ansible/hosts

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/nfs.yml --ask-pass

 

копи­ру­ем
[root@ansible ansible]# scp -r /etc/ansible/kubespray-official/nfs-provision root@192.168.1.120:~/

с кли­ен­та захо­дим и пра­вим кон­фиг файл:

root@debian:~# cd ~/nfs-provision/
root@debian:~/nfs-provision# nano nfs_provision.yaml

уста­нав­ли­ва­ем ip адрес наше­го nfs сервера
192.168.1.108

всё, мож­но ста­вить все компоненты
root@debian:~/nfs-provision# kubectl apply -f rbac.yaml -f nfs_class.yaml -f nfs_provision.yaml
если что, внут­ри этой дирек­то­рии есть README.md

про­ве­ря­ем:

запро­сим тесто­вые volume

root@debian:~/nfs-provision# kubectl apply -f test-claim.yaml

 

GlusterFS provisioner

Добав­ля­ем доступ для наших k8s серверов:

/etc/ansible/hosts

[root@ansible ansible]# ansible-playbook -u root /etc/ansible/playbooks/roles_play/glusterfs.yml --ask-pass

копи­ру­ем фай­лы на клиента

[root@ansible ansible]# scp -r /etc/ansible/kubespray-official/glusterfs-provision root@192.168.1.120:~/

захо­дим на наш кли­ент и пра­вим файл:

root@debian:~# cd glusterfs-provision/
root@debian:~/glusterfs-provision# nano endpont.yml

добав­ля­ем IP наших glusterfs серверов

192.168.1.109
192.168.1.110

root@debian:~/glusterfs-provision# helm repo add olli-ai https://olli-ai.github.io/helm-charts/
root@debian:~/glusterfs-provision# helm repo update

про­ве­ря­ем:

ста­вим

glusterfs.volume: gluster-tom  - это том кото­рый мы зада­ва­ли при настрой­ке плейбука:
glusterfs.path / - это путь кото­рый в самом glusterfs будет смот­реть в самый корень т.е. вот сюда:

 

/etc/ansible/playbooks/roles_play/glusterfs.yml

ответ при­мер­но такой

про­ве­ря­ем

root@debian:~/glusterfs-provision# kubectl  apply -f test-claim.yaml

 

Seaweedfs provisioner

сра­зу ска­жу что есть про­бле­мы с под­клю­че­ни­ем по fuse

  1. не рабо­та­ет chown (при­шлось отклю­чать у grafana init контейнер)
  2. если делать репли­ка­цию 2 то тогда metadata у vmsingle victoria-metrics  не работает

так что как то так - для victoria-metrics не подо­шло, воз­мож­но отстре­лит ещё что то.

https://github.com/seaweedfs/seaweedfs-csi-driver/tree/master/deploy/helm/seaweedfs-csi-driver

ста­вим сам seaweedfs

/etc/ansible/hosts

root@ansible:/etc/ansible# ansible-playbook playbooks/roles_play/seaweedfs.yml --ask-pass 

теперь ста­вим provisioner

/etc/ansible/kubespray-official/seaweedfs-provision/values.yaml

helm repo add seaweedfs-csi-driver https://seaweedfs.github.io/seaweedfs-csi-driver/helm
helm repo update
helm install seaweedfs-csi-driver seaweedfs-csi-driver/seaweedfs-csi-driver   --namespace seaweedfs-csi-driver   --create-namespace   -f values.yaml --version 0.2.2

для про­вер­ки можем использовать:

/etc/ansible/kubespray-official/seaweedfs-provision/pvc-test.yaml

kubectl apply -f pvc-test.yaml -n seaweedfs-csi-driver

 

Prometheus, grafana, alertmanager

копи­ру­ем values кото­рый будем исполь­зо­вать для раз­вёр­ты­ва­ния prom stack

[root@ansible ansible]# scp -r /etc/ansible/kubespray-official/prometheus root@192.168.1.120:~/

далее на нашем PC с кото­ро­го есть доступ до кла­сте­ра ста­вим всё необходимое:
namespace:
root@debian:~# kubectl create ns monitoring

репо­зи­то­рий
root@debian:~# helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
root@debian:~# helm repo update
смот­рим вер­сии чартов
root@debian:~# helm search repo prometheus

мы будем исполь­зо­вать prometheus-community/kube-prometheus-stack  вер­сии 61.2.0

root@debian:~# cd prometheus/

в фай­ле my-values.yaml пра­вим домен­ные имена:
alertmanager.test.local
grafana.test.local
prometheus.test.local
даль­ше правим
storageClassName в моём слу­чае это nfs-client

выстав­ля­ем необ­хо­ди­мые объ­ё­мы для persistant volume
в полях storage
и size
так же если мы хотим соби­рать мет­ри­ки толь­ко с опре­де­лён­ных нейм­с­пей­сов мы можем исполь­зо­вать функ­ци­о­нал serviceMonitorNamespaceSelector

т.е. нуж­но будет добав­лять label к тем нейм­с­пей­сам с кото­рых хотим соби­рать метрики

при­ме­ним CRD

 

после это­го мож­но запус­кать установку:
root@debian:~/prometheus# helm install prometheus prometheus-community/kube-prometheus-stack --version 61.2.0 -n monitoring -f my-values.yaml

ста­вим леб­лы на все неймспейсы:
root@debian:~/prometheus# kubectl label namespace --all "prometheus=enabled"

отме­чу что есть про­бле­ма с prometheus-kube-proxy он стар­ту­ет на 127,0,0,1
а про­ме­те­ус лезет на айпиш­ник т.е. щимит­ся на ноды а там ни кто не отвечает.
для исправ­ле­ния дела­ем, НА МАСТЕРАХ правим:
vim /etc/kubernetes/kubeadm-config.yaml
c
metricsBindAddress: 127.0.0.1:10249
на
metricsBindAddress: 0.0.0.0:10249

 

мы вос­поль­зу­ем­ся скриптом:

for ip in 192.168.1.112 192.168.1.113 192.168.1.114; do ssh root@$ip "sed -i 's/metricsBindAddress: 127.0.0.1:10249/metricsBindAddress: 0.0.0.0:10249/' /etc/kubernetes/kubeadm-config.yaml"; done

редак­ти­ру­ем кон­фиг­мап, так же правим:
    metricsBindAddress: 127.0.0.1:10249
на
    metricsBindAddress: 0.0.0.0:10249
root@debian:~/prometheus# kubectl -n kube-system get cm kube-proxy -o yaml | sed 's/metricsBindAddress: 127.0.0.1:10249/metricsBindAddress: 0.0.0.0:10249/' | kubectl apply -f -
после чего пере­за­пус­ка­ем все kube-proxy:
for i in `kubectl get pod -n kube-system | grep kube-proxy | awk '{print $1}'`; do kubectl delete pod -n kube-system $i; done
про­ве­ря­ем:

http://grafana.test.local/
по умол­ча­нию логин admin пароль prom-operator

Victoria-metrics, grafana, alertmanager

в отли­чие от prometheus потреб­ля­ет мень­ше ресурсов.
kubectl create ns monitoring
ста­вим CRD
helm repo add vm https://victoriametrics.github.io/helm-charts/
helm repo update
helm search repo vm/victoria-metrics-operator-crds -l
helm install vmoc vm/victoria-metrics-operator-crds -n monitoring --version 0.2.1
смот­рим послед­ние версии

созда­ём сертификат:

/etc/ansible/kubespray-official/victoria-metrics/certs/ca_openssl.cnf

/etc/ansible/kubespray-official/victoria-metrics/certs/vm_openssl.cnf

openssl genrsa -out ca.key 4096
openssl req -x509 -sha256 -new -key ca.key -days 10000 -out ca.crt
openssl genrsa -out vmsingle.key 4096
openssl req -new -key vmsingle.key -out vmsingle.csr -config vm_openssl.cnf
openssl x509 -req -in vmsingle.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out vmsingle.crt -days 10000 -sha256 -extfile ca_openssl.cnf -extensions v3_ca
добав­ля­ем сер­ти­фи­кат в секреты

/etc/ansible/kubespray-official/victoria-metrics/values.yaml
helm upgrade --install vmks vm/victoria-metrics-k8s-stack -f values.yaml -n monitoring --version 0.52.0

 

Exporter on node not in the k8s

на нодах кото­рые не в кубе­ре мы можем запу­стить ком­поз­ник что­бы соби­рать с них метрики
/etc/ansible/kubespray-official/victoria-metrics/docker-compose-vmagent/prometheus.yml

тут ука­зы­ва­ем job_name: и груп­пи­ру­ем его по 'node-vault' , т.е. в спис­ке мы будем полу­чать все ноды под этой группой
тут ука­зы­ва­ем targets: ['192.168.1.103:9100'] это где IP адрес на кото­ром запу­щен сбор метрик
/etc/ansible/kubespray-official/victoria-metrics/docker-compose-vmagent/docker-compose.yml

тут ука­зы­ва­ем для vmagent '--remoteWrite.url=http://vmsingle.test.local/api/v1/write'  это адрес наше­го vmsingle.
если нету DNS внут­рен­не­го то нуж­но под­ки­нуть в хосты
cat /etc/hosts | grep vms
192.168.1.191 vmsingle.test.local
всё после это­го мож­но стартовать
docker-compose up -d
мы полу­ча­ем груп­пи­ро­ван­ные сер­ве­ра, (груп­пы и ip адре­са мы можем выбирать)

VMServiceScrape - for ingress controller

что­бы соби­рать мет­ри­ки с ingress controller во пер­вых на самом кон­трол­ле­ре долж­но быть включено:

а что­бы мет­ри­ки попа­ли в victoria-metrics нуж­но исполь­зо­вать сле­ду­ю­щий конфиг:

/etc/ansible/kubespray-official/victoria-metrics/scrape-ingress-controller.yaml

при­ме­ня­ем
kubectl apply -f scrape-ingress-controller.yaml

далее будут доступ­ны такие мет­ри­ки как:

nginx_ingress_controller_requests
nginx_ingress_controller_nginx_process_connections
и другие.

Metrics servers

root@debian:~/prometheus# helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
root@debian:~/prometheus# helm upgrade --install metrics-server metrics-server/metrics-server --set args={"--kubelet-insecure-tls"} -n monitoring
про­ве­ря­ем:

Правим COREDNS и LOCALDNS чтобы работал resolv

cat > coredns.yaml

kubectl apply -f coredns.yaml

тут мы ука­за­ли test.local чтоб искал ip в нашем freeipa 192.168.1.100 192.168.1.101

ещё пра­вил nodelocaldns

kubectl edit configmaps -n kube-system nodelocaldns

мы добав­ля­ем туда:

и рестар­ту­ем:

kubectl rollout restart -n kube-system daemonset nodelocaldns

Логирование - elk

[root@ansible ansible]# scp -r /etc/ansible/kubespray-official/elk/ root@192.168.1.120:~/
захо­дим на наше­го клиента
root@debian:~# cd elk/
созда­ём неймспейс
root@debian:~/elk# kubectl create ns elk
добав­ля­ем репозиторий
root@debian:~/elk# helm repo add elastic https://helm.elastic.co
сге­не­рим сер­ти­фи­ка­ты на осно­ве кото­рый всё будет работать
root@debian:~/elk# cd certs/
чтоб не захлам­лять систе­му соби­рать всё будем в докере
ста­вим докер, если его нет:

apt-get update
apt-get install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

apt-get update

root@debian:~/elk/certs# apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
root@debian:~/elk/certs# systemctl start docker.socket
коман­дой ниже будет сге­не­ре­ны само­под­пи­сан­ные сер­ти­фи­ка­ты име­на зада­ём через коман­ду --dns
и выпол­ня­ем коман­ду ниже:

про­ве­ря­ем что сер­ти­фи­ка­ты созданы

root@debian:~/elk/certs# openssl pkey -in elastic-certificate.pem -out cert.key
root@debian:~/elk/certs# openssl crl2pkcs7 -nocrl -certfile elastic-certificate.pem | openssl pkcs7 -print_certs -out cert.crt
root@debian:~/elk/certs# kubectl create secret tls tls-kibana --namespace elk --key cert.key --cert cert.crt
теперь мож­но ставить:
root@debian:~/elk/certs# cd ../
пра­вим файл elastic.yaml

можем задать хра­ни­ли­ще, я буду использовать

storageClassName: nfs-client
можем задать опе­ра­тив­ку и т.д. в дан­ном при­ме­ре я остав­лю всё по дефолту
root@debian:~/elk# helm upgrade --install elasticsearch elastic/elasticsearch --version 8.5.1 -n elk -f elastic.yaml
дожи­да­ем­ся уста­нов­ки, проверяем:

настра­и­ва­ем kibana, для это­го в фай­ле kibana.yaml  пра­вим домен на наш kibana.test.local и ставим:

root@debian:~/elk# helm upgrade --install kibana elastic/kibana -n elk -f kibana.yaml

 

ста­вим logstash

root@debian:~/elk# helm upgrade --install logstash elastic/logstash -n elk -f logstash.yaml
ста­вим flebeat
root@debian:~/elk# helm upgrade --install filebeat elastic/filebeat -n elk -f filebeat.yaml
про­ве­ря­ем

 

смот­рим пароль:

root@debian:~/elk# kubectl get secrets --namespace=elk elasticsearch-master-credentials -ojsonpath='{.data.password}' | base64 -d
k57UN6bFQ01tLjhU

захо­дим

https://kibana.test.local/

в каче­стве логи­на исполь­зу­ем elastic
в каче­стве паро­ля k57UN6bFQ01tLjhU

про­ве­рим что дан­ные попа­да­ют в индекс:

что­бы посмот­реть логи нуж­но создать data views

про­ве­ря­ем

созда­дим поль­зо­ва­те­ля с пра­ва­ми админа

всё, мож­но логи­нить­ся под новы­ми кре­да­ми  admin Secret123

 

Loki

 

в каче­стве аль­тер­на­ти­вы рас­смот­рим исполь­зо­ва­ние loki, в каче­стве хра­ни­ли­ща у нас будет s3

Рас­смот­рим 2 варианта
1 когда s3-minio исполь­зу­ет логин пароль (без ldap)
2 когда для s3-minio вклю­чён ldap

1 Вариант - у s3 minio НЕ включён ldap и мы создаём обычного пользователя.

созда­ём бакет

созда­ём policy:

созда­ём поль­зо­ва­те­ля с наши­ми access-key и secret-key

созда­ём клю­чи доступа

  • Access Key (Ключ досту­па): Уни­каль­ный иден­ти­фи­ка­тор пользователя.
  • Secret Key (Сек­рет­ный ключ): Пароль для доступа.

полу­ча­ем

access key  iXToAdDvt0gx0fEJ1bXl
secret key  8bpWxY7fNKi0zEL85UI9Sg22floLjqMhPdxs2kVS

 

про­ве­ря­ем что нуж­ный к наше­му баке­ту добав­лен нуж­ный пользователь

 

теперь при­сту­пим к настрой­ке LOKI

вот наш values

в этом values endpoint исполь­зу­ем IP а не хост­нейм пото­му что  pod loki backend не резолвит домен  - хотя все осталь­ные  pod-ы  нор­маль­но  резолвят доме­ны с freeipa

root@debian:~# helm repo add grafana https://grafana.github.io/helm-charts
root@debian:~# helm repo update

kubectl create ns loki

helm upgrade --install loki grafana/loki --namespace loki --version 6.30.1 -f loki.yaml

2. Второй вариант  когда у s3-minio включён ldap

идём во https://freeipa-1.test.local/ и созда­ём поль­зо­ва­те­ля user-loki
и добав­ля­ем его в группу
про­ве­ря­ем что ldap нор­маль­но всё под­тя­нул, для это­го идём в s3-minio
http://s3-minio.test.local:9001/
как видим всё ок. поль­зо­ва­тель подтянулся.
теперь нам надо назна­чить ему policy кото­рую мы созда­ва­ли ранее, вот она:

 
как видим доба­вить поль­зо­ва­те­ля мы не можем это про­ис­хо­дит пото­му что вклю­чён LDAP
теперь назна­чим policy для поль­зо­ва­те­ля, для это­го идём на сер­вер s3-minio
[root@ansible ]# ssh 192.168.1.118
root@s3-minio-1:~#
root@s3-minio-1:~# mc idp ldap policy attach myminio loki-policy --user=user-loki
ответ дол­жен быть такой:

а теперь созда­ём access-key и secret-key

root@s3-minio-1:~# mc admin user svcacct add myminio user-loki

всё, теперь пра­вим наш values  c новы­ми access и secret key

и инстал­лим:

root@client:~/LOKI# helm upgrade --install loki grafana/loki --namespace loki --version 6.30.1 -f loki.yaml

теперь ста­вим сбор­щик логов promtail

 

Loki - s3 bucket (seaweedfs)

захо­дим на мастер

root@ansible:/etc/ansible# ssh 192.168.1.121

под­клю­ча­ем­ся

root@debian:~# weed shell

про­ве­ря­ем что есть:

созда­ём новый бакет loki-bucket:

> s3.bucket.create --name loki-bucket

ок, настра­и­ва­ем values

helm upgrade --install loki grafana/loki --namespace loki --version 6.30.1 -f loki-seaweedfs-s3.yaml

 

Promtail

Promtail — агент, кото­рый чита­ет и отправ­ля­ет логи на сер­вер. Он уста­нав­ли­ва­ет­ся как daemonset так как логи соби­ра­ют­ся со всех нод в кластере.

 

    helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
    helm repo update
    helm install prometheus-crds prometheus-community/prometheus-operator-crds --namespace loki
root@client:~/LOKI# helm upgrade --install promtail grafana/promtail --namespace loki --values promtail.yaml

про­ве­ря­ем:

как видим promtail уста­нов­лен на каж­дой ноде в кла­сте­ре. Про­ве­рим так же наш бакет:

как видим логи собираются.

 

Grafana - Loki

Идём в нашу grafana

http://grafana.test.local/login

настра­и­ва­ем datasource

для Connection URL указываем

http://loki-read.loki.svc.cluster.local:3100

всё это­го хва­та­ет, даль­ше скро­лим вниз и нажи­ма­ем save & test

как видим полу­ча­ем сообщение
Data source successfully connected.

про­ве­ря­ем рабо­ту дашборды
можем полу­чить такую проблему:
мож­но попро­бо­вать поко­вы­рять настрой­ки самой бор­ды но мне было лень я про­сто поста­вил новую
https://grafana.com/grafana/dashboards/15324-loki-logs-dashboard/
вот ID этой бор­ды 15324
далее импор­ти­ру­ем её:
про­ве­ря­ем саму борду
как видим всё ок, за послед­ний час в namespace monitoring логи были.
на этом с  лога­ми из loki всё. Може­те выби­рать что вам удоб­ней ELK/EFK/Grafana-Loki

Auto unseal для vault кластера

в чём идея, у нас уже есть кла­стер vault

vault1.test.local =192.168.1.103
vault2.test.local =192.168.1.104
vault3.test.local =192.168.1.105
нам нуж­но сде­лать его авто­раз­бло­ки­ров­ку в слу­чае рестар­та одной из node

идея в том что в k8s будет так же под­нят vault кото­рый будет настро­ен для раз­бло­ки­ров­ки наше­го кла­сте­ра,  а vault в кла­сте­ре будет раз­бло­ки­ро­вать­ся cronjob.

ЗАПОМНИТЕ!!!! НЕЛЬЗЯ НАСТРАИВАТЬ AUTOUNSEAL ДРУГ ДРУГАЕСЛИ В ВАШЕМ ДЦ ОТКЛЮЧАТ СВЕТ И У ВАС ОДНОВРЕМЕННО ВЫКЛЮЧАТЬСЯ ОБА КЛАСТЕРА, ОНИ НЕ СМОГУТ СТАРТАНУТ И РАСПЕЧАТАТЬ ДРУГ ДРУГА.
Отме­чу что все исполь­зу­е­мые доме­ны у нас резолвят­ся через freeipa или через hosts - кому как удобней
Уста­нов­ка vault в k8s
не забы­ва­ем что мы всё ещё используем
https://github.com/midnight47/ansible-playbook.git
кото­рый я пере­та­щил в /etc/ansible
пере­вхо­дим в
[root@ansible ~]# cd /etc/ansible/kubespray-official/vault-autounseal/
созда­ём неймспейс
root@client:~# kubectl create ns vault
добав­ля­ем репозиторй
root@client:~# helm repo add hashicorp https://helm.releases.hashicorp.com
уста­нав­ли­ва­ем vault,  отме­чу что я исполь­зую в каче­стве бэкен­да raft а для него исполь­зую дис­ки от провиженера
nfs-client  так что если у вас будет дру­гой про­ви­жи­нер то исполь­зуй­те его.

root@client:~/vault-autounseal# helm upgrade --install -n vault vault hashicorp/vault -f values.yaml

созда­ём клю­чи и запи­сы­ва­ем их в файл:
root@client:~/vault-autounseal# kubectl -n vault exec vault-0 -- vault operator init -key-shares=5 -key-threshold=3 -format=json > cluster-keys.json
ста­вим jq
root@client:~/vault-autounseal# apt-get install jq -y
дела­ем unseal пер­во­го vault
root@client:~/vault-autounseal# for i in `cat cluster-keys.json | jq -r ".unseal_keys_b64[]"`; do kubectl -n vault exec vault-0 -- vault operator unseal $i; done
соби­ра­ем raft в кластер:
root@client:~/vault-autounseal# kubectl -n vault exec -ti vault-1 -- vault operator raft join http://vault-0.vault-internal:8200
root@client:~/vault-autounseal# kubectl -n vault exec -ti vault-2 -- vault operator raft join http://vault-0.vault-internal:8200
дела­ем unseal для вто­ро­го и тре­тье­го vault
root@client:~/vault-autounseal# for i in `cat cluster-keys.json | jq -r ".unseal_keys_b64[]"`; do kubectl -n vault exec vault-1 -- vault operator unseal $i; done
root@client:~/vault-autounseal# for i in `cat cluster-keys.json | jq -r ".unseal_keys_b64[]"`; do kubectl -n vault exec vault-2 -- vault operator unseal $i; done
Auto unseal через cronjob
сде­ла­ем сра­зу cronjob кото­рая будет рас­шиф­ро­вы­вать vault кото­рый у нас запу­щен в кубере:
созда­ём конфигмап
root@client:~/vault-autounseal# kubectl create configmap vault-unseal-keys --from-file=cluster-keys.json -n vault
теперь можем при­ме­нять нашу cronjob:
root@client:~/vault-autounseal# kubectl apply -f auto-unseal-cronjob.yaml
сам скрипт выгля­дит вот так:

 

теперь при­сту­пим к настрой­ке autounseal с помо­щью tranzit

root@client:~/vault-autounseal# kubectl exec -it -n vault vault-0 -- sh

/ $ vault login
/ $ vault secrets enable transit
/ $ vault write -f transit/keys/vault-unseal-key
/ $ cd /tmp/
/tmp $ cat > transit-policy.yaml

/tmp $ vault policy write unseal-policy transit-policy.yaml
/tmp $ vault token create -policy=unseal-policy

полу­ча­ем token

теперь идём в кон­фи­гу­ра­ции наших vault на вир­ту­ал­ках и добав­ля­ем следующее:

root@client:~/vault-autounseal# ssh 192.168.1.103
root@vault1:~# nano /etc/vault.d/vault.hcl

root@client:~/vault-autounseal# ssh 192.168.1.104
root@vault2:~# nano /etc/vault.d/vault.hcl

root@client:~/vault-autounseal# ssh 192.168.1.105
root@vault3:~# nano /etc/vault.d/vault.hcl

Добав­ля­ем в хосты наш сервер(который в кубере)
root@vault1:~# echo "192.168.1.191 vault-unseal.test.local" >> /etc/hosts
root@vault2:~# echo "192.168.1.191 vault-unseal.test.local" >> /etc/hosts
root@vault3:~# echo "192.168.1.191 vault-unseal.test.local" >> /etc/hosts

[root@vault1 ~]# systemctl restart vault
[root@vault2 ~]# systemctl restart vault
[root@vault3 ~]# systemctl restart vault

теперь нуж­но рас­пе­ча­тать наше хра­ни­ли­ще с параметром:
'-migrate'

после каж­дой коман­ды нуж­но вве­сти ключ для разблокировки

[root@vault1 ~]# vault operator unseal -migrate
[root@vault1 ~]# vault operator unseal -migrate
[root@vault1 ~]# vault operator unseal -migrate

[root@vault2 ~]# vault operator unseal -migrate
[root@vault2 ~]# vault operator unseal -migrate
[root@vault2 ~]# vault operator unseal -migrate

[root@vault3 ~]# vault operator unseal -migrate
[root@vault3 ~]# vault operator unseal -migrate
[root@vault3 ~]# vault operator unseal -migrate

напом­ню вот мои ключи

всё, можем про­ве­рять что наш кла­стер успеш­но распечатывается:

глав­ный сер­вер https://vault2.test.local:8201  про­ве­ря­ем что и вир­ту­аль­ный ip на этом сервере:

рестар­ту­ем vault и про­ве­ря­ем статус:

как видим после рестар­та кла­стер успеш­но распечатан
Sealed false
основ­ной нодой явля­ет­ся https://vault1.test.local:8201
вир­ту­аль­ный адрес пере­ехал на дру­гую ноду.

как видим auto unseal успеш­но настроен.

напом­ню что все доме­ны у нас заве­де­ны через freeipa

 

обновить токен для распечатывая основного vault

если токен сдох и основ­ной волт не рас­пе­ча­ты­ва­ет­ся то нуж­но его обно­вить, для это­го смот­рим основ­ной рут токен:

root@kub-master1:~# kubectl get configmaps -n vault vault-unseal-keys -o yaml | grep root
"root_token": "hvs.hOrdYvRpvieSUF1yuWDIeegB"

root@kub-master1:~# kubectl exec -ti -n vault vault-0 -- sh
/ $ vault login
про­ве­ря­ем что тран­зит создан
/ $ vault secrets list | grep transit
transit/      transit      transit_1622485e      n/a
созда­ём новый токен:
токен мак­си­мум созда­ёт­ся на 768h изме­ним это число:
/ $ vault auth tune -max-lease-ttl=90000h token/
Success! Tuned the auth method at: token/
и созда­дим новый токен:
vault token create -policy=unseal-policy -period=90000h -orphan

теперь этот токен рас­ки­да­ем по всем волтам:
vault1  vault2  vault3 в блок seal "transit"
/etc/vault.d/vault.hcl

 

всё мож­но ребу­тать тач­ки вол­тов ну или рестар­тить волты

Добавим интеграцию vault(виртуалки) в k8s "Vault Secrets Operator"

вот офи­ци­аль­ная репка:

https://github.com/hashicorp/vault-secrets-operator

ста­вим
helm repo add hashicorp https://helm.releases.hashicorp.com
добав­ля­ем адрес наше­го vault в values чтоб установить
cat vault-secrets-operator.yaml

адрес луч­ше конеч­но ука­зать vault.test.local  хоть оно и резолвит:

но могут воз­ни­кать проблемы:

поэто­му я оста­вил  ip address 192.168.1.111

ста­вим:
helm upgrade --install --namespace vault vault-secrets-operator hashicorp/vault-secrets-operator --version 0.9.0 -f vault-secrets-operator.yaml
даль­ше нам надо настро­ить инте­гра­цию с нашим vault кла­сте­ром, кото­рый на вир­ту­ал­ках, для это­го нам пона­до­бит­ся сер­ти­фи­кат поэто­му выпол­ня­ем команду:
root@client:~/vault-autounseal# kubectl get cm kube-root-ca.crt -o jsonpath="{['data']['ca\.crt']}"
полу­ча­ем наш серт:

созда­ём сер­вис аккаунт

root@client:~/vault-autounseal# kubectl create serviceaccount vault-auth -n kube-system

на осно­ве это­го сер­вис акка­ун­та полу­ча­ем jwt token  уста­нав­ли­ваю вре­мя на 100 лет 876000h

root@client:~/vault-autounseal# kubectl create token vault-auth -n kube-system --duration 876000h

 

далее под­клю­ча­ем­ся к наше­му vault кото­рый на виртуалках

root@client:~/vault-autounseal# ssh 192.168.1.103

напо­ми­наю root token

hvs.UuG0QJvRRfwUHUTGxDTjFaAd
root@vault1:~# vault login

созда­ём сек­рет кото­рый будем подкидывать:

root@vault1:~# vault secrets enable -path=test/secret/ kv

добав­ля­ем туда ключ значение:

root@vault1:~# vault kv put test/secret/namespace-test/first-app password="db-secret-password"

вклю­ча­ем аутен­ти­фи­ка­цию в k8s
root@vault1:~# vault auth enable kubernetes

сер­ти­фи­кат кото­рый полу­чи­ли ранее, кла­дём в файл /root/ca.crt 

даль­ше при­сва­и­ва­ем пере­мен­ной TOKEN_REVIEWER_JWT наш jwt токен кото­рый мы созда­ли выше

root@vault1:~#

теперь настра­и­ва­ем auth к кластеру

 

root@vault1:~#

созда­ём policy  "test-policy" на чте­ние ТОЛЬКО наше­го секрета

созда­ём роль "test-role"

Роль свя­зы­ва­ет учет­ную запись служ­бы Kubernetes(serviceaccaunt), кото­рую назо­вём test-serviceaccaunt (но луч­ше исполь­зо­вать уже суще­ству­ю­щий сер­вис акка­унт наше­го при­ло­же­ния ) в про­стран­стве имен test с поли­ти­кой Vault, test-policy Токе­ны, воз­вра­щен­ные после аутен­ти­фи­ка­ции, дей­стви­тель­ны в тече­ние 10 минут

  • bound_service_account_names: Имя сер­вис­но­го акка­ун­та, кото­ро­му раз­ре­ше­но аутентифицироваться.
  • bound_service_account_namespaces: Про­стран­ство имён, в кото­ром нахо­дит­ся сер­вис­ный аккаунт.

 

созда­ём namespace test

root@client:~# kubectl create ns test

созда­ём serviceaccaunt

kubectl create serviceaccount test-serviceaccount -n test

созда­ём объ­ект VaultConnection кото­рый будет исполь­зо­вать­ся для под­клю­че­ния к vault во всех неймспейсах

как видим он исполь­зу­ет namespace: kube-system
192.168.1.111  - это вир­ту­аль­ный  ip  vault кластера

теперь созда­ём объ­ект VaultAuth

как видим для под­клю­че­ния к VaultConnection  исполь­зу­ет­ся запись: kube-system/vault-connection
так же тут ука­зы­ва­ем роль создан­ную в vault test-role и сер­вис акка­унт test-serviceoccount - кото­рый так же дол­жен сов­па­дать с тем что мы ука­за­ли в vault и с тем что у нас уже создан в k8s

теперь созда­ём объ­ект VaultStaticSecret

тут мы ука­зы­ва­ем как будет назы­вать­ся secret и как часто его обновлять.

теперь созда­ём несколь­ко объ­ек­тов ClusterRole  и ClusterRoleBinding


как мы видим ClusterRoleBinding смот­рит на ServiceAccount  vault-auth рас­по­ло­жен­ный kube-system мы его созда­ва­ли вруч­ную и jwt token созда­ва­ли на его основе.

[root@ansible ansible]# scp -r /etc/ansible/kubespray-official/vault-autounseal/ root@192.168.1.121:~/

теперь запус­ка­ем по очереди:
root@client:~/vault-autounseal# kubectl apply -f vault-secrets-operator-rbac.yaml
root@client:~/vault-autounseal# kubectl apply -f vault-secrets-operator-VaultConnection.yaml
root@client:~/vault-autounseal# kubectl apply -f vault-secrets-operator-VaultAuth.yaml
root@client:~/vault-autounseal# kubectl apply -f vault-secrets-operator-VaultSecret.yaml
про­ве­ря­ем:



про­ве­ря­ем создан­ный секрет:

а теперь доба­вим в vault сек­рет пару новый значений

как видим допол­ни­тель­ные key - value  123 и test  доба­ви­лись в секрет.

Пример с autoreloader после изменения секрета в vault

сде­ла­ем сле­ду­ю­щую струк­ту­ру у секретов.
/dev/service/app1(app2/app3)
/prod/service/app1(app2/app3)
не забы­ва­ем выстав­лять вер­сию сек­ре­тов я исполь­зую 1ую версию
в ито­ге получаем:
теперь созда­ём полиси.
сде­ла­ем одну поли­си кото­рая смо­жет читать все сек­ре­ты в dev/service и вто­рую кото­рая будет читать всё в prod/service

вот эти policy  read-dev-service и read-prod-service

 

теперь созда­ём roles - нуж­но знать как будет назы­вать­ся serviceaccaunt у наше­го при­ло­же­ния.  если не использовать

fullnameOverride то имя serviceaccount будет состо­ять из име­ни рели­за и име­ни чар­та, в моём слу­чае это:
root@client:~/vault-autounseal# helm upgrade --install --namespace dev first-app ./common-chart/ --values ./common-chart/values.yaml
поэто­му мой сер­вис акка­унт будет выгля­деть так:
first-app-common-chart
В одну роль мож­но запих­нуть несколь­ко акка­ун­тов, но мы созда­дим каж­до­му при­ло­же­нию свою роль

сра­зу сде­ла­ем для вто­рой апки в dev и апки в prod  схе­ма запус­ка будет такой же


 

про­ве­рить мож­но так:

vault list auth/kubernetes/role

деталь­но смот­рим пару ролей
vault read auth/kubernetes/role/ИМЯ_РОЛИ

 

а вот values, я тут пока­жу толь­ко отли­чия в values для секретов:

/etc/ansible/kubespray-official/vault-autounseal/common-chart/values-dev-app1.yaml

/etc/ansible/kubespray-official/vault-autounseal/common-chart/values-dev-app2.yaml

/etc/ansible/kubespray-official/vault-autounseal/common-chart/values-prod-app1.yaml

у нас будет 2 namespace  dev и prod

root@client:~/vault-autounseal# kubectl create ns dev
root@client:~/vault-autounseal# kubectl create ns prod
ста­вим теперь наши апки:

root@client:~/vault-autounseal# helm upgrade --install --namespace dev first-app ./common-chart/ --values ./common-chart/values-dev-app1.yaml

root@client:~/vault-autounseal# helm upgrade --install --namespace dev second-app ./common-chart/ --values ./common-chart/values-dev-app2.yaml

root@client:~/vault-autounseal# helm upgrade --install --namespace prod first-app ./common-chart/ --values ./common-chart/values-prod-app1.yaml

что нуж­но доба­вить в helm template
/etc/ansible/kubespray-official/vault-autounseal/common-chart/templates/vault-secrets-operator-VaultAuth.yaml

/etc/ansible/kubespray-official/vault-autounseal/common-chart/templates/vault-secrets-operator-VaultSecret.yaml

rolloutRestartTargets  - будет рестар­то­вать деп­лой­мент при изме­не­нии секрета

и нуж­но отре­дак­ти­ро­вать deployment

/etc/ansible/kubespray-official/vault-autounseal/common-chart/templates/deployment.yaml

доба­вив:

всё теперь под­ки­ды­вая новые или уда­ляя ста­рые сек­ре­ты - будет рестар­то­вать­ся и деплоймент

 

Аутентификация, авторизация в k8s (SSO в kubernetes)

В Kubernetes есть два типа пользователей:

  • Service Accounts — акка­ун­ты, управ­ля­е­мые Kubernetes API;
  • Users — «нор­маль­ные» поль­зо­ва­те­ли, управ­ля­е­мые внеш­ни­ми, неза­ви­си­мы­ми сервисами.

Основ­ное отли­чие этих типов в том, что для Service Accounts суще­ству­ют спе­ци­аль­ные объ­ек­ты в Kubernetes API (они так и назы­ва­ют­ся — ServiceAccounts), кото­рые при­вя­за­ны к про­стран­ству имён и набо­ру авто­ри­за­ци­он­ных дан­ных, хра­ня­щих­ся в кла­сте­ре в объ­ек­тах типа Secrets. Такие поль­зо­ва­те­ли (Service Accounts) пред­на­зна­че­ны в основ­ном для управ­ле­ния пра­ва­ми досту­па к Kubernetes API про­цес­сов, рабо­та­ю­щих в кла­сте­ре Kubernetes.

Обыч­ные же Users не име­ют запи­сей в Kubernetes API: управ­ле­ние ими долж­но осу­ществ­лять­ся внеш­ни­ми меха­низ­ма­ми. Они пред­на­зна­че­ны для людей или про­цес­сов, живу­щих вне кластера.

Каж­дый запрос к API при­вя­зан либо к Service Account, либо к User, либо счи­та­ет­ся анонимным.

Аутен­ти­фи­ка­ци­он­ные дан­ные поль­зо­ва­те­ля вклю­ча­ют в себя:

  • Username — имя поль­зо­ва­те­ля (зави­сит от регистра!);
  • UID — машин­но-чита­е­мая стро­ка иден­ти­фи­ка­ции поль­зо­ва­те­ля, кото­рая «более кон­си­стент­на и уни­каль­на, чем имя пользователя»;
  • Groups — спи­сок групп, к кото­рым при­над­ле­жит пользователь;
  • Extra — допол­ни­тель­ные поля, кото­рые могут быть исполь­зо­ва­ны меха­низ­мом авторизации.

Kubernetes может исполь­зо­вать боль­шое коли­че­ство меха­низ­мов аутен­ти­фи­ка­ции: сер­ти­фи­ка­ты X509, Bearer-токе­ны, аутен­ти­фи­ци­ру­ю­щий прок­си, HTTP Basic Auth. При помо­щи этих меха­низ­мов мож­но реа­ли­зо­вать боль­шое коли­че­ство схем авто­ри­за­ции: от ста­тич­но­го фай­ла с паро­ля­ми до OpenID OAuth2.

Более того, допус­ка­ет­ся исполь­зо­ва­ние несколь­ких схем авто­ри­за­ции одно­вре­мен­но. По умол­ча­нию в кла­сте­ре используются:

  • service account tokens — для Service Accounts;
  • X509 — для Users.

Loft

вот офи­ци­аль­ный блог  с инструкцией
https://www.loft.sh/blog/kubernetes-and-ldap-enterprise-authentication-for-kubernetes
под­го­тав­ли­ва­ем values.yaml  кото­рый рас­по­ло­жен у меня тут:
 cd /etc/ansible/kubespray-official/sso-loft/

тут мы ука­зы­ва­ем логин  пароль с кото­рым будем заходить
admin
Secret123

настра­и­ва­ем persistant volume и ingress
loft.test.local

ста­вим

root@client:~# kubectl create ns loft
root@client:~# helm repo add loft https://charts.loft.sh
root@client:~# helm repo update
root@client:~# helm search repo loft
послед­ний коман­дой смот­рим послед­нюю версию,

всё теперь может устанавливать:
root@client:~/sso-loft# helm install loft loft/loft --namespace loft -f values.yaml --version 4.1.0

ждём окон­ча­ния уста­нов­ки и заходим:

http://loft.test.local/login

далее нуж­но запол­нить дан­ные о компании
эта панель поз­во­ля­ет созда­вать вир­ту­аль­ные кла­сте­ра внут­ри наше­го кла­сте­ра но этот функ­ци­о­нал нам не нужен, так как сама панель она триальная:
созда­ём пользователя:

и созда­ём для него ключ

Dex - dexK8sAuthenticator

Dex —  сер­вер аутен­ти­фи­ка­ции, реа­ли­зу­ю­щий про­то­ко­лы OpenID Connect (OIDC) и OAuth 2.0. Он высту­па­ет в каче­стве посред­ни­ка меж­ду раз­лич­ны­ми внеш­ни­ми про­вай­де­ра­ми аутен­ти­фи­ка­ции и при­ло­же­ни­я­ми, кото­рым тре­бу­ет­ся аутен­ти­фи­ка­ция через OIDC.

Функ­ци­о­наль­ность Dex:

  • Аутен­ти­фи­ка­ция поль­зо­ва­те­лей: Dex поз­во­ля­ет инте­гри­ро­вать раз­лич­ные внеш­ние источ­ни­ки аутен­ти­фи­ка­ции, такие как LDAP, SAML, GitHub, Google и другие.
  • Про­вай­дер OIDC: Предо­став­ля­ет стан­дарт­ный интер­фейс OIDC для при­ло­же­ний, тре­бу­ю­щих аутентификации.
  • (SSO): Поз­во­ля­ет реа­ли­зо­вать еди­ную точ­ку вхо­да для аутен­ти­фи­ка­ции поль­зо­ва­те­лей в раз­лич­ных при­ло­же­ни­ях и сервисах.

В кон­тек­сте Kubernetes:

  • Аутен­ти­фи­ка­ция кла­сте­ра: Dex может исполь­зо­вать­ся как OIDC-про­вай­дер для Kubernetes, поз­во­ляя поль­зо­ва­те­лям аутен­ти­фи­ци­ро­вать­ся в кла­сте­ре через внеш­ний источник.
  • Инте­гра­ция с kubectl: Поль­зо­ва­те­ли могут полу­чать токе­ны досту­па для вза­и­мо­дей­ствия с кла­сте­ром через kubectl.

dex-auth— это сто­рон­ний про­ект или инстру­мент, кото­рый поз­во­ля­ет настро­ить инте­гра­цию Dex с Kubernetes для более удоб­но­го исполь­зо­ва­ния, напри­мер, для вхо­да в Kubernetes с помо­щью Dex и управ­ле­ния OIDC токе­на­ми. Он обыч­но исполь­зу­ет­ся для авто­ма­ти­за­ции и упро­ще­ния аутен­ти­фи­ка­ции через Dex.

Основ­ные воз­мож­но­сти dexK8sAuthenticator:

  1. Упро­ще­ние про­цес­са вхо­да:
    • Поль­зо­ва­тель может вой­ти в Kubernetes через Dex, не выпол­няя слож­ных опе­ра­ций с токе­на­ми OIDC вручную.
    • Предо­став­ля­ет интер­фейс для вво­да логина/пароля или исполь­зо­ва­ния внеш­не­го бра­у­зе­ра для аутентификации.

 

  1. Авто­ма­ти­че­ское управ­ле­ние токе­на­ми:
    • После успеш­но­го вхо­да авто­ма­ти­че­ски полу­ча­ет OIDC токен (ID-токен, Access-токен).
    • Токен добав­ля­ет­ся в kubeconfig, что­бы поль­зо­ва­тель мог рабо­тать с Kubernetes, исполь­зуя стан­дарт­ные инстру­мен­ты (kubectl, helm и т.д.).

 

  1. Инте­гра­ция с Dex:
    • Рабо­та­ет как кли­ент для Dex.
    • Исполь­зу­ет OIDC про­то­кол для полу­че­ния токенов.
Созда­ем кор­не­вой сертификат
root@client:~# mkdir certs
root@client:~# cd certs/
root@client:~/certs# openssl genrsa -out ca.key 4096
root@client:~/certs# openssl req -x509 -sha256 -new -key ca.key -days 10000 -out ca.crt
root@client:~/certs# openssl genrsa -out dex.key 4096
cat dex_openssl.cnf

root@client:~/certs# openssl req -new -key dex.key -out dex.csr -config dex_openssl.cnf
cat ca_openssl.cnf

root@client:~/certs# openssl x509 -req -in dex.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out dex.crt -days 10000 -sha256 -extfile ca_openssl.cnf -extensions v3_ca

про­ве­ря­ем:

как видим оба доме­на есть в сертификатах

созда­ём неймспейсы:

root@client:~/certs# kubectl create ns dex
созда­ём сек­ре­ты с эти­ми сертификатами:
root@client:~/certs# kubectl create secret tls dex-tls --key dex.key --cert dex.crt --namespace dex
и сек­рет для ca.crt
root@client:~/certs# kubectl create secret generic dex-ca-cert --from-file=ca.crt=./ca.crt -n dex
теперь созда­дим во freeipa груп­пы для досту­па к k8s кла­сте­ру а так же систем­но­го пользователя:
[root@freeipa-1 ~]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

вво­дим домен ldap сер­ве­ра freeipa-1.test.local

3 вво­дим admin
4 вво­дим пароль Secret123
5 выклю­ча­ем ssl
теперь созда­дим поль­зо­ва­те­ля k8s-access с паро­лем Secret123

теперь под­го­то­вим values

вот dex.yaml

 

и dex-auth.yaml

есть осо­бен­ность для caCerts

в value добав­ля­ем наш ca.crt в base64

ста­вим:

root@client:~/certs# helm repo add dex https://charts.dexidp.io
root@client:~/certs# helm repo update
root@client:~/autentification-dex-dex-auth# helm upgrade --install dex dex/dex -f dex.yaml --namespace dex --version 0.19.1
root@client:~/autentification-dex-dex-auth# helm upgrade --install dex-auth wiremind/dex-k8s-authenticator -n dex -f dex-auth.yaml
есть ещё про­бле­ма с резолвом адре­сов у dex поэто­му надо ещё попра­вить деп­лой­мен­ты dex и dex-auth а имен­но заме­нить dnspolicy: ClusterFirst

на

root@client:~/autentification-dex-dex-auth# kubectl edit deployments.apps -n dex dex
root@client:~/autentification-dex-dex-auth# kubectl edit deployments.apps -n dex dex-auth-dex-k8s-authenticator

резуль­тат выгля­дит вот так:


проверяем:

идём по адресу:

https://dex-auth.test.local

нас сра­зу пере­ки­нет на

https://dex.test.local/auth/freeipa/login?back=&state=c365acph2k6v35bqqcbhig72d

тут вво­дим логин пароль наше­го поль­зо­ва­те­ля из freeipa
user1
user1
попа­да­ем во внутрь и видим
дан­ные с freeipa под­тя­ну­лись и есть инструк­ция как сде­лать подключение
нам нуж­но доба­вить сер­ти­фи­кат k8s на наш клиент:
идём на мастер сервер:
root@kub-master1:~# sudo cat /etc/kubernetes/pki/ca.crt

добав­ля­ем его на нашем клиенте

root@client:~# cat > /usr/local/share/ca-certificates/myca.crt

обнов­ля­ем

так же добав­ля­ем сер­ти­фи­кат с dex

root@client:~# kubectl get secret -n dex dex-tls -o yaml

берём толь­ко
tls.crt

вот наш сертификат:

 

 

root@client:~# sudo update-ca-certificates

после того как выпол­ним все коман­ды в https://dex-auth.test.local/  под нашим тесто­вым поль­зо­ва­те­лем test1
нуж­но попра­вить конфиг
test1@client:~$ nano ~/.kube/config
в стро­ке с сер­ве­ром пра­вим порт
server: https://192.168.1.112:6443
про­ве­рим кста­ти token кото­рый полу­ча­ем  из dex
test1@client:~$ echo eyJhbGciOiJSUzI1NiIsImtpZCI6IjkxOWZiNzM4OGI5NmRjYjI4YTdjZjZhZDk5YjJiNzczODgwOTNlMjAifQ.eyJpc3MiOiJodHRwczovL2RleC50ZXN0LmxvY2FsIiwic3ViIjoiQ2dWMWMyVnlNUklIWm5KbFpXbHdZUSIsImF1ZCI6Imt1YmVybmV0ZXMiLCJleHAiOjE3MzQ5NTUzNzYsImlhdCI6MTczNDg2ODk3NiwiYXRfaGFzaCI6IlFuODNpRWdvV1ZyLTRHRXlWdERoeHciLCJjX2hhc2giOiJpaG4wSkxqeGo0c0FnV004YVNsczVRIiwiZW1haWwiOiJ1c2VyMUB0ZXN0LmxvY2FsIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImdyb3VwcyI6WyJpcGF1c2VycyIsIm5leHVzLWFkbWlucyIsInZhdWx0LWFkbWlucyIsInMzLW1pbmlvLWFkbWlucyIsIms4cy1kZXZvcHMiXSwibmFtZSI6InVzZXIxIHVzZXIxIn0.PUTW-3sZI48JXHqAb-Xhtut2F0Mxv0FvmsR3_QtPL6sB5hVq_ZqwwekWiJQtoSLiv0_0hr62ZJK3zipRK19fNL3mIpYHbRicFPSpfnm560tNxn-5yVq9IkJR_NGIkKGy2AsG6GYOE-jXWDovde4FRw5k4wh5LDopPxpBgSrq6AGK4H591YZnH7SNyZgTotu7HjVC_fzd6LQwuK7b5YiQskiYe6CBCScJnvEB4bwML1HJ8AnuW7UGYPeONyNlU1dThy5M2dA2GsIDEBkL8cBi49JA9ydtuY1pYdk8KQ92AEcZbLPV7HOHXV3JL7qLKbArdWwnEm2gA-xBhHVx7LGx3g | cut -d '.' -f2 | base64 -d | jq
полу­ча­ем такой результат:

види­мо что в груп­пе под­тя­ну­лись все груп­пы из freeipa

теперь надо попра­вить на масте­рах api для oidc

root@kub-master1:~# cat /etc/kubernetes/manifests/kube-apiserver.yaml

вот весь конфиг:

мы же добав­ля­ем толь­ко oidc

root@kub-master1:~# cat /etc/kubernetes/manifests/kube-apiserver.yaml| grep -i oidc

добав­ля­ем наш dex сер­ти­фи­кат: /etc/kubernetes/ssl/dex.crt  и дан­ные изме­не­ния по oidc на все мастер сервера:

- --oidc-client-id=<client_id> # Дол­жен сов­па­дать с тем, что в Dex (напри­мер 'kubernetes')
- --oidc-username-claim=email # Или дру­гой claim, кото­рый воз­вра­ща­ет Dex
- --oidc-groups-claim=groups # Если хоти­те мап­пить группы
- --oidc-ca-file=/etc/kubernetes/ssl/dex.crt # или дру­гой путь к CA, кото­рый выда­ло Dex (если Dex исполь­зу­ет свой сертификат)

теперь нам нуж­но создать rbac роли:

  1. для админов/девопсов будем исполь­зо­вать уже суще­ству­ю­щий ClusterRole - cluster-admin

он уже есть в систе­ме, поэто­му для него нуж­но создать толь­ко ClusterRoleBinding

group-devops.yaml

root@client:~/autentification-dex-dex-auth# kubectl apply -f group-devops.yaml

 

про­ве­ря­ем:

как видим под поль­зо­ва­те­лем  test1@client нам теперь досту­пен вывод серверов.

2. созда­дим теперь Role и RoleBinding для досту­па поль­зо­ва­те­лей в опре­де­лён­ный namespace в нашем слу­чае это dev. Вот файл group-k8s-users-ro.yaml

при­ме­ним его:

root@client:~/autentification-dex-dex-auth# kubectl apply -f group-k8s-users-ro.yaml

доба­вим поль­зо­ва­те­ля user2 в груп­пу k8s-users-ro в наш AD  Freeipa
логи­ним­ся в https://dex-auth.test.local/ под нашим user2
далее на нашем кли­ен­те созда­дим ново­го поль­зо­ва­те­ля - пусть будет test2
root@client:~# adduser test2
root@client:~# su - test2
далее копи­ру­ем дан­ные из dex




далее надо попра­вить порт для кла­сте­ра пото­му что у меня исполь­зу­ет­ся 6443

test2@client:~$ nano ~/.kube/config

про­ве­ря­ем:

как видим мы не можем выве­сти ни ноды ни поды из нейм­с­пей­са dex, но нам доступ­ны поды в нейм­с­пей­се dev

 

rancher

 

kubectl create namespace cattle-system
helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
helm repo update

[root@ansible ansible]# cd kubespray-official/autentification-keycloak/certs-rancher/

ca_openssl.cnf

rancher_openssl.cnf

[root@ansible kubespray-official]# scp -r /etc/ansible/kubespray-official/autentification-keycloak/ root@192.168.1.121:~/

root@client:~# cd ~/autentification-keycloak/certs-rancher/
root@client:~/autentification-keycloak/certs-rancher# openssl genrsa -out ca.key 4096
root@client:~/autentification-keycloak/certs-rancher# openssl req -x509 -sha256 -new -key ca.key -days 10000 -out ca.crt
root@client:~/autentification-keycloak/certs-rancher# openssl genrsa -out rancher.key 4096
root@client:~/autentification-keycloak/certs-rancher# openssl req -new -key rancher.key -out rancher.csr -config rancher_openssl.cnf
root@client:~/autentification-keycloak/certs-rancher# openssl x509 -req -in rancher.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out rancher.crt -days 10000 -sha256 -extfile ca_openssl.cnf -extensions v3_ca

 

созда­ём секрет

root@client:~/autentification-keycloak/certs-rancher# kubectl -n cattle-system create secret tls tls-rancher-ingress --cert=./rancher.crt --key=./rancher.key

запус­ка­ем установку:

values-rancher.yaml

root@client:~/autentification-keycloak# scp root@192.168.1.112:/etc/kubernetes/ssl/ca.crt ./ca.crt

root@client:~/autentification-keycloak# kubectl -n cattle-system create secret generic tls-ca --from-file=cacerts.pem=./ca.crt

root@client:~/autentification-keycloak# helm install rancher rancher-stable/rancher -n cattle-system --version 2.9.3 -f values-rancher.yaml --set bootstrapPassword=ddjjKKSSlldd345hhRRsd

 

kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{ "\n" }}'

echo https://rancher.test.local/dashboard/?setup=$(kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}')

полу­ча­ем

https://rancher.test.local/dashboard/?setup=ddjjKKSSlldd345hhRRsd

 

================================================

так как rancher в кла­сте­ре жрёт слиш­ком мно­го ресур­сов и у меня тупо сет­ка отва­ли­ва­лась, я под­нял его на отдель­ной виртуалке:

192.168.1.128

пер­во­на­чаль­ная уста­нов­ка 4 ядра 4 гб оперативки.

в доке­ре

смот­рим пароль

root@debian:~# docker logs  v2.11-head  2>&1 | grep "Bootstrap Password:"
2025/03/29 06:46:41 [INFO] Bootstrap Password: 9ppkpqdbmwv9txs9w8png5jc4h2btzhktdn6km6b2rp96gk9s9rngv

идём в панель

https://192.168.1.128/dashboard/auth/login

зада­ём пароль

Password must be at least 12 characters

после уста­нов­ки ресур­сы мож­но поре­зать до 2 ядер и 2гб оперативки.

Rancher интеграция с Freeipa

созда­ём систем­но­го поль­зо­ва­те­ля во freeipa

[root@freeipa-1 ~]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

выби­ра­ем 1
вво­дим freeipa-1.test.local
выби­ра­ем 3
вво­дим admin
выби­ра­ем 4
вво­дим Secret123

даль­ше можем добав­лять ново­го пользователя,
вво­дим add
имя поль­зо­ва­те­ля  rancher
пароль Secret123 (мож­но любой но я делаю вез­де одинаковый)

про­ве­ря­ем поль­зо­ва­те­лей нажи­ма­ем ls

 

запол­ня­ем поля:

Service Account DN  uid=rancher,cn=sysaccounts,cn=etc,dc=test,dc=local
User Search Base cn=users,cn=accounts,dc=test,dc=local
Group Search Base cn=groups,cn=accounts,dc=test,dc=local
Object Class (Users) inetorgperson
Login Attribute uid
Username Attribute uid
User Member Attribute memberOf
Object Class (Groups) groupofnames
Group Name Attribute cn
Group Member Attribute member
Group DN Attribute entrydn

 

в самом низу user1 это из freeipa поль­зо­ва­тель, под кото­ро­го вы сра­зу пере­клю­чи­тесь если всё пра­виль­но настроено.

 

про­ве­ря­ем:

как видим появи­лась воз­мож­ность авто­ри­за­ции через freeipa

так же можем авто­ри­зо­вы­вать­ся и через локаль­но­го пользователя.

как видим под­клю­че­ние успеш­но произведено.

 

Rancher подключение к k8s кластеру

захо­дим в rancher под рутом далее

Import -> Generic

cluster-name: cluster-local

полу­ча­ем спи­сок команд

так как у меня само­под­пи­сан­ный сер­ти­фи­кат то я исполь­зую вто­рую команду:

curl --insecure -sfL https://192.168.1.128/v3/import/57pzg7t2dnxvtjqn6tj7w2bhwttkr7gddgzcwc9xvgxgsfzw65ml74_c-sv925.yaml | kubectl apply -f -

резуль­тат коман­ды такой

можем посмот­реть состо­я­ние процесса:

тут можем посмот­реть какие сер­ве­ра доба­ви­лись в кластер:

даль­ше можем посмот­реть раз­ные дан­ные по кла­сте­ру сто­радж клас­сы, ноды и т.д.

одну ноду я выклю­чил так как у меня не хва­та­ло ресур­сов на моём компе

 

добав­ля­ем груп­пы, захо­дим из под поль­зо­ва­те­ля user1 так как из под рута будет недо­ступ­но - х.з. почему

груп­па k8s-devops будет с пол­ны­ми доступами

доба­вим груп­пу k8s-users-ro для пользователей:

так же огра­ни­чи­ва­ем доступ группами

что­бы огра­ни­чить груп­пу нейм­с­пей­са­ми - созда­дим про­ект с назва­ни­ем limited-access-project

созда­ли про­ект теперь доба­вим к нему груп­пу k8s-users-ro и уда­лим поль­зо­ва­те­ля user1

теперь пере­ме­стим в этот про­ект нуж­ный нам namespace

любо­му про­ек­ту мож­но назна­чать несколь­ко групп с раз­ны­ми пра­ва­ми, напри­мер доба­вим груп­пу k8s-devops как owner

мож­но касто­май­зить досту­пы при добав­ле­нии группы:

так же все­гда мож­но добав­лять RBAC рука­ми  - rancher нор­маль­но это подтягивает.

Rancher проверка авторизации для пользователей k8s

во freeipa есть поль­зо­ва­тель user-2 в груп­пе k8s-users-ro

авто­ри­зу­ем­ся с этим поль­зо­ва­те­лем в rancher

теперь нуж­но ска­чать kubeconfig

там на выбор мож­но файл ска­чать мож­но в буфер обме­на скопировать

теперь идём в консоль

созда­ём директорию:
user2@client:~$ mkdir ~/.kube

созда­ём файл:
user2@client:~$ cat > .kube/config

и встав­ля­ем содер­жи­мое кото­рое скопировали:

пыта­ем отоб­ра­зить все POD

user2@client:~$ kubectl get pod -A
полу­ча­ем ответ

смот­рим наш нейм­с­пейс dev там всё ок

как видим всё работает

 

 

удаление rancher из кластера

 

 

для уда­ле­ния crd используем:

как толь­ко про­цесс оста­но­вит­ся отме­ня­ем про­цесс и пере­за­пус­ка­ем и так до победного

 

 

 

Keycloak

Keycloak - это при­ло­же­ние для реа­ли­за­ции еди­ной точ­ки аутен­ти­фи­ка­ции и авто­ри­за­ции. Дан­ную тех­но­ло­гию еди­но­го вхо­да так­же назы­ва­ют Single Sign-On или, сокра­щен­но, SSO. А подоб­ные сер­ви­сы име­ют общее назва­ние "Систе­ма управ­ле­ния иден­ти­фи­ка­ци­ей и досту­пом" или Identity and Access Management (IAM).

Keycloak может предо­ста­вить воз­мож­ность поль­зо­ва­те­лям полу­чать пра­ва для раз­лич­ных при­ло­же­ний, прой­дя один раз про­цесс аутен­ти­фи­ка­ции. Раз­ра­бот­чи­кам не нуж­но для это­го писать мно­го кода. А инже­не­ры DevOps могут настро­ить аутен­ти­фи­ка­цию через общую базу поль­зо­ва­те­лей для при­ло­же­ний, у кото­рых нет допол­ни­тель­ных меха­низ­мов интеграции.

Сре­ди функ­ций и воз­мож­но­стей выделяют:

  • SSO.
  • Выда­чу токенов.
  • Двух­фак­тор­ную аутентификацию.
  • Авто­ри­за­цию через соци­аль­ные сети.
  • Воз­мож­ность инте­гра­ции со служ­ба­ми каталогов.
  • Авто­ма­ти­че­скую аутен­ти­фи­ка­цию с исполь­зо­ва­ни­ем тике­тов Kerberos.
  • Управ­ле­ние раз­ны­ми изо­ли­ро­ван­ны­ми сре­да­ми (Realm) со сво­и­ми настройками.
  • Свой интер­фейс для реги­стра­ции и аутен­ти­фи­ка­ции поль­зо­ва­те­лей с воз­мож­но­стью настрой­ки внеш­не­го вида.

Keycloak име­ет кли­ент-сер­вер­ную инфра­струк­ту­ру. В каче­стве сер­ве­ра исполь­зу­ет­ся гото­вый пакет, уста­нав­ли­ва­е­мый на опе­ра­ци­он­ную систе­му (есть под­держ­ка Linux, Windows) или docker-при­ло­же­ние. В каче­стве кли­ен­та исполь­зу­ет­ся адап­тер — блок кода, кото­рый дол­жен исполь­зо­вать раз­ра­бот­чик для инте­гра­ции сво­е­го при­ло­же­ния с сервером.

Под­дер­жи­ва­ет­ся два стан­дар­та обме­на дан­ны­ми аутен­ти­фи­ка­ции и авто­ри­за­ции: OpenID Connect и SAML. В зави­си­мо­сти от дан­но­го стан­дар­та Keycloak пред­ла­га­ет гото­вые шаб­ло­ны адап­те­ров для язы­ков про­грам­ми­ро­ва­ния, плат­форм или при­ло­же­ний а так­же их фреймворков/расширений:

1. Для OpenID Connect:

  • Java (Spring Boot, Wildfly Elytron OIDC).
  • JavaScript.
  • Node.js.
  • C#.
  • Python.
  • Android/iOS.
  • Apache Web Server (mod_auth_openidc).

2. Для SAML:

  • Java.
  • Apache Web Server (mod_auth_mellon).

Подроб­нее о под­дер­жи­ва­е­мых язы­ках мож­но почи­тать в офи­ци­аль­ной доку­мен­та­ции.

 

ста­вим keycloak в k8s вот офф helm чарт

https://github.com/codecentric/helm-charts/tree/master

добав­ля­ем репозиторий

helm repo add codecentric https://codecentric.github.io/helm-charts
созда­ём namespace
kubectl create ns keycloak
созда­ём сек­рет с логи­ном и паро­лем - для keycloak:

созда­ём сер­ти­фи­ка­ты чтоб рабо­ты по https
root@client:~# cd ~/autentification-keycloak/certs/
root@client:~# cat ca_openssl.cnf

root@client:~# cat keycloak_openssl.cnf

root@client:~/autentification-keycloak/certs# openssl genrsa -out ca.key 4096
root@client:~/autentification-keycloak/certs# openssl req -x509 -sha256 -new -key ca.key -days 10000 -out ca.crt
root@client:~/autentification-keycloak/certs# openssl genrsa -out keycloak.key 4096
root@client:~/autentification-keycloak/certs# openssl req -new -key keycloak.key -out keycloak.csr -config keycloak_openssl.cnf
root@client:~/autentification-keycloak/certs# openssl x509 -req -in keycloak.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out keycloak.crt -days 10000 -sha256 -extfile ca_openssl.cnf -extensions v3_ca

 

созда­ём секреты

root@client:~/autentification-keycloak/certs# kubectl create secret tls keycloak-tls --key keycloak.key --cert keycloak.crt --namespace keycloak
root@client:~/autentification-keycloak/certs# kubectl create secret generic keycloak-ca-cert --from-file=ca.crt=./ca.crt -n keycloak

 

 

вот values

тут я настраивал:

ingressClassName
ingress
postgresql.persistence.storageClass
postgresql.persistence.size

ста­вим:

root@client:~/ cd /etc/ansible/kubespray-official/autentification-keycloak/

root@client:~/autentification-keycloak# helm upgrade --install keycloak oci://ghcr.io/codecentric/helm-charts/keycloak --version 18.9.0 -n keycloak -f values.yaml
даль­ше ждём пока всё уста­но­вит­ся и можем заходить:
https://keycloak.test.local/
напом­ню
логин admin
пароль Secret123

интеграция c Freeipa

для нача­ла созда­дим систем­но­го поль­зо­ва­те­ля во freeipa

[root@freeipa-1 ~]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

создал поль­зо­ва­те­ля keycloak а пароль Secret123

про­ве­рим всем пользователей:

всё гото­во.

 

Настройка федерации

Пер­вым делом созда­дим новый realm. Realm — это про­стран­ство наше­го при­ло­же­ния. Каж­дое при­ло­же­ние может иметь свой realm с раз­ны­ми поль­зо­ва­те­ля­ми и настрой­ка­ми авто­ри­за­ции. Master realm исполь­зу­ет­ся самим Keycloak и исполь­зо­вать его для чего-нибудь еще неправильно.

Нажи­ма­ем Add realm

Kubernetes по умол­ча­нию про­ве­ря­ет под­твер­жден у поль­зо­ва­те­ля email или нет. Так как мы исполь­зу­ем соб­ствен­ный LDAP-сер­вер, то тут эта про­вер­ка почти все­гда будет воз­вра­щать false. Давай­те отклю­чим пред­став­ле­ние это­го пара­мет­ра в Kubernetes:

Client scopes --> Email --> Mappers --> Email verified (Delete)

Теперь настро­им феде­ра­цию, для это­го перей­дем в:

User federation --> Add provider… --> ldap

При­ве­ду при­мер настрой­ки для FreeIPA:

Console Display Name -  freeipa-1.test.local
Edit Mode - READ_ONLY
Vendor - Red Hat Directory Server
Connection URL - ldap://freeipa-1.test.local:389
UUID LDAP attribute - ipaUniqueID
Users DN - cn=users,cn=accounts,dc=test,dc=local
Bind DN - uid=keycloak ,cn=sysaccounts,cn=etc,dc=test,dc=local
Bind Credential - Secret123
Allow Kerberos authentication - on
Kerberos Realm - TEST.LOCAL
Server Principal - HTTP/freeipa-1.test.local@TEST.LOCAL
KeyTab - /etc/krb5.keytab

теперь перей­дём:

User federation --> freeipa.test.local --> Mappers --> First Name

Ldap attribure - givenName

Теперь вклю­чим мап­пинг групп:

User federation --> freeipa.test.local --> Mappers --> Create

Name - groups
Mapper type - group-ldap-mapper
LDAP Groups DN - cn=groups,cn=accounts,dc=test,dc=local
User Groups Retrieve Strategy  - GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE

На этом настрой­ка феде­ра­ции закон­че­на, перей­дем к настрой­ке клиента.

Настройка клиента

Созда­дим ново­го кли­ен­та (при­ло­же­ние кото­рое будет полу­чать поль­зо­ва­те­лей из Keycloak). Переходим:

Clients --> Create

Client ID - kubernetes
Client Protocol - openid-connect
Root URL - http://kubernetes.test.local/

Access Type - confidential
Valid Redirect URIs - http://kubernetes.test.local/*
Admin URL - http://kubernetes.test.local/

 

Так же созда­дим scope для групп:

Client Scopes --> Create

Name groups

И настро­им mapper для них:

Client Scopes --> groups --> Mappers --> Create

Name - groups
Mapper Type  - Group membership
Token Claim Name - groups

Теперь нам нуж­но вклю­чить мап­пинг груп в нашем client scope:

Clients --> kubernetes --> Client Scopes --> Default Client Scopes

Выби­ра­ем groups в Available Client Scopes, нажи­ма­ем Add selected

Теперь настро­им аутен­ти­фи­ка­цию наше­го при­ло­же­ния, переходим:

Clients --> kubernetes

Authorization EnabledON

Нажи­мем save и на этом настрой­ка кли­ен­та завершена,

про­ве­рим что в keycloak под­тя­ги­ва­ют­ся груп­пы и поль­зо­ва­те­ли с Freeipa

теперь на вкладке

Clients --> kubernetes --> Credentials

вы смо­же­те полу­чить Secret кото­рый мы будем исполь­зо­вать в дальнейшем.

 

Настройка Kubernetes

 

Настрой­ка Kubernetes для OIDC-авто­ри­за­ции. Все что вам нуж­но это поло­жить CA-сер­ти­фи­кат ваше­го OIDC-сер­ве­ра в /etc/kubernetes/ssl/keycloak.crt и доба­вить необ­хо­ди­мые опции для kube-apiserver.
Для это­го обно­ви­те /etc/kubernetes/manifests/kube-apiserver.yaml на всех ваших мастерах:

сна­ча­ла рас­ки­да­ем сер­ти­фи­ка­ты по всем серверам:

root@client:~/autentification-keycloak/certs# scp keycloak.crt root@192.168.1.112:/etc/kubernetes/ssl/keycloak.crt
root@client:~/autentification-keycloak/certs# scp keycloak.crt root@192.168.1.113:/etc/kubernetes/ssl/keycloak.crt
root@client:~/autentification-keycloak/certs# scp keycloak.crt root@192.168.1.114:/etc/kubernetes/ssl/keycloak.crt
root@client:~/autentification-keycloak/certs# scp keycloak.crt root@192.168.1.115:/etc/kubernetes/ssl/keycloak.crt
root@client:~/autentification-keycloak/certs# scp keycloak.crt root@192.168.1.116:/etc/kubernetes/ssl/keycloak.crt
root@client:~/autentification-keycloak/certs# scp keycloak.crt root@192.168.1.117:/etc/kubernetes/ssl/keycloak.crt

теперь на масте­рах пра­вим файл /etc/kubernetes/manifests/kube-apiserver.yaml

добав­ля­ем следующее:

root@kub-master1:~# nano /etc/kubernetes/manifests/kube-apiserver.yaml

весь файл выгля­дит вот так:

root@kub-master2:~# nano /etc/kubernetes/manifests/kube-apiserver.yaml
root@kub-master3:~# nano /etc/kubernetes/manifests/kube-apiserver.yaml

А так-же попра­вим kubeadm кон­фиг в кла­сте­ре, что бы не поте­рять эти настрой­ки при обновлении:

root@client:~# kubectl edit -n kube-system configmaps kubeadm-config

вот так выгля­дит весь конфиг:

root@client:~# kubectl get -n kube-system configmaps kubeadm-config -o yaml

 

Teleport

Teleport – это инстру­мент для  без­опас­но­го под­клю­че­ния к Kubernetes-кла­сте­рам, а так­же к дру­го­му ПО .  Поми­мо Kubernetes, Teleport мож­но исполь­зо­вать для аутен­ти­фи­ка­ции с таки­ми систе­ма­ми как:

  • Облач­ные про­вай­де­ры – Amazon, Google Cloud, Microsoft Azure;
  • Опе­ра­ци­он­ные систе­мы – Windows, Linux;
  • СУБД – Redis, CockroachDB, MongoDB;
  • Систе­мы для поис­ка и ана­ли­за дан­ных – Elasticsearch

досто­ин­ства Teleport:

Способы подключения

Teleport поз­во­ля­ет уда­лен­но под­клю­чать­ся к Kubernetes-кла­сте­рам с исполь­зо­ва­ни­ем про­то­ко­лов SSH или TLS. Так­же при­сут­ству­ет встро­ен­ный веб-интерфейс.

Аудит

Teleport отсле­жи­ва­ет все дей­ствия, кото­рые поль­зо­ва­тель совер­ша­ет внут­ри систе­мы (кла­сте­ра), и предо­став­ля­ет рас­ши­рен­ные функ­ции, такие как филь­тры, хро­но­ло­гия, уве­дом­ле­ния, управ­ле­ние учет­ны­ми запи­ся­ми и т. д.

Аутентификация

Teleport исполь­зу­ет мно­го­фак­тор­ную аутен­ти­фи­ка­цию, что­бы удо­сто­ве­рить лич­ность пользователя.

Управление учетными записями

Teleport может управ­лять учет­ны­ми запи­ся­ми для того, что­бы про­ве­рить, что поль­зо­ва­тель име­ет доступ толь­ко к раз­ре­шен­ным ресурсам.

Архитектура и принцип работы Teleport

Teleport напи­сан на язы­ке Go и состо­ит из трех неза­ви­си­мых  испол­ня­е­мых файлов:

  • tsh (кли­ент команд­ной строки);
  • tctl (инстру­мент администрирования);
  • teleport (сер­вер­ный демон).

Пред­став­ля­ет собой прок­си-сер­вер, пред­на­зна­чен­ный для досту­па и аутен­ти­фи­ка­ции к тре­бу­е­мым систе­мам (опе­ра­ци­он­ным систе­мам, СУБД и т. д.). Управ­ле­ние досту­пом реа­ли­зо­ва­но на осно­ве ролей RBAC.

Кли­ент команд­ной стро­ки tsh пред­на­зна­чен для вхо­да на конеч­ные ресур­сы и выпол­не­ния команд.

Инстру­мент адми­ни­стри­ро­ва­ния tctl исполь­зу­ет­ся для созда­ния поль­зо­ва­те­лей, клю­чей сер­ти­фи­ка­тов, а так­же может при­ме­нять­ся для изме­не­ния дина­ми­че­ской кон­фи­гу­ра­ции кла­сте­ров Kubernetes, напри­мер, для созда­ния новых ролей.

Демон сер­ве­ра teleport может рабо­тать в трех режимах:

  • Node. В этом режи­ме демон предо­став­ля­ет SSH и Kubernetes доступ к сер­ве­ру, на кото­ром он работает;
  • Прок­си-сер­вер. В этом режи­ме демон дей­ству­ет как удо­сто­ве­ря­ю­щий лич­ность прок­си для всех про­то­ко­лов, под­дер­жи­ва­е­мых Teleport (SSH, HTTPS, Kubernetes API);
  • Сер­вер аутен­ти­фи­ка­ции. В этом режи­ме демон дей­ству­ет как центр сер­ти­фи­ка­ции, кото­рый выда­ет сер­ти­фи­ка­ты для поль­зо­ва­те­лей. Так­же хра­нит жур­нал аудита.

рабо­та­ет Teleport сле­ду­ю­щим образом:

  1. Поль­зо­ва­тель выби­ра­ет один из несколь­ких спо­со­бов под­клю­че­ния к кла­сте­ру Kubernetes (напри­мер tsh);
  2. Далее запрос пере­хо­дит к сер­вер­но­му демо­ну teleport, кото­рый, в свою оче­редь, отправ­ля­ет запрос Identity Provider – систе­ме, пред­на­зна­чен­ной для созда­ния и хра­не­ния циф­ро­вых иден­ти­фи­ка­ци­он­ных дан­ных (логин, пароль и т. д). В каче­стве про­вай­де­ров Teleport под­дер­жи­ва­ет сле­ду­ю­щие системы:
  • Azure Active Directory;
  • Active Directory;
  • Google Workspace;
  • GitHub;
  • GitLab;
  • OneLogin;
  • OIDC;
  • SSO
  1. После того как в Identity Provider най­де­ны аутен­ти­фи­ка­ци­он­ные дан­ные поль­зо­ва­те­ля, запрос воз­вра­ща­ет­ся демо­ну teleport, кото­рый обра­ба­ты­ва­ет посту­пив­ший запрос и раз­ре­ша­ет доступ к кла­сте­ру Kubernetes или дру­гой конеч­ной системе.

 

установка teleport

офф доку­мен­та­ция

https://goteleport.com/docs/admin-guides/deploy-a-cluster/helm-deployments/custom/

вот мой values

домен
teleport.test.local

helm repo add teleport https://charts.releases.teleport.dev
helm repo update
kubectl create ns teleport
созда­ём сертификат
cat > ca_openssl.cnf

cat > teleport_openssl.cnf
openssl genrsa -out ca.key 4096
openssl req -x509 -sha256 -new -key ca.key -days 10000 -out ca.crt
openssl genrsa -out teleport.key 4096
openssl req -new -key teleport.key -out teleport.csr -config teleport_openssl.cnf
openssl x509 -req -in teleport.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out teleport.crt -days 10000 -sha256 -extfile ca_openssl.cnf -extensions v3_ca

созда­ём сек­рет в k8s

kubectl -n teleport create secret generic teleport-ca-cert --from-file=ca.pem=./ca.crt
на кли­ен­тах добав­ля­ем сер­ти­фи­ка­ты в доверенные
mkdir /usr/local/share/ca-certificates/teleport/
cp teleport.crt ca.crt /usr/local/share/ca-certificates/teleport/
update-ca-certificates
ста­вим сам чарт
helm upgrade --install teleport-cluster teleport/teleport-cluster -n teleport -f values.yaml --version 17.4.5

заходим

https://teleport.test.local/

созда­ём админа

kubectl exec -it -n teleport deploy/teleport-cluster-auth -- tctl users add admin --roles=editor,auditor,access

полу­ча­ем токен, по кото­ро­му заходим

https://teleport.test.local:443/web/invite/01ea692b034d44afb0ea6e61a6c6b3a5

пароль мини­мум 12 символов

мы можем исполь­зо­вать толь­ко passkey -там нуж­но исполь­зо­вать usb флеш­ку или mfa через моби­лу при­ло­же­ние на анд­рой­де назы­ва­ет­ся AUTHENTICATOR
там ска­ним наш код
teleport НЕ ПОДДЕРЖИВАЕТ инте­гра­цию с freeipa напря­мую, воз­мож­но будет в плат­ной версии

Подключение кластера Kubernetes к Teleport

Для того что­бы исполь­зо­вать Teleport для вхо­да в кла­стер Kubernetes, необ­хо­ди­мо уста­но­вить агент. Для нача­ла про­ве­рим, рабо­та­ет ли аутен­ти­фи­ка­ция в Teleport при помо­щи сле­ду­ю­щей команды:

ста­вим teleport-connect, вот офф сайт
https://goteleport.com/download/?product=connect
вер­сия сер­ве­ра 17.4.5  такую же вер­сию ста­вим и для клиента
вот коман­да
curl https://goteleport.com/static/install-connect.sh | bash -s 17.4.5
про­ве­рим кон­нект, для это­го полу­чим коман­ду вот тут:
tsh login --proxy=teleport.test.local:443 --auth=local --user=admin teleport.test.local

нуж­но будет вве­сти пароль от наше­го адми­на и OTP код с мобилы.

что­бы был доступ к кла­сте­ру нуж­но доба­вить прав,

Созда­дим роль k8s-admin

в груп­пу добавим
system:masters

роль созда­на:

теперь доба­вим наше­му поль­зо­ва­те­лю эту роль:
после добав­ле­ния новой роли нуж­но поль­зо­ва­те­лю перелогиниться:

как видим при обыч­ном логине Roles оста­ют­ся ста­ры­ми поэто­му дела­ем логаут

всё, теперь как видим в наших ролях есть k8s-admin
воз­вра­ща­ем­ся сюда:
мы уже зало­ги­ни­лись, выпол­ним сле­ду­ю­щие команды:
export KUBECONFIG=${HOME?}/teleport-kubeconfig.yaml
tsh kube login teleport.test.local
полу­чим сле­ду­ю­щее уведомление:

это гово­рит о том что так как мы исполь­зу­ем  ingress т.е. 7 уро­вень моде­ли osi (application layer - при­клад­ной уровень)
исполь­зо­вать напря­мую ути­ли­ту kubectl будет невоз­мож­но, поэто­му есть 2 вари­ан­та 1 это добав­лять tsh перед kubectl или запу­стить в одной консоли
tsh proxy kube -p 8443

а в дру­гой исполь­зо­вать kubectl.
проверим:

как видим работает.

 

Проверим ограниченный доступ только к одному из namespace например это будет пользователь user2

 

созда­дим пользователя

user2

https://teleport.test.local/web/invite/70e8b53c1468f5ed82efa35480dc13ef

полу­чив ссыл­ку про­хо­дим по ней:

при­вя­зы­ва­ем­ся по OTP

 

 

созда­дим ещё одну роль с досту­пом к namespace dev
доба­вим поль­зо­ва­те­лю роль
теперь нам нуж­но создать RBAC в кла­сте­ре, с админ ролью мож­но было его не созда­вать так как такой rbac есть по умол­ча­нию в k8s
cat > dev-admins.yaml

root@client:~# kubectl apply -f dev-admins.yaml
про­ве­рим:
создам ново­го пользователя:
root@client:~# adduser user2
root@client:~# su - user2
полу­чим адрес для подключения:
tsh login --proxy=teleport.test.local:443 --auth=local --user=user2 teleport.test.local

user2@client:~$ export KUBECONFIG=${HOME?}/teleport-kubeconfig.yaml
user2@client:~$ tsh kube login teleport.test.local

полу­ча­ем уведомление:

вот резуль­тат запросов:

как видим в dev всё ок, а посмот­реть в дру­гом namespace или отоб­ра­зить все ns не возможно

Интеграция teleport - keycloak

 

 

Обновление кластера k8s

ранее я использовал:

https://github.com/kubernetes-incubator/kubespray.git

сей­час он переехал:

https://github.com/kubernetes-sigs/kubespray

обновление 1,24 на 1,25

что­бы обно­вить­ся нуж­ная новая вер­сия ansible

cd /etc/ansible/kubespray-official/kubespray-new
git clone https://github.com/kubernetes-sigs/kubespray.git
cd /etc/ansible/kubespray-official/kubespray-new/kubespray
git checkout release-2.20
apt-get update && apt-get install -y python3-venv python3-pip rsync
apt-get install -y build-essential python3-dev libyaml-dev
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
mkdir -p filter_plugins
cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
в фай­ле
/etc/ansible/kubespray-official/kubespray-new/kubespray/roles/kubernetes/preinstall/vars/debian.yml
меня­ем python-apt на python3-apt  и ком­мен­тим aufs-tools

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml

и запус­ка­ем установку:

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

про­ве­ря­ем:

как видим обно­ви­лись до v1.24.6

обнов­ля­ем­ся дальше

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# deactivate

root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# rm -rf .venv-ansible/
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git add .
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git commit -m "20"

root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git checkout release-2.21

нуж­но сей­час так же попра­вить инвен­то­ри и будем обнов­лять даль­ше на  v1.25.6

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml

/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini

/etc/ansible/kubespray-official/kubespray-new/kubespray/roles/kubernetes/preinstall/vars/debian.yml

 
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt

mkdir -p filter_plugins
cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

обновляемся дальше до 1,26

root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# rm -rf .venv-ansible/
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git add .
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git commit -m "21"
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# python3 -m venv .venv-ansible
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# source .venv-ansible/bin/activate
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# pip install --upgrade pip setuptools wheel
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# sed -i '/ruamel.yaml.clib/d' requirements.txt
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# pip install -r requirements.txt

mkdir -p filter_plugins

cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
тут пра­вим инвен­то­ри и все фай­лы кото­рые и про­шлые разы правили.
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

обновляем до 1,27

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# deactivate
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# rm -rf .venv-ansible/
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git add .
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git branch
master
release-2.20
release-2.21
* release-2.22
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git commit -m "22"
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git checkout release-2.23

пра­вим все те же фай­лы - запол­ня­ем inventory, но в вер­сии release-2.23 есть отли­чие, там появил­ся playbook для debian 12

/etc/ansible/kubespray-official/kubespray-new/kubespray/roles/kubernetes/preinstall/vars/debian-12.yml

поэто­му мож­но не пра­вить файл debian.yaml

root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# python3 -m venv .venv-ansible
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# source .venv-ansible/bin/activate
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# pip install --upgrade pip setuptools wheel
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# sed -i '/ruamel.yaml.clib/d' requirements.txt
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# pip install -r requirements.txt

mkdir -p filter_plugins

cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema

 

запус­ка­ем upgrade

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

обновляем до 1,28

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# deactivate
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# rm -rf .venv-ansible/
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git add .
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git commit -m "23"
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# git checkout release-2.24
не забы­ва­ем править:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# python3 -m venv .venv-ansible
root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# source .venv-ansible/bin/activate
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# pip install --upgrade pip setuptools wheel
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# sed -i '/ruamel.yaml.clib/d' requirements.txt
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# pip install -r requirements.txt

mkdir -p filter_plugins

cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema

запус­ка­ем upgrade

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

обновляем до 1,29

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# deactivate
rm -rf .venv-ansible/
git add .
git commit -m "24"
git checkout release-2.25
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install -r requirements.txt

mkdir -p filter_plugins

cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
не забы­ва­ем править:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
и запус­ка­ем апгрейд
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

обновляем до 1,30

deactivate
rm -rf .venv-ansible/
git add .
git commit -m "24"
git checkout release-2.26
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install -r requirements.txt

mkdir -p filter_plugins

cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/
pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
не забы­ва­ем править:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
и запус­ка­ем апгрейд
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

адейт про­шёл не совсем по плану:

root@kub-master1:~# kubectl uncordon kub-master2.test.local
node/kub-master2.test.local uncordoned

обновляем до 1,31

deactivate
rm -rf .venv-ansible/
git add .
git commit -m "26"
git checkout release-2.27
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install -r requirements.txt

mkdir -p filter_plugins
cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/

pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
не забы­ва­ем править:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
и запус­ка­ем апгрейд
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

обновляем до 1,32

deactivate
rm -rf .venv-ansible/
git add .
git commit -m "27"
git checkout release-2.28
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install -r requirements.txt

mkdir -p filter_plugins
cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/

pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
не забы­ва­ем править:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
и запус­ка­ем апгрейд
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

обновляем до 1.32.9

пока писал всю ста­тью при­ле­те­ли ещё обнов­ле­ния поэто­му сей­час нуж­но обно­вить­ся с 1.32.5 до 1.32.9

поэто­му выпол­ня­ем все дей­ствия что и на преды­ду­щем шаге и запус­ка­ем апдейт

я выка­чи­вал
https://github.com/kubernetes-sigs/kubespray/tree/release-2.28
в директорию:

/etc/ansible/kubespray-official/kub-new

потом пере­име­ную и вер­ну как было

(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kub-new/kubespray/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

ждём и проверяем:

гото­во.
обнов­ля­ем­ся дальше:

обновляем до 1.33.5  (install PLUTO)

перед обнов­ле­ни­ем поста­вим ещё ути­ли­ту pluto что­бы про­ве­рить есть про­бле­мы с сов­ме­сти­мо­стью api

https://github.com/FairwindsOps/pluto/releases

на момент напи­са­ния ста­тьи послед­няя версия

https://github.com/FairwindsOps/pluto/releases/download/v5.22.6/pluto_5.22.6_linux_amd64.tar.gz

кача­ем её
wget https://github.com/FairwindsOps/pluto/releases/download/v5.22.6/pluto_5.22.6_linux_amd64.tar.gz

root@kub-master1:~# tar -xvf pluto_5.22.6_linux_amd64.tar.gz

root@kub-master1:~# chmod +x pluto

root@kub-master1:~# mv ./pluto /usr/bin/

мож­но про­ве­рить как api в кластере:

так и все файлы:

как видим най­де­на ста­рая вер­сия api apps/v1beta1 и её нуж­но заме­нить на apps/v1, дру­гих про­блем у меня не най­де­но поэто­му про­дол­жим обновление:

deactivate
rm -rf .venv-ansible/
git add .
git commit -m "28"
git checkout release-2.29
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install -r requirements.txt

mkdir -p filter_plugins
cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/

pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
не забы­ва­ем править:
/etc/ansible/kubespray-official/kub-new/kubespray/kubespray/inventory/sample/inventory.ini
потом я эту дирек­то­рию пере­де­лаю в:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
и запус­ка­ем апгрейд
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

Про­ве­ря­ем:

 

обновляем до 1.34.1

deactivate
rm -rf .venv-ansible/
git add .
git commit -m "29"

так как ещё нет послед­не­го апдей­та минор­но­го и новой вер­сии то пере­клю­ча­ем­ся на мастера
git checkout master
python3 -m venv .venv-ansible
source .venv-ansible/bin/activate
pip install --upgrade pip setuptools wheel
sed -i '/ruamel.yaml.clib/d' requirements.txt
pip install -r requirements.txt

mkdir -p filter_plugins
cp ~/.ansible/collections/ansible_collections/ansible/utils/plugins/filter/ipaddr.py filter_plugins/

pip install netaddr
pip install cryptography
pip install jmespath
pip install jsonschema
не забы­ва­ем править:
/etc/ansible/kubespray-official/kub-new/kubespray/kubespray/inventory/sample/inventory.ini
потом я эту дирек­то­рию пере­де­лаю в:
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/inventory.ini
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/all/all.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/addons.yml
/etc/ansible/kubespray-official/kubespray-new/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
и запус­ка­ем апгрейд
(.venv-ansible) root@ansible:/etc/ansible/kubespray-official/kubespray-new/kubespray# ansible-playbook -i inventory/sample/inventory.ini upgrade-cluster.yml -b --become-user=root --ask-pass

 

Про­ве­ря­ем:

 

 

 

 

Gitlab in k8s

берём оф чарт:

https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/charts/gitlab

исполь­зу­ем само­под­пи­сан­ный сертификат:

/etc/ansible/kubespray-official/gitlab-gitlab-runner/certs/ca_openssl.cnf

/etc/ansible/kubespray-official/gitlab-gitlab-runner/certs/gitlab_openssl.cnf

созда­ём сертификат

созда­ём namespace

kubectl create ns gitlab
созда­ём сек­рет с нашим  сертификатом:
создан­ный сер­ти­фи­кат рас­ки­ды­ва­ем по всем тачкам:

 
будем исполь­зо­вать встро­ен­ную базу дан­ных, мож­но исполь­зо­вать и внеш­нюю базу для это­го нуж­но рас­ком­мен­ти­ро­вать и запол­нить psql часть, а postgresql выклю­чить ( это в values)

нам нуж­но несколь­ко s3 баке­тов (встро­ен­ный minio не будет использовать)

gitlab-lfs

gitlab-artifacts

gitlab-uploads

gitlab-packages

gitlab-backups

дела­ем для них policy

созда­ём пользователя

и асай­ним на него нашу policy

созда­ём клю­чи для него:

созда­ём сек­рет с досту­па­ми к баке­ту, мож­но делать отдель­ные сек­ре­ты но я решил исполь­зо­вать 1 на все

/etc/ansible/kubespray-official/gitlab-gitlab-runner/s3-conf.yml

kubectl -n gitlab create secret generic gitlab-s3-config --from-file=s3.yml=./s3-conf.yml
ок вот наш values
/etc/ansible/kubespray-official/gitlab-gitlab-runner/gitlab.yaml

ставим:
helm repo add gitlab https://charts.gitlab.io/
helm repo update
helm upgrade --install gitlab gitlab/gitlab -n gitlab --version 8.9.2 --values gitlab.yaml

ждём пока всё установится,

и смот­рим пароль от админки:

root@kub-master1:~# kubectl get secrets -n gitlab gitlab-gitlab-initial-root-password -o yaml | grep password: | awk '{print $2}' | base64 -d
что­бы рабо­тал git clone так как мы ука­за­ли порт 2222 то доба­вим в ingress controller
/etc/ansible/kubespray-official/ingress-controller/values.yaml

весь values для ingress выгля­дит так:

обнов­ля­ем новую кон­фи­гу­ра­цию values
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --version 4.12.1 \
  -f values.yaml

про­ве­ря­ем что порт на ingress добавился:

всё, даль­ше мож­но добав­лять  наш пуб­лич­ный ssh ключ и рабо­тать с репозиториями:

git clone ssh://git@gitlab.test.local:2222/test/test-project.git

 

Gitlab runner

созда­ём сек­рет с нашим само­под­пи­сан­ным сертификатом:

root@kub-master1:~/gitlab-gitlab-runner/certs# kubectl create secret generic gitlab-ssl   --namespace gitlab   --from-file=gitlab.test.local.crt=./gitlab.crt

 

при уста­нов­ке helm chart gitlab я выклю­чил уста­нов­ку gitlab-runner, буду ста­вить его отдель­но, нор­маль­но рабо­та­ет как с self hosted так и с облач­ным gitlab
созда­ём token в пане­ли gitlab
полу­ча­ем токен:
glrt-t3_sFjXrYwuz-xDWPx_A-5a
вот values:
/etc/ansible/kubespray-official/gitlab-gitlab-runner/gitlab-runner.yaml

root@kub-master1:~/gitlab-gitlab-runner# helm upgrade --install gitlab-runner gitlab/gitlab-runner -n gitlab --version 0.74.1 --values gitlab-runner.yaml

про­ве­ря­ем:
как видим всё ок.
созда­ём файл:
.gitlab-ci.yml

2 эта­па и созда­ёт­ся артифакт.

про­ве­ря­ем что всё ок:

про­ве­ря­ем что арте­факт создался

 

теперь про­ве­рим что дан­ный файл доба­вил­ся в s3-minio

как видим всё ок

 

Gitlab helm chart с Freeipa

для инте­гра­ции с freeipa исполь­зу­ем ранее создан­ный sysaccount

uid=gitlab,cn=sysaccounts,cn=etc,dc=test,dc=local

созда­ём сек­рет с паролем:

/etc/ansible/kubespray-official/gitlab-gitlab-runner/gitlab-ldap-secret.yaml

kubectl apply -f gitlab-ldap-secret.yaml

вот наш values:

/etc/ansible/kubespray-official/gitlab-gitlab-runner/gitlab-ldap.yaml

от преды­ду­ще­го отли­ча­ет­ся вот этой частью:

во freeipa у нас есть груп­па gitlab и поль­зо­вать user1

 

про­бу­ем зало­ги­нить­ся с ним:

как видим всё ок.

 

Резервное копирование etcd в hostPath

так как мы на сво­ём желе­зе нам нуж­но делать бэка­пы etcd, тут мы будет делать snapshot etcd и сохра­нять его локаль­но на мастерах

для это­го пер­вым делом созда­дим на всем масте­рах дирек­то­рию под бэкапы:

/var/backups/etcd
for node in $(kubectl get nodes -o wide | grep -i master | awk '{print $6}' ); do ssh root@$node mkdir -p /var/backups/etcd; done
скрипт будет запус­кать каж­дый день в 2 часа ночи, бэкап будет сохра­нять­ся на той тач­ке где запу­стил­ся job
/etc/ansible/kubespray-official/etcd-backup/backup-to-host/backup.yaml

kubectl apply -f backup.yaml
вруч­ную запу­стим проверим:
kubectl create job etcd-backup-now1 --from=cronjob/etcd-backup -n kube-system

ок снап­шот создаётся.

Резервное копирование etcd в s3-minio

так же созда­ём снап­шот но будет хра­нить его в s3-minio
для это­го сна­ча­ла созда­дим bucket  etcd-snapshots
вот его policy

поль­зо­ва­тель etcd  и вот кре­ды пользователя:

access: YcGmA6wqztm5FX4Pfwnf
secret: t0TkdM2Om2P4ZX4mgXx6Sxy9E9SsYnYO9MkIJsCI

теперь созда­ём секрет
kubectl create secret generic s3-credentials \
--from-literal=access-key=ВАШ_ACCESS_KEY \
--from-literal=secret-key=ВАШ_SECRET_KEY \
-n kube-system
в моём слу­чае это:

а вот cronjob

/etc/ansible/kubespray-official/etcd-backup/backup-to-s3-minio/backup.yaml

тут нам нуж­но поправить
--bucket  ука­зы­ва­ем наш создан­ный бакет
--endpoint-url ука­зы­ва­ем адрес наше­го s3-minio

алпа­им

kubectl apply -f etcd-backup/backup-to-s3-minio/backup.yaml
про­ве­ря­ем
kubectl create job etcd-backup-s3 --from=cronjob/etcd-backup-to-s3 -n kube-system

всё норм.
про­ве­ря­ем бакет

всё норм

 

Резервное копирование etcd в s3-minio (LDAP enabled)

 

не забы­ва­ем если вклю­чён LDAP гене­рить токен нуж­но в кон­со­ли, для нача­ла созда­дим поль­зо­ва­те­ля в freeipa, добав­ля­ем его в груп­пу s3-minio-admins (выше по ста­тье я всё опи­сы­вал как мы его создавали)
про­ве­ря­ем что поль­зо­ва­тель подтягивается
при пер­вой про­вер­ке ну будет вид­но что поль­зо­ва­те­лю при­а­та­че­на policy, поэто­му идём в кон­соль на сервер
ssh 192.168.1.118
root@s3-minio-1:~# mc idp ldap policy attach myminio etcd-snapshots --user=user-etcd
Attached Policies: [etcd-snapshots]
To User: user-etcd
гене­рим токен
root@s3-minio-1:~# mc admin user svcacct add myminio user-etcd
Access Key: O0TQHSCRWF7ZXQXGLUGG
Secret Key: ZBCUUUSl+xmOQRXK4KqczWfUKks6xzXm9sovPPIl
Expiration: no-expiry
про­ве­ря­ем в пане­ли всё ок:
ну и созда­ём секрет:

про­ве­ря­ем что cronjob созда­ёт­ся и работает:

root@kub-master1:~# kubectl create job etcd-backup-s3 --from=cronjob/etcd-backup-to-s3 -n kube-system

 

 

Cert-manager (self-signed - самоподписанный)

https://github.com/cert-manager/cert-manager/tree/master/deploy/charts/cert-manager

что­бы каж­дый раз не бегать и рука­ми не создать сер­ти­фи­кат и сек­ре­ты - мож­но исполь­зо­вать cert-manager

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.crds.yaml
helm repo add jetstack https://charts.jetstack.io --force-update
kubectl create ns cert-manager
/etc/ansible/kubespray-official/cert-manager/values.yaml
helm upgrade --install cert-manager --namespace cert-manager --version v1.18.2 jetstack/cert-manager --values values.yaml
/etc/ansible/kubespray-official/cert-manager/issuer-selfsigned.yaml

/etc/ansible/kubespray-official/cert-manager/certificate-root-ca.yaml

/etc/ansible/kubespray-official/cert-manager/issuer-ca.yaml

/etc/ansible/kubespray-official/cert-manager/certificate-wildcard.yaml

мы будем выпи­сы­вать само­под­пи­сан­ный сер­ти­фи­кат *.test.local
kubectl apply -f issuer-selfsigned.yaml
kubectl apply -f certificate-root-ca.yaml
kubectl apply -f issuer-ca.yaml
kubectl apply -f certificate-wildcard.yaml
Issuer selfSigned (issuer-selfsigned.yaml)
Гене­ри­ру­ет кор­не­вой ключ/сертификат CA в пер­вом Certificate-шаге.
Certificate Root-CA (certificate-root-ca.yaml)
Сам Certificate с isCA: true — он под­пи­сы­ва­ет­ся пер­вым Issuer’ом и сохра­ня­ет в Secret ваш кор­не­вой CA.
Issuer CA (issuer-ca.yaml)
Берёт этот кор­не­вой CA-сек­рет (ключ + cert) и ста­но­вит­ся «насто­я­щим» под­пи­сы­ва­ю­щим Issuer’ом для любых downstream-запросов.
Certificate wildcard (certificate-wildcard.yaml)
Запрос сер­ти­фи­ка­та *.test.local, под­пи­сан­но­го уже вашим CA-Issuer’ом.
что­бы полу­чать сер­ти­фи­кат - нуж­но доба­вить в аннотации
вот при­мер:
kubectl create ns argocd
/etc/ansible/kubespray-official/cert-manager/example-cert.yaml
kubectl apply -f example-cert.yaml

там будут
  tls.crt:   # пуб­лич­ный сер­ти­фи­кат *.test.local
  tls.key:   # при­ват­ный ключ к нему
  ca.crt:    # кор­не­вой CA-сер­ти­фи­кат, на базе кото­ро­го был под­пи­сан tls.crt
на этом всё.

Argocd

kubectl create ns argocd
helm repo add argo-cd https://argoproj.github.io/argo-helm
/etc/ansible/kubespray-official/argocd/values.yaml
helm upgrade --install argo-cd argo-cd/argo-cd -n argocd --values values.yaml --version 8.1.3

ждём пока уста­но­вит­ся, потом смот­рим пароль:

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d 

Argocd add user

# 1) Гене­рим пароль
kubectl exec -ti -n argocd argo-cd-argocd-server-84c56df477-h6mnl -- bash
argocd account bcrypt --password '4CL8do3zkZzPHfuk22'
полу­ча­ем:
$2a$10$R1OkCf90A7Kg/aMA.DD3DOv9y12FPLP6eh0ViukCt/NIf.c/Q/oDy
# 2) полу­чен­ный hash при­сва­и­ва­ем переменной
RAW_HASH='$2a$10$R1OkCf90A7Kg/aMA.DD3DOv9y12FPLP6eh0ViukCt/NIf.c/Q/oDy'
# 3) Коди­ру­ем его в base64 (это и будет ваше accounts.test.password)
HASH_B64=$(echo -n "$RAW_HASH" | base64 -w0)
# 4) Зада­ём пра­виль­ный RFC3339-штамп:
RAW_MTIME='2025-07-14T12:48:50Z'
# 5) Коди­ру­ем штамп в base64 (это будет ваше accounts.test.passwordMtime)
MTIME_B64=$(echo -n "$RAW_MTIME" | base64 -w0)
# 6) Добав­ля­ем пароль для поль­зо­ва­те­ля test

 
# 7) Добав­ля­ем само­го поль­зо­ва­те­ля test в конфигмап

 
# 8) Выдать досту­пы, напри­мер поль­зо­ва­тель test будет адми­ном а поль­зо­ва­тель alice будет иметь досту­пы readonly

 
про­ве­ря­ем:

 
# 9) Рестар­ту­ем и можем про­ве­рять аутентификацию
kubectl rollout restart  -n argocd deployment argo-cd-argocd-server
про­ве­ря­ем:
Захо­дим под поль­зо­ва­те­лем test - у кото­ро­го есть все права
как видим про­ект успеш­но создан
теперь зай­дём под поль­зо­ва­те­лем alice и так же попро­бу­ем создать проект:
как видим всё ок. досту­пов не хва­та­ет - как и задумано.

Argocd интеграция с Freeipa

для нача­ла созда­ём sysaccount во freeipa
[root@freeipa-1 ]# cd /etc/ipa
[root@freeipa-1 ipa]# bash freeipa-sam.sh

созда­ём 2 группы

в адми­нах у меня user1
в read only user2

про­ве­рить нали­чие поль­зо­ва­те­ля в груп­пах мы можем вот такой командой:

ldapsearch -H ldap://192.168.1.100 -D "uid=argocd,cn=sysaccounts,cn=etc,dc=test,dc=local" -W -b "uid=user1,cn=users,cn=accounts,dc=test,dc=local" "(objectClass=*)" memberOf

 

про­ве­рить какие поль­зо­ва­те­ли есть в груп­пе вот такой командой:

ldapsearch -H ldap://192.168.1.100 -D "uid=argocd,cn=sysaccounts,cn=etc,dc=test,dc=local" -W -b "cn=argocd-admin,cn=groups,cn=accounts,dc=test,dc=local" "(objectClass=*)" member

пароль для sysaccount будем хра­нить в secret

/etc/ansible/kubespray-official/argocd/argocd-ldap-secret.yaml

root@kub-master1:~/argocd# kubectl apply -f argocd-ldap-secret.yaml

 

вот values
/etc/ansible/kubespray-official/argocd/values-ldap.yaml

тут:

host: 192.168.1.100:389 адрес freeipa сервера
bindDN: $LDAP_BIND_DN  логин из секрета
bindPW: $LDAP_BIND_PW  пароль из секрета
filter: "(&(objectClass=posixAccount)(|(memberOf=cn=argocd-admin,cn=groups,cn=accounts,dc=test,dc=local)(memberOf=cn=argocd-ro-users,cn=groups,cn=accounts,dc=test,dc=local)))"     огра­ни­чи­ва­ем доступ 2мя груп­па­ми argocd-admin и argocd-ro-users

а тут выда­ём rbac досту­пы для групп
dex:
env:
- name: LDAP_BIND_DN

тут под­тя­ги­ва­ем в пере­мен­ные логин и пароль
можем ста­вить
root@kub-master1:~/argocd# helm upgrade --install argo-cd argo-cd/argo-cd -n argocd --values values-ldap.yaml --version 8.1.3

 

про­ве­ря­ем:

как видим поль­зо­ва­тель user3 не име­ет доступа

про­ве­рим user2

как видим мы можем зай­ти но ниче­го создать не можем

про­ве­рим теперь user1

можем уви­деть в каких груп­пах состо­ит этот пользователь

созда­дим группу:

как видим всё ок - успеш­но созда­ёт­ся, прав хватает.

 

Argocd создание проекта, настройка деплоя

 

в моей репке
https://gitlab.test.local/argo/test-app/app1.git
есть толь­ко 1 файл:

deployment.yaml

кото­рые запус­ка­ет деп­лой­мент в 2х репли­ках с мини­маль­ны­ми ресур­са­ми и liveness readiness пробами.

 

созда­ём новый проект

добав­ля­ем целе­вой кластер

ука­зы­ва­ем что про­ек­ту будет разрешено

для под­клю­че­ния репо­зи­то­рия будем исполь­зо­вать access token

токен дела­ет­ся на уровне группы:

создаю argo-token  из досту­пов хва­та­ет read_repository  но я ещё тык­нул на api лень было пере­со­зда­вать оста­вил так.
после созда­ния будет пока­зан пароль кото­рый пока­зы­ва­ет­ся толь­ко 1 раз, сохра­ни­те его

воз­вра­ща­ем­ся в argocd

запол­ня­ем все ука­зан­ные поля, и не забы­ва­ем вклю­чить Skip server verification

кста­ти под­клю­чить репо­зи­то­рий мож­но командой:

как видим репо­зи­то­рий подключен

теперь созда­дим application кото­рый будет авто­ма­ти­че­ски синхронизироваться

выби­ра­ем наш репо­зи­то­рий ука­зы­ва­ем что по branch дол­жен син­кать­ся, мож­но ещё выбрать по тэгам, и в path ста­вим точ­ку (если прям в корне лежат фай­лы кото­рые нуж­но апла­ить, а если в какой то дру­гой дирек­то­рии то ука­зы­ва­ем до неё путь, мож­но ещё вклю­чить и рекур­сив­ную про­хо­ду по всем вло­жен­ны­ми дирек­то­ри­ям в path)

сохра­ня­ем и получаем:

как видим сра­зу пошёл про­цесс син­хро­ни­за­ции,  так как мы ука­за­ли Sync Policy  автоматически.

как видим всё ок, и оба наших pod задеплоились

про­ве­рим:

мы можем скей­лить наш деп­лой­мент в любое коли­че­ство - argocd будет воз­вра­щать к исход­но­му в 2 реплики.

для при­ме­ра выклю­чу SELF HEAL и деп­лой­мент заскей­лю в 1.

выби­раю апку

про­ме­ты­ва­ем ниже:

выклю­ча­ем SELF HEAL

при­во­дим к тако­му виду:

скей­лим апку вниз:

как видим толь­ко 1 pod

про­ве­ря­ем:

как видим SYNC STATUS = OutOfSync

если нажать на OutOfSync  откро­ет­ся diff

кото­рый пока­жет различие:

для вос­ста­нов­ле­ния может нажать sync

как видим всё ок  - синканулось

 

Argocd создание проекта, настройка деплоя Helm

 

Теперь с помо­щью argocd уста­но­вим апку кото­рая исполь­зу­ет helm.

у нас есть репка
https://gitlab.test.local/argo/test-helm/app1.git

я создал дефолт­ный chart
helm create helm-app1

и пуш­нул его в gitlab repo

добав­ля­ем этот репо­зи­то­рий в argocd

напо­ми­наю что для мое­го про­ек­та project-dev мож­но деп­ло­ить в любой неймспейс

теперь созда­дим application

будем авто­ма­ти­че­ски ста­вить без руч­ной син­хро­ни­за­ции + вклю­чим созда­ние namespace

ука­зы­ва­ем нашу реп­ку имя нейм­с­пей­са test2 и путь где лежит чарт

даль­ше появ­ля­ет­ся меню где можем выста­вить настрой­ки для values кото­рые НЕ закомменчены

как видим всё ок.

 

Argocd создание проекта из конфиг файла

Всё ок, мы наты­ка­ли application в пане­ли, но есть про­бле­ма если мы уда­лим его в пане­ли то с вклю­чён­ным фина­лай­зе­ром  уда­лит­ся и апка и потом надо будет вруч­ную добав­лять всё.
поэто­му нуж­но хра­нить апли­кей­ше­ны  в конфигах.

выта­щить кон­фиг файл можем так:

кон­фиг полу­ча­ем следующий:

helm app вот такой:

сло­жим эти кон­фи­ги в репку

https://gitlab.test.local/argo/argo-config.git

фай­лы будут лежать тут:

argo-config/app1/app1.yaml
argo-config/helm-app1/helm-app1.yaml

далее уда­ля­ем наши applications

настро­ем теперь реп­ку, так же как и остальные

теперь настро­им application

обя­за­тель­но отме­ча­ем DIRECTORY RECURSE

про­ве­ря­ем что всё ок:

как видим ок - мы запус­ка­ем наши applications с помо­щью дру­го­го application

 

Argocd создание проекта. настройка деплоя Helm когда values и chart в разных репозиториях

у нас есть реп­ка где лежит основ­ной helm chart:
https://gitlab.test.local/argo/test-helm/app1.git

а вот в эту репку:
https://gitlab.test.local/argo/test-helm/app2.git

поло­жим толь­ко values
helm/values.yaml

добав­ля­ем репку

даль­ше есть про­бле­ма так как UI у ArgoCD не уме­ет добав­лять к application несколь­ко репо­зи­то­ри­ев, мы будем настра­и­вать это через кон­фиг  test123.yaml

при­ме­ним его

kubectl apply -f test123.yaml

про­ве­ря­ем:

как видим при такой кон­фи­гу­ра­ции у нас появи­лась допол­ни­тель­ная вклад­ка SOURCES кото­рой не было  при запус­ке из панели

по сути всё, гото­во. у нас есть основ­ной репо­зи­то­рий в кото­ром нахо­дит­ся helm chart и у нас может быть мно­же­ство дру­гих репо­зи­то­ри­ев в кото­рых может быть толь­ко values.

всё раз­ру­ли­ва­ет­ся на уровне кон­фи­га в sources

вот офи­ци­аль­ная дока:
https://argo-cd.readthedocs.io/en/latest/user-guide/multiple_sources/

 

Keda

кеда поз­во­ля­ет скей­лить при­ло­же­ния на осно­ве раз­ных мет­рик из promethtus или victoria-metrics

офф чарт

https://github.com/kedacore/charts/tree/main/keda

созда­ём тесто­вую апку:
helm create test-app-keda
kubectl create ns app1
cd ~/keda/example
helm upgrade --install -n app1 app1 ./test-app-keda/

 

созда­ём тесто­вый домен

при­ме­ня­ем файл /etc/ansible/kubespray-official/keda/example/scale-object.yaml

он будет смот­реть в вик­то­рию и в слу­чае если за 2 мину­ты будет боль­ше 100 запро­сов он будет скей­лить апку вверх
для про­вер­ки запускаем
root@kub-master1:~/keda/example# for i in {1..1000}; do curl -Ik test.test.local ; sleep 1; done
резуль­тат такой:
сам запрос к victoriametrics может быть любой
как видим всё ок,  апка заскей­ли­лась в максимум
если выклю­чим цикл для curl и подо­ждём, то уви­дим что апка заскей­ли­лась вниз:

 

Patrony

это кла­стер для бд postgresql
поз­во­ля­ет пере­клю­чать мастер репли­ка на лету. будем исполь­зо­вать ansible role
https://github.com/midnight47/ansible-playbook/tree/master/roles/patroni
Про­те­сти­ро­ва­но на сер­ве­рах debian
схе­ма такая нуж­ны 3 ноды для etcd базы будет 2, они будут рас­по­ла­гать­ся на тех же нодах что и etcd, на них же будет haproxy кото­рый будет отправ­лять весь тра­фик на мастер ноду, репли­ка не будет полу­чать тра­фик. так же для удоб­ства настро­ен keepalived с вир­ту­аль­ным ip на кото­рый мы будем обращаться.
нам нуж­но будет настро­ить сле­ду­ю­щие переменные:
/etc/ansible/roles/patroni/defaults/main.yml

тут мы можем задать пор­ты для postgresql/haproxy/patroni
под­сеть в кото­рой будет рас­по­ло­жен кластер
вер­сия postgres
вир­ту­аль­ный IP
/etc/ansible/roles/patroni/handlers/main.yml

/etc/ansible/roles/patroni/tasks/install_etcd.yml

/etc/ansible/roles/patroni/tasks/install_haproxy.yml

/etc/ansible/roles/patroni/tasks/install_keepalived.yml

/etc/ansible/roles/patroni/tasks/install_patroni.yml

/etc/ansible/roles/patroni/tasks/install_postgres.yml

/etc/ansible/roles/patroni/tasks/ntp.yml

/etc/ansible/roles/patroni/tasks/main.yml

/etc/ansible/roles/patroni/templates/etcd.conf

/etc/ansible/roles/patroni/templates/haproxy.cfg.j2

/etc/ansible/roles/patroni/templates/keepalived.conf

/etc/ansible/roles/patroni/templates/patroni.service

/etc/ansible/roles/patroni/templates/patroni.yml.j2

/etc/ansible/playbooks/roles_play/patroni.yml

/etc/ansible/hosts

уста­нов­ку запус­ка­ем так:

root@ansible:/etc/ansible# ansible-playbook playbooks/roles_play/patroni.yml --ask-pass

про­ве­рить что etcd кла­стер запущен
etcdctl member list
про­ве­рить что патро­ни запущен:
patronictl -c /etc/patroni.yml list
ответ дол­жен быть такой:
если нуж­но сме­нить лидера:

в интер­ак­тив­ном режи­ме команда

patronictl -c /etc/patroni.yml failover

он там сам пред­ло­жит варианты

про­ве­рить подключение:
psql -h 192.168.1.155 -p 5432 -U postgres -c "SELECT pg_is_in_recovery();"
(ip вир­ту­аль­ный а пароль тот кото­рый задан в superuser_password)
посмот­реть логи:
journalctl -u patroni.service -b --no-pager | tail -n50
в целом всё, мож­но под­клю­чать­ся по вир­ту­аль­но­му ip 192.168.1.155 haproxy сам най­дёт кто мастер и будет слать тра­фик туда.

Helm-chart

Helm - это мене­джер паке­тов для Kubernetes. Этот инстру­мент поз­во­ля­ет нам обер­нуть Kubernetes при­ло­же­ния в удоб­ные паке­ты, назы­ва­е­мые чар­та­ми, кото­рые мож­но лег­ко раз­вер­ты­вать, обнов­лять и управ­лять ими в любой момент времени.

Чар­ты – это паке­ты, кото­рые могут вклю­чать в себя все для запус­ка при­ло­же­ния в Kubernetes, от deployments до services. Все это дает воз­мож­ность рабо­тать с при­ло­же­ни­я­ми как с еди­ной сущ­но­стью, а не как с набо­ром отдель­ных ресур­сов, кото­рые еще и в руч­ную нуж­но настраивать…

Так же Helm упро­ща­ет управ­ле­ние зави­си­мо­стя­ми меж­ду при­ло­же­ни­я­ми, поз­во­ля­ет лег­ко пара­мет­ри­зи­ро­вать настрой­ки при­ло­же­ний через фай­лы values.yaml и дает воз­мож­ность повтор­но­го исполь­зо­ва­ния чар­тов с помо­щью шаблонизации.

Создание дефолтного чарта

root@kub-master1:~# helm create common-chart
kubectl create ns app
root@kub-master1:~/helm-charts/1_default# helm upgrade --install app -n app ./common-chart/ --values ./common-chart/values.yaml
Что­бы убрать из име­ни пода суф­фикс common-chart, нуж­но пере­опре­де­лить шаб­лон пол­но­го име­ни ресур­са в Helm. В стан­дарт­ном чар­те common-chart это дела­ет­ся через зна­че­ние fullnameOverride.
Добавь­те в ваш values.yaml (/etc/ansible/kubespray-official/helm-charts/1_default/common-chart/values.yaml) строку:
fullnameOverride: app
Это заста­вит Helm гене­ри­ро­вать имя Deployment (и, соот­вет­ствен­но, подов) ров­но как <Release.Name>, без добав­ле­ния име­ни чарта.

как видим имя сменилось.

 

Добавление секретов из vault

настро­им под­клю­че­ние vault secret к наше­му чарту

не забу­дем что у нас дол­жен быть установлен
"Vault Secrets Operator"

ну настро­ем ещё разок

https://github.com/hashicorp/vault-secrets-operator/blob/main/chart/Chart.yaml

ста­вим
helm repo add hashicorp https://helm.releases.hashicorp.com
helm upgrade --install --namespace vault vault-secrets-operator hashicorp/vault-secrets-operator --version 0.10.0 -f vault-secrets-operator.yaml

даль­ше нам надо настро­ить инте­гра­цию с нашим vault кла­сте­ром, кото­рый на вир­ту­ал­ках, для это­го нам пона­до­бит­ся сер­ти­фи­кат поэто­му выпол­ня­ем команду:

kubectl get cm kube-root-ca.crt -o jsonpath="{['data']['ca\.crt']}"
полу­ча­ем наш серт
созда­ём сер­вис аккаунт
kubectl create serviceaccount vault-auth -n kube-system
на осно­ве это­го сер­вис акка­ун­та полу­ча­ем jwt token  уста­нав­ли­ваю вре­мя на 100 лет 876000h
kubectl create token vault-auth -n kube-system --duration 876000h
далее под­клю­ча­ем­ся к наше­му vault кото­рый на виртуалках
ssh 192.168.1.103
напо­ми­наю root token
hvs.UuG0QJvRRfwUHUTGxDTjFaAd
root@vault1:~# vault login
созда­ём сек­рет кото­рый будем подкидывать:
root@vault1:~# vault secrets enable -path=test/secret/ kv
добав­ля­ем туда ключ значение:
root@vault1:~# vault kv put test/secret/app/first-app password="db-secret-password"
вклю­ча­ем аутен­ти­фи­ка­цию в k8s
root@vault1:~# vault auth enable kubernetes
сер­ти­фи­кат кото­рый полу­чи­ли ранее коман­дой kubectl get cm kube-root-ca.crt -o jsonpath="{['data']['ca\.crt']}" , кла­дём в файл /root/ca.crt
даль­ше при­сва­и­ва­ем пере­мен­ной TOKEN_REVIEWER_JWT наш jwt токен кото­рый мы созда­ли выше
root@vault1:~# export TOKEN_REVIEWER_JWT=''

теперь настра­и­ва­ем auth к кластеру

созда­ём policy  "test-policy" на чте­ние ТОЛЬКО наше­го секрета
созда­ём роль "test-role"
Роль свя­зы­ва­ет учет­ную запись служ­бы Kubernetes(serviceaccaunt), кото­рую назо­вём app (но луч­ше исполь­зо­вать уже суще­ству­ю­щий сер­вис акка­унт наше­го при­ло­же­ния ) в про­стран­стве имен app с поли­ти­кой Vault, test-policy Токе­ны, воз­вра­щен­ные после аутен­ти­фи­ка­ции, дей­стви­тель­ны в тече­ние 10 минут
На роли дол­жен быть задан audience — с Vault ≥1.21 он обя­за­те­лен. Зна­че­ние долж­но сов­па­дать с aud в JWT сер­вис-акка­ун­та, кото­рым логи­нит­ся pod. При­мер обнов­ле­ния роли:
bound_service_account_names: Имя сер­вис­но­го акка­ун­та, кото­ро­му раз­ре­ше­но аутентифицироваться.
bound_service_account_namespaces: Про­стран­ство имён, в кото­ром нахо­дит­ся сер­вис­ный аккаунт.
Как выбрать audience:
Самый надёж­ный вари­ант — выдать pod’у projected токен с нуж­ной audience и поста­вить её же в роли Vault:
созда­ём объ­ект VaultConnection кото­рый будет исполь­зо­вать­ся для под­клю­че­ния к vault во всех неймспейсах
kubectl apply -f vault-connection.yaml

kubectl apply -f vault-auth.yaml

для под­клю­че­ния к VaultConnection  исполь­зу­ет­ся запись: kube-system/vault-connection
так же тут указываем
роль создан­ную в vault test-role и
сер­вис акка­унт app - кото­рый так же дол­жен сов­па­дать с тем что мы ука­за­ли в vault и с тем что у нас уже создан в k8s
kubectl apply -f vault-static-secret.yaml