Перейти к основному содержимому

5.1.5.2. Алиасы

Данный блок будет полезен с точки зрения оптимизации запросов на подключение. Рассмотрим несколько вариантов подключения к ETCD кластеру.

  • (alias=cidsearch) Поиск ID контейнера
  • (alias=cpidsearch) Поиск PID контейнера
  • (alias=etcdctl) Прямое подключение
  • (alias=ectl) Подключение через crictl
  • (alias=nectl) Подключение через nsenter
  • (alias=kectl) Подключение через kubelet
Обратите внимание

Просьба обратить внимание, что все команды кроме пункта 5.1.5.2.5 (Подключение через kubectl) выполняются на узлах, где размещается ETCD инстанс.

5.1.5.2.1. Поиск ID контейнера​

Данный алиас поможет быстро найти ID контейнера по меткам io.kubernetes.pod.name и io.kubernetes.pod.namespace

cidsearch() {
crictl ps \
--label io.kubernetes.pod.name="$1" \
--label io.kubernetes.pod.namespace="$2" \
-o json | jq -r '.containers[].id'
}

5.1.5.2.2. Поиск PID контейнера​

Данный алиас поможет быстро найти PID контейнера по меткам io.kubernetes.container.name и io.kubernetes.pod.namespace

cpidsearch() {
crictl inspect \
$(cidsearch "$1" "$2") | jq .info.pid
}

5.1.5.2.3. Прямое подключение​

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

Подключение​

alias etcdctl='etcdctl \
--cert=/etc/kubernetes/pki/etcd/peer.crt \
--key=/etc/kubernetes/pki/etcd/peer.key \
--cacert=/etc/kubernetes/pki/etcd/ca.crt'

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

etcdctlMembers() {
etcdctl member list -w json | \
jq -r '[.members[].clientURLs[]?] | join(",")'
}

Актуальная ревизия​

etcdctlRevision() {
etcdctl \
--endpoints=$(etcdctlMembers) \
endpoint status \
-w json | jq \
-r .[].Status.header.revision
}

Подключение​

alias etcdctl='etcdctl \
--cert=/etc/kubernetes/pki/etcd/peer.crt \
--key=/etc/kubernetes/pki/etcd/peer.key \
--cacert=/etc/kubernetes/pki/etcd/ca.crt'

Уплотение​

alias etcdctlCompaction='etcdctl \
--endpoints=$(etcdctlMembers) \
compaction $(etcdctlRevision)'

Дефрагментация​

alias etcdctlDefrag='etcdctl \
--endpoints=$(etcdctlMembers) \
defrag'

5.1.5.2.4. Подключение через crictl​

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

Обратите внимание

Чтобы обеспечить правильную отправку запросов в нужный контейнер, укажите Namespace и PodName, с которыми хотите взаимодействовать.

export SEARCH_NAMESPACE=undefined
export SEARCH_POD_NAME=undefined
к сведению

Просьба обратить на зависимость от alias=(cidsearch, ectlflagsearch) указанных ниже

Поиск ID контейнера​

cidsearch() {
crictl ps \
--label io.kubernetes.pod.name="$1" \
--label io.kubernetes.pod.namespace="$2" \
-o json | jq -r '.containers[].id'
}

Флаги для подключения к etcdctl​

alias функции, которая подставляет флаги с указанием PEER-сертификата, PEER-ключа , CA-сертификата ETCD кластера и ENDPOINT-а.

ectlflagsearch() {
ETCD_ARGS=$( \
crictl inspect $(cidsearch "$1" "$2") | jq -r \
'.info.runtimeSpec.process.args[]' ) ; \
echo -n \
'--cert='$(grep --\
'--peer-cert-file=' <<< $ETCD_ARGS | sed 's/[^=]*=//') \
'--key='$(grep --\
'--peer-key-file=' <<< $ETCD_ARGS | sed 's/[^=]*=//') \
'--cacert='$(grep --\
'--trusted-ca-file=' <<< $ETCD_ARGS | sed 's/[^=]*=//') \
'--endpoints='$(grep --\
'--advertise-client-urls=' <<< $ETCD_ARGS | sed 's/[^=]*=//')
}

