Показаны сообщения с ярлыком devops. Показать все сообщения
Показаны сообщения с ярлыком devops. Показать все сообщения

30 июля 2026

Обновление зависимостей в GitLab

Делал исследование на тему автоматизации обновления зависимостей в GitLab по аналогии с GitHub Dependabot.

Чаще всего приходится обновлять:

  • GitLab CI скрипты
  • Версии Helm чартов
  • Теги контейнерных образов, которые использует Helm чарт

Поиск в сети дал три кандидата, которые более-менее подходили под эти требования:

Dependabot-gitlab 

Про dependabot-gitlab особо рассказать нечего. Он является обёрткой над dependabot-core. Я не нашёл какой-либо информации о поддержке обновления CI скриптов GitLab поэтому этот вариант был сразу отброшен.

15 июня 2026

Ковыряние в shell скриптах

Досталась по работе задача прикрутить к CI поддержку нескольких веток разработки. Например ветка development это текущий код, который давно поддерживается, но уже есть планы перевести его в разряд наследия и начать с чистого листа в лучших AI практиках.

Разработчики заводят новую ветку development-X.Y в которую заливается код "не имеющий ничего общего" с кодом в ветке development. Проблема в том что CI не поддерживает такой сценарий и как только будет выпущена версия X.Y.0, то собьётся версионирование в ветке development чего нужно избежать.

За версионирование в CI отвечает shell портянка строк на 200. Благо к ней есть тесты, написанные для bats и это большое благо, иначе количество сюрпризов повысилось бы кратно.

Вот несколько интересных граблей, на которые наступил в процессе:

Добавил новый параметр для фильтрации версий local filter="$10" - тесты отвалились, т.к. в значении переменной filter было "имя_сценария0", а не "0.[0-9]+" как должно было быть. Дело в том что bash трактует "$10" как обращение к первому параметру к которому в строке добавили ноль. Чтобы этого не происходило нужно писать local filter="${10}". Забавно что shellcheck на такое не ругается.

