Tag: DevOps

Debug Kubernetes like a shrimp

Пиша за бъдещото си аз (и бъдеща статия за дейбъг на k8s). Тук ми е списъка с малките радости в живота при дебъг и по-точно:

  1. tail -f like experience with kubect get pods podname:
kubectl logs -f podname

2. За повече инфо около някой pod (особено когато вече е умрял и не можем да му видим логовете с горната команда) имаме:

kubectl describe pod

Имаме доооста информация включително и малко логове, имаме си и друга информация като volumes, портове, от къде се контролира (особено полезно ако като тепърва започвате с k8s и тръгнете да триете под и той след 5 секунди пак възкръсва като Марая Кери при падането на първата снежинка за годината) и още много.

3. Филтриране на подове и игра с output-а на kubectl. Ако искате да видите всички running pods какво правите? Мда, със сигурност не правите като мен – първичното решение да направите kubectl get pods и после да въртите разни bash тъпотии за да филтрирате. Можете обаче да използвате супер полезните field-selectors и да правите с output-а каквото си пожелаете. Нещо, което ми трябваше е да видя всички работещи pod-ове на кои node-ове живеят. Стана с една команда:

kubectl get pods --field-selector status.phase=Running -o wide

4. Какво става на клъстъра ми? Всеки се пита понякога, особено ако си хоствате сами k8s-а. Е, можете да намерите много информация с:

kubectl get events

Изсипва ви тонове с информация. Можете да сортирате по време с kubectl get events –sort-by=’.lastTimestamp’, но и нещо, което не знаех до момента в който не тръгнах да пиша тази статия. Можете да видите предишните stage-ове на вече умрели pod-ове! Което е супер полезно стига да им знаете името – kubectl get events podname

5. CPU/Memory usage per node/pod, особено както сега се боря като дебела женичка в добричка дискотека 2000 г.

kubectl top node nodename
kubectl top pod podname

6. Приключвам с най-верния ми приятел – kubectl exec, който ми позволява да се логна на pod-а и да видя логове и каквото друго ми е нужно. Тук е хубаво да отбележим, че докато работите по някой dockerfile, който е по-засукан можете да използвате root user-а. Не е стандартна, нито добра практика, но ще ни спести няколко билда. Като посвикне човек вече става интинктивно. Имайте предвид, че тук викаме bash, но ако ти каже, че няма използвайте sh:

kubectl exec -it podname -- bash

Също така можете да изпълнявте команди директно на пода, например искаме да видим всички env vars на pod-а:

kubectl exec -it podname -- env

7. Get k8s secrets directly (convert base64 secrets on the fly)

Когато работим със secrets или sealedSecrets ни се налага понякога да видим някой secret. Тяхната природа е да бъдат base64 кодирани и имаме още една стъпка в декриптирането. Е, с тази команда (забележете, че трябва да имате инсталиран jq):

kubectl get secrets some-secret -o jsonpath='{.data}' | jq -r 'to_entries[] | "\(.key): \(.value | @base64d)"'

7.1 Ако пък не искате да използвате горната команда (хинт – можете да си я сложите като alias) – можете да декодирате и кодирате стрингове по base64 директно в конзолата с:

~ echo "https://www.youtube.com/watch?v=dQw4w9WgXcQ" | base64
aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUQo=

~ echo "aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUQo=" | base64 -d
https://www.youtube.com/watch?v=dQw4w9WgXcQ


Edit – мислих да кръстя статията “Debug Kubernetes like a pro”, но съм много далеч от pro та за това – shrimp.

How to view jar version with unzip

Набързо пиша са future self, че ако искам да видя каква версия на application-а съм деплойнал може да стане лесно с unzip и по-специално с:

# unzip -q -c example-app.jar META-INF/MANIFEST.MF
Manifest-Version: 1.0
Implementation-Title: example-app
Implementation-Version: 1.23.4
Start-Class: com.example.example.app.ExampleApp
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 3.2.1.RELEASE
Created-By: Maven Archiver 3.6.1
Implementation-Vendor: example
Main-Class: org.springframework.boot.loader.JarLauncher

