✋ Deckhouse Kubernetes Platform Operations Cheatsheet

🗿 Для повышения привилегий до root-пользователя, пожалуйста, используйте sudo -i или sudo su -, просто sudo su не используйте (не проходит процедура login)

  1. Очередь и Алерты
  2. "Bad" Pod Information
  3. Секреты deckhouse
  4. 🔞 God Mode
  5. CNI Cilium
  6. pods
  7. Функция вывода информации о сертификате (show_certs)
  8. Функция входа на ноду (exec_node)
  9. Commander
  10. chrony
  11. etcd
  12. Проблема: поды deckhouse падают, в логах ошибка валидации поля stage

Очередь и Алерты

d8 system queue list

Старый вариант:

d8 k -n d8-system exec -ti svc/deckhouse-leader -c deckhouse -- deckhouse-controller queue list

Алерты:

d8 k get clusteralerts

Содержимое алерта:

d8 k get clusteralerts ALERT_NAME -o yaml

"Bad" Pod Information

d8 k get pods -A -o wide | grep -Pv '\s+([1-9]+[\d]*)\/\1\s+' | grep -v 'Completed\|Evicted'

Чтобы удалить "плохие" поды:

d8 k get pods -A --no-headers -o wide | grep -Pv '\s+([1-9]+[\d]*)\/\1\s+' | grep -v 'Completed\|Evicted' | awk '{ print "d8 k -n", $1, "delete pods", $2 }'

Секреты deckhouse

Раскодированный секрет deckhouse-registry

d8 k -n d8-system get secrets deckhouse-registry -o json | jq '.data | map_values(@base64d)'

Раскодированный секрет ClusterConfiguration

d8 k -n kube-system get secrets d8-cluster-configuration -o json | jq -r '.data."cluster-configuration.yaml" | @base64d'

Раскодированный секрет StaticClusterConfiguration

d8 k -n kube-system get secrets d8-static-cluster-configuration -o json | jq -r '.data."static-cluster-configuration.yaml" | @base64d'

Раскодированный секрет ProviderClusterConfiguration

d8 k -n kube-system get secrets d8-provider-cluster-configuration -o json | jq -r '.data."cloud-provider-cluster-configuration.yaml" | @base64d'
d8 k -n kube-system get secrets d8-provider-cluster-configuration -o json | jq -r '.data."cloud-provider-discovery-data.json" | @base64d | fromjson'

🔞 God Mode

🎭 Внимание! Повышенные привилегии (IDKFA, без IDDQD). Пользуйтесь на свой страх и риск:

d8 k --as=system:sudouser edit

Fallback:

d8 k -n d8-system exec -ti svc/deckhouse-leader -c deckhouse -- kubectl edit

Ещё один вариант это удалить валидацию:

d8 k delete validatingadmissionpolicybindings.admissionregistration.k8s.io heritage-label-objects.deckhouse.io

CNI Cilium

Общее здоровье:

d8 k -n d8-cni-cilium exec -ti daemonsets/agent -- cilium-health status

Подробный статус:

d8 k -n d8-cni-cilium exec -ti daemonsets/agent -- cilium status --verbose

alias cilium

alias cilium="d8 k -n d8-cni-cilium exec -ti daemonsets/agent -- cilium"

Hubble: Inspecting Network Flows with the CLI

