kubernetes.minikub.практика-запуск простейших сущностей

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

1.POD
2.REPLICASET
3.DEPLOYMENT
4.readinessProbe и livenessProbe
5.LIMITS
6.SERVICE
7.INGRESS
8.CONFIGMAP
9.Deployment apache
10.log-nfs-server
11. Dynamic NFS provision
12.Nginx apache nfs-dinamic provision
13.Helm
14.Helm прак­ти­ка
15.Autoscaling 
16.ci/cd gitlab

Дошли руки до раз­бо­ра и прак­ти­че­ско­го запус­ка. Име­ет­ся уста­нов­лен­ный мини­куб на нём рас­смот­рим прак­ти­че­ский запуск от про­стей­щей сущ­но­сти пода до более сложных
и так для нача­ла запу­стим pod в кото­ром будет 1 кон­тей­нер nginx
Но для нача­ла настро­им авто­за­пол­не­ние, что­бы поль­зо­вать­ся табом, для это­го выполним:

yum install bash-completion

[root@minikub ~]# kubectl completion -h | grep bash
Output shell completion code for the specified shell (bash or zsh). The shell code must be evaluated to provide interactive completion of kubectl commands. This can be done by sourcing it from the .bash _profile.
# Installing bash completion on macOS using homebrew
brew install bash-completion
brew install bash-completion@2
kubectl completion bash > $(brew --prefix)/etc/bash_completion.d/kubectl
# Installing bash completion on Linux
## If bash-completion is not installed on Linux, please install the 'bash-completion' package
## Load the kubectl completion code for bash into the current shell
source <(kubectl completion bash)
## Write bash completion code to a file and source if from .bash_profile
kubectl completion bash > ~/.kube/completion.bash.inc
source '$HOME/.kube/completion.bash.inc'
" >> $HOME/.bash_profile
source $HOME/.bash_profile

[root@minikub ~]# kubectl completion bash > ~/.kube/completion.bash.inc
[root@minikub ~]# source '/root/.kube/completion.bash.inc'

Созда­дим кон­фиг файл:

[root@minikub ~]# cat pod.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# kubectl create -f pod.yaml

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

теперь запу­стим несколь­ко кон­тей­не­ров через replicaset

[root@minikub ~]# cat replicaset.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# kubectl create -f replicaset.yaml
replicaset.apps/my-replicaset created

про­ве­ря­ем, как мы видим replicaset успеш­но запу­ще­на, смот­рим поды, есть наш ста­рый под с име­нем my-pod и 3 пода запу­щен­ные репли­ка­се­том, с име­нем my-replicaset-(id)

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

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

[root@minikub ~]# cat deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# kubectl create -f deployment.yaml
deployment.apps/my-deployment created

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

Теперь добавим проверки на доступность, а именно readinessProbe и livenessProbe

[root@minikub ~]# cat deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

что­бы при­ме­нить изме­не­ния, необ­хо­ди­мо выпол­нить команду:
[root@minikub ~]# kubectl apply -f deployment.yaml
deployment.apps/my-deployment configured

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

Теперь добавим лимиты


Limits - 
коли­че­ство ресур­сов кото­рые pod может использовать(верхняя граница)
Requies -
коли­че­ство ресур­сов кото­рые резер­ви­ру­ют­ся для pod на ноде (не делят­ся с дру­ги­ми пода­ми на ноде)

[root@minikub ~]# cat deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

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

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

посмот­рим подроб­ное опи­са­ние пода:
[root@minikub ~]# kubectl describe pod my-deployment-7c88b95897-bcbsw

[codesyntax lang="php"]

[/codesyntax]

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

Теперь опишем service

Сер­вис по меткам(лейблам) даёт ука­за­ния, что надо отправ­лять тра­фик на pod-ы

[root@minikub ~]# cat service.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# kubectl apply -f service.yaml
service/my-service created

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

ну а что­бы отпра­вить тра­фик на my-service исполь­зу­ет­ся INGRESS

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

INGRESS

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

[root@minikub ~]# cat ingress.yml

[codesyntax lang="php"]

[/codesyntax]

 

[root@minikub ~]# kubectl apply -f ingress.yml
ingress.extensions/my-ingress created

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

видим что ингресс создан и обра­ще­ния на домен test.ru, на 80 порт, будут ухо­дить на  наш сер­вис my-service, это можем уви­деть если посмот­рим describe

[codesyntax lang="php"]

[/codesyntax]

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

Configmap

Доба­вим к наше­му nginx кон­фиг файл, кото­рый будет прок­си­ро­вать все запро­сы на наш деп­лой­мент с apache.

[root@minikub my-project]# cat nginx-configmap.conf
[codesyntax lang="php"]

[/codesyntax]

созда­ём конфигмап

[root@minikub my-project]# kubectl create -f nginx-configmap.conf
configmap/nginx-conf created

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

[codesyntax lang="php"]

[/codesyntax]

 

и попра­вим деп­лой­мент у nginx что­бы он мог под­та­щить новый конфигмап

[root@minikub my-project]# cat deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