И виждаме, че използваме версия 1.23.4. Супер удобно както в моя случай като администрирам доста различни Java сървиса и непременно в някакъв момент започват едни – кой какво е деплойнал, къде ,ама как, кога и подобни.

Можете да направите и в един oneliner връщайки само версията:

# unzip -q -c example-app.jar META-INF/MANIFEST.MF | grep 'Implementation-Version' | cut -d ':' -f 2
2.13.4

бтв докато писах последното изречение – ако се наложи да инспектирате например кога е направена последната промяна по някой конкретен файл или искате малко повече инфо можете да използвате stat:

# stat example-app.jar
  File: ‘example-app.jar’
  Size: 90837539        Blocks: 177424     IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 8669310     Links: 1
Access: (0500/-r-x------)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:usr_t:s0
Access: 2024-01-10 10:53:52.964543333 +0100
Modify: 2024-01-10 10:53:33.700533240 +0100
Change: 2024-01-10 10:53:33.700533240 +0100
 Birth: -

12.11.2023

Marvinator-а, брат на marvin, който съвсем скоро вдигнах имаше нужда от мониторинг. И тръгвам аз да инсталирам prometheus/alertsmanager/grafana и в един момент започнах да смятам колко рам ще ми е нужна. И понеже съм скръндза реших да изнеса целия мониторинг към Grafana.com и да им използвам безплатния tier, който като единствен минус към момента ми е, че metrics & log retention-а ми е само 14 дни, но yolo.

Инсталацията на агента, който е единственото нещо, което живее на моя хост е бърза и лесна, а откъм потребление към момента е около 140 MB RAM. Ако бях хостнал локално целия стак щеше със сигурност да бъде много повече.

A project of the day отива при tuning-primer – bash скрипт, който дава добър анализ на mysql/mariadb бази. Нужни са само root user/pass към базата и като резултат ви изплюва всичко, което му е харесало и което не е ок. Има доста данни покрай анализите и можете да си направите един добър fine tuning.

05.01.2023

Ако някога ви се случи да се логвате в (private) docker repo и тръгне да ви гърми с:

It reports: Error saving credentials: error storing credentials - err: exit status 1, out: status code not OK but 401: {"detail":"Incorrect authentication credentials"}

Първото нещо, което искате да направите преди да променяте конфигурацията в ~/.docker/config.json е да направите

docker logout

You’ll thank me later. Моя train of thought тръгна към друга посока и изгубих 15 минути докато се сетя да опитам да logout-на преди да дебъгвам по на дълбоко.

Docker tips and tricks – choosing the right image

Some time ago I start an article about microservices but I got no time to continue the series. Nevertheless, I’ll publish the first one of the series. It’s a simple yet effective article on how to optimize often tremendous by size images to something that takes a lot less space and therefore can be run much faster.

The original code of a Dockerfile to run quite a simple python app looks like this:

FROM ubuntu:latest
WORKDIR /app
COPY ./app /app
RUN apt-get update && apt-get install python3 -y
RUN apt-get update && apt-get install python3-pip -y
RUN pip install requests==2.27.1
ENTRYPOINT [“echo”,”Hello”]

The result after we build the Dockerfile:

~/repo/docker-articles$ time docker build . -t original:0.1 --quiet
docker build . -t original:0.1 --quiet  0.10s user 0.09s system 0% cpu 35.108 total
$ docker images -a                                                                                                                                                                 REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
original     0.1       27cfff826324   7 seconds ago   438MB

Let’s optimize:

FROM python:3.8-alpine
WORKDIR /app
COPY ./app /app
RUN pip install --no-cache-dir requests==2.27.1
ENTRYPOINT ["python", "hello.py"]

Changes:

  • Update the docker image to a python alpine (use the latest python on lightweight Alpine Linux)
  • Remove install python & pip steps (they come prepackaged)
  • Use –no-cache-dir to save some space