pwru: Packet, where are you? (https://github.com/cilium/pwru). Копируем, вставляем в bash и вызываем по имени deploy_pwru

function deploy_pwru() {
    if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then echo -e "Usage: PWRU_KEEP=false $FUNCNAME NODE_NAME [ARGS]\nExample: PWRU_KEEP=true $FUNCNAME master-0 \"--output-tuple 'host 1.1.1.1'\""; return 1; fi
    local NODE_NAME="$1"
    local PWRU_ARGS="${@:2}"
    local -r LOCAL_KEEP_DEPLOYMENT=${PWRU_KEEP:-false}
    d8 k cluster-info >/dev/null 2>&1 || { echo "Deckhouse k8s cluster not reachable"; return 1; }
    d8 k get node "$NODE_NAME" >/dev/null 2>&1 || { echo "Node '$NODE_NAME' not found in the cluster."; return 1; }
    local -r POD_NAME="pwru-$NODE_NAME"
    $LOCAL_KEEP_DEPLOYMENT || trap 'd8 k -n d8-monitoring delete --wait=false --ignore-not-found deployment '"$POD_NAME"'' EXIT
    local CMD="pwru${PWRU_ARGS:+ $PWRU_ARGS}"
    d8 k apply -f - << EOF
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"$POD_NAME","namespace":"d8-monitoring"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"$POD_NAME"}},"template":{"metadata":{"labels":{"app":"$POD_NAME"}},"spec":{"nodeSelector":{"kubernetes.io/hostname":"$NODE_NAME"},"containers":[{"name":"pwru","image":"docker.io/cilium/pwru:latest","command":["/bin/sh"],"args":["-c","$CMD"],"securityContext":{"privileged":true},"volumeMounts":[{"mountPath":"/sys/kernel/debug","name":"sys-kernel-debug"}]}],"volumes":[{"name":"sys-kernel-debug","hostPath":{"path":"/sys/kernel/debug","type":"DirectoryOrCreate"}}],"hostNetwork":true,"hostPID":true,"tolerations":[{"operator":"Exists"}]}}}}
EOF
    local POD
    POD=$(d8 k -n d8-monitoring get pods -l app="$POD_NAME" --no-headers -o name --field-selector=status.phase!=Terminating | sed -n 1p)
    [[ -z "$POD" ]] && { echo "Pod not found. Check d8 k -n d8-monitoring get events"; return 1; }
    d8 k -n d8-monitoring wait "$POD" --for=condition=Ready --timeout=60s || { echo "Pod not ready after 60s"; return 1; }
    d8 k -n d8-monitoring logs -f "$POD"
    $LOCAL_KEEP_DEPLOYMENT || d8 k -n d8-monitoring delete --wait=false --ignore-not-found deployment "$POD_NAME"
}

Сценарий использования:

Запустите pwru в одной консоли необходимой ноде:

deploy_pwru WORKER_NODE "--output-tuple 'host 1.1.1.1'"

Запустите нагрузку во второй консоли:

d8 k create deployment alpine --image=docker.io/library/alpine:latest -- /bin/sh -c 'sleep infinity'

Поделайте запросы:

d8 k exec -ti deployment alpine -- /bin/sh -c 'wget --spider http://1.1.1.1/'

Pods

Создать подик

d8 k create deployment alpine --image=docker.io/library/alpine:latest -- /bin/sh -c 'sleep infinity'

Провалиться в контейнер с помощью

d8 k exec -ti deployment/alpine -- /bin/sh -c 'apk add --no-cache curl; sh'

И сделать запрос к API

curl --verbose --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/services/ ; echo

Функция вывода информации о сертификате (show_certs)

Копируем, вставляем в bash и вызываем по имени show_certs

function show_certs() {
    if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then echo "Usage: $FUNCNAME DOMAIN_TLD [PORT]"; return 1; fi
    local domain="$1"
    local port="${2:-443}"
    echo | openssl s_client -showcerts -servername "$domain" -connect "$domain":"$port"
}

Посмотреть информацию о сертификате

openssl x509 -in /path/to/cert.crt -noout -text

Провести verify сертификата с CA:

openssl verify -CAfile /path/to/ca.crt /path/to/cert.crt

Функция входа на ноду (exec_node)

Копируем, вставляем в bash и вызываем по имени exec_node