при­ме­ним новые изменения:
[root@minikub my-project]# kubectl apply -f deployment.yaml

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

Теперь запустим deployment с apache 

[root@minikub my-project]# cat deployment-apache.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub my-project]# kubectl apply -f deployment-apache.yaml
deployment.apps/my-deployment-apache created

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

[root@minikub my-project]# cat service-apache.yaml

[codesyntax lang="php"]

[/codesyntax]

my-service-apache - вот на это имя и нуж­но прок­си­ро­вать запро­сы с наше­го nginx

[root@minikub my-project]# kubectl apply -f service-apache.yaml
service/my-service-apache created

про­ве­ря­ем что всё запущено:

про­ве­рим что  запро­сы дей­стви­тель­но доле­та­ют до апача.
Смот­рим на каком ip висит наш pod с nginx

отпра­вим пару запро­сов по доме­ну test.ru ука­зан­но­му в ingress
[root@minikub my-project]# curl -I test.ru/TEEEEST
HTTP/1.1 404 Not Found
Server: openresty/1.15.8.2
Date: Mon, 04 May 2020 12:39:20 GMT
Content-Type: text/html; charset=iso-8859-1
Connection: keep-alive
Vary: Accept-Encoding

теперь смот­рим лог пода apache

[root@minikub my-project]# kubectl log my-deployment-apache-859486bd8c-vxnbk | grep TEEEEST
log is DEPRECATED and will be removed in a future version. Use logs instead.
172.17.0.6 - - [04/May/2020:12:39:18 +0000] "HEAD /TEEEEST HTTP/1.0" 404 -

как видим всё ок, запро­шен­но­го урла нету, апач отве­тил 404, и запрос при­ле­тел с ip 172.17.0.6

 

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

Теперь прокинем директории для логов и файлов сайта на nfs сервер.

 

у нас уста­нов­лен отдель­ный nfs сер­вер 192.168.1.82 кото­рый при­мон­ти­ро­ван к наше­му мини­ку­бу в директории:
/nfs-client

созда­ём PersistentVolume на 2 гига в директории:
/nfs-client/test

[root@minikub ~]# cat pv.yaml

[codesyntax lang="php"]

[/codesyntax]

 

так­же созда­ём PersistentVolumeClaim - это запрос на PersistentVolume (на 1 гига­байт) с типом
ReadWriteMany – том может быть смон­ти­ро­ван к мно­же­ству подов в режи­ме чте­ния и записи.

[root@minikub ~]# cat pvc.yaml

[codesyntax lang="php"]

[/codesyntax]

 

при­ме­ним

про­ве­рим:
[codesyntax lang="php"]

[/codesyntax]

 

теперь под­клю­чим этот pv к наше­му деплойменту:

[root@minikub ~]# cat my-project/deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

 

при­ме­ним изменения:
[root@minikub ~]# kubectl apply -f my-project/deployment.yaml

подо­ждём когда поды обно­вят­ся и проверим:

[codesyntax lang="php"]

[/codesyntax]

запись
/var/log/nginx/ from research-vol (rw)
гово­рит нам, что наш том успеш­но про­ки­нул­ся внутрь пода.

====

теперь доба­вим pv для фай­лов сайта.

созда­дим pv и pvc

[root@minikub ~]# cat persistent-volume-for-site-files.yaml

[codesyntax lang="php"]

[/codesyntax]

тут:
pv-files-of-site-test.ru  - наш вольюм
pvc-files-of-site-test.ru -
запрос на вольюм
/nfs-client/files-of-site-test.ru -
дирек­то­рия на nfs сервере

созда­ём директорию
[root@minikub ~]# mkdir /nfs-client/files-of-site-test.ru

и созда­ём наши новые pv и pvc
[root@minikub ~]# kubectl apply -f persistent-volume-for-site-files.yaml
persistentvolume/pv-files-of-site-test.ru created
persistentvolumeclaim/pvc-files-of-site-test.ru created

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

теперь попра­вим наши кон­фиг фай­лы для nginx и для apache

[root@minikub ~]# cat my-project/nginx-configmap.conf

[root@minikub ~]# kubectl apply -f my-project/nginx-configmap.conf
configmap/nginx-conf created
configmap/apache-conf created

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

[root@minikub ~]# cat my-project/deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat my-project/deployment-apache.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# kubectl apply -f my-project/deployment-apache.yaml

[root@minikub ~]# kubectl apply -f my-project/deployment.yaml

всё, после того как поды обно­вят­ся мож­но загру­жать фай­лы сай­та в директорию:
/nfs-client/files-of-site-test.ru/

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

Dynamic NFS provision

доба­вим дина­ми­че­скую рабо­ту с pv

у нас уже уста­нов­лен nfs сервер:

192.168.1.82 и у него общая дирек­то­рия /nfs
на кли­ен­тах дирек­то­рия /nfs

cat rbac.yaml

[codesyntax lang="php"]

[/codesyntax]

cat class.yaml

[codesyntax lang="php"]

[/codesyntax]