Когда добрался до сравнения версий, которое было сделано в виде хака version() { echo "$@" | awk -F. '{ printf("%d%03d%03d\n", $1,$2,$3); }'; } нашёл "спящую" ошибку, которая проявится спустя какое-то время. При использовании такой функции версия 0.48.0 на выходе имела вид 0048000, но если в начале числа стоит 0, то bash воспринимает его как восьмеричное число и ловит ошибку -bash: [[: 0048000: value too great for base (error token is "0048000").

20 мая 2026

Отладка HTTP заголовков

В рамках активности по замене bitnami чартов дошли руки обновить oauth2-proxy. В процессе столкнулся с тем что перестала работать авторизация в одном из приложений для которого был использован alpha config.

Чтобы проверить какие HTTP заголовки oauth2-proxy передаёт на бэкенд после прохождения авторизации можно запустить "echo" сервис, который будет отображать всю информацию о запросе который к нему поступил.

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
        - name: echo
          image: docker.io/mendhak/http-https-echo:31
          ports:
            - containerPort: 8080
          env:
            - name: HTTP_PORT
              value: "8080"
---
apiVersion: v1
kind: Service
metadata:
  name: echo
spec:
  selector:
    app: echo
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

После применения манифеста остаётся заменить бэкенд на http://echo и посмотреть какие заголовки были переданы со стороны oauth2-proxy.

14 мая 2026

Использование rclone для копирования файлов в GCS бакет

Попробовал использовать rclone для переноса файлов из on-prem хостинга в облако Google. В отличии от утилит gcloud или gsutil, rclone есть в репозитарии Debian/Ubuntu и его легко поставить через APT.

Для переноса я не стал создавать user-managed ключ для IAM сервис аккаунта, вместо этого взял токен от виртуальной машины которая запущена с нужными правами в GCP.

$ curl -H 'Metadata-Flavor:Google' 169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
{"access_token":"ya29.c.[redacted]_af","expires_in":3599,"token_type":"Bearer"}

Тут важно взять весь вывод целиком если задаётся параметр "token", либо только значение "access_token" для соответствующего параметра в rclone. В противном случае будет ошибка вида:

Failed to create file system for "gcs:example-files/": failed to configure Google Cloud Storage: google: could not find default credentials. See https://cloud.google.com/docs/authentication/external/set-up-adc for more information

Далее создание конфигурации для GCS (можно отвечать на вопросы в rclone config, но на всякий случай оставлю готовую конфигурацию для приватных бакетов с uniform access) и собственно сама миграция.

04 мая 2026

GitLab CI/CD job token

Решил сделать пометку на память, т.к. было потрачено изрядное количество времени на отладку пайплайна Terraform в GitLab.

Началось с рутинной установки нового компонента, которая прервалась на этапе выполнения инициализации Terraform:

│ Error: Error accessing remote module registry
│ 
│   on example.tf line 1:
│    1: module "example" {
│ 
│ Failed to retrieve available versions for module "example" (example.tf:1)
│ from gitlab.example.com: error looking up module versions: 403 Forbidden.

Выглядело как "протухший" токен, но локально с этими кредами новый модуль выкачивался. Дальше было несколько часов возни и в итоге коллега нашёл что дело в изменениях, связанных с GitLab CI/CD job token.

03 апреля 2026

Возня с Kyverno

Какое-то время пришлось возиться с Kyverno в GKE и решил сделать пометки для истории. Началось всё с обратной связи от разработчиков, которым Kyverno не давал создать сервис Knative.

Failed to create Ingress: admission webhook "validate.kyverno.svc-fail" denied the request: resource Ingress/NAMESPACE/SERVICE was blocked due to the following policies disallow-empty-ingress-host: disallow-empty-ingress-host: The Ingress host name must be defined, not empty.

Это результат работы политики disallow-empty-ingress-host, которая написана без учёта того что одинаковые kind Ingress может быть у разных apiVersion и скорее всего они будут несовместимы.

Добавил исключение в конфигурацию, но обновление чарта с политиками Kyverno завершилась с ошибками:

admission webhook "validate-policy.kyverno.svc" denied the request: no unique match for kind Service
admission webhook "validate-policy.kyverno.svc" denied the request: no unique match for kind Ingress

В общем отделаться по-быстрому исключением и закинуть улучшение в бэклог не вышло. Выпустил новый релиз чарта с подправленными политиками (/v1/Service вместо Service и networking.k8s.io/*/Ingress вместо Ingress) и раз полез в Kyverno, то заодно подтянул изменения с нижних окружений, которые касались Kyverno.

В числе этих изменений было и обновление версии самого Kyverno. Полистал коротенький upgrading kyverno, но там подсветили только риск при обновлении до 1.13, которая уже была позади. Список изменений в GitHub это просто компиляция сообщений из комитов, но на всякий случай полистал и его. Обновление версии Kyverno в GKE принесло проблему, которая не проявлялась в AKS - большое количество полиси отчётов стали содержать ошибки вида:

26 марта 2026

Продолжение истории с Cilium в GKE

Какое-то время назад я писал про отваливающиеся пробы у подов в GKE кластере после установки Cilium. Тогда пришлось сделать шаг назад и удалить Cilium из кластера чтобы не блокировать команды разработки.

Отладку продолжил в изолированном кластере и в итоге получилось решить изначальную проблему с отваливающимися пробами. Около двух недель как Cilium снова управляет сетью в GKE, но периодически приходится решать мелкие проблемы.

Из свежего - несколько часов разбирался почему некоторые поды определённых демонсетов становятся "not ready" спустя несколько часов после создания. Интриги добавляло что это происходило ночью и один из них смог сам починиться и продолжить работу. Эта проблема отличалась от той, с которой я разбирался в отдельном кластере, т.к. там поды не проходили проверки сразу после создания. В итоге причина снова была в Cilium.

16 марта 2026

Ошибка "metadata.resourceVersion: Invalid value: 0: must be specified for an update" в Terraform после редактирования ресурса

После редактирования ресурса knativeserving в Kubernetis кластере через kubectl edit Terraform не может применить к нему изменения через gavinbunney/kubectl провайдер:

│ Resource: "operator.knative.dev/v1beta1, Resource=knativeservings", GroupVersionKind: "operator.knative.dev/v1beta1, Kind=KnativeServing"
│ Name: "knative-serving", Namespace: "knative-serving"
│ for: "/tmp/1389615405kubectl_manifest.yaml": error when patching "/tmp/1389615405kubectl_manifest.yaml": knativeservings.operator.knative.dev "knative-serving" is invalid: metadata.resourceVersion: Invalid value: 0: must be specified for an update
│ 
│   with kubectl_manifest.knative_serving,
│   on knative.tf line 163, in resource "kubectl_manifest" "knative_serving":
│  163: resource "kubectl_manifest" "knative_serving" {

Я пробовал использовать параметр force_conflicts = true, но это не даёт эффекта.

Исправляется ошибка удалением аннотации kubectl.kubernetes.io/last-applied-configuration с нужного ресурса.

kubectl -n knative-serving annotate knativeserving knative-serving kubectl.kubernetes.io/last-applied-configuration-

Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

17 февраля 2026

Как завершить зависшее SSH соединение

 Если по какой-либо причине SSH соединение зависает (например сменился внешний IP адрес) то такое соединение не получится завершить через Ctrl+D или Ctrl+C. Обычно я убивал локальный SSH процесс и заново логинился на сервер.

Оказывается есть способ проще - нужно использовать escape последовательность и для завершения соединения последовательно нажать <Enter> "~" и ".".

OpenSSH клиент поддерживает больше escape последовательностей, справку по которым можно получить через <Enter> "~" и "?".

Supported escape sequences:
     ~.   - terminate connection (and any multiplexed sessions)
     ~B   - send a BREAK to the remote system
     ~C   - open a command line
     ~R   - request rekey
     ~V/v - decrease/increase verbosity (LogLevel)
     ~^Z  - suspend ssh
     ~#   - list forwarded connections
     ~&   - background ssh (when waiting for connections to terminate)
     ~?   - this message
     ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

05 февраля 2026

Случайным образом отваливаются пробы в GKE после установки Cilium и Istio Ambient

 Устанавливал в GKE (Google Kubernetes Engine) кластер Cilium с Istio в режиме ambient и столкнулся со случайными ошибками readiness/liveness проб. Версия GKE 1.34.3, Cilium 1.18.4 и Istio 1.26.3 - не самые свежайшие версии, но работают в других окружениях.

Факты таковы:

  • из десятка подов которые разворачиваются в тестовом окружении один или несколько не проходит readiness/liveness пробу
  • внутри пода и с соседнего пода можно запросить нужный URL который используют пробы
  • если вручную удалить этот под, то он начинает работать нормально
  • автоматический рестарт из-за liveness не исправляет ситуацию

Я уже сталкивался с "отвалившимися" пробами после включения Istio Ambient, но тогда пробы не работали в 100% случаев, а здесь это происходит случайным образом. Исправление удалением пода намекает на проблемы связанные с работой CNI.

20 января 2026

Poetry всегда использует системный python

 Всё началось с жалобы разработчика в рабочем чате что после публикации приложения на GitHub тесты стали валиться с ошибкой.

poetry env use python3.13
Recreating virtualenv app in /home/runner/work/app/app/.venv
Using virtualenv: /home/runner/work/app/app/.venv
poetry install --with dev

Current Python version (3.12.3) is not allowed by the project (>=3.13,<3.14).
Please change python executable via the "env use" command.

Проект использует poetry 2.1.1 которая не самая свежая (последняя это 2.2.1), но и не слишком древняя. При этом выше по логу видна установка python 3.13.11 и он вызывается без проблем если выполнить python3.13 --version.

13 января 2026

Сделать дамп кучи и потоков для Java приложения

Сделать дамп кучи и потоков для Java приложения в Kubernetes

$ JVM_PID=1
$ JVM_POD=some-pod

$ kubectl exec $JVM_POD -- /bin/sh -c "jmap -dump:live,format=b,file=/tmp/heap-dump.hprof $JVM_PID; gzip /tmp/heap-dump.hprof"

$ kubectl cp $JVM_POD:/tmp/heap-dump.hprof.gz $PWD/heap-dump.hprof.gz

$ gunzip $PWD/heap-dump.hprof.gz

$ kubectl exec $JVM_POD -- rm /tmp/heap-dump.hprof.gz

Посмотреть состояние можно через VisualVM.


Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

24 декабря 2025

Добавить метку времени к событиям в Kubernetes

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

$ kubectl -n default get events -w | ts
Dec 24 09:39:13 LAST SEEN   TYPE     REASON              OBJECT                        MESSAGE
Dec 24 09:39:13 15s         Normal   Scheduled           pod/debug-658b996798-52g2g    Successfully assigned default/debug-658b996798-52g2g to aks-workerf1f9-29801352-vmss000003
Dec 24 09:39:13 14s         Normal   Pulling             pod/debug-658b996798-52g2g    Pulling image "nicolaka/netshoot"
Dec 24 09:39:13 14s         Normal   Pulled              pod/debug-658b996798-52g2g    Successfully pulled image "nicolaka/netshoot" in 237ms (237ms including waiting). Image size: 207893848 bytes.
Dec 24 09:39:13 14s         Normal   Created             pod/debug-658b996798-52g2g    Created container: netshoot
Dec 24 09:39:13 14s         Normal   Started             pod/debug-658b996798-52g2g    Started container netshoot
Dec 24 09:39:13 15s         Normal   SuccessfulCreate    replicaset/debug-658b996798   Created pod: debug-658b996798-52g2g
Dec 24 09:39:13 15s         Normal   ScalingReplicaSet   deployment/debug              Scaled up replica set debug-658b996798 from 0 to 1

Dec 24 09:39:26 0s          Normal   ScalingReplicaSet   deployment/debug              Scaled down replica set debug-658b996798 from 1 to 0
Dec 24 09:39:26 0s          Normal   Killing             pod/debug-658b996798-52g2g    Stopping container netshoot
Dec 24 09:39:26 0s          Normal   SuccessfulDelete    replicaset/debug-658b996798   Deleted pod: debug-658b996798-52g2g

Я раньше не знал про утилиту "ts" из пакета moreutils и узнал о ней из вопроса на stackoverlow. Забавно что больше откликов набрал другой вариант ответа на вопрос.


Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

12 декабря 2025

Distribution не работает через workload identity в Azure

 Довольно долго провозился с настройкой distribution в Azure через workload identity в AKS который не хотел работать.

Сама настройка простая:

  • аннотация на сервис аккаунт в кластере (azure.workload.identity/client-id)
  • метка на под (azure.workload.identity/use: "true")
  • настроить конфигурацию в distribution
    storage:
      azure:
        accountname: accountname
        container: containername
        credentials:
          type: default_credentials
    

Но в лог валится ошибка "403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."

14 ноября 2025

Ingress-nginx уходит на покой

На днях в блоге Kubernetes появилась запись Ingress NGINX Retirement: What You Need to Know в которой сообщается что поддержка Ingress Nginx будет осуществляться до марта 2026 и далее не стоит ожидать каких-либо новых выпусков или исправлений.

To prioritize the safety and security of the ecosystem, Kubernetes SIG Network and the Security Response Committee are announcing the upcoming retirement of Ingress NGINX. Best-effort maintenance will continue until March 2026. Afterward, there will be no further releases, no bugfixes, and no updates to resolve any security vulnerabilities that may be discovered. Existing deployments of Ingress NGINX will continue to function and installation artifacts will remain available.

Другими словами, самое время начинать двигаться дальше и искать альтернативу. Жаль конечно, на мой взгляд это был один из самых популярных ингресс контроллеров, но отсутствие ресурсов на поддержку и "излишняя гибкость" сделали своё дело.


Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

11 ноября 2025

Сломалась сборка образов в Gitlab

 Сегодня сборка Docker образов сломалась на docker-machine ранерах.

*** WARNING: Service runner-xxxxxxxx-project-xxxxx-concurrent-0-xxxxxxxxxxxxxx-docker-0 probably didn't start properly.
Health check error:
service "runner-xxxxxxxx-project-xxxxx-concurrent-0-xxxxxxxxxxxxxx-docker-0-wait-for-service" health check: exit code 1
Health check container logs:
2025-11-11T14:15:01.392368160Z FATAL: No HOST or PORT found                      
Service container logs:
2025-11-11T14:15:01.155180886Z cat: can't open '/proc/net/ip6_tables_names': No such file or directory
2025-11-11T14:15:01.156146175Z cat: can't open '/proc/net/arp_tables_names': No such file or directory
2025-11-11T14:15:01.159149102Z iptables v1.8.11 (nf_tables)
2025-11-11T14:15:01.198255845Z time="2025-11-11T14:15:01.197837859Z" level=info msg="Starting up"
2025-11-11T14:15:01.201660747Z time="2025-11-11T14:15:01.201577762Z" level=warning msg="Binding to IP address without --tlsverify is insecure and gives root access on this machine to everyone who has access to your network." host="tcp://0.0.0.0:2375"
2025-11-11T14:15:01.201682858Z time="2025-11-11T14:15:01.201643206Z" level=warning msg="Binding to an IP address, even on localhost, can also give access to scripts run in a browser. Be safe out there!" host="tcp://0.0.0.0:2375"
2025-11-11T14:15:01.201770114Z time="2025-11-11T14:15:01.201692789Z" level=warning msg="[DEPRECATION NOTICE] In future versions this will be a hard failure preventing the daemon from starting! Learn more at: https://docs.docker.com/go/api-security/" host="tcp://0.0.0.0:2375"

Вызовы docker завершались ошибкой

ERROR: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?

Связано это с выходом Docker 29.0.0, который перестал быть совместимым с docker-machine (подробности есть в gitlab-org/gitlab-runner #39100 и cattle-ops/terraform-aws-gitlab-runner #1324).

Для исправления достаточно откатиться на предыдущую версию Docker добавив engine-install-url=https://releases.rancher.com/install-docker/28.3.3.sh в MachineOptions

Если используется модуль cattle-ops/terraform-aws-gitlab-runner, то это делается через добавление параметра

  runner_worker_docker_machine_ec2_options = [
    "engine-install-url=https://releases.rancher.com/install-docker/28.3.3.sh",
  ]

Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

23 сентября 2025

Диски в GCP заметно дороже

Давно не заглядывал в стоимость ресурсов Google Cloud Platform и сегодня удивился стоимости дисков в GCP. Для сравнения зональный диск на 100 GB в AWS и GCP:

Т.е. за большие деньги получаешь меньше производительности. Если пытаться подобрать аналогичную производительность диска, то это уже нужен pd-extreme где минимальный размер 500GB и стоимость больше 250 USD в месяц.


Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

21 августа 2025

Не проходят пробы после включения Istio Ambient

 Возился с переносом наработок по Istio Ambient из GKE (Google Kubernetes Engine) в EKS (Elastic Kubernetes Service) и столкнулся с "отваливающимися" проверками готовности подов в Knative сервисах после включения пространства имён в ambient mesh.

Новый под стартует, но через 30 секунд у него отваливается readiness check без каких либо сообщений в логе пода. Проверил логи ztunnel, но ничего интересного не увидел. Для верности почитал Platform-Specific Prerequisites для EKS но описанный там случай не подходил для моего кластера.

Попробовал искать в сообщениях об ошибках в Istio, но ничего подходящего не нашлось. Потом вспомнил про kubernetes network policy которая есть в этом неймспейсе и после её удаления проверки стали проходить нормально.

Стал искать целенаправленно и натнулся на раздел Ambient, health probes, and Kubernetes NetworkPolicy в документации Istio Ambient и стало ясно чего не хватает.

18 августа 2025

Ошибки при установке Istio в GKE

 Если вы ставите Istio в ambient режиме в GKE (Google Kubernetes Engine) кластер и не прочли Platform-Specific Prerequisites, то при установке CNI node agent вы столкнётесь с двумя ошибками.

Первая не даст установить Helm релиз (в событиях будет ошибка):

LAST SEEN   TYPE      REASON                    OBJECT                           MESSAGE
3s          Warning   FailedCreate              daemonset/istio-cni-node         Error creating: insufficient quota to match these scopes: [{PriorityClass In [system-node-critical system-cluster-critical]}]

Это связано с тем что по-умолчанию разрешает использовать priorityClassName: system-node-critical только в пространстве имён "kube-system". Чтобы разрешить использовать его в "istio-system" нужно создать ResourceQuota в соответствующем пространстве имён

apiVersion: v1
kind: ResourceQuota
metadata:
  name: gcp-critical-pods
  namespace: istio-system
spec:
  hard:
    pods: 1000
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values:
      - system-node-critical

Вторая проблема проявляется как постоянный перезапуск пода istio-cni и в логах будет подсказка как это чинить:

2025-08-15T14:03:48.272826Z     info    controllers     starting        controller=repair pods
2025-08-15T14:03:48.357825Z     info    cni-agent       initialization complete, watching node CNI dir
2025-08-15T14:03:48.358220Z     error   cni-agent       failed file copy of /opt/cni/bin/istio-cni to /host/opt/cni/bin: open /host/opt/cni/bin/istio-cni.tmp.2135482355: read-only file system
2025-08-15T14:03:48.358243Z     warn    hint: some Kubernetes environments require customization of the CNI directory. Ensure you properly set global.platform=<name> during installation
2025-08-15T14:03:48.358311Z     error   cni-agent       installer failed: copy binaries: open /host/opt/cni/bin/istio-cni.tmp.2135482355: read-only file system
2025-08-15T14:03:48.369141Z     info    cni-agent       terminating, but parent DS istio-cni-node is still present, this is an upgrade, leaving plugin in place
2025-08-15T14:03:48.369180Z     info    cni-agent       Ambient node agent shutting down - is upgrade shutdown? true

Для исправления достаточно задать --set global.platform=gke при установке Helm релиза.


Вы можете следить за обновлениями блога с помощью Atom/RSS и Telegram.

17 июля 2025

Wildcard SSL сертификат

Понадобилось сгенерировать wildcard SSL сертификат и раскладывать его по пространствам имён в Kubernetes кластере. Этот сертификат будет использоваться в тестах которые выполняются для набора приложений на каждый запрос на слияние.

В cert-manager настроен ClusterIssuer LE с валидацией через DNS01. Выпуск wildcard сертификата у Let's Encrypt поддерживается только через DNS валидацию и протокол ACMEv2. В примере использован сервис Cloud DNS от Google Cloud Platform.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
spec:
  acme:
    email: certificates@example.com
    privateKeySecretRef:
      name: letsencrypt-production
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - dns01:
        cloudDNS:
          project: GCP_PROJECT_ID

Манифест для wildcard сертификата (сам сертификат и ключ будут созданы в пространстве имён cert-manager)