Подключение​

alias ectl='crictl exec \
-ti $(cidsearch ${SEARCH_POD_NAME} ${SEARCH_NAMESPACE}) \
etcdctl \
$(ectlflagsearch ${SEARCH_POD_NAME} ${SEARCH_NAMESPACE})'

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

ectlMembers() {
ectl member list \
--write-out=json | jq \
-r '[.members[].clientURLs[]] | join(",")'
}

Актуальная ревизия​

ectlRevision() {
ectl \
endpoint status \
--cluster \
-w json | jq -r \
'[.[].Status.header.revision] | join(" ")'
}

Уплотение​

alias ectlCompaction='ectl \
compaction $(ectlRevision) \
--cluster'

Дефрагментация​

alias ectlDefrag='ectl \
defrag \
--cluster'

5.1.5.2.5. Подключение через nsenter​

Для использования etcdctl, который находится внутри пространства имен процесса запущенного контейнера, необходимо сначала получить CONTAINER_ID. На основе этого идентификатора можно определить PID процесса. Далее создадим псевдоним nectl (чтобы избежать конфликтов с другими псевдонимами). При каждом вызове этого псевдонима будем обновлять данные о текущем контейнере и процессе. Также важно указать путь к сертификатам.

к сведению

Просьба обратить на зависимость от alias=(cpidsearch)

Обратите внимание

Чтобы обеспечить правильную отправку запросов в нужный контейнер, укажите Namespace и PodName, с которыми хотите взаимодействовать.

export SEARCH_NAMESPACE=undefined
export SEARCH_POD_NAME=undefined

Поиск ID контейнера​

Данный алиас поможет быстро найти ID контейнера по меткам io.kubernetes.container.name и io.kubernetes.pod.namespace

cidsearch() {
crictl ps \
--label io.kubernetes.pod.name="$1" \
--label io.kubernetes.pod.namespace="$2" \
-o json | jq -r '.containers[].id'
}

Поиск PID контейнера​

Данный алиас поможет быстро найти PID контейнера по меткам io.kubernetes.container.name и io.kubernetes.pod.namespace

cpidsearch() {
crictl inspect \
$(cidsearch "$1" "$2") | jq .info.pid
}

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

nectlMembers() {
nectl member list \
--write-out=json | jq \
-r '[.members[].clientURLs[]] | join(",")'
}

Актуальная ревизия​

nectlMembers() {
nectl member list \
--write-out=json | jq \
-r '[.members[].clientURLs[]] | join(",")'
}

Подключение​

alias nectl='nsenter \
-m -n -t \
$(cpidsearch ${SEARCH_CONTAINER_NAME} ${SEARCH_NAMESPACE}) \
etcdctl \
--cert=/etc/kubernetes/pki/etcd/peer.crt \
--key=/etc/kubernetes/pki/etcd/peer.key \
--cacert=/etc/kubernetes/pki/etcd/ca.crt'

Уплотение​

alias nectlCompaction='nectl \
--endpoints=$(nectlMembers) \
compaction $(nectlRevision)'

Дефрагментация​

alias nectlDefrag='nectl \
--endpoints=$(nectlMembers) \
defrag'

5.1.5.2.5. Подключение через kubectl​

Подключение через kubectl нам подходит в ситуациях, когда приложение запущено в виде пода в k8s кластере, все данные примонтированы внутрь контейнерной файловой системы, а манипуляции выполняются через kube-api.

Обратите внимание

Чтобы обеспечить правильную отправку запросов в нужный контейнер, укажите Namespace и PodName, с которыми хотите взаимодействовать.

export SEARCH_NAMESPACE=undefined
export SEARCH_POD_NAME=undefined
к сведению

Просьба обратить на зависимость от alias=(kectlflagsearch) указанной ниже

Флаги для подключения к kectl​

alias функции, которая подставляет флаги с указанием PEER-сертификата, PEER-ключа , CA-сертификата ETCD кластера и ENDPOINT-а.