cat deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

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

cat pvc.yaml

[codesyntax lang="php"]

[/codesyntax]

теперь при­ме­ня­ем:

kubectl apply -f rbac.yaml
kubectl apply -f class.yaml
kubectl apply -f deployment.yaml
kubectl apply -f pvc.yaml

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

apache nginx + файлы сайта на nfs сервере c auto provision.

[root@minikub ~]# cat nfs-auto-provisioner/rbac.yaml
[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat nfs-auto-provisioner/class.yaml
[codesyntax lang="php"]

 

[root@minikub ~]# cat nfs-auto-provisioner/deployment.yaml

 

[root@minikub ~]# kubectl apply -f rbac.yaml
[root@minikub ~]# kubectl apply -f class.yaml
[root@minikub ~]# kubectl apply -f deployment.yaml

cat pvc.yaml

[codesyntax lang="php"]

[/codesyntax]

cat httpd/service-apache.yaml

[codesyntax lang="php"]

[/codesyntax]

cat httpd/deployment-apache.yaml

 

 

cat nginx/service-nginx.yaml

[codesyntax lang="php"]

[/codesyntax]

cat nginx/deployment-nginx.yaml

[codesyntax lang="php"]

[/codesyntax]

kubectl apply -f pvc.yaml
kubectl apply -f httpd/service-apache.yaml
kubectl apply -f httpd/deployment-apache.yaml
kubectl apply -f nginx/service-nginx.yaml
kubectl apply -f nginx/deployment-nginx.yaml

cat /nfs-client/default-volume-for-site-testru-pvc-8e1b883e-1407-441f-9d24-162e7d83b015/index.html
ttt

 

Helm

Уста­но­вим helm
yum install epel-release
yum install snapd
systemctl enable --now snapd.socket
systemctl enable snapd
systemctl restart snapd

ln -s /var/lib/snapd/snap /snap
snap install helm --classic
echo 'export PATH="$PATH:/snap/bin" ' >> ~/.profile
export PATH="$PATH:/snap/bin"

Полу­чить справ­ку по воз­мож­но­стям хельма:

[root@minikub ~]# helm help

Создание Helm Chart

Далее — созда­дим свой чарт, обно­вим в нём шаб­ло­ны, и заде­п­ло­им какое-то при­ло­же­ние в Kubernretes.

Созда­ём новый чарт:

[root@minikub ~]# mkdir helm
[root@minikub ~]# cd helm/
[root@minikub helm]# helm create example-chart
Creating example-chart

посмот­рим содержимое:

[root@minikub helm]# tree example-chart
example-chart
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│   └── test-connection.yaml
└── values.yaml

3 directories, 10 files

Содер­жи­мое его деплоймента:

[codesyntax lang="php"]

[/codesyntax]

[codesyntax lang="php"]

[/codesyntax]

Тут всё доста­точ­но оче­вид­но — для replicas: {{ .Values.replicaCount }} в templates/deployment.yaml будет исполь­зо­ва­но зна­че­ние replicaCount: 1 из values.yaml.

Но мы эти шаб­ло­ны исполь­зо­вать не будем — а напи­шем свой вело­си­пед чарт.

Уда­ля­ем их:

[root@minikub helm]# rm -rf example-chart/templates/*

Далее доба­вим свой ConfigMap.

Добавление template

Созда­дим файл example-chart/templates/configmap.yaml, а в нём — содер­жи­мое для фай­ла index.html:

[codesyntax lang="php"]

[/codesyntax]

chart linter

Перед уста­нов­кой чар­та име­ет смысл выпол­нить про­вер­ку син­так­си­са чар­та — исполь­зу­ем helm lint:

[root@minikub helm]# helm lint example-chart/
==> Linting example-chart/
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, 0 chart(s) failed

chart install

Ещё раз про­ве­рим — на какой кла­стер настро­ен наш kubectl:

[root@minikub helm]# kubectl config current-context
minikube

Для уста­нов­ки выпол­ня­ем helm install, кото­ро­му пер­вым аргу­мен­том пере­да­ём имя рели­за, потом опции, и путь к фай­лам чарта.

Перед выпол­не­ни­ем реаль­ных дей­ствий име­ет смысл выпол­нить «тесто­вый про­гон» — исполь­зу­ем --dry-run, и доба­вим --debug для деталей:

[codesyntax lang="php"]

[/codesyntax]

Оши­бок нет — уста­нав­ли­ва­ем его:

[root@minikub helm]# helm install example-chart example-chart/
NAME: example-chart
LAST DEPLOYED: Sun Jul 5 20:18:35 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

Про­ве­ря­ем его статус:

[codesyntax lang="php"]

[/codesyntax]

helm вывел инфор­ма­цию о ресур­сах и фай­лах, кото­рые были при­ме­не­ны к релизу.

Про­ве­рим с kubectl:

[root@minikub helm]# kubectl describe cm nginx-configmap
Name: nginx-configmap
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: example-chart
meta.helm.sh/release-namespace: default

Data
====
index.html:
----
Hello, World
Events: <none>

chart uninstall

Ана­ло­гич­но, для уда­ле­ния исполь­зу­ем helm uninstall и имя релиза:

[root@minikub helm]# helm uninstall example-chart
release "example-chart" uninstalled

Template переменные

Хоро­шо — всё рабо­та­ет, но сей­час все дан­ные в нашем ConfigMap статичны.

Изме­ним это — вклю­чим в рабо­ту шаблонизатор.

Для helm дост­пен набор пред­опре­де­лён­ных зна­че­ний, напри­мер — Release.Name, см. пол­ный спи­сок в доку­мен­та­ции.

Редак­ти­ру­ем шаб­лон наше­го ConfigMap:

[codesyntax lang="php"]

[/codesyntax]

И доба­вим сво­их пере­мен­ных — уда­ля­ем теку­щий файл values.yaml:

[root@minikub helm]# rm -rf example-chart/values.yaml

И созда­ём его зано­во, но с одним полем — user: "Username":

[codesyntax lang="php"]

[/codesyntax]

А затем исполь­зу­ем пере­мен­ную user в шаблоне:

[codesyntax lang="php"]

[/codesyntax]

Тут через .Values мы ука­зы­ва­ем обра­ще­ние к наше­му values,yaml, из кото­ро­го helm дол­жен под­тя­нуть зна­че­ние пере­мен­ной user.

При­ме­ня­ем:

[root@minikub helm]# helm install example-chart example-chart/
NAME: example-chart
LAST DEPLOYED: Sun Jul 5 20:26:11 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

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

И содер­жи­мое:

[root@minikub helm]# kubectl describe cm example-chart-configmap
Name: example-chart-configmap
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: example-chart
meta.helm.sh/release-namespace: default

Data
====
index.html:
----
Hello, Username
Events: <none>

chart upgrade

Что, если мы хотим изме­нить зна­че­ние Username?

Мож­но уда­лить релиз, и заде­п­ло­ить зано­во, пере­дав новое зна­че­ние либо через редак­ти­ро­ва­ние values.yaml, либо через --set:

[root@minikub helm]# helm uninstall example-chart
release "example-chart" uninstalled

[root@minikub helm]# helm install example-chart example-chart/ --set user=NewUser
NAME: example-chart
LAST DEPLOYED: Sun Jul 5 20:28:53 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

Про­ве­ря­ем

[root@minikub helm]# kubectl describe cm example-chart-configmap
Name: example-chart-configmap
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: example-chart
meta.helm.sh/release-namespace: default

Data
====
index.html:
----
Hello, NewUser
Events: <none>

Дру­гой вари­ант — вызвать helm upgrade, пере­дать имя рели­за и новое значение:

[root@minikub helm]# helm upgrade example-chart example-chart/ --set user=AnotherOneUser
Release "example-chart" has been upgraded. Happy Helming!
NAME: example-chart
LAST DEPLOYED: Sun Jul 5 20:29:57 2020
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None

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

[root@minikub helm]# kubectl describe cm example-chart-configmap
Name: example-chart-configmap
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: example-chart
meta.helm.sh/release-namespace: default

Data
====
index.html:
----
Hello, AnotherOneUser
Events: <none>

helm package

Что бы пере­дать наш чарт дру­гим поль­зо­ва­те­лем — мож­но его упа­ко­вать в tgz-файл.

Исполь­зу­ем helm package, кото­рый создаст файл вида имя-чарта-версия-чарта.tgz.

Вер­сию helm полу­чит из мета­дан­ных чарта:

[root@minikub helm]# cat example-chart/Chart.yaml | grep version:
version: 0.1.0

Упа­ко­вы­ва­ем

[root@minikub helm]# helm package example-chart/
Successfully packaged chart and saved it to: /root/helm/example-chart-0.1.0.tgz

И содер­жи­мое архива:

[root@minikub helm]# tar tf example-chart-0.1.0.tgz
example-chart/Chart.yaml
example-chart/values.yaml
example-chart/templates/configmap.yaml
example-chart/.helmignore

Helm репозитории

Для пере­да­чи чар­тов исполь­зу­ем helm-репозитории.

Рань­ше мож­но было запу­стить локаль­ный репо­изто­рий с помо­щью helm serve, но в Helm v3 его выпилили.

Для рабо­ты с репо­зи­то­ри­я­ми в V3 исполь­зу­ем helm repo.

По-умол­ча­нию в спи­сок репо­зи­то­ри­ев сра­зу добав­ля­ет­ся репо­зи­то­рий от Google:

[root@minikub helm]# helm repo add stable https://kubernetes-charts.storage.googleapis.com/
"stable" has been added to your repositories

[root@minikub helm]# helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com/

Running local Helm repo

Для того, что бы создать свой репо­зи­то­рий — доста­точ­но выпол­нить helm package чар­та, после чего сге­не­ри­ро­вать файл index.yaml в ката­ло­ге, кото­рый хра­нит архив.

В каче­стве бекен­да для репо­зи­то­ри­ев может быть что угод­но — от Github Pages, до AWS S3, см. The Chart Repository Guide.

Тут при­мер локаль­но­го репозитория.

Созда­ём ката­лог, пере­но­сим в него архив:

[root@minikub helm]# mkdir helm-local-repo
[root@minikub helm]# mv example-chart-0.1.0.tgz helm-local-repo/

Ини­ци­а­ли­зи­ру­ем репозиторий:

[root@minikub helm]# helm repo index helm-local-repo/

Содер­жи­мое

[root@minikub helm]# tree helm-local-repo/
helm-local-repo/
├── example-chart-0.1.0.tgz
└── index.yaml

0 directories, 2 files

Что бы полу­чить к нему доступ — запу­стим про­стой NGINX:

[root@minikub helm]# docker run -ti -v $(pwd)/helm-local-repo/:/usr/share/nginx/html -p 80:80 nginx

Про­ве­ря­ем подключение:

[root@minikub helm]# curl localhost/index.yaml

apiVersion: v1
entries:
example-chart:
- apiVersion: v2
appVersion: 1.16.0
created: "2020-05-03T14:04:44.896115358+03:00"
description: A Helm chart for Kubernetes
digest: afa314247a03c4c85f339bda665659f3ab13a5e8656336e14ed37ed7f31b5352
name: example-chart
type: application
urls:
- example-chart-0.1.0.tgz
version: 0.1.0
generated: "2020-05-03T14:04:44.895678349+03:00"
Добав­ля­ем этот репо­зи­то­рий в спи­сок заре­ги­стри­ро­ван­ных в локаль­ном Helm:
[root@minikub helm]# helm repo add example-chart http://localhost
"example-chart" has been added to your repositories
Про­ве­ря­ем
[root@minikub helm]# helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com/
example-chart   http://localhost
Про­бу­ем поиск чарта:
elm search repo example
NAME                            CHART VERSION   APP VERSION     DESCRIPTION
example-chart/example-chart     0.1.0           1.16.0          A Helm chart for Kubernetes
Уста­нав­ли­ва­ем его:
helm install example-chart-from-repo example-chart/example-chart
NAME: example-chart-from-repo
LAST DEPLOYED: Sun May  3 14:15:51 2020
NAMESPACE: default
STATUS: deployed
Про­ве­ря­ем в Kubernretes:
kubectl get cm
NAME                                DATA   AGE
example-chart-configmap             1      34m
example-chart-from-repo-configmap   1      22s

Helm практика

рас­смот­рим наш деп­лой­мент apache nginx

[root@minikub ~]# mkdir -p /root/helm/my-site/{charts,templates}

[root@minikub ~]# cat /root/helm/my-site/Chart.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat /root/helm/my-site/values.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# vim /root/helm/my-site/templates/ingress.yml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat /root/helm/my-site/templates/service-nginx.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat /root/helm/my-site/templates/service-apache.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat /root/helm/my-site/templates/deployment-nginx.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cat /root/helm/my-site/templates/deployment-apache.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub ~]# cd /root/helm/my-site/
[root@minikub my-site]# helm install site-testru ../my-site/
NAME: site-testru
LAST DEPLOYED: Wed Jul 22 17:46:19 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

 

 

Autoscaling

HorizontalPodAutoscaler не может быть при­ме­нен к объ­ек­там, кото­рые не пред­на­зна­че­ны для мас­шта­би­ро­ва­ния, напри­мер DaemonSets. Horizontal Pod Autoscaler состо­ит из Kubernetes ресур­са (объ­ек­та) и кон­трол­ле­ра, пове­де­ние кото­ро­го опи­сы­ва­ет­ся ресурсом.

C пери­о­дич­но­стью 15 секунд (мож­но изме­нить с помо­щью пара­мет­ра --horizontal-pod-autoscaler-sync-period), кон­трол­лер соби­ра­ет дан­ные по исполь­зо­ва­нию мет­рик, опре­де­лен­ных в мани­фе­сте ресур­са HorizontalPodAutoscaler. Мет­ри­ки соби­ра­ют­ся или с resource metrics API (мет­ри­ки исполь­зо­ва­ния ресур­сов пода­ми) или с custom metrics API (осталь­ные мет­ри­ки, напри­мер, мет­ри­ки приложения).

Для каж­до­го под­кон­троль­но­го пода, кон­трол­лер соби­ра­ет мет­ри­ки (напри­мер, исполь­зо­ва­ния CPU) с resource metrics API (metrics.k8s.io, предо­став­ля­ет­ся metrics-server). Далее, про­ис­хо­дит вычис­ле­ние теку­ще­го зна­че­ния исполь­зо­ва­ния CPU в про­цен­тах от запро­шен­ных ресур­сов (resource request) кон­тей­не­ра­ми каж­до­го пода, после чего это зна­че­ние срав­ни­ва­ет­ся с “целе­вым” (target) зна­че­ни­ем - поро­гом, после кото­ро­го коли­че­ство подов долж­но быть увеличено.

Важ­но! Если не ука­за­ны resource request хотя бы для одно­го из кон­тей­не­ров в Replication Controller, Replica Set или Deployment, то теку­щее зна­че­ние исполь­зо­ва­ние CPU пода­ми не может быть кор­рект­но опре­де­ле­но, и, в резуль­та­те, HorizontalPodAutoscaler не будет пред­при­ни­мать ника­ких дей­ствий по масштабированию.

Фор­му­ла, по кото­рой HorizontalPodAutoscaler вычис­ля­ет тре­бу­е­мое коли­че­ство реплик выгля­дит так:

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
Напри­мер, если теку­щее зна­че­ние мет­ри­ки (currentMetricValue) рав­но 200m,
а ожи­да­е­мое (desiredMetricValue) уста­нов­ле­но в 100m,
то коли­че­ство реплик будет удво­е­но (200.0 / 100.0 == 2.0).
Если же теку­щее зна­че­ние мет­ри­ки рав­но все­го лишь 50m, то коли­че­ство реплик долж­но быть умень­ше­но вдвое (50.0 / 100.0 == 0.5). Если соот­но­ше­ние теку­ще­го зна­че­ния мет­ри­ки к ожи­да­е­мо­му зна­че­нию доста­точ­но близ­ко к 1, то ника­ких дей­ствий не будет предпринято.

если ука­за­ли targetAverageUtilization при опи­са­нии ресур­са HorizontalPodAutoscaler, то теку­щее зна­че­ние мет­ри­ки (currentMetricValue) исполь­зо­ва­ния CPU рас­счи­ты­ва­ет­ся как сред­нее зна­че­ние этой мет­ри­ки для всех подов, кон­тро­ли­ру­е­мых дан­ным автоскейлером.

После того, как теку­щее зна­че­ние исполь­зо­ва­ния CPU сни­зи­лось и оста­ва­лось низ­ким в тече­нии 5 минут (уста­нав­ли­ва­ет­ся с помо­щью пара­мет­ра --horizontal-pod-autoscaler-downscale-stabilization), коли­че­ство реплик было авто­ма­ти­че­ски уменьшается.

Итак для нача­ла надо уста­но­вить metrics-server

helm repo add stable https://charts.helm.sh/stable

helm upgrade -i metrics-server stable/metrics-server --set args='{--kubelet-preferred-address-types=InternalIP,--kubelet-insecure-tls,--metric-resolution=30s}' --namespace=kube-system

Посмот­реть ресур­сы на нодах:
kubectl top node
посмот­реть ресур­сы на деплойментах:
kubectl top deployment
посмот­реть ресур­сы на подах:
kubectl top pod

у нас есть сле­ду­ю­щий деп­лой­мент и сервис
[codesyntax lang="php"]

[/codesyntax]

 

доба­вим к нему  автос­кей­лер по CPU и MEMORY

[codesyntax lang="php"]

[/codesyntax]

 

ниже рас­смот­рим что куда зачем:
Для CPU:

1.Имя это­го автоскейлера
2.Версия API мас­шта­би­ру­е­мо­го объекта
3.Тип объ­ек­та для масштабирования
4.Название мас­шта­би­ру­е­мо­го объекта
5.Минимальное коли­че­ство реплик для уменьшения
6.Максимальное коли­че­ство реплик для масштабирования
7.Средний про­цент запро­шен­ной памя­ти, кото­рую дол­жен исполь­зо­вать каж­дый модуль. т.е. % от requests исполь­зо­ва­ния CPU, при дости­же­нии кото­ро­го НРА нач­нёт добав­лять или уда­лять поды

 

Для MEMORY:

1.Имя это­го автоскейлера
2.Версия API мас­шта­би­ру­е­мо­го объекта
3.Тип объ­ек­та для масштабирования
4.Название мас­шта­би­ру­е­мо­го объекта
5.Минимальное коли­че­ство реплик для уменьшения
6.Максимальное коли­че­ство реплик для масштабирования
7.Средний про­цент запро­шен­ной памя­ти, кото­рую дол­жен исполь­зо­вать каж­дый модуль.

что­бы про­те­сти­ро­вать авто­сей­линг  запу­стим нагрузку:
kubectl run load-generator --image=busybox -- /bin/sh -c "while true; do wget -q -O- http://hello-world-app-service; done"

 

 ci/cd проекта - gitlab

 

Рас­смот­рим как деп­ло­ить про­ект в кубер через ci/cd от gitlab

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

захо­дим под рутом и созда­ём ново­го пользователя:

далее надо задать ему пароль

выхо­дим из под рута

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

ука­зы­ва­ем новый пароль

нас выки­ну­ло, пароль успеш­но задан:

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

и зада­ём SSH ключ

 

гене­рим ключ если нету:

[root@minikub ~]# ssh-keygen

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

[root@minikub ~]# cat /root/.ssh/id_rsa.pub

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

копи­ру­ем URL

и выка­чи­ва­ем:

[root@minikub ~]# git clone git@192.168.1.190:kubernetes/street-terminal.git

[root@minikub ~]# cd street-terminal/

Созда­ём namespace :

[root@minikub ~]# kubectl create namespace terminal-soft

там у нас уже есть redis (как его доба­вить мы опи­сы­ва­ли вот в этой статье:
Redis in kubernetes
так же в кубе­ре будет запу­ще­на база postgres, вооот по этой статье:
postgres - stolon
)

на них пока не обра­ща­ем вни­ма­ния, рас­смот­рим поэтап­ный деп­лой 1 это будет сбор­ка кон­тей­не­ра и загруз­ка его в gitlab registry.

у нас есть докерфайл:
[root@minikub ~]# cat street-terminal/service/Dockerfile

[codesyntax lang="php"]

[/codesyntax]

 

в пап­ке app нахо­дит­ся наше ском­пи­ли­ро­ван­ное java при­ло­же­ние и файл с под­клю­че­ни­ем к базе и к редису:
[codesyntax lang="php"]

[/codesyntax]

 

созда­ём 2 ран­не­ра один docker дру­гой shell, для это­го смот­рим токен, необ­хо­ди­мый для реги­стра­ции ранера:

вот наш токен:

TyJT8b8vdcMRNDG7trE5

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

Уста­нов­ка и настрой­ка Gitlab и Gitlab Runner

у меня он уже установлен
При­сту­пим к реги­стра­ции SHELL раннера:

[codesyntax lang="php"]

[/codesyntax]

 

Теперь уста­но­вим DOCKER runner:

[codesyntax lang="php"]

[/codesyntax]

 

при реги­стра­ции ране­ра я забыл доба­вить тег shell ране­ру, - его все­гда мож­но мож­но добавить/поправить в панели:

Про­ве­рим ста­тус и  вклю­че­ны ли Docker и Gitlab ран­нер при запус­ке системы:

[codesyntax lang="php"]

[/codesyntax]

 

теперь про­ве­рим в пане­ли появи­лись ли наши runner-ы

 

добав­ля­ем пра­ва на нашей целе­вой тачке:
[root@minikub street-terminal]# adduser gitlab-runner
[root@minikub street-terminal]# usermod -a -G docker gitlab-runner
[root@gitlab ~]# usermod -a -G docker gitlab-runner
[root@minikub street-terminal]# id gitlab-runner
uid=1004(gitlab-runner) gid=1004(gitlab-runner) groups=1004(gitlab-runner),993(docker)
[root@minikub street-terminal]# systemctl restart docker
[root@minikub street-terminal]# passwd gitlab-runner
Changing password for user gitlab-runner.
New password:
BAD PASSWORD: The password is a palindrome
Retype new password:
passwd: all authentication tokens updated successfully.

[root@minikub street-terminal]# cat /etc/sudoers | grep wheel | grep -v '#'
%wheel ALL=(ALL) NOPASSWD: ALL

С сер­ве­ра с кото­ро­го runer будет про­из­во­дить деп­лой,  долж­ны быть рас­ки­да­ны ssh клю­чи (из под поль­зо­ва­те­ля gitlab-runner )

[root@gitlab ~]# su - gitlab-runner
[gitlab-runner@gitlab ~]$ cat /etc/hosts | grep minikub
192.168.1.120 minikub
[gitlab-runner@gitlab ~]$ ssh-keygen
[gitlab-runner@gitlab ~]$ ssh-copy-id gitlab-runner@minikub

так же копи­ру­ем кон­фиг что­бы ран­нер мог выпол­нять уда­лён­ные команды:

[root@minikub street-terminal]# cp /etc/kubernetes/admin.conf /home/gitlab-runner/.kube/config
[root@minikub street-terminal]# chown -R gitlab-runner:gitlab-runner /home/gitlab-runner/.kube/

на всех тач­ках добавляем:
cat /etc/docker/daemon.json

{ "insecure-registries" : ["192.168.1.190:4567"] }

systemctl daemon-reload 
systemctl restart docker

 

Созда­ём в корне про­ек­та файл .gitlab-ci.yml

[root@minikub street-terminal]# cat /root/street-terminal/.gitlab-ci.yml

[codesyntax lang="php"]

[/codesyntax]

 

дан­ный pipeline будет производить:
1.сборку образа
2.тегирование и загруз­ку обра­за в gitlab
3.выкачивание обра­за на целе­вой сервер.

пушим его в наш репозиторий:

[root@minikub street-terminal]# git add .
[root@minikub street-terminal]# git commit -m "add ci/cd8"
[master 4dd6343] add ci/cd8
1 file changed, 1 insertion(+)
[root@minikub street-terminal]# git push

далее в нашей пане­ли захо­дим в пайплайны:
не обра­ща­ем вни­ма­ния на осталь­ные ком­ми­ты пай­плай­нов это я тестил пока писал инструк­цию. Выби­ра­ем наш послед­ний коммит:

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

видим что изме­нил­ся ста­тус на running

попа­да­ем в сле­ду­ю­щее меню кото­рое пока­зы­ва­ет про­цесс выполнения(на скрин­шо­те пока­за­но успеш­ное выполнение)

про­ве­ря­ем нали­чие собран­но­го обра­за в нашем registry:

пои­дее мини­маль­ная часть выпол­не­на. НОООООО  там паро­ли логи­ны висят в откры­том виде а это не есть хоро­шо, поэто­му надо исполь­зо­вать пере­мен­ные. Пере­мен­ные эти будут рабо­тать в рам­ках одно­го проекта.
Доба­вим пере­мен­ные в сам gitlab а в /root/street-terminal/.gitlab-ci.yml будем их вызывать

Доба­вим 2 пере­мен­ные в сам гитлаб:
login_kubernetes
и
kubernetes_password

В фай­ле .gitlab-ci.yml будем вызы­вать эти пере­мен­ные сле­ду­ю­щим образом:

${login_kubernetes}
${kubernetes_password}

так же доба­вим пере­мен­ные в сам gitlab-ci
gitlab_server: '192.168.1.190:4567'
gitlab_user_project: 'kubernetes/street-terminal'

их будем вызы­вать сле­ду­ю­щим образом:
$gitlab_server
$gitlab_user_project

[root@minikub street-terminal]# cat /root/street-terminal/.gitlab-ci.yml

[codesyntax lang="php"]

[/codesyntax]

добав­ля­ем эти дан­ные в наш гитлаб:
[root@minikub street-terminal]# git add .
[root@minikub street-terminal]# git commit -m "add ci/cd14"
[root@minikub street-terminal]# git push

Ниже helm chart наше­го деплоймента
[root@minikub street-terminal]# cat /root/street-terminal/service/deployment-helm/Chart.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub street-terminal]# cat /root/street-terminal/service/deployment-helm/templates/deployment.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub street-terminal]# cat /root/street-terminal/service/deployment-helm/templates/service.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub street-terminal]# cat /root/street-terminal/service/deployment-helm/templates/ingress.yaml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub street-terminal]# cat /root/street-terminal/service/deployment-helm/values.yaml

[codesyntax lang="php"]

[/codesyntax]

 

[root@minikub street-terminal]# cat /root/street-terminal/.gitlab-ci.yml

[codesyntax lang="php"]

[/codesyntax]

[root@minikub street-terminal]# git add .
[root@minikub street-terminal]# git commit -m "add ci/cd34"
[root@minikub street-terminal]# git push

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

как видим всё ок, оба эта­па отра­бо­та­ли автоматически

 

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

попра­вим нашу CI/CD для чело­ве­че­ско­го использования:

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

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

[root@gitlab~]# yum install epel-release
[root@gitlab~]# yum install snapd
[root@gitlab~]# systemctl enable --now snapd.socket
[root@gitlab~]# systemctl enable snapd
[root@gitlab~]# systemctl restart snapd

[root@gitlab~]# ln -s /var/lib/snapd/snap /snap
[root@gitlab~]# snap install helm --classic
[root@gitlab~]# echo 'export PATH="$PATH:/snap/bin" ' >> ~/.profile
echo 'export PATH="$PATH:/var/lib/snapd/snap/bin"' >> ~/.profile
[root@gitlab~]# export PATH="$PATH:/snap/bin"

 

Так же что­бы с ране­ра рабо­тал kubectrl  надо его поставить:

[root@gitlab~]# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

[root@gitlab~]# yum install kubectl

Теперь надо доба­вить kubeconfig что­бы всё нор­маль­но запус­ка­лось, для это­го созда­дим пере­мен­ную в нашем gitlab

содер­жи­мое файла:
[root@minikub street-terminal]# cat /etc/kubernetes/admin.conf
пиха­ем в пере­мен­ную:  KUBECONFIG

ну и сра­зу доба­вим пере­мен­ную для паро­ля базы данных:
kubernetes_database_password

ci/cd будет выгля­деть сле­ду­ю­щим образом:

[codesyntax lang="php"]

[/codesyntax]

но делать про­вер­ку базы в ci/cd не кошер­но поэто­му убе­рём этот этап.

[codesyntax lang="php"]

[/codesyntax]

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

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

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

[codesyntax lang="php"]

[/codesyntax]

Пере­мен­ная terminal_sof_redis_password_kubctl_secret  это пере­мен­ная FILE в самом гитла­бе, с пол­ным содер­жи­мым файла:

redis/secret-password.yaml

что­бы тэг пере­дал­ся надо сде­лать следующее:

git add .
git tag -a v2 -m "commit new tag v2"
git commit -m "new image with tag"
git push
git push origin --tags

после это­го пере­дан­ный нами тэг будет взят и образ собе­рёт­ся с тэгом v2

уда­лить tag локаль­ный мож­но командой:
git tag -d v1
уда­лить tag в гитла­бе мож­но командой
git push origin :refs/tags/v2

что­бы gitlab-runner запус­кал несколь­ко задач парал­лель­но надо в файле:
/etc/gitlab-runner/config.toml
доба­вить или изме­нить параметр:
concurrent = 2

после чего надо сделать:
gitlab-ctl restart