Result:

~/repo/docker-articles$ docker images -a
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
optimized    0.1       f5036ae50ca7   16 seconds ago   55MB

Build time:

~/repo/docker-articles$ time docker build . -t optimized:0.1 --quiet
docker build . -t optimized:0.1 --quiet  0.08s user 0.07s system 2% cpu 7.027 total

Build size reduced by 155.375%

Build time reduced by 133.291%

Choosing the right image with Docker is crucial. With a simple change, we can save 155% on the container’s size and reduce build time by 133%! With the next tutorial we’ll see multi-stage builds and how we can produce miniature, yet completely working and idempotent docker containers adding just a little more code in our Dockerfile.

Смених работата and why I love nitropack.io

След като преминах от света на QA към DevOps нещата при мен се развиха много динамично. Ама много. За поледните четири години не съм спрял да уча и за секунда всичко от което имам (или нямам :D ) нужда – основно AWS (в който вече съм AWS Certified Solutions Architect Associate), linux, git, CI/CD, методологии, технологии и практически всичко, което ми се е изпречвало на пътя.

Но при всичките работи, които съм сменил държа на няколко основни фактора като единия, който често пропускаме умишлено или не е фирмената култура. Това понякога е много по-важно дори и от заплатата, защото ако работиш с да речем сърдити лелки и чичковци е трудно, меко казано.


ТА преди по-малко от 2 месеца се свърза с мен HR-ката на nitropack и реших да се чуя с нея, защото job description-а беше доста интересен, интервюто беше супер приятно, без помпозности и обещания, грандомански изпълнения и каквото се сетите още. Светна ми зелената лампа в главата и след като се уговорихме за разговор с технически човек бях доста развълнуван. Чухме се след няколко дни и интервюто прочете страхотно – пак приятно отношение, а не все едно съм крепостен селянин, точни въпроси, време да помисля на глас, говорихме си за Linus Tech Tips и homelab и като приключи разговора знаех, че ще приема офертата ако са ме харесали. Имайте предвид, че те дори и не използват AWS! Е, 40 минути след като приключих техническото интеревю ми звънна HR, разбрахме се за 5 минути какво, кое и как да направя, оповестих на текущия си работодател и се разбрахме да си стиснем ръцете още за същия ден (за което съм наистина благодарен, защото момента беше много подходящ (между два проекта)) и след 2 дни бях в София на първия си работен ден в nitropack.io. Офисът се намира в CampusX и вътре цареше много спокойна и приятна обстановка, бяха много приятелски настроени колегите и започнахме с onboarding-а.

Месец по-късно съм в Боровец с още 36 чудесни човека и правим team activities, смеем се и пием бира, разказваме си вицове, но аз си пазя най-смешните (или най-тъпите по-скоро) за вечерта, защото предложих да направим един dad jokes contest в който два отбора от двама човека си разказваме вицове на които ако другия отбор се разсмее губи точка. Беше супер забавно, а аз щях да пукна от стискане да не се разсмея като ученик на две глъдки бира. И самият факт, че ей така вмъкнаха една простотия, която знаете, че може да ескалира много бързо ако се бъзикна с някакви not okay неща, в програмата за вечерта и че всички се събраха и се смяхме като побъркани ми даде ясен сигнал, че това е моето място.

Работата за момента е супер – правим CI/CD, занимаваме се с k8s и срещам разнообразни проблеми, които решавам сам или с помоща на хора, на които мога да разчитам.
Абе като цяло съм доволен. Плюс използвах техния плъгин (free версията, която си е доста щедра) в блога преди да кандидатствам изобщо и съм им и фен освен другото. Ако сте забелязали, че блога е по-бърз, а той е по-бърз е от плъгина. За бога преди година и нещо отделих няколко дни да го забързам малко, а сега имам 100 от 100 точки в google page speed за десктоп и 93 за mobile!

Едит – ей, забравих да напиша, че Нитропак е най-динамичната IT компания за 2021 г. Още едно мега признание за това какво прави компанията и в какви обеми оперираме + какви отговорности има всеки един от нас в екипа.