exec_node() {
    if [ "$#" -lt 1 ]; then echo -e "Usage: $FUNCNAME NODE_NAME [CMD]\nExample: exec_node master-2\nExample: exec_node master-2 ls -lah /\nExample: exec_node master-2 /bin/sh -c 'cat /etc/hostname; arch'" >&2; return 1; fi
    local NODE_NAME="$1"
    shift
    local USER_ARGS=("$@")
    [[ ${#USER_ARGS[@]} -eq 0 ]] && USER_ARGS=("bash")
    d8 k cluster-info >/dev/null 2>&1 || { echo "Deckhouse k8s cluster not reachable"; return 1; }
    d8 k get node "$NODE_NAME" >/dev/null 2>&1 || { echo "Node '$NODE_NAME' not found"; return 1; }
    local -r POD_NAME="exec-node-$NODE_NAME"
    trap 'd8 k -n d8-monitoring delete --wait=false --ignore-not-found pod "$POD_NAME" >/dev/null 2>&1 || true' EXIT
    local CMD_JSON
    CMD_JSON=$(jq -c -n --argjson base '["nsenter","--mount=/proc/1/ns/mnt","--"]' --argjson extra "$(printf '%s\n' "${USER_ARGS[@]}" | jq -R . | jq -s .)" '$base + $extra')
    local overrides=$(cat << EOF
{"spec":{"nodeName":"$NODE_NAME","hostPID":true,"hostNetwork":true,"enableServiceLinks":false,"containers":[{"securityContext":{"privileged":true},"image":"docker.io/library/alpine:latest","name":"$POD_NAME","stdin":true,"tty":true,"command":$CMD_JSON}],"tolerations":[{"operator":"Exists"}]}}
EOF
)
    d8 k -n d8-monitoring delete pod "$POD_NAME" --ignore-not-found --force 2>/dev/null
    d8 k -n d8-monitoring run --image=docker.io/library/alpine:latest --restart=Never --rm --overrides="$overrides" --pod-running-timeout=1m --tty --stdin "$POD_NAME"
}

Commander

Commander UUID Config Map

d8 k -n kube-system get cm d8-commander-uuid -o yaml

Commander DB - View Clusters

d8 k -n d8-commander exec -ti commander-postgres-0 -- psql -P expanded=off -U postgres -d commander -c "SELECT name FROM clusters;"

chrony

d8 k -n d8-chrony exec -ti daemonsets/chrony-master -- chronyc sources -v

etcd

Копируем, вставляем в bash и затем обращаемся с командой etcdctl

etcd_pod=$(d8 k -n kube-system get pod -l component=etcd,tier=control-plane -o name | sed -n 1p)
alias etcdctl="d8 k -n kube-system exec -ti ${etcd_pod} -- etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key --endpoints https://127.0.0.1:2379/" # make alias
endpoints=$(d8 k -n kube-system exec -t ${etcd_pod} -- etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key --endpoints https://127.0.0.1:2379/ member list -w json | jq -r '.members[].clientURLs[]' | paste -sd, -) # endpoints var

Для дальнейших вызовов etcdctl используем алиас etcdctl. Примеры конструкций:

Список членов кластера:

etcdctl member list -w table

Здоровье членов кластера:

etcdctl endpoint health --endpoints $endpoints

Статус членов кластера:

etcdctl endpoint status -w table --endpoints $endpoints

Помогаторы

Проблема: поды deckhouse падают, в логах ошибка валидации поля stage.
Решение: Применить манифест:

apiVersion: deckhouse.io/v1alpha1
kind: NodeGroupConfiguration
metadata:
  name: delete-stage-from-module.sh
spec:
  bundles:
    - '*'
  content: |
    find /var/lib/deckhouse/downloaded/ -type f -name 'module.yaml' | while read -r file; do
      if grep -q '^stage:' "$file"; then
        sed -i '/^stage:/d' "$file"
      fi
    done
  nodeGroups:
    - "master"
  weight: 102

При необходимости: поcле успешной прокатки bashible

journalctl -fu bashible.service

принудительно удалить поды deckhouse:

d8 k -n d8-system delete pods -l app=deckhouse