kectlflagsearch() {
ETCD_ARGS=$( kubectl get pod \
-n ${SEARCH_NAMESPACE} \
${SEARCH_POD_NAME} \
-o yaml) ; \
echo -n \
'--cert='$(grep --\
'--peer-cert-file=' <<< $ETCD_ARGS | sed 's/[^=]*=//') \
'--key='$(grep --\
'--peer-key-file=' <<< $ETCD_ARGS | sed 's/[^=]*=//') \
'--cacert='$(grep --\
'--trusted-ca-file=' <<< $ETCD_ARGS | sed 's/[^=]*=//') \
'--endpoints='$(grep --\
'--advertise-client-urls=' <<< $ETCD_ARGS |
sed 's/[^=]*=//' |
sed 's/$(POD_NAME)/'${SEARCH_POD_NAME}'/' |
sed 's/$(POD_NAMESPACE)/'${SEARCH_NAMESPACE}'/')
}

Подключение​

alias kectl='kubectl exec -it \
-n ${SEARCH_NAMESPACE} \
${SEARCH_POD_NAME} \
-- \
etcdctl \
$(kectlflagsearch ${SEARCH_POD_NAME} ${SEARCH_NAMESPACE})'

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

kectlMembers() {
kectl member list \
--write-out=json | jq \
-r '[.members[].clientURLs[]] | join(",")'
}

Актуальная ревизия​

kectlRevision() {
kectl \
endpoint status \
--cluster \
-w json | jq -r \
'[.[].Status.header.revision] | join(" ")'
}

Уплотение​

alias kectlCompaction='kectl \
compaction $(kectlRevision) \
--cluster'

Дефрагментация​

alias kectlDefrag='kectl \
defrag \
--cluster'

Получение пути data-dir​

kgdatadirpath() {
jq -r '.spec.containers[0].command[], .spec.containers[0].args[]? | select(startswith("--data-dir"))' <<< "$(kubectl get pod -n "$1" "$2" -o json)" |
awk -F= '{print $2}' | head -n1
}

Загрузка файла резервной копии​

Данная функция загрузит файл бэкапа из data-dir на локальную машину в текущий каталог.

dlbackupfile() {
local POD_JSON=$(kubectl get pod -n "$1" "$2" -o json)
local DATA_DIR_PATH=$(jq -r '.spec.containers[0].command[], .spec.containers[0].args[]? | select(startswith("--data-dir"))' <<< "$POD_JSON" |
awk -F= '{print $2}' | head -n1)
local MOUNT_PATH=$DATA_DIR_PATH
while [[ -n "$MOUNT_PATH" ]]; do
local MOUNT_NAME=$(jq -r --arg path "$MOUNT_PATH" '.spec.containers[0].volumeMounts[] | select(.mountPath==$path) | .name' <<< "$POD_JSON") ;
[[ -n "$MOUNT_NAME" ]] && break
MOUNT_PATH=${MOUNT_PATH%/*}
done
local VOLUME_JSON=$(jq -r --arg name "$MOUNT_NAME" '.spec.volumes[] | select(.name==$name)' <<< "$POD_JSON")
local NODE_IP=$(kubectl get node "$(jq -r .spec.nodeName <<< "$POD_JSON")" -o json | jq -r '.status.addresses[] | select(.type=="ExternalIP") | .address')
if jq -e '.hostPath' <<< "$VOLUME_JSON" > /dev/null; then
local PVC_MOUNT_PATH=$(jq -r '.hostPath.path' <<< "$VOLUME_JSON")
else
local PVC_NAME=$(jq -r '.persistentVolumeClaim.claimName' <<< "$VOLUME_JSON")
local VOLUME_NAME=$(kubectl get pvc -n "$1" "$PVC_NAME" -o json | jq -r .spec.volumeName)
local PVC_MOUNT_PATH=$(ssh "$3@$NODE_IP" "sudo lsblk -o MOUNTPOINT | grep '$VOLUME_NAME'")
fi
rsync --rsync-path="sudo rsync" $3@$NODE_IP:${PVC_MOUNT_PATH}${DATA_DIR_PATH#"$MOUNT_PATH"}/$4 ./
}