29.02.2020 – dump

Просто дъмп – смесени изречения опитващи се да дадат форма на ненормалните дни, които се случват около мен.

На първо място е сватбата – тооооолкова много детайли, толкова много детайли, толкова много …. да, детайли. Хубаво е, но е ненужно сложно. Все едно да използвам Oracle cloud да обслужва базата на блога.

После идва работата, която смених преди няколко месеца. Още не мога да повярвам, че всеки ден уча по толкова много неща, че имам повече табове в конзолата (както се шегувахме с колегите) отколкото в браузъра, Ubuntu пак ми е основна OS и съм доста щастлив от това (макар, че гледам с прикрита завист на новата конзола на микромеките, която изглежда доста прилично), работя си от нас и като цяло нещата изглеждат прилично.

После идва липсата на тренировки – мина много време откакто карах за последно, което е долу-горе момента в който паднах и се пребих. После ходих да катеря връх Ботев с MTB, история за която тръгнах да пиш на няколко пъти, но сигурно няма да види бял свят, там се запознах със супер приятните хора (и още едно доказателство, че MTB хората са далеч по-сърдечни и приятни отколкото някои шосейни “състезатели” (можете да ми теглите една в коментарите, но знаете, че е така).

И накрая, но не на последно място – котката Иво е още жив, има козина и там всичко останало и даже отвреме на време като работя идва и се сгушва в мен докато дъни Rotting Christ или Lee Hazlewood.

И говорейки за музика, смятам да направя един отделен пост с музикалните ми открития от миналата година – има някои истински находки, които са били скрити от мен толкова много време.

И малък тийз – Жлъча издаде нов албум, Вяра, мога да го сравнявам с брилиантната поезия от неговите Вода и вино (2017) и Удар (2015).

И НАКРАЯ, да, да, знам, обещавам, за последно – текат последните ми приготовления за QA: Challenge Accepted 2020. Там ще си говорим за това как да не изпадаме в панка на сцената, малко психология, малко орхан мурад джоукс, малко съвети и после, надявам се, величествен биропой. Ако някой от хората, които четат блога е там ще се радвам да се видим там.

Да видите как си спазвам обещанията от горния абзац, guess what – има още! Последно време събирам кратки и тъпи вицове (don’t ask) та ето ви малко:

Баща на седем дъщери в отчаянието си кръсти осмата Иван
- Мамо, мамо, къде е костенурката?
- На балкона, чупят орехи с баща ти!
Синът на Джепето - Джешесто.
Разговор между идеалния мъж и идеалната жена:
- Скъпа, искаш ли да отидем до бижутерията и да ти купя пръстен с огромен диамант?
- Не.
Tази вечер смятам да назнача Джак Даниелс за министър на вътрешните ми работи.
Както си чистих ухото с отвертката и изчезна звукът на телевизора...

Ще говоря на QA:Challenge Accepted 6.0

Бях се решил след последната лудост на ISTACon 2019 и лекцията ми 2 дни по-късно в dev.bg 2020 година да не бъде годината на лекциите, но няколко дни преди да приключи записването за лектори не се стърпях и реших да кандидатствам с две бързи теми – “Career path from QA to DevOps” и “Как да (не) говорим по конференции”.

Избраха втората, ще бъде 25 минути и ще бъде последна лекция от събитието (и единствена на български). И понеже не претендирам да съм Юли Тонкин на презентациите, но съм изял доволно количество лайна (за малко да го цензурирам, но се сетих, че си пиша в блога) и мога да дам някакви идеи на хората, които се страхуват да говорят пред другите.

И така, програмата на събитието можете да видите на сайта на QA: Challenge Accepted (където още се мъдри моята страхотна снимка на която приличам на бавно развиващ се чеченец).

Ако смятате да присъствате на събитието ще се радвам да се видим. Или не. Зависи каква бира ми носите, защото вероятно ще имам нужда :D