Это многостраничный печатный вид этого раздела. Нажмите что бы печатать.

Вернуться к обычному просмотру страницы.

Документация

1 - Документация по Kubernetes

1.1 - Версии Kubernetes с поддержкой документации

На сайте можно найти документацию для текущей и четырёх прошлых версий Kubernetes.

2 - Установка инструментов

2.1 - Установка и настройка kubectl

Инструмент командной строки Kubernetes kubectl позволяет запускать команды для кластеров Kubernetes. Вы можете использовать kubectl для развертывания приложений, проверки и управления ресурсов кластера, а также для просмотра логов. Полный список возможных операций для kubectl смотрите в Обзоре kubectl.

Подготовка к работе

Используемая вами мажорная версия kubectl не должна отличаться от той, которая используется в кластере. Например, версия v1.2 может работать с версиями v1.1, v1.2 и v1.3. Использование последней версии kubectl поможет избежать непредвиденных проблем.

Установка kubectl в Linux

Установка бинарного файла kubectl с помощью curl в Linux

  1. Загрузите последнюю версию с помощью команды:

    curl -LO https://dl.k8s.io/release/`curl -LS https://dl.k8s.io/release/stable.txt`/bin/linux/amd64/kubectl
    

    Чтобы загрузить определенную версию, вставьте в фрагмент команды $(curl -LS https://dl.k8s.io/release/stable.txt) нужную версию.

    Например, команда загрузки версии 1.31.0 для Linux будет выглядеть следующим образом:

    curl -LO https://dl.k8s.io/release/v1.31.0/bin/linux/amd64/kubectl
    
  2. Сделайте бинарный файл kubectl исполняемым:

    chmod +x ./kubectl
    
  3. Переместите бинарный файл в директорию из переменной окружения PATH:

    sudo mv ./kubectl /usr/local/bin/kubectl
    
  4. Убедитесь, что установлена последняя версия:

    kubectl version --client
    

Установка с помощью встроенного пакетного менеджера

sudo apt-get update && sudo apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl

sudo 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/rpm-package-key.gpg
EOF
sudo yum install -y kubectl

Установка с помощью стороннего пакетного менеджера

Если вы используете Ubuntu или другой Linux-дистрибутив, в котором есть пакетный менеджер snap, kubectl доступен в виде приложения snap.

snap install kubectl --classic

kubectl version

Если вы работаете в Linux и используете пакетный менеджер Homebrew, то kubectl можно установить через него.

brew install kubectl

kubectl version

Установка kubectl в macOS

Установка бинарного файла kubectl с помощью curl в macOS

  1. Загрузите последнюю версию:

    curl -LO "https://dl.k8s.io/release/$(curl -LS https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
    

    Чтобы загрузить определенную версию, вставьте в фрагмент команды $(curl -LS https://dl.k8s.io/release/stable.txt) нужную версию.

    Например, команда загрузки версии 1.31.0 для macOS будет выглядеть следующим образом:

    curl -LO https://dl.k8s.io/release/v1.31.0/bin/darwin/amd64/kubectl
    
  2. Сделайте бинарный файл kubectl исполняемым:

    chmod +x ./kubectl
    
  3. Переместите бинарный файл в директорию из переменной окружения PATH:

    sudo mv ./kubectl /usr/local/bin/kubectl
    
  4. Убедитесь, что установлена последняя версия:

    kubectl version --client
    

Установка с помощью Homebrew в macOS

Если вы используете macOS и Homebrew, то kubectl можно установить с помощью пакетного менеджера Homebrew.

  1. Выполните команду установки:

    brew install kubectl
    

    Или:

    brew install kubernetes-cli
    
  2. Убедитесь, что установлена последняя версия:

    kubectl version --client
    

Установка с помощью Macports в macOS

Если вы используйте macOS и Macports, то kubectl можно установить с помощью пакетного менеджера Macports.

  1. Выполните команду установки:

    sudo port selfupdate
    sudo port install kubectl
    
  2. Убедитесь, что установлена последняя версия:

    kubectl version --client
    

Установка kubectl в Windows

Установка бинарного файла kubectl с помощью curl в Windows

  1. Загрузите последнюю версию 1.31.0 по этой ссылке.

    Либо, если у вас установлен curl, выполните команду ниже:

    curl -LO https://dl.k8s.io/release/v1.31.0/bin/windows/amd64/kubectl.exe
    

    Последнюю стабильную версию (например, при написании скриптов) вы можете узнать из файла по ссылке https://dl.k8s.io/release/stable.txt.

  2. Переместите бинарный файл в директорию из переменной окружения PATH:

  3. Убедитесь, что версия kubectl соответствует загружённой:

    kubectl version --client
    

Установка с помощью Powershell из PSGallery

Если вы работаете в Windows и используете менеджер пакетов Powershell Gallery, вы можете установить и обновить kubectl с помощью Powershell.

  1. Выполните команды по установке (обязательно укажите DownloadLocation):

    Install-Script -Name install-kubectl -Scope CurrentUser -Force
    install-kubectl.ps1 [-DownloadLocation <path>]
    

    Установщик создаст $HOME/.kube вместе с конфигурационным файлом.

  2. Убедитесь, что установлена последняя версия:

    kubectl version --client
    

Установка в Windows с помощью Chocolatey или Scoop

Для установки kubectl в Windows вы можете использовать либо менеджер пакетов Chocolatey, либо установщик в командной строке Scoop.

choco install kubernetes-cli

scoop install kubectl
  1. Убедитесь, что установлена последняя версия:

    kubectl version --client
    
  2. Перейдите в домашнюю директорию:

    cd %USERPROFILE%
    
  3. Создайте директорию .kube:

    mkdir .kube
    
  4. Перейдите в созданную только что директорию .kube:

    cd .kube
    
  5. Настройте kubectl, чтобы было возможно использовать удаленный кластер Kubernetes:

    New-Item config -type file
    

Установка kubectl из SDK Google Cloud

Вы можете использовать kubectl из SDK Google Cloud, который использует этот CLI-инструмент.

  1. Установите Google Cloud SDK.

  2. Выполните команду для установки kubectl:

    gcloud components install kubectl
    
  3. Убедитесь, что установлена последняя версия:

    kubectl version --client
    

Проверка конфигурации kubectl

Чтобы kubectl мог найти и получить доступ к кластеру Kubernetes, нужен файл kubeconfig, который создаётся автоматически при создании кластера с помощью скрипта kube-up.sh или при успешном развертывании кластера Minikube. По умолчанию конфигурация kubectl находится в ~/.kube/config.

Посмотрите на состояние кластера, чтобы убедиться, что kubectl правильно сконфигурирован:

kubectl cluster-info

Если вы видите URL в ответ, значит kubectl корректно настроен для работы с вашим кластером.

Если вы видите сообщение следующего содержания, то значит kubectl настроен некорректно или не может подключиться к кластеру Kubernetes:

The connection to the server <server-name:port> was refused - did you specify the right host or port?

Например, если вы собираетесь запустить кластер Kubernetes на своем ноутбуке (локально), вам потребуется сначала установить специальный для этого инструмент, например Minikube, а затем снова выполнить указанные выше команды.

Если команда kubectl cluster-info возвращает URL в ответ, но вы не можете подключиться к своему кластеру, чтобы убедиться, что он правильно настроен, воспользуйтесь этой командой:

kubectl cluster-info dump

Дополнительная конфигурация kubectl

Включение автодополнения ввода shell

kubectl поддерживает автодополнение (автозаполнение) ввода в Bash и Zsh, которое сэкономит вам много времени на набор команд.

Ниже приведены инструкции по настройке автодополнения для Bash (для Linux и macOS) и Zsh.

Основные сведения

Скрипт дополнения ввода kubectl для Bash может быть сгенерирован с помощью команды kubectl completion bash. Подключение скрипта дополнения ввода в вашу оболочку включает поддержку автозаполнения ввода для kubectl.

Однако скрипт дополнения ввода зависит от bash-completion, поэтому вам нужно сначала установить этот пакет (вы можете выполнить команду type _init_completion, чтобы проверить, установлен ли у вас уже bash-completion).

Установка bash-completion

bash-completion можно установить через многие менеджеры пакеты (см. здесь). Вы можете установить его с помощью apt-get install bash-completion или yum install bash-completion и т.д.

Приведенные выше команды создадут файл /usr/share/bash-completion/bash_completion, который является основным скриптом bash-completion. Возможно, вам потребуется вручную подключить этот файл в ~/.bashrc (необходимость выполнять эту операцию зависит от используемого менеджера пакетов).

Чтобы убедиться, что всё работает, перезагрузите оболочку и выполните команду type _init_completion. Если команда отработала успешно, установка сделана правильно, в противном случае добавьте следующее содержимое в файл ~/.bashrc:

source /usr/share/bash-completion/bash_completion

Перезагрузите вашу оболочку и убедитесь, что bash-completion правильно установлен, выполнив команду type _init_completion.

Включение автодополнения ввода kubectl

Теперь нужно убедиться, что скрипт дополнения ввода kubectl выполняется во всех сессиях командной оболочки. Есть два способа сделать это:

  • Добавьте запуск скрипта дополнения ввода в файл ~/.bashrc:

    echo 'source <(kubectl completion bash)' >>~/.bashrc
    
  • Добавьте скрипт дополнения ввода в директорию /etc/bash_completion.d:

    kubectl completion bash >/etc/bash_completion.d/kubectl
    
  • Если у вас определён псевдоним для kubectl, вы можете интегрировать его с автодополнением оболочки:

    echo 'alias k=kubectl' >>~/.bashrc
    echo 'complete -F __start_kubectl k' >>~/.bashrc
    

Оба подхода эквивалентны. После перезагрузки вашей оболочки автодополнение ввода для kubectl должно работать.

Основные сведения

Скрипт дополнения ввода kubectl для Bash может быть сгенерирован с помощью команды kubectl completion bash. Подключение скрипта дополнения ввода в вашей оболочке включает поддержку автозаполнения ввода для kubectl.

Однако скрипт дополнения ввода kubectl зависит от пакета bash-completion, который первым делом нужно установить.

Установка bash-completion

Вы можете проверить, установлен ли у вас bash-completion v2, набрав команду type _init_completion. Если он не установлен, вы можете сделать это с помощью Homebrew:

brew install bash-completion@2

Как указано в выводе этой команды, добавьте следующий код в файл ~/.bashrc:

export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d"
[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"

Перезагрузите вашу командную оболочку и убедитесь, что bash-completion v2 корректно установлен, выполнив команду type _init_completion.

Включение автодополнения ввода kubectl

Теперь нужно убедиться, что скрипт дополнения ввода kubectl выполняется во всех сессиях командной оболочки. Есть два способа сделать это:

  • Добавьте запуск скрипта дополнения ввода в файл ~/.bashrc:

    echo 'source <(kubectl completion bash)' >>~/.bashrc
    
  • Добавьте скрипт дополнения ввода в директорию /etc/bash_completion.d:

    kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl
    
  • Если у вас определён псевдоним для kubectl, вы можете интегрировать его с автодополнением оболочки:

    echo 'alias k=kubectl' >>~/.bashrc
    echo 'complete -F __start_kubectl k' >>~/.bashrc
    

Если вы установили kubectl с помощью Homebrew (как описано выше), то скрипт дополнения ввода kubectl уже должен быть находится в /usr/local/etc/bash_completion.d/kubectl. В этом случае вам не нужно ничего делать.

Какой бы вариант вы ни выбрали, после перезагрузки командной оболочки автодополнение ввода для kubectl должно заработать.

Скрипт дополнения ввода kubectl для Zsh может быть сгенерирован с помощью команды kubectl completion zsh. Подключение скрипта дополнения ввода в вашу оболочку включает поддержку автодополнения ввода для kubectl.

Чтобы подключить его во все сессии командной оболочки, добавьте следующую строчку в файл ~/.zshrc:

source <(kubectl completion zsh)

Если у вас определён псевдоним для kubectl, вы можете интегрировать его с автодополнением оболочки:

echo 'alias k=kubectl' >>~/.zshrc
echo 'compdef __start_kubectl k' >>~/.zshrc

После перезагрузки командной оболочки должны появляться дополнения ввода kubectl.

Если появляется ошибка complete:13: command not found: compdef, то добавьте следующее содержимое в начало вашего файла ~/.zshrc:

autoload -Uz compinit
compinit

Что дальше

2.2 - Установка Minikube

На этой странице рассказано, как установить Minikube, инструмент для запуска одноузлового кластера Kubernetes на виртуальной машине в персональном компьютере.

Подготовка к работе

Чтобы проверить, поддерживается ли виртуализация в Linux, выполните следующую команду и проверьте, что вывод не пустой:

grep -E --color 'vmx|svm' /proc/cpuinfo

Чтобы проверить, поддерживается ли виртуализация в macOS, выполните следующую команду в терминале:

sysctl -a | grep -E --color 'machdep.cpu.features|VMX'

Если вы видите VMX в выводе (должен быть окрашенным), значит в вашем компьютере поддерживается виртуализация VT-x.

Чтобы проверить, поддерживается ли виртуализация в Windows 8 и выше, выполните следующую команду в Windows Terminal или в командной строке.

systeminfo

Если вы видите следующий вывод, значит виртуализация поддерживается в Windows.

Hyper-V Requirements:     VM Monitor Mode Extensions: Yes
                          Virtualization Enabled In Firmware: Yes
                          Second Level Address Translation: Yes
                          Data Execution Prevention Available: Yes

Если вы видите следующий вывод, значит системе уже установлен гипервизор, значит вы можете пропустить следующий шаг установке гипервизора.

Hyper-V Requirements:     A hypervisor has been detected. Features required for Hyper-V will not be displayed.

Установка minikube

Установка kubectl

Убедитесь, что у вас установлен kubectl. Вы можете установить kubectl согласно инструкциям в разделе Установка и настройка kubectl.

Установка Hypervisor

Если у вас ещё не установлен гипервизор, установите один из них:

KVM, который также использует QEMU

VirtualBox

Minikube также поддерживает опцию --vm-driver=none, которая запускает компоненты Kubernetes на хосте, а не на виртуальной машине. Для использования этого драйвера требуется только Docker и Linux, но не гипервизор.

Если вы используете драйвер none в Debian и его производных, используйте пакеты .deb для Docker, а не snap-пакет, который не работает с Minikube. Вы можете скачать .deb-пакеты с сайта Docker.

Minikube также поддерживает vm-driver=podman, похожий на драйвер Docker. Podman, работающий с правами суперпользователя (пользователь root) — это лучший способ гарантировать вашим контейнерам полный доступ ко всем возможностям в системе.

Установка Minikube через пакет

Доступны экспериментальные пакеты для Minikube; Вы можете загрузить пакеты для Linux (AMD64) со страницы релизов Minikube на GitHub.

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

Установка Minikube с помощью прямой ссылки

Вы также можете загрузить двоичный файл и использовать его вместо установки пакета:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
  && chmod +x minikube

Чтобы исполняемый файл Minikube был доступен из любой директории выполните следующие команды:

sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/

Установка Minikube через Homebrew

В качестве ещё одной альтернативы вы можете установить Minikube с помощью Linux Homebrew:

brew install minikube

Установка kubectl

Убедитесь, что у вас установлен kubectl. Вы можете установить kubectl согласно инструкциям в разделе Установка и настройка kubectl.

Установка Hypervisor

Если у вас ещё не установлен гипервизор, установите один из них:

HyperKit

VirtualBox

VMware Fusion

Установка Minikube

Простейший способ установить Minikube в macOS — использовать Homebrew:

brew install minikube

Вы также можете установить его в macOS, загрузив двоичный файл:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 \
  && chmod +x minikube

Чтобы исполняемый файл Minikube был доступен из любой директории выполните следующие команды:

sudo mv minikube /usr/local/bin

Установка kubectl

Убедитесь, что у вас установлен kubectl. Вы можете установить kubectl согласно инструкциям в разделе Установка и настройка kubectl.

Установка Hypervisor

Если у вас ещё не установлен гипервизор, установите один из них:

Hyper-V

VirtualBox

Установка Minikube с помощью Chocolatey

Простейший способ установить Minikube в Windows — использовать Chocolatey (запущенный с правами администратора):

choco install minikube

После установки Minikube нужно перезапустить терминал. Minikube должен быть автоматически добавлен в директорию с исполняемыми файлами.

Установка Minikube с помощью исполняемого файла установки

Для ручной установки Minikube в Windows с помощью установщика Windows, загрузите и запустите установщик minikube-installer.exe.

Установка Minikube с помощью прямой ссылки

Для ручной установки Minikube в Windows, загрузите minikube-windows-amd64, переименуйте его в minikube.exe и добавьте его в директорию исполняемых файлов.

Проверка установки

Чтобы убедиться в том, что гипервизор и Minikube были установлены корректно, выполните следующую команду, которая запускает локальный кластер Kubernetes:

minikube start --vm-driver=<driver_name>

После того, как команда minikube start отработала успешно, выполните команду для проверки состояния кластера:

minikube status

Если ваш кластер запущен, то в выводе команды minikube status должно быть что-то вроде этого:

host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Теперь, когда вы убедились, что Minikube работает с выбранным вами гипервизором, вы можете продолжить использовать Minikube или остановить кластер. Чтобы остановить кластер выполните команду ниже:

minikube stop

Очистка локального состояния

Если вы уже установили Minikube, то выполните следующую команду:

minikube start

В таком случае команда minikube start вернёт ошибку:

machine does not exist

Чтобы исправить это, нужно очистить локальное состояние:

minikube delete

Что дальше

3 - Генерация сертификатов вручную

При аутентификации с помощью клиентского сертификата сертификаты можно генерировать вручную с помощью easyrsa, openssl или cfssl.

easyrsa

easyrsa поддерживает ручную генерацию сертификатов для кластера.

  1. Скачайте, распакуйте и инициализируйте пропатченную версию easyrsa3.

    curl -LO https://dl.k8s.io/easy-rsa/easy-rsa.tar.gz
    tar xzf easy-rsa.tar.gz
    cd easy-rsa-master/easyrsa3
    ./easyrsa init-pki
    
  2. Создайте новый центр сертификации (certificate authority, CA). --batch задает автоматический режим; --req-cn указывает общее имя (Common Name, CN) для нового корневого сертификата CA.

    ./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
    
  3. Сгенерируйте сертификат и ключ сервера.

    Аргумент --subject-alt-name задает допустимые IP-адреса и DNS-имена, с которых будет осуществляться доступ к серверу API. MASTER_CLUSTER_IP обычно является первым IP из CIDR сервиса, который указан в качестве аргумента --service-cluster-ip-range как для сервера API, так и для менеджера контроллеров. Аргумент --days задает количество дней, через которое истекает срок действия сертификата. В приведенном ниже примере предполагается, что cluster.local используется в качестве доменного имени по умолчанию.

    ./easyrsa --subject-alt-name="IP:${MASTER_IP},"\
    "IP:${MASTER_CLUSTER_IP},"\
    "DNS:kubernetes,"\
    "DNS:kubernetes.default,"\
    "DNS:kubernetes.default.svc,"\
    "DNS:kubernetes.default.svc.cluster,"\
    "DNS:kubernetes.default.svc.cluster.local" \
    --days=10000 \
    build-server-full server nopass
    
  4. Скопируйте pki/ca.crt, pki/issued/server.crt и pki/private/server.key в свою директорию.

  5. Заполните и добавьте следующие параметры в параметры запуска сервера API:

    --client-ca-file=/yourdirectory/ca.crt
    --tls-cert-file=/yourdirectory/server.crt
    --tls-private-key-file=/yourdirectory/server.key
    

openssl

openssl поддерживает ручную генерацию сертификатов для кластера.

  1. Сгенерируйте 2048-разрядный ключ ca.key:

    openssl genrsa -out ca.key 2048
    
  2. На основе ca.key сгенерируйте ca.crt (используйте -days для установки времени действия сертификата):

    openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
    
  3. Сгенерируйте 2048-битный ключ server.key:

    openssl genrsa -out server.key 2048
    
  4. Создайте файл конфигурации для генерации запроса на подписание сертификата (Certificate Signing Request, CSR).

    Замените значения, помеченные угловыми скобками (например, <MASTER_IP>), нужными значениями перед сохранением в файл (например, csr.conf). Обратите внимание, что значение для MASTER_CLUSTER_IP – это cluster IP сервиса для сервера API, как описано в предыдущем подразделе. В приведенном ниже примере предполагается, что cluster.local используется в качестве доменного имени по умолчанию.

    [ req ]
    default_bits = 2048
    prompt = no
    default_md = sha256
    req_extensions = req_ext
    distinguished_name = dn
    
    [ dn ]
    C = <country>
    ST = <state>
    L = <city>
    O = <organization>
    OU = <organization unit>
    CN = <MASTER_IP>
    
    [ req_ext ]
    subjectAltName = @alt_names
    
    [ alt_names ]
    DNS.1 = kubernetes
    DNS.2 = kubernetes.default
    DNS.3 = kubernetes.default.svc
    DNS.4 = kubernetes.default.svc.cluster
    DNS.5 = kubernetes.default.svc.cluster.local
    IP.1 = <MASTER_IP>
    IP.2 = <MASTER_CLUSTER_IP>
    
    [ v3_ext ]
    authorityKeyIdentifier=keyid,issuer:always
    basicConstraints=CA:FALSE
    keyUsage=keyEncipherment,dataEncipherment
    extendedKeyUsage=serverAuth,clientAuth
    subjectAltName=@alt_names
    
  5. Сгенерируйте запрос на подписание сертификата, используя файл конфигурации:

    openssl req -new -key server.key -out server.csr -config csr.conf
    
  6. С помощью ca.key, ca.crt и server.csr сгенерируйте сертификат сервера:

    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
        -CAcreateserial -out server.crt -days 10000 \
        -extensions v3_ext -extfile csr.conf  -sha256
    
  7. Используйте следующую команду, чтобы просмотреть запрос на подписание сертификата:

    openssl req  -noout -text -in ./server.csr
    
  8. Используйте следующую команду, чтобы просмотреть сертификат:

    openssl x509  -noout -text -in ./server.crt
    

Наконец, добавьте эти параметры в конфигурацию запуска сервера API.

cfssl

cfssl – еще один инструмент для генерации сертификатов.

  1. Скачайте, распакуйте и подготовьте пакеты, как показано ниже.

    Обратите внимание, что команды необходимо адаптировать под архитектуру и используемую версию cfssl.

    curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_linux_amd64 -o cfssl
    chmod +x cfssl
    curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_linux_amd64 -o cfssljson
    chmod +x cfssljson
    curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl-certinfo_1.5.0_linux_amd64 -o cfssl-certinfo
    chmod +x cfssl-certinfo
    
  2. Создайте директорию для хранения артефактов и инициализируйте cfssl:

    mkdir cert
    cd cert
    ../cfssl print-defaults config > config.json
    ../cfssl print-defaults csr > csr.json
    
  3. Создайте JSON-конфиг для генерации файла CA (например, ca-config.json):

    {
      "signing": {
        "default": {
          "expiry": "8760h"
        },
        "profiles": {
          "kubernetes": {
            "usages": [
              "signing",
              "key encipherment",
              "server auth",
              "client auth"
            ],
            "expiry": "8760h"
          }
        }
      }
    }
    
  4. Создайте JSON-конфиг для запроса на подписание сертификата (CSR) (например, ca-csr.json). Замените значения, помеченные угловыми скобками, на нужные.

    {
      "CN": "kubernetes",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names":[{
        "C": "<country>",
        "ST": "<state>",
        "L": "<city>",
        "O": "<organization>",
        "OU": "<organization unit>"
      }]
    }
    
  5. Сгенерируйте ключ CA (ca-key.pem) и сертификат (ca.pem):

    ../cfssl gencert -initca ca-csr.json | ../cfssljson -bare ca
    
  6. Создайте конфигурационный JSON-файл для генерации ключей и сертификатов для сервера API (например, server-csr.json). Замените значения, помеченные угловыми скобками, на нужные. MASTER_CLUSTER_IP – это cluster IP сервиса для сервера API, как описано в предыдущем подразделе. В приведенном ниже примере предполагается, что cluster.local используется в качестве доменного имени по умолчанию.

    {
      "CN": "kubernetes",
      "hosts": [
        "127.0.0.1",
        "<MASTER_IP>",
        "<MASTER_CLUSTER_IP>",
        "kubernetes",
        "kubernetes.default",
        "kubernetes.default.svc",
        "kubernetes.default.svc.cluster",
        "kubernetes.default.svc.cluster.local"
      ],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [{
        "C": "<country>",
        "ST": "<state>",
        "L": "<city>",
        "O": "<organization>",
        "OU": "<organization unit>"
      }]
    }
    
  7. Сгенерируйте ключ и сертификат для сервера API (по умолчанию они сохраняются в файлах server-key.pem и server.pem соответственно):

    ../cfssl gencert -ca=ca.pem -ca-key=ca-key.pem \
         --config=ca-config.json -profile=kubernetes \
         server-csr.json | ../cfssljson -bare server
    

Распространение самоподписанного сертификата CA

Клиентский узел может отказаться признавать самоподписанный сертификат CA действительным. В случае его использования не в production или в инсталляциях, защищенных межсетевым экраном, самоподписанный сертификат CA можно распространить среди всех клиентов и обновить локальный список действительных сертификатов.

Для этого на каждом клиенте выполните следующие операции:

sudo cp ca.crt /usr/local/share/ca-certificates/kubernetes.crt
sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....
done.

API для сертификатов

Для создания сертификатов x509, которые будут использоваться для аутентификации, можно воспользоваться API certificates.k8s.io. Для дополнительной информации см. Управление TLS-сертификатами в кластере.

4 - Настройка Pod'ов и контейнеров

4.1 - Задание ресурсов памяти для контейнеров и Pod'ов

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

Подготовка к работе

Вам нужен Kubernetes кластер и инструмент командной строки kubectl должен быть настроен на связь с вашим кластером. Если у вас ещё нет кластера, вы можете создать, его используя Minikube, или вы можете использовать одну из песочниц Kubernetes:

Чтобы проверить версию, введите kubectl version.

Каждая нода вашего кластера должна располагать хотя бы 300 Мб памяти.

Некоторые операции на этой странице предполагают работу сервера метрик на вашем кластере. Если сервер метрик у вас уже запущен, следующие действия можно пропустить.

Если вы используете Minikube, выполните следующую команду, чтобы запустить сервер метрик:

minikube addons enable metrics-server

Чтобы проверить работу сервера меток или другого провайдера API ресурсов метрик (metrics.k8s.io), запустите команду:

kubectl get apiservices

Если API ресурсов метрики доступно, в выводе команды будет содержаться ссылка на metrics.k8s.io.

NAME      
v1beta1.metrics.k8s.io

Создание пространства имён

Создадим пространство имён, чтобы ресурсы, которыми будем пользоваться в данном упражнении, были изолированы от остального кластера:

kubectl create namespace mem-example

Установка запроса памяти и лимита памяти

Для установки запроса памяти контейнеру подключите поле resources:requests в манифест ресурсов контейнера. Для ограничений по памяти - добавьте resources:limits.

В этом упражнении создаётся Pod, содержащий один контейнер. Зададим контейнеру запрос памяти в 100 Мб и её ограничение в 200 Мб. Конфигурационный файл для Pod'а:

apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-ctr
    image: polinux/stress
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

Раздел args конфигурационного файла содержит аргументы для контейнера в момент старта. Аргументы "--vm-bytes", "150M" указывают контейнеру попытаться занять 150 Мб памяти.

Создадим Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example

Убедимся, что контейнер Pod'a запущен:

kubectl get pod memory-demo --namespace=mem-example

Посмотрим подробную информацию о Pod'е:

kubectl get pod memory-demo --output=yaml --namespace=mem-example

В выводе мы видим, что для контейнера в Pod'е зарезервировано 100 Мб памяти и выставлено 200 Мб ограничения.

...
resources:
  limits:
    memory: 200Mi
  requests:
    memory: 100Mi
...

Запустим kubectl top, чтобы получить метрики Pod'a:

kubectl top pod memory-demo --namespace=mem-example

Вывод команды показывает, что Pod использовал примерно 162900000 байт памяти - и это около 150 Мб. Данная величина больше установленного запроса в 100 Мб, но укладывается в имеющееся ограничение на 200 Мб.

NAME                        CPU(cores)   MEMORY(bytes)
memory-demo                 <something>  162856960

Удалим Pod:

kubectl delete pod memory-demo --namespace=mem-example

Превышение контейнером лимита памяти

Контейнер может превысить величину запроса памяти, если нода имеет достаточно ресурсов памяти. Но превышение заданного ограничения памяти не допускается. Если контейнер запрашивает больше памяти, чем ему разрешено использовать, то он становится кандидатом на удаление. Если превышение лимита памяти продолжится, контейнер удаляется. Если удалённый контейнер может быть перезапущен, то kubelet перезапускает его, как и в случае любой другой неполадки в работе.

В этом упражнении создадим Pod, который попытается занять больше памяти, чем для него ограничено. Ниже представлен конфигурационный файл для Pod'a с одним контейнером, имеющим 50 Мб на запрос памяти и 100 Мб лимита памяти:

apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-2
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-2-ctr
    image: polinux/stress
    resources:
      requests:
        memory: "50Mi"
      limits:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]

В разделе args можно увидеть, что контейнер будет пытаться занять 250 Мб - и это значительно превышает лимит в 100 Мб.

Создадим Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example

Посмотрим подробную информацию о Pod'е:

kubectl get pod memory-demo-2 --namespace=mem-example

В этот момент контейнер уже либо запущен, либо убит. Будем повторять предыдущую команду, пока контейнер не окажется убитым:

NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          24s

Посмотрим ещё более подробный вид статуса контейнера:

kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example

В выводе показано, что контейнер был убит по причине недостатка памяти (OOM):

lastState:
   terminated:
     containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
     exitCode: 137
     finishedAt: 2017-06-20T20:52:19Z
     reason: OOMKilled
     startedAt: null

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

kubectl get pod memory-demo-2 --namespace=mem-example

Вывод показывает, что контейнер убит, перезапущен, снова убит, перезапущен, и т.д.:

kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          37s

kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-2   1/1       Running   2          40s

Посмотрим подробную информацию об истории Pod'a:

kubectl describe pod memory-demo-2 --namespace=mem-example

Вывод показывает, что контейнер постоянно запускается и падает:

... Normal  Created   Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff   Back-off restarting failed container

Посмотрим детальную информацию о нодах на кластере:

kubectl describe nodes

В выводе содержится запись о том, что контейнер убивается по причине нехватки памяти:

Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child

Удалим Pod:

kubectl delete pod memory-demo-2 --namespace=mem-example

Установка слишком большого для нод запроса памяти

Запросы и ограничения памяти связаны с контейнерами, но полезно также рассматривать эти параметры и для Pod'а. Запросом памяти для Pod'a будет сумма всех запросов памяти контейнеров, имеющихся в Pod'е. Также и лимитом памяти будет сумма всех ограничений, установленных для контейнеров.

Планирование Pod'a основано на запросах. Pod запускается на ноде лишь в случае, если нода может удовлетворить запрос памяти Pod'a.

В данном упражнении мы создадим Pod, чей запрос памяти будет превышать ёмкость любой ноды в кластере. Ниже представлен конфигурационный файл для Pod'a с одним контейнером, имеющим запрос памяти в 1000 Гб (что наверняка превышает ёмкость любой имеющейся ноды):

apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-3
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-3-ctr
    image: polinux/stress
    resources:
      limits:
        memory: "1000Gi"
      requests:
        memory: "1000Gi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

Создадим Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example

Проверим статус Pod'a:

kubectl get pod memory-demo-3 --namespace=mem-example

Вывод показывает, что Pod имеет статус PENDING. Это значит, что он не запланирован ни на одной ноде, и такой статус будет сохраняться всё время:

kubectl get pod memory-demo-3 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-3   0/1       Pending   0          25s

Посмотрим подробную информацию о Pod'е, включающую события:

kubectl describe pod memory-demo-3 --namespace=mem-example

Вывод показывает невозможность запуска контейнера из-за нехватки памяти на нодах:

Events:
  ...  Reason            Message
       ------            -------
  ...  FailedScheduling  No nodes are available that match all of the following predicates:: Insufficient memory (3).

Удалим Pod:

kubectl delete pod memory-demo-3 --namespace=mem-example

Единицы измерения памяти

Ресурсы памяти измеряются в байтах. Их можно задавать просто целым числом либо целым числом с одним из следующих окончаний: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki. Например, представленные здесь варианты задают приблизительно одну и ту же величину:

128974848, 129e6, 129M , 123Mi

Если лимит памяти не задан

Если вы не задали ограничение памяти для контейнера, возможны следующие варианты:

  • У контейнера отсутствует верхняя граница для памяти, которую он может использовать. Такой контейнер может занять всю память, доступную на ноде, где он запущен, что, в свою очередь, может вызвать OOM Killer. Также контейнеры без ограничений по ресурсам имеют более высокие шансы быть убитыми в случае вызова OOM Kill.

  • Контейнер запущен в пространстве имён, в котором настроена величина ограничений по умолчанию. Тогда контейнеру автоматически присваивается это стандартное значение лимита. Администраторы кластера могут использовать LimitRange для задания стандартной величины ограничений по памяти.

Мотивация для использования запросов и ограничений памяти

При помощи задания величины запросов и лимитов памяти для контейнеров, запущенных на вашем кластере, можно эффективно распоряжаться имеющимися на нодах ресурсами. Задание Pod'у небольшого запроса памяти даёт хорошие шансы для него быть запланированным. Ограничение памяти, превышающее величину запроса памяти, позволяет достичь 2 вещей:

  • Pod может иметь всплески активности, в течение которых ему может потребоваться дополнительная память.

  • Величина памяти, доступная Pod'у при повышении активности, ограничена некоторой разумной величиной.

Очистка

Удалим пространство имён. Эта операция удалит все Pod'ы, созданные в рамках данного упражнения:

kubectl delete namespace mem-example

Что дальше

Для разработчиков приложений

Для администраторов кластера

4.2 - Задание ресурсов CPU для контейнеров и Pod'ов

На этой странице показывается, как настроить запрос CPU и лимит CPU для контейнера. Контейнер не сможет использовать больше ресурсов CPU, чем для него ограничено. Если в системе есть свободное время CPU, контейнеру гарантируется выдача запрошенных им ресурсов CPU.

Подготовка к работе

Вам нужен Kubernetes кластер и инструмент командной строки kubectl должен быть настроен на связь с вашим кластером. Если у вас ещё нет кластера, вы можете создать, его используя Minikube, или вы можете использовать одну из песочниц Kubernetes:

Чтобы проверить версию, введите kubectl version.

На кластере должен быть хотя бы 1 доступный для работы CPU, чтобы запускать учебные примеры.

Для некоторых шагов с этой страницы понадобится запущенный сервер метрик на вашем кластере. Если сервер метрик уже запущен, следующие шаги можно пропустить.

Если вы используете Minikube, выполните следующую команду, чтобы запустить сервер метрик:

minikube addons enable metrics-server

Проверим, работает ли сервер метрик (или другой провайдер API ресурсов метрик, metrics.k8s.io), выполните команду:

kubectl get apiservices

Если API ресурсов метрик доступно, в выводе будет присутствовать ссылка на metrics.k8s.io.

NAME
v1beta1.metrics.k8s.io

Создание пространства имён

Создадим Пространство имен, чтобы создаваемые в этом упражнении ресурсы были изолированы от остального кластера.

kubectl create namespace cpu-example

Установка запроса CPU и лимита CPU

Чтобы установить запрос CPU для контейнера, подключите поле resources:requests в манифест ресурсов контейнера. Для установки ограничения по CPU подключите resources:limits.

В этом упражнении мы создадим Pod, имеющий один контейнер. Зададим для контейнера запрос в 0.5 CPU и лимит в 1 CPU. Конфигурационный файл для такого Pod'а:

apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr
    image: vish/stress
    resources:
      limits:
        cpu: "1"
      requests:
        cpu: "0.5"
    args:
    - -cpus
    - "2"

Раздел args конфигурационного файла содержит аргументы для контейнера в момент старта. Аргумент -cpus "2" говорит контейнеру попытаться использовать 2 CPU.

Создадим Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example

Удостоверимся, что Pod запущен:

kubectl get pod cpu-demo --namespace=cpu-example

Посмотрим детальную информацию о Pod'е:

kubectl get pod cpu-demo --output=yaml --namespace=cpu-example

В выводе видно, что Pod имеет один контейнер с запросом в 500 милли-CPU и с ограничением в 1 CPU.

resources:
  limits:
    cpu: "1"
  requests:
    cpu: 500m

Запустим kubectl top, чтобы получить метрики Pod'a:

kubectl top pod cpu-demo --namespace=cpu-example

В этом варианте вывода Pod'ом использовано 974 милли-CPU, что лишь чуть меньше заданного в конфигурации Pod'a ограничения в 1 CPU.

NAME                        CPU(cores)   MEMORY(bytes)
cpu-demo                    974m         <something>

Напомним, что установкой параметра -cpu "2" для контейнера было задано попытаться использовать 2 CPU, однако в конфигурации присутствует ограничение всего в 1 CPU. Использование контейнером CPU было отрегулировано, поскольку он попытался занять больше ресурсов, чем ему позволено.

Удалим Pod:

kubectl delete pod cpu-demo --namespace=cpu-example

Единицы измерения CPU

Ресурсы CPU измеряются в CPU единицах. Один CPU, в Kubernetes, соответствует:

  • 1 AWS vCPU
  • 1 GCP Core
  • 1 Azure vCore
  • 1 гипертрединговое ядро на физическом процессоре Intel с Гипертредингом

Дробные значения возможны. Контейнер, запрашивающий 0.5 CPU, получит вполовину меньше ресурсов, чем контейнер, запрашивающий 1 CPU. Можно использовать окончание m для обозначения милли. Например, 100m CPU, 100 milliCPU и 0.1 CPU обозначают одно и то же. Точность выше 1m не поддерживается.

CPU всегда запрашивается в абсолютных величинах, не в относительных; 0.1 будет одинаковой частью от CPU для одноядерного, двухъядерного или 48-ядерного процессора.

Запрос ресурсов CPU больше доступного на ноде

Запросы и лимиты CPU устанавливаются для контейнеров, но также полезно рассматривать и Pod имеющим эти характеристики. Запросом CPU для Pod'а является сумма запросов CPU всех его контейнеров. Аналогично и лимит CPU для Pod'а - сумма всех ограничений CPU у его контейнеров.

Планирование Pod'а основано на запросах. Pod попадает в расписание запуска на ноде лишь в случае достаточного количества доступных ресурсов CPU на ноде, чтобы удовлетворить запрос CPU Pod'а.

В этом упражнении мы создадим Pod с запросом CPU, превышающим мощности любой ноды в вашем кластере. Ниже представлен конфигурационный файл для Pod'а с одним контейнером. Контейнер запрашивает 100 CPU, что почти наверняка превышает имеющиеся мощности любой ноды в кластере.

apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo-2
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr-2
    image: vish/stress
    resources:
      limits:
        cpu: "100"
      requests:
        cpu: "100"
    args:
    - -cpus
    - "2"

Создадим Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example

Проверим статус Pod'а:

kubectl get pod cpu-demo-2 --namespace=cpu-example

Вывод показывает Pending статус у Pod'а. То есть Pod не запланирован к запуску ни на одной ноде и будет оставаться в статусе Pending постоянно:

NAME         READY     STATUS    RESTARTS   AGE
cpu-demo-2   0/1       Pending   0          7m

Посмотрим подробную информацию о Pod'е, включающую в себя события:

kubectl describe pod cpu-demo-2 --namespace=cpu-example

В выводе отражено, что контейнер не может быть запланирован из-за нехватки ресурсов CPU на нодах:

Events:
  Reason                        Message
  ------                        -------
  FailedScheduling      No nodes are available that match all of the following predicates:: Insufficient cpu (3).

Удалим Pod:

kubectl delete pod cpu-demo-2 --namespace=cpu-example

Если ограничения на CPU не заданы

Если ограничения на использование контейнером CPU не установлены, возможны следующие варианты:

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

  • Контейнер запущен в пространстве имён, в котором задана стандартная величина ограничения ресурсов CPU. Тогда контейнеру автоматически присваивается это ограничение. Администраторы кластера могут использовать LimitRange, чтобы задать стандартную величину ограничения ресурсов CPU.

Мотивация для использования запросов и лимитов CPU

Вы можете распоряжаться ресурсами CPU на нодах вашего кластера эффективнее, если для запущенных контейнеров установлены запросы и ограничения на использование ресурсов CPU. Задание небольшого запроса CPU даёт Pod'у хорошие шансы быть запланированным. Установка лимита на ресурсы CPU, большего, чем запрос, позволяет достичь 2 вещей:

  • При увеличении нагрузки Pod может задействовать дополнительные ресурсы CPU.
  • Количество ресурсов CPU, которые Pod может задействовать при повышении нагрузки, ограничено некоторой разумной величиной.

Очистка

Удалим созданное для этого упражнения пространство имён:

kubectl delete namespace cpu-example

Что дальше

Для разработчиков приложений

Для администраторов кластера

4.3 - Настройка Liveness, Readiness и Startup проб

На этой странице рассказывается, как настроить liveness, readiness и startup пробы для контейнеров.

Kubelet использует liveness пробу для проверки, когда перезапустить контейнер. Например, liveness проба должна поймать блокировку, когда приложение запущено, но не может ничего сделать. В этом случае перезапуск приложения может помочь сделать приложение более доступным, несмотря на баги.

Kubelet использует readiness пробы, чтобы узнать, готов ли контейнер принимать траффик. Pod считается готовым, когда все его контейнеры готовы.

Одно из применений такого сигнала - контроль, какие Pod будут использованы в качестве бек-енда для сервиса. Пока Pod не в статусе ready, он будет исключен из балансировщиков нагрузки сервиса.

Kubelet использует startup пробы, чтобы понять, когда приложение в контейнере было запущено. Если проба настроена, он блокирует liveness и readiness проверки, до того как проба становится успешной, и проверяет, что эта проба не мешает запуску приложения. Это может быть использовано для проверки работоспособности медленно стартующих контейнеров, чтобы избежать убийства kubelet'ом прежде, чем они будут запущены.

Подготовка к работе

Вам нужен Kubernetes кластер и инструмент командной строки kubectl должен быть настроен на связь с вашим кластером. Если у вас ещё нет кластера, вы можете создать, его используя Minikube, или вы можете использовать одну из песочниц Kubernetes:

Чтобы проверить версию, введите kubectl version.

Определение liveness команды

Многие приложения, работающие в течение длительного времени, ломаются и могут быть восстановлены только перезапуском. Kubernetes предоставляет liveness пробы, чтобы обнаруживать и исправлять такие ситуации.

В этом упражнении вы создадите Pod, который запускает контейнер, основанный на образе registry.k8s.io/busybox. Конфигурационный файл для Pod'а:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: registry.k8s.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

В конфигурационном файле вы можете видеть, что Pod состоит из одного Container. Поле periodSeconds определяет, что kubelet должен производить liveness пробы каждые 5 секунд. Поле initialDelaySeconds говорит kubelet'у, что он должен ждать 5 секунд перед первой пробой. Для проведения пробы kubelet исполняет команду cat /tmp/healthy в целевом контейнере. Если команда успешна, она возвращает 0, и kubelet считает контейнер живым и здоровым. Если команда возвращает ненулевое значение, kubelet убивает и перезапускает контейнер.

Когда контейнер запускается, он исполняет команду

/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"

Для первых 30 секунд жизни контейнера существует файл /tmp/healthy. Поэтому в течение первых 30 секунд команда cat /tmp/healthy возвращает код успеха. После 30 секунд cat /tmp/healthy возвращает код ошибки.

Создание Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml

В течение 30 секунд посмотрим события Pod:

kubectl describe pod liveness-exec

Вывод команды показывает, что ещё ни одна liveness проба не завалена:

FirstSeen    LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
24s       24s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "registry.k8s.io/busybox"
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "registry.k8s.io/busybox"
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e

После 35 секунд посмотрим события Pod снова:

kubectl describe pod liveness-exec

Внизу вывода появились сообщения, показывающие, что liveness проба завалена и containers был убит и пересоздан.

FirstSeen LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
37s       37s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "registry.k8s.io/busybox"
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "registry.k8s.io/busybox"
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e
2s        2s      1   {kubelet worker0}   spec.containers{liveness}   Warning     Unhealthy   Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

Подождите ещё 30 секунд и убедитесь, что контейнер был перезапущен:

kubectl get pod liveness-exec

Вывод команды показывает, что RESTARTS увеличено на 1:

NAME            READY     STATUS    RESTARTS   AGE
liveness-exec   1/1       Running   1          1m

Определение liveness HTTP запроса

Другой вид liveness пробы использует запрос HTTP GET. Ниже представлен файл конфигурации для Pod, который запускает контейнер, основанный на образе registry.k8s.io/e2e-test-images/agnhost.

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: registry.k8s.io/e2e-test-images/agnhost:2.40
    args:
    - liveness
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

В конфигурационном файле вы можете видеть Pod с одним контейнером. Поле periodSeconds определяет, что kubelet должен производить liveness пробы каждые 3 секунды. Поле initialDelaySeconds сообщает kubelet'у, что он должен ждать 3 секунды перед проведением первой пробы. Для проведения пробы kubelet отправляет запрос HTTP GET на сервер, который запущен в контейнере и слушает порт 8080. Если обработчик пути /healthz на сервере возвращает код успеха, kubelet рассматривает контейнер как живой и здоровый. Если обработчик возвращает код ошибки, kubelet убивает и перезапускает контейнер.

Любой код, больший или равный 200 и меньший 400, означает успех. Любой другой код интерпретируется как ошибка.

Вы можете посмотреть исходные коды сервера в server.go.

В течение первых 10 секунд жизни контейнера обработчик /healthz возвращает статус 200. После обработчик возвращает статус 500.

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
    duration := time.Now().Sub(started)
    if duration.Seconds() > 10 {
        w.WriteHeader(500)
        w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
    } else {
        w.WriteHeader(200)
        w.Write([]byte("ok"))
    }
})

Kubelet начинает выполнять health checks через 3 секунды после старта контейнера. Итак, первая пара проверок будет успешна. Но после 10 секунд health checks будут завалены и kubelet убьёт и перезапустит контейнер.

Чтобы попробовать HTTP liveness проверку, создайте Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml

Через 10 секунд посмотрите события Pod, чтобы проверить, что liveness probes завалилась и container перезапустился:

kubectl describe pod liveness-http

В релизах до v1.13 (включая v1.13), если переменная окружения http_proxy (или HTTP_PROXY) определена на node, где запущен Pod, HTTP liveness проба использует этот прокси. В версиях после v1.13, определение локальной HTTP прокси в переменной окружения не влияет на HTTP liveness пробу.

Определение TCP liveness пробы

Третий тип liveness проб использует TCP сокет. С этой конфигурацией kubelet будет пытаться открыть сокет к вашему контейнеру на определённый порт. Если он сможет установить соединение, контейнер будет считаться здоровым, если нет, будет считаться заваленным.

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: registry.k8s.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

Как вы можете видеть, конфигурация TCP проверок довольно похожа на HTTP проверки. Этот пример использует обе - readiness и liveness пробы. Kubelet будет отправлять первую readiness пробу через 5 секунд после старта контейнера. Он будет пытаться соединиться с goproxy контейнером на порт 8080. Если проба успешна, Pod будет помечен как ready. Kubelet будет продолжать запускать эту проверку каждые 10 секунд.

В дополнение к readiness пробе, конфигурация включает liveness пробу. Kubelet запустит первую liveness пробу через 15 секунд после старта контейнера. Аналогично readiness пробе, он будет пытаться соединиться с контейнером goproxy на порт 8080. Если liveness проба завалится, контейнер будет перезапущен.

Для испытаний TCP liveness проверки, создадим Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml

Через 15 секунд посмотрим события Pod'а для проверки liveness пробы:

kubectl describe pod goproxy

Использование именованных портов

Вы можете использовать именованный порт ContainerPort для HTTP или TCP liveness проверок:

ports:
- name: liveness-port
  containerPort: 8080

livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port

Защита медленно запускающихся контейнеров со startup пробами

Иногда приходится иметь дело со старыми приложениями, которым может требоваться дополнительное время для запуска на их первую инициализацию. В таких случаях бывает сложно настроить параметры liveness пробы без ущерба для скорости реакции на deadlock'и, для выявления которых как раз и нужна liveness проба. Хитрость заключается в том, чтобы настроить startup пробу с такой же командой, что и HTTP или TCP проверка, но failureThreshold * periodSeconds должно быть достаточным, чтобы покрыть наихудшее время старта.

Итак, предыдущий пример будет выглядеть так:

ports:
- name: liveness-port
  containerPort: 8080
  
livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 1
  periodSeconds: 10

startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10

Благодаря startup пробе, приложению дано максимум 5 минут (30 * 10 = 300 сек.) для завершения его старта. Как только startup проба успешна 1 раз, liveness проба начинает контролировать дедлоки контейнеров. Если startup probe так и не заканчивается успехом, контейнер будет убит через 300 секунд и подвергнется restartPolicy pod'а.

Определение readiness проб

Иногда приложения временно не могут обслужить траффик. Например, приложение может требовать загрузки огромных данных или конфигурационных файлов во время старта, или зависит от внешних сервисов после старта. В таких случаях вы не хотите убивать приложение, но и отправлять ему клиентские запросы тоже не хотите. Kubernetes предоставляет readiness пробы для определения и нивелирования таких ситуаций. Pod с контейнерами сообщает, что они не готовы принимать траффик через Kubernetes Services.

Readiness пробы настраиваются аналогично liveness пробам. Единственная разница в использовании поля readinessProbe вместо livenessProbe.

readinessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

Конфигурация HTTP и TCP readiness проб также идентичны liveness пробам.

Readiness и liveness пробы могут быть использованы одновременно на одном контейнере. Использование обеих проб может обеспечить отсутствие траффика в контейнер, пока он не готов для этого, и контейнер будет перезапущен, если сломается.

Конфигурация проб

Probes имеют несколько полей, которые вы можете использовать для более точного контроля поведения liveness и readiness проверок:

  • initialDelaySeconds: Количество секунд от старта контейнера до начала liveness или readiness проб. По умолчанию 0 секунд. Минимальное значение 0.
  • periodSeconds: Длительность времени (в секундах) между двумя последовательными проведениями проб. По умолчанию 10 секунд. Минимальное значение 1.
  • timeoutSeconds: Количество секунд ожидания пробы. По умолчанию 1 секунда. Минимальное значение 1.
  • successThreshold: Минимальное количество последовательных проверок, чтобы проба считалась успешной после неудачной. По умолчанию 1. Должна быть 1 для liveness. Минимальное значение 1.
  • failureThreshold: Когда Pod стартует и проба даёт ошибку, Kubernetes будет пытаться failureThreshold раз перед тем, как сдаться. Сдаться в этом случае для liveness пробы означает перезапуск контейнера. В случае readiness пробы Pod будет помечен Unready. По умолчанию 3. Минимальное значение 1.

HTTP пробы имеют дополнительные поля, которые могут быть установлены для httpGet:

  • host: Имя хоста для соединения, по умолчанию pod IP. Вы, возможно, захотите установить заголовок "Host" в httpHeaders вместо этого.
  • scheme: Схема для соединения к хосту (HTTP or HTTPS). По умолчанию HTTP.
  • path: Путь для доступа к HTTP серверу.
  • httpHeaders: Кастомные заголовки запроса. HTTP позволяет повторяющиеся заголовки.
  • port: Имя или номер порта для доступа к контейнеру. Номер должен быть в диапазоне от 1 до 65535.

Для HTTP проб kubelet отправляет HTTP запрос на настроенный путь и порт для проведения проверок. Kubelet отправляет пробу на IP адрес pod’а, если адрес не переопределён необязательным полем host в httpGet. Если поле scheme установлено в HTTPS, kubelet отправляет HTTPS запрос, пропуская проверку сертификата. В большинстве сценариев вам не нужно устанавливать поле host. Рассмотрим один сценарий, где бы он мог понадобиться. Допустим, контейнер слушает 127.0.0.1 и поле Pod'а hostNetwork задано в true. Поле host опции httpGet должно быть задано в 127.0.0.1. Если pod полагается на виртуальные хосты, что, скорее всего, более распространённая ситуация, лучше вместо поля host устанавливать заголовок Host в httpHeaders.

Для TCP проб kubelet устанавливает соединение с ноды, не внутри pod, что означает, что вы не можете использовать service name в параметре host, пока kubelet не может выполнить его резолв.

Что дальше

Вы также можете прочитать API references для:

5 - Настройка

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

Решение о том, как запускать Kubernetes, зависит от доступных ресурсов и необходимого уровня гибкости использования. Запуск Kubernetes возможен практически на чём угодно, от вашего ноутбука или виртуальных машины у облачного провайдера и до физических серверов. Решения позволяют как настроить полностью управляемый кластер запуском единственной команды так и создать пользовательский кластер на физических серверах.

Решения для запуска на локальной машине

Запуск на локальной машине позволяет легко начать работу с Kubernetes. Можно создавать и тестировать кластер Kubernetes не беспокоясь о трате облачных ресурсов и квотах.

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

  • Пробуете или начинаете работу с Kubernetes
  • Локально разрабатываете и тестируете кластер

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

Управляемые решения

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

Вам следует выбрать управляемое решение, если вы:

  • Хотите получить полностью самоуправляемое решение
  • Хотите сконцентрироваться на разработке собственных приложений или сервисов
  • Хотите получить высокую доступность, но у вас нет выделенной команды по обеспечению надёжности приложения (SRE).
  • Не имеете ресурсов для размещения и мониторинга собственных кластеров

Выбрать управляемое решение.

Облачные решения "под ключ"

Такие решения позволяют создавать кластеры Kubernetes с помощью небольшого количества команд. Эти решения имеют большую поддержку сообществом и активно развиваются. Они могут быть размещены на разнообразных IaaS облачных провайдерах, при этом предлагая большую свободу и гибкость в обмен на приложенные усилия.

Вам следует выбрать облачное решение "под ключ", если вы:

  • Хотите получить больший контроль над кластерами, чем позволяют размещённые решения
  • Хотите получить больше контроля над операциями

Выбрать облачное решение "под ключ"

Местное резервное решение "под ключ"

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

Вам следует выбрать местное резервное решение "под ключ", если:

  • Вы хотите развернуть кластер в приватной облачной сети
  • У вас есть выделенная команда SRE-специалистов
  • У вас есть ресурсы для размещения и мониторинга собственных кластеров

Выбрать местное резервное решение "под ключ".

Пользовательские решения

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

Выбрать пользовательское решение.

Что дальше

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

5.1 - Среда обучения

5.1.1 - Установка Kubernetes с помощью Minikube

Minikube — это инструмент, позволяющий легко запускать Kubernetes на локальной машине. Для тех, кто хочет попробовать Kubernetes или рассмотреть возможность его использования в повседневной разработке, Minikube станет отличным вариантом, потому что он запускает одноузловой кластер Kubernetes внутри виртуальной машины (VM) на компьютере пользователя.

Возможности Minikube

Minikube поддерживает следующие возможности Kubernetes:

  • DNS
  • Сервисы NodePort
  • Словари конфигурации (ConfigMaps) и секреты (Secrets)
  • Панель управления (Dashboard)
  • Среда выполнения контейнера: Docker, CRI-O и containerd
  • Поддержка CNI (Container Network Interface)
  • Ingress

Установка

Посмотрите страницу Установка Minikube.

Краткое руководство

Эта простая демонстрация поможет запустить, использовать и удалить Minikube на локальной машине. Следуйте перечисленным ниже шагам, чтобы начать знакомство с Minikube.

  1. Запустите Minikube и создайте кластер:

    minikube start
    

    Вывод будет примерно следующим:

    Starting local Kubernetes cluster...
    Running pre-create checks...
    Creating machine...
    Starting local Kubernetes cluster...
    

    Дополнительную информацию о запуске кластера в определенной версии Kubernetes, виртуальной машине или среде выполнения контейнера смотрите в разделе Запуск кластера.

  2. Теперь вы можете работать со своим кластером через CLI-инструмент kubectl. Для получения дополнительной информации смотрите раздел Работа с кластером.

    Давайте создадим развёртывание (Deployment) в Kubernetes, используя существующий образ echoserver, представляющий простой HTTP-сервер, и сделаем его доступным на порту 8080 с помощью --port.

    kubectl create deployment hello-minikube --image=registry.k8s.io/echoserver:1.10
    

    Вывод будет примерно следующим:

    deployment.apps/hello-minikube created
    
  3. Чтобы получить доступ к объекту Deployment hello-minikube извне, создайте объект сервиса (Service):

    kubectl expose deployment hello-minikube --type=NodePort --port=8080
    

    Опция --type=NodePort определяет тип сервиса.

    Вывод будет примерно следующим:

    service/hello-minikube exposed
    
  4. Под (Pod) hello-minikube теперь запущен, но нужно подождать, пока он начнёт функционировать, прежде чем обращаться к нему.

    Проверьте, что под работает:

    kubectl get pod
    

    Если в столбце вывода STATUS выводится ContainerCreating, значит под все еще создается:

    NAME                              READY     STATUS              RESTARTS   AGE
    hello-minikube-3383150820-vctvh   0/1       ContainerCreating   0          3s
    

    Если в столбце STATUS указано Running, то под теперь в рабочем состоянии:

    NAME                              READY     STATUS    RESTARTS   AGE
    hello-minikube-3383150820-vctvh   1/1       Running   0          13s
    
  5. Узнайте URL-адрес открытого (exposed) сервиса, чтобы просмотреть подробные сведения о сервисе:

    minikube service hello-minikube --url
    
  6. Чтобы ознакомиться с подробной информацией о локальном кластере, скопируйте и откройте полученный из вывода команды на предыдущем шаге URL-адрес в браузере.

    Вывод будет примерно следующим:

    Hostname: hello-minikube-7c77b68cff-8wdzq
    
    Pod Information:
        -no pod information available-
    
    Server values:
        server_version=nginx: 1.13.3 - lua: 10008
    
    Request Information:
        client_address=172.17.0.1
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://192.168.99.100:8080/
    
    Request Headers:
        accept=*/*
        host=192.168.99.100:30674
        user-agent=curl/7.47.0
    
    Request Body:
        -no body in request-
    

    Если сервис и кластер вам больше не нужны, их можно удалить.

  7. Удалите сервис hello-minikube:

    kubectl delete services hello-minikube
    

    Вывод будет примерно следующим:

    service "hello-minikube" deleted
    
  8. Удалите развёртывание hello-minikube:

    kubectl delete deployment hello-minikube
    

    Вывод будет примерно следующим:

    deployment.extensions "hello-minikube" deleted
    
  9. Остановите локальный кластер Minikube:

    minikube stop
    

    Вывод будет примерно следующим:

    Stopping "minikube"...
    "minikube" stopped.
    

    Подробности смотрите в разделе Остановка кластера.

  10. Удалите локальный кластер Minikube:

    minikube delete
    

    Вывод будет примерно следующим:

    Deleting "minikube" ...
    The "minikube" cluster has been deleted.
    

    Подробности смотрите в разделе Удаление кластера.

Управление кластером

Запуск кластера

Команда minikube start используется для запуска кластера. Эта команда создаёт и конфигурирует виртуальную машину, которая запускает одноузловой кластер Kubernetes. Эта команда также настраивает вашу установку kubectl для взаимодействия с этим кластером.

Указание версии Kubernetes

Вы можете указать используемую версию Kubernetes в Minikube, добавив параметр --kubernetes-version в команду minikube start. Например, чтобы запустить Minikube из-под версии 1.31.0, вам нужно выполнить следующую команду:

minikube start --kubernetes-version 1.31.0

Указание драйвера виртуальной машины

Вы можете изменить драйвер виртуальной машины, добавив флаг --vm-driver=<enter_driver_name> в команду minikube start.

Тогда команда будет выглядеть так:

minikube start --vm-driver=<driver_name>

Minikube поддерживает следующие драйверы:

Запуск кластера в других средах выполнения контейнеров

Вы можете запустить Minikube в следующих средах выполнения контейнеров.

Чтобы использовать containerd в качестве среды выполнения контейнера, выполните команду ниже:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --container-runtime=containerd \
    --bootstrapper=kubeadm

Также можете использовать расширенную вариант команды:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --extra-config=kubelet.container-runtime=remote \
    --extra-config=kubelet.container-runtime-endpoint=unix:///run/containerd/containerd.sock \
    --extra-config=kubelet.image-service-endpoint=unix:///run/containerd/containerd.sock \
    --bootstrapper=kubeadm

Чтобы использовать CRI-O в качестве среды выполнения контейнера, выполните команду ниже:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --container-runtime=cri-o \
    --bootstrapper=kubeadm

Также можете использовать расширенную вариант команды:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --extra-config=kubelet.container-runtime=remote \
    --extra-config=kubelet.container-runtime-endpoint=/var/run/crio.sock \
    --extra-config=kubelet.image-service-endpoint=/var/run/crio.sock \
    --bootstrapper=kubeadm

Использование локальных образов путём повторного использования демона Docker

При использовании одной виртуальной машины для Kubernetes легко повторно использовать демон Docker, встроенный в Minikube. В этом случае нет необходимости создавать реестр Docker на вашей хост-машине и отправлять образ туда. Вместо этого вы можете создать реестр внутри того же демона Docker, который использует Minikube, что позволит ускорить локальные запуски.

Для работы с Docker-демоном на вашем хосте под управлением Mac/Linux, запустите последнюю строку из вывода команды minikube docker-env.

Теперь вы можете использовать Docker в командной строке вашего хост-компьютера на Mac/Linux для взаимодействия с демоном Docker внутри виртуальной машины Minikube:

docker ps

Конфигурация Kubernetes

Minikube имеет такую возможность как "конфигуратор" ("configurator"), позволяющая пользователям настраивать компоненты Kubernetes произвольными значениями. Чтобы использовать эту возможность, используйте флаг --extra-config в команде minikube start.

Этот флаг можно дублировать, поэтому вы можете указать его несколько раз с несколькими разными значениями, чтобы установить несколько опций.

Этот флаг принимает строку вида component.key=value, где component — это одно из значение в приведённом ниже списка, key — ключ из структуры конфигурации, а value — значение, которое нужно установить.

Допустимые ключи можно найти в документации по componentconfigs в Kubernetes каждого компонента. Ниже вы найдете документации по каждой поддерживаемой конфигурации:

Примеры

Чтобы изменить настройку MaxPods на значение 5 в Kubelet, передайте этот флаг --extra-config=kubelet.MaxPods=5.

Эта возможность также поддерживает вложенные структуры. Для изменения настройки LeaderElection.LeaderElect на значение true в планировщике, передайте флаг --extra-config=scheduler.LeaderElection.LeaderElect=true.

Чтобы изменить настройку AuthorizationMode в apiserver на значение RBAC, используйте флаг --extra-config=apiserver.authorization-mode=RBAC.

Остановка кластера

Команда minikube stop используется для остановки кластера. Эта команда выключает виртуальную машины Minikube, но сохраняет всё состояние кластера и данные. Повторный запуск кластера вернет его в прежнее состояние.

Удаление кластера

Команда minikube delete используется для удаления кластера. Эта команда выключает и удаляет виртуальную машину Minikube. Данные или состояние не сохраняются.

Обновление minikube

Смотрите инструкцию по обновлению minikube.

Работа с кластером

Kubectl

Команда minikube start создает контекст kubectl под именем "minikube". Этот контекст содержит конфигурацию для взаимодействия с кластером Minikube.

Minikube автоматически устанавливает этот контекст, но если вам потребуется явно использовать его в будущем, выполните команду ниже:

kubectl config use-context minikube

Либо передайте контекст при выполнении команды следующим образом: kubectl get pods --context=minikube.

Панель управления

Чтобы получить доступ к веб-панели управления Kubernetes, запустите эту команду в командной оболочке после запуска Minikube, чтобы получить адрес:

minikube dashboard

Сервисы

Чтобы получить доступ к сервису, открытой через порт узла, выполните команду в командной оболочке после запуска Minikube, чтобы получить адрес:

minikube service [-n NAMESPACE] [--url] NAME

Организация сети

Виртуальная машина Minikube доступна только хост-системе через IP-адрес, который можно получить с помощью команды minikube ip. Вы можете использовать IP-адрес для доступа к любому сервису типа NodePort.

Чтобы определить NodePort для вашего сервиса, вы можете использовать такую команду kubectl:

kubectl get service $SERVICE --output='jsonpath="{.spec.ports[0].nodePort}"'

Постоянные тома

Minikube поддерживает PersistentVolumes типа hostPath. Эти постоянные тома монтируются в виртуальную машину Minikube.

Виртуальная машина Minikube загружается в файловую систему tmpfs, поэтому большинство директорий не будет сохранено при перезагрузках (minikube stop). Однако Minikube сконфигурирован на сохранение файлов, хранящихся в перечисленных ниже директорий хоста.

  • /data
  • /var/lib/minikube
  • /var/lib/docker

Пример конфигурации PersistentVolume для сохранения данных в директории /data:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: /data/pv0001/

Смонтированные директории хоста

Некоторые драйверы монтируют директорию хоста в виртуальную машину, чтобы можно было легко обмениваться файлами между виртуальной машиной и хостом. В настоящее время это не настраивается и отличается от используемого драйвера и ОС.

Driver OS HostFolder VM
VirtualBox Linux /home /hosthome
VirtualBox macOS /Users /Users
VirtualBox Windows C://Users /c/Users
VMware Fusion macOS /Users /mnt/hgfs/Users
Xhyve macOS /Users /Users

Приватные реестры контейнеров

Для доступа к реестру приватных контейнеров, выполните шаги, описанные на этой странице.

Мы рекомендуем использовать ImagePullSecrets, но если вам нужно обратиться к нему из виртуальной машины Minikube, нужно поместить файл .dockercfg в директорию /home/docker или config.json в директорию /home/docker/.docker.

Дополнения

Для того, чтобы Minikube смог запустить или перезапустить пользовательские дополнения, поместите дополнения, которые вы хотите запускать с помощью Minikube, в директорию ~/.minikube/addons. Дополнения в этой директории будут перемещены в виртуальную машину Minikube и запускаться каждый раз при запуске или перезапуске Minikube.

Использование Minikube с помощью HTTP-прокси

Minikube создаёт виртуальную машину, включающая в себя Kubernetes и демон Docker. Когда Kubernetes планирует выполнение контейнеров с использованием Docker, демону Docker может потребоваться доступ к внешней сети для получения контейнеров.

Если вы работаете через HTTP-прокси, вам нужно сконфигурировать настройки прокси для Docker. Для этого нужно передать необходимые переменные окружения в флаги перед выполнением команды minikube start.

Например:

minikube start --docker-env http_proxy=http://$YOURPROXY:PORT \
                 --docker-env https_proxy=https://$YOURPROXY:PORT

Если адрес вашей виртуальной машины 192.168.99.100, то, скорее всего, настройки прокси помешают kubectl обратиться к ней. Чтобы прокси игнорировал этот IP-адрес, нужно скорректировать настройки no_proxy следующим образом:

export no_proxy=$no_proxy,$(minikube ip)

Известные проблемы

Функциональность, для которой требуется несколько узлов, не будет работать в Minikube.

Реализация

Minikube использует libmachine для подготовки виртуальных машин и kubeadm для инициализации кластера Kubernetes.

Для получения дополнительной информации о Minikube посмотрите статью.

Дополнительные ссылки

  • Цели: цели проекта Minikube смотрите в дорожной карте.
  • Руководство по разработке: посмотрите CONTRIBUTING.md, чтобы ознакомиться с тем, как отправлять пулрексты.
  • Сборка Minikube: инструкции по сборке/тестированию Minikube из исходного кода смотрите в руководстве по сборке.
  • Добавление новой зависимости: инструкции по добавлению новой зависимости в Minikube смотрите в руководстве по добавлению зависимостей.
  • Добавление нового дополнения: инструкции по добавлению нового дополнения для Minikube смотрите в руководстве по добавлению дополнений.
  • MicroK8: пользователи Linux, которые не хотят использовать виртуальную машину, могут в качестве альтернативы посмотреть в сторону MicroK8s.

Сообщество

Помощь, вопросы и комментарии приветствуются и поощряются! Разработчики Minikube проводят время на Slack в канале #minikube (получить приглашение можно здесь). У нас также есть список рассылки dev@kubernetes на Google Groups. Если вы отправляете сообщение в список, пожалуйста, начните вашу тему с "minikube: ".

5.1.2 - Установка Kubernetes с помощью Kind

Kind — это инструмент для запуска локальных кластеров Kubernetes с помощью "узлов" контейнера Docker.

Установка

Смотрите страницу по установке Kind.

5.2 - Пользовательские облачные решения

6 - Концепции

Раздел "Концепции" поможет вам узнать о частях системы Kubernetes и об абстракциях, которые Kubernetes использует для представления вашего кластера, и помогает вам глубже понять, как работает Kubernetes.

Краткий обзор

Чтобы работать с Kubernetes, вы используете объекты API Kubernetes для описания желаемого состояния вашего кластера: какие приложения или другие рабочие нагрузки вы хотите запустить, какие образы контейнеров они используют, количество реплик, какие сетевые и дисковые ресурсы вы хотите использовать и сделать доступными и многое другое. Вы устанавливаете желаемое состояние, создавая объекты с помощью API Kubernetes, обычно через интерфейс командной строки kubectl. Вы также можете напрямую использовать API Kubernetes для взаимодействия с кластером и установки или изменения желаемого состояния.

После того, как вы установили желаемое состояние, Управляющий слой Kubernetes (control plane) заставляет текущее состояние кластера соответствовать желаемому состоянию с помощью генератора событий жизненного цикла подов (Pod Lifecycle Event Generator, PLEG). Для этого Kubernetes автоматически выполняет множество задач, таких как запуск или перезапуск контейнеров, масштабирование количества реплик данного приложения и многое другое. Управляющий слой Kubernetes состоит из набора процессов, запущенных в вашем кластере:

  • Мастер Kubernetes — это коллекция из трех процессов, которые выполняются на одном узле в вашем кластере, который обозначен как главный узел. Это процессы: kube-apiserver, kube-controller-manager и kube-scheduler.
  • Каждый отдельный неосновной узел в вашем кластере выполняет два процесса:
    • kubelet, который взаимодействует с мастером Kubernetes.
    • kube-proxy, сетевой прокси, который обрабатывает сетевые сервисы Kubernetes на каждом узле.

Объекты Kubernetes

Kubernetes содержит ряд абстракций, которые представляют состояние вашей системы: развернутые контейнеризованные приложения и рабочие нагрузки, связанные с ними сетевые и дисковые ресурсы и другую информацию о том, что делает ваш кластер. Эти абстракции представлены объектами в API Kubernetes. См. Понимание объектов Kubernetes для получения более подробной информации.

Основные объекты Kubernetes включают в себя:

Kubernetes также содержит абстракции более высокого уровня, которые опираются на Контроллеры для создания базовых объектов и предоставляют дополнительные функциональные и удобные функции. Они включают:

Управляющий слой Kubernetes

Различные части управляющего слоя Kubernetes (control plane), такие как мастер Kubernetes и процессы kubelet, определяют, как Kubernetes взаимодействует с кластером. Управляющий слой поддерживает запись всех объектов Kubernetes в системе и запускает непрерывные циклы управления для обработки состояния этих объектов. В любое время циклы управления управляющего слоя будут реагировать на изменения в кластере и работать, чтобы фактическое состояние всех объектов в системе соответствовало желаемому состоянию, которое вы указали.

Например, когда вы используете API Kubernetes для создания развертывания, вы предоставляете новое желаемое состояние для системы. Управляющий слой Kubernetes записывает создание этого объекта и выполняет ваши инструкции, запуская необходимые приложения и планируя их на узлы кластера, чтобы фактическое состояние кластера соответствовало желаемому состоянию.

Мастер Kubernetes

Мастер Kubernetes отвечает за поддержание желаемого состояния для вашего кластера. Когда вы взаимодействуете с Kubernetes, например, используя интерфейс командной строки kubectl, вы работаете с мастером Kubernetes вашего кластера.

Под "мастером" понимается совокупность процессов, которые управляют состоянием кластера. Обычно все эти процессы выполняются на одном узле кластера, и поэтому этот узел называется главным (master). Мастер также может быть реплицирован для доступности и резервирования.

Узлы Kubernetes

Узлы в кластере - это машины (виртуальные машины, физические серверы и т.д.), на которых работают ваши приложения и облачные рабочие процессы. Мастер Kubernetes контролирует каждый узел; вы редко будете взаимодействовать с узлами напрямую.

Что дальше

Если вы хотите описать концепт, обратитесь к странице Использование шаблонов страниц для получения информации о типе страницы и шаблоне концепции.

6.1 - Обзор

6.1.1 - Что такое Kubernetes

Эта страница посвящена краткому обзору Kubernetes.

Kubernetes — это портативная расширяемая платформа с открытым исходным кодом для управления контейнеризованными рабочими нагрузками и сервисами, которая облегчает как декларативную настройку, так и автоматизацию. У платформы есть большая, быстро растущая экосистема. Сервисы, поддержка и инструменты Kubernetes широко доступны.

Название Kubernetes происходит от греческого, что означает рулевой или штурман. Google открыл исходный код Kubernetes в 2014 году. Kubernetes основывается на десятилетнем опыте работы Google с масштабными рабочими нагрузками, в сочетании с лучшими в своем классе идеями и практиками сообщества.

История

Давайте вернемся назад и посмотрим, почему Kubernetes так полезен.

Эволюция развертывания

Традиционная эра развертывания: Ранее организации запускали приложения на физических серверах. Не было никакого способа определить границы ресурсов для приложений на физическом сервере, и это вызвало проблемы с распределением ресурсов. Например, если несколько приложений выполняются на физическом сервере, могут быть случаи, когда одно приложение будет занимать большую часть ресурсов, и в результате чего другие приложения будут работать хуже. Решением этого было запустить каждое приложение на другом физическом сервере. Но это не масштабировалось, поскольку ресурсы использовались не полностью, из-за чего организациям было накладно поддерживать множество физических серверов.

Эра виртуального развертывания: В качестве решения была представлена виртуализация. Она позволила запускать несколько виртуальных машин (ВМ) на одном физическом сервере. Виртуализация изолирует приложения между виртуальными машинами и обеспечивает определенный уровень безопасности, поскольку информация одного приложения не может быть свободно доступна другому приложению.

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

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

Эра контейнеров: Контейнеры похожи на виртуальные машины, но у них есть свойства изоляции для совместного использования операционной системы (ОС) между приложениями. Поэтому контейнеры считаются легкими. Подобно виртуальной машине, контейнер имеет свою собственную файловую систему, процессор, память, пространство процесса и многое другое. Поскольку они не связаны с базовой инфраструктурой, они переносимы между облаками и дистрибутивами ОС.

Контейнеры стали популярными из-за таких дополнительных преимуществ как:

  • Гибкое создание и развертывание приложений: простота и эффективность создания образа контейнера по сравнению с использованием образа виртуальной машины.
  • Непрерывная разработка, интеграция и развертывание: обеспечивает надежную и частую сборку и развертывание образа контейнера с быстрым и простым откатом (благодаря неизменности образа).
  • Разделение задач между Dev и Ops: создавайте образы контейнеров приложений во время сборки/релиза, а не во время развертывания, тем самым отделяя приложения от инфраструктуры.
  • Наблюдаемость охватывает не только информацию и метрики на уровне ОС, но также информацию о работоспособности приложений и другие сигналы.
  • Идентичная окружающая среда при разработке, тестировании и релизе: на ноутбуке работает так же, как и в облаке.
  • Переносимость облачных и операционных систем: работает на Ubuntu, RHEL, CoreOS, on-prem, Google Kubernetes Engine и в любом другом месте.
  • Управление, ориентированное на приложения: повышает уровень абстракции от запуска ОС на виртуальном оборудовании до запуска приложения в ОС с использованием логических ресурсов.
  • Слабосвязанные, распределенные, гибкие, выделенные микросервисы: вместо монолитного стека на одной большой выделенной машине, приложения разбиты на более мелкие независимые части, которые можно динамически развертывать и управлять.
  • Изоляция ресурсов: предсказуемая производительность приложения.
  • Грамотное использование ресурсов: высокая эффективность и компактность.

Зачем вам Kubernetes и что он может сделать?

Контейнеры — отличный способ связать и запустить ваши приложения. В производственной среде необходимо управлять контейнерами, которые запускают приложения, и гарантировать отсутствие простоев. Например, если контейнер выходит из строя, необходимо запустить другой контейнер. Не было бы проще, если бы такое поведение обрабатывалось системой?

Вот тут Kubernetes приходит на помощь! Kubernetes дает вам фреймворк для гибкой работы распределенных систем. Он занимается масштабированием и обработкой ошибок в приложении, предоставляет шаблоны развертывания и многое другое. Например, Kubernetes может легко управлять канареечным развертыванием вашей системы.

Kubernetes предоставляет вам:

  • Мониторинг сервисов и распределение нагрузки Kubernetes может обнаружить контейнер, используя имя DNS или собственный IP-адрес. Если трафик в контейнере высокий, Kubernetes может сбалансировать нагрузку и распределить сетевой трафик, чтобы развертывание было стабильным.
  • Оркестрация хранилища Kubernetes позволяет вам автоматически смонтировать систему хранения по вашему выбору, такую как локальное хранилище, провайдеры общедоступного облака и многое другое.
  • Автоматическое развертывание и откаты Используя Kubernetes можно описать желаемое состояние развернутых контейнеров и изменить фактическое состояние на желаемое. Например, вы можете автоматизировать Kubernetes на создание новых контейнеров для развертывания, удаления существующих контейнеров и распределения всех их ресурсов в новый контейнер.
  • Автоматическое распределение нагрузки Вы предоставляете Kubernetes кластер узлов, который он может использовать для запуска контейнерных задач. Вы указываете Kubernetes, сколько ЦП и памяти (ОЗУ) требуется каждому контейнеру. Kubernetes может разместить контейнеры на ваших узлах так, чтобы наиболее эффективно использовать ресурсы.
  • Самоконтроль Kubernetes перезапускает отказавшие контейнеры, заменяет и завершает работу контейнеров, которые не проходят определенную пользователем проверку работоспособности, и не показывает их клиентам, пока они не будут готовы к обслуживанию.
  • Управление конфиденциальной информацией и конфигурацией Kubernetes может хранить и управлять конфиденциальной информацией, такой как пароли, OAuth-токены и ключи SSH. Вы можете развертывать и обновлять конфиденциальную информацию и конфигурацию приложения без изменений образов контейнеров и не раскрывая конфиденциальную информацию в конфигурации стека.

Чем Kubernetes не является

Kubernetes ― это не традиционная комплексная система PaaS (платформа как услуга). Поскольку Kubernetes работает на уровне контейнеров, а не на уровне оборудования, у него имеется определенные общеприменимые возможности, характерные для PaaS, такие как развертывание, масштабирование, балансировка нагрузки, ведение журналов и мониторинг. Тем не менее, Kubernetes это не монолитное решение, поэтому указанные возможности по умолчанию являются дополнительными и подключаемыми. У Kubernetes есть компоненты для создания платформы разработчика, но он сохраняет право выбора за пользователем и гибкость там, где это важно.

Kubernetes:

  • Не ограничивает типы поддерживаемых приложений. Kubernetes стремится поддерживать широкий спектр рабочих нагрузок, включая те, у которых есть или отсутствует состояние, а также связанные с обработкой данных. Если приложение может работать в контейнере, оно должно отлично работать и в Kubernetes.
  • Не развертывает исходный код и не собирает приложение. Рабочие процессы непрерывной интеграции, доставки и развертывания (CI/CD) определяются культурой и предпочтениями организации, а также техническими требованиями.
  • Не предоставляет сервисы для приложения, такие как промежуточное программное обеспечение (например, очереди сообщений), платформы обработки данных (например, Spark), базы данных (например, MySQL), кеши или кластерные системы хранения (например, Ceph), как встроенные сервисы. Такие компоненты могут работать в Kubernetes и/или могут быть доступны для приложений, работающих в Kubernetes, через переносные механизмы, такие как Open Service Broker.
  • Не включает решения для ведения журнала, мониторинга или оповещения. Он обеспечивает некоторые интеграции в качестве доказательства концепции и механизмы для сбора и экспорта метрик.
  • Не указывает и не требует настройки языка/системы (например, Jsonnet). Он предоставляет декларативный API, который может быть нацелен на произвольные формы декларативных спецификаций.
  • Не предоставляет и не принимает никаких комплексных систем конфигурации, технического обслуживания, управления или самовосстановления.
  • Кроме того, Kubernetes — это не просто система оркестрации. Фактически, Kubernetes устраняет необходимость в этом. Техническое определение оркестрации — это выполнение определенного рабочего процесса: сначала сделай A, затем B, затем C. Напротив, Kubernetes содержит набор независимых, компонуемых процессов управления, которые непрерывно переводит текущее состояние к предполагаемому состоянию. Неважно, как добраться от А до С. Не требуется также централизованный контроль. Это делает систему более простой в использовании, более мощной, надежной, устойчивой и расширяемой.

Что дальше

6.1.2 - Компоненты Kubernetes

При развёртывании Kubernetes вы имеете дело с кластером.

Кластер Kubernetes cluster состоит из набор машин, так называемые узлы, которые запускают контейнеризированные приложения. Кластер имеет как минимум один рабочий узел.

В рабочих узлах размещены поды, являющиеся компонентами приложения. Управляющий слой (control plane) управляет рабочими узлами и подами в кластере. В промышленных средах управляющий слой обычно запускается на нескольких компьютерах, а кластер, как правило, развёртывается на нескольких узлах, гарантируя отказоустойчивость и высокую надёжность.

На этой странице в общих чертах описывается различные компоненты, необходимые для работы кластера Kubernetes.

Ниже показана диаграмма кластера Kubernetes со всеми связанными компонентами.

Компоненты Kubernetes

Компоненты управляющего слоя

Компоненты управляющего слоя (control plane) отвечают за основные операции кластера (например, планирование), а также обрабатывают события кластера (например, запускают новый под, когда поле replicas развертывания не соответствует требуемому количеству реплик).

Компоненты управляющего слоя могут быть запущены на любой машине в кластере. Однако для простоты сценарии настройки обычно запускают все компоненты управляющего слоя на одном компьютере и в то же время не позволяют запускать пользовательские контейнеры на этом компьютере. Смотрите страницу Создание высоконадёжных кластеров для примера настройки нескольких ведущих виртуальных машин.

kube-apiserver

Сервер API — компонент Kubernetes панели управления, который представляет API Kubernetes. API-сервер — это клиентская часть панели управления Kubernetes

Основной реализацией API-сервера Kubernetes является kube-apiserver. kube-apiserver предназначен для горизонтального масштабирования, то есть развёртывание на несколько экземпляров. Вы можете запустить несколько экземпляров kube-apiserver и сбалансировать трафик между этими экземплярами.

etcd

Распределённое и высоконадёжное хранилище данных в формате "ключ-значение", которое используется как основное хранилище всех данных кластера в Kubernetes.

Если ваш кластер Kubernetes использует etcd в качестве основного хранилища, убедитесь, что у вас настроено резервное копирование данных.

Вы можете найти подробную информацию о etcd в официальной документации.

kube-scheduler

Компонент управляющего слоя (control plane), который отслеживает созданные поды без привязанного узла и выбирает узел, на котором они должны работать.

При планировании развёртывания подов на узлах учитываются множество факторов, включая требования к ресурсам, ограничения, связанные с аппаратными/программными политиками, принадлежности (affinity) и непринадлежности (anti-affinity) узлов/подов, местонахождения данных, предельных сроков.

kube-controller-manager

Компонент Control Plane запускает процессы контроллера.

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

Эти контроллеры включают:

  • Контроллер узла (Node Controller): уведомляет и реагирует на сбои узла.
  • Контроллер репликации (Replication Controller): поддерживает правильное количество подов для каждого объекта контроллера репликации в системе.
  • Контроллер конечных точек (Endpoints Controller): заполняет объект конечных точек (Endpoints), то есть связывает сервисы (Services) и поды (Pods).
  • Контроллеры учетных записей и токенов (Account & Token Controllers): создают стандартные учетные записи и токены доступа API для новых пространств имен.

cloud-controller-manager

cloud-controller-manager запускает контроллеры, которые взаимодействуют с основными облачными провайдерами. Двоичный файл cloud-controller-manager — это альфа-функциональность, появившиеся в Kubernetes 1.6.

cloud-controller-manager запускает только циклы контроллера, относящиеся к облачному провайдеру. Вам нужно отключить эти циклы контроллера в kube-controller-manager. Вы можете отключить циклы контроллера, установив флаг --cloud-provider со значением external при запуске kube-controller-manager.

С помощью cloud-controller-manager код как облачных провайдеров, так и самого Kubernetes может разрабатываться независимо друг от друга. В предыдущих версиях код ядра Kubernetes зависел от кода, предназначенного для функциональности облачных провайдеров. В будущих выпусках код, специфичный для облачных провайдеров, должен поддерживаться самим облачным провайдером и компоноваться с cloud-controller-manager во время запуска Kubernetes.

Следующие контроллеры зависят от облачных провайдеров:

  • Контроллер узла (Node Controller): проверяет облачный провайдер, чтобы определить, был ли удален узел в облаке после того, как он перестал работать
  • Контроллер маршрутов (Route Controller): настраивает маршруты в основной инфраструктуре облака
  • Контроллер сервисов (Service Controller): создаёт, обновляет и удаляет балансировщики нагрузки облачного провайдера.
  • Контроллер тома (Volume Controller): создаёт, присоединяет и монтирует тома, а также взаимодействует с облачным провайдером для оркестрации томов.

Компоненты узла

Компоненты узла работают на каждом узле, поддерживая работу подов и среды выполнения Kubernetes.

kubelet

Агент, работающий на каждом узле в кластере. Он следит за тем, чтобы контейнеры были запущены в поде.

Утилита kubelet принимает набор PodSpecs, и гарантирует работоспособность и исправность определённых в них контейнеров. Агент kubelet не отвечает за контейнеры, не созданные Kubernetes.

kube-proxy

kube-proxy — сетевой прокси, работающий на каждом узле в кластере, и реализующий часть концепции сервис.

kube-proxy конфигурирует правила сети на узлах. При помощи них разрешаются сетевые подключения к вашими подам изнутри и снаружи кластера.

kube-proxy использует уровень фильтрации пакетов в операционной системы, если он доступен. В противном случае, kube-proxy сам обрабатывает передачу сетевого трафика.

Среда выполнения контейнера

Иcполняемая среда контейнера — это программа, предназначенная для запуска контейнера в Kubernetes.

Kubernetes поддерживает различные среды для запуска контейнеров: Docker, containerd, CRI-O, и любые реализации Kubernetes CRI (Container Runtime Interface).

Дополнения

Дополнения используют ресурсы Kubernetes (DaemonSet, Deployment и т.д.) для расширения функциональности кластера. Поскольку дополнения охватывают весь кластер, ресурсы относятся к пространству имен kube-system.

Некоторые из дополнений описаны ниже; более подробный список доступных расширений вы можете найти на странице Дополнения.

DNS

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

Кластерный DNS — это DNS-сервер наряду с другими DNS-серверами в вашем окружении, который обновляет DNS-записи для сервисов Kubernetes.

Контейнеры, запущенные посредством Kubernetes, автоматически включают этот DNS-сервер в свои DNS.

Веб-интерфейс (Dashboard)

Dashboard — это универсальный веб-интерфейс для кластеров Kubernetes. С помощью этой панели, пользователи могут управлять и устранять неполадки кластера и приложений, работающих в кластере.

Мониторинг ресурсов контейнера

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

Логирование кластера

Механизм логирования кластера отвечает за сохранение логов контейнера в централизованном хранилище логов с возможностью их поиска/просмотра.

Что дальше

6.1.3 - API Kubernetes

Общие соглашения API описаны на странице соглашений API.

Конечные точки API, типы ресурсов и примеры описаны в справочнике API.

Удаленный доступ к API обсуждается в Controlling API Access doc.

API Kubernetes также служит основой декларативной схемы конфигурации системы. С помощью инструмента командной строки kubectl можно создавать, обновлять, удалять и получать API-объекты.

Kubernetes также сохраняет сериализованное состояние (в настоящее время в хранилище etcd) каждого API-ресурса.

Kubernetes как таковой состоит из множества компонентов, которые взаимодействуют друг с другом через собственные API.

Изменения в API

Исходя из нашего опыта, любая успешная система должна улучшаться и изменяться по мере появления новых сценариев использования или изменения существующих. Поэтому мы надеемся, что и API Kubernetes будет постоянно меняться и расширяться. Однако в течение продолжительного периода времени мы будем поддерживать хорошую обратную совместимость с существующими клиентами. В целом, новые ресурсы API и поля ресурсов будут добавляться часто. Удаление ресурсов или полей регулируются соответствующим процессом.

Определение совместимого изменения и методы изменения API подробно описаны в документе об изменениях API.

Определения OpenAPI и Swagger

Все детали API документируется с использованием OpenAPI.

Начиная с Kubernetes 1.10, API-сервер Kubernetes основывается на спецификации OpenAPI через конечную точку /openapi/v2. Нужный формат устанавливается через HTTP-заголовки:

Заголовок Возможные значения
Accept application/json, application/com.github.proto-openapi.spec.v2@v1.0+protobuf (по умолчанию заголовок Content-Type установлен в application/json с */*, допустимо также пропускать этот заголовок)
Accept-Encoding gzip (можно не передавать этот заголовок)

До версии 1.14 конечные точки с форматом (/swagger.json, /swagger-2.0.0.json, /swagger-2.0.0.pb-v1, /swagger-2.0.0.pb-v1.gz) предоставляли спецификацию OpenAPI в разных форматах. Эти конечные точки были объявлены устаревшими и удалены в Kubernetes 1.14.

Примеры получения спецификации OpenAPI:

До 1.10 С версии Kubernetes 1.10
GET /swagger.json GET /openapi/v2 Accept: application/json
GET /swagger-2.0.0.pb-v1 GET /openapi/v2 Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf
GET /swagger-2.0.0.pb-v1.gz GET /openapi/v2 Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf Accept-Encoding: gzip

В Kubernetes реализован альтернативный формат сериализации API, основанный на Protobuf, который в первую очередь предназначен для взаимодействия внутри кластера. Описание этого формата можно найти в проектом решении, а IDL-файлы по каждой схемы — в пакетах Go, определяющих API-объекты.

До версии 1.14 apiserver Kubernetes также представлял API, который можно использовать для получения спецификации Swagger v1.2 для API Kubernetes по пути /swaggerapi. Эта конечная точка устарела и была удалена в Kubernetes 1.14

Версионирование API

Чтобы упростить удаления полей или изменение ресурсов, Kubernetes поддерживает несколько версий API, каждая из которых доступна по собственному пути, например, /api/v1 или /apis/extensions/v1beta1.

Мы выбрали версионирование API, а не конкретных ресурсов или полей, чтобы API отражал четкое и согласованное представление о системных ресурсах и их поведении, а также, чтобы разграничивать API, которые уже не поддерживаются и/или находятся в экспериментальной стадии. Схемы сериализации JSON и Protobuf следуют одним и тем же правилам по внесению изменений в схему, поэтому описание ниже охватывают оба эти формата.

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

Разные версии API характеризуются разными уровнями стабильности и поддержки. Критерии каждого уровня более подробно описаны в документации изменений API. Ниже приводится краткое изложение:

  • Альфа-версии:
    • Названия версий включают надпись alpha (например, v1alpha1).
    • Могут содержать баги. Включение такой функциональности может привести к ошибкам. По умолчанию она отключена.
    • Поддержка функциональности может быть прекращена в любое время без какого-либо оповещения об этом.
    • API может быть несовместим с более поздними версиями без упоминания об этом.
    • Рекомендуется для использования только в тестировочных кластерах с коротким жизненным циклом из-за высокого риска наличия багов и отсутствия долгосрочной поддержки.
  • Бета-версии:
    • Названия версий включают надпись beta (например, v2beta3).
    • Код хорошо протестирован. Активация этой функциональности — безопасно. Поэтому она включена по умолчанию.
    • Поддержка функциональности в целом не будет прекращена, хотя кое-что может измениться.
    • Схема и/или семантика объектов может стать несовместимой с более поздними бета-версиями или стабильными выпусками. Когда это случится, мы даем инструкции по миграции на следующую версию. Это обновление может включать удаление, редактирование и повторного создание API-объектов. Этот процесс может потребовать тщательного анализа. Кроме этого, это может привести к простою приложений, которые используют данную функциональность.
    • Рекомендуется только для неосновного производственного использования из-за риска возникновения возможных несовместимых изменений с будущими версиями. Если у вас есть несколько кластеров, которые возможно обновить независимо, вы можете снять это ограничение.
    • Пожалуйста, попробуйте в действии бета-версии функциональности и поделитесь своими впечатлениями! После того как функциональность выйдет из бета-версии, нам может быть нецелесообразно что-то дальше изменять.
  • Стабильные версии:
    • Имя версии vX, где vX — целое число.
    • Стабильные версии функциональностей появятся в новых версиях.

API-группы

Чтобы упростить расширение API Kubernetes, реализованы группы API. Группа API указывается в пути REST и в поле apiVersion сериализованного объекта.

В настоящее время используется несколько API-групп:

  1. Группа core, которая часто упоминается как устаревшая (legacy group), доступна по пути /api/v1 и использует apiVersion: v1.

  2. Именованные группы находятся в пути REST /apis/$GROUP_NAME/$VERSION и используют apiVersion: $GROUP_NAME/$VERSION (например, apiVersion: batch/v1). Полный список поддерживаемых групп API можно увидеть в справочнике API Kubernetes.

Есть два поддерживаемых пути к расширению API с помощью пользовательских ресурсов:

  1. CustomResourceDefinition для пользователей, которым нужен очень простой CRUD.
  2. Пользователи, которым нужна полная семантика API Kubernetes, могут реализовать собственный apiserver и использовать агрегатор для эффективной интеграции для клиентов.

Включение или отключение групп API

Некоторые ресурсы и группы API включены по умолчанию. Их можно включить или отключить, установив --runtime-config для apiserver. Флаг --runtime-config принимает значения через запятую. Например, чтобы отключить batch/v1, используйте --runtime-config=batch/v1=false, а чтобы включить batch/v2alpha1, используйте флаг --runtime-config=batch/v2alpha1. Флаг набор пар ключ-значение, указанных через запятую, который описывает конфигурацию во время выполнения сервера.

Включение определённых ресурсов в группу extensions/v1beta1

DaemonSets, Deployments, StatefulSet, NetworkPolicies, PodSecurityPolicies и ReplicaSets в API-группе extensions/v1beta1 по умолчанию отключены. Например: чтобы включить deployments и daemonsets, используйте флаг --runtime-config=extensions/v1beta1/deployments=true,extensions/v1beta1/daemonsets=true.

6.1.4 - Работа с объектами Kubernetes

6.1.4.1 - Изучение объектов Kubernetes

На этой странице объясняется, как объекты Kubernetes представлены в API Kubernetes, и как их можно определить в формате .yaml.

Изучение объектов Kubernetes

Объекты Kubernetes — сущности, которые хранятся в Kubernetes. Kubernetes использует их для представления состояния кластера. В частности, они описывают следующую информацию:

  • Какие контейнеризированные приложения запущены (и на каких узлах).
  • Доступные ресурсы для этих приложений.
  • Стратегии управления приложения, которые относятся, например, к перезапуску, обновлению или отказоустойчивости.

После создания объекта Kubernetes будет следить за существованием объекта. Создавая объект, вы таким образом указываете системе Kubernetes, какой должна быть рабочая нагрузка кластера; это требуемое состояние кластера.

Для работы с объектами Kubernetes – будь то создание, изменение или удаление — нужно использовать API Kubernetes. Например, при использовании CLI-инструмента kubectl, он обращается к API Kubernetes. С помощью одной из клиентской библиотеки вы также можете использовать API Kubernetes в собственных программах.

Спецификация и статус объекта

Почти в каждом объекте Kubernetes есть два вложенных поля-объекта, которые управляют конфигурацией объекта: spec и status. При создании объекта в поле spec указывается требуемое состояние (описание характеристик, которые должны быть у объекта).

Поле status описывает текущее состояние объекта, которое создаётся и обновляется самим Kubernetes и его компонентами. Управляющий слой Kubernetes непрерывно управляет фактическим состоянием каждого объекта, чтобы оно соответствовало требуемому состоянию, которое было задано пользователем.

Например: Deployment — это объект Kubernetes, представляющий работающее приложение в кластере. При создании объекта Deployment вы можете указать в его поле spec, что хотите иметь три реплики приложения. Система Kubernetes получит спецификацию объекта Deployment и запустит три экземпляра приложения, таким образом обновит статус (состояние) объекта, чтобы он соответствовал заданной спецификации. В случае сбоя одного из экземпляров (это влечет за собой изменение состояние), Kubernetes обнаружит несоответствие между спецификацией и статусом и исправит его, т.е. активирует новый экземпляр вместо того, который вышел из строя.

Для получения дополнительной информации о спецификации объекта, статусе и метаданных смотрите документ с соглашениями API Kubernetes.

Описание объекта Kubernetes

При создании объекта в Kubernetes нужно передать спецификацию объекта, которая содержит требуемое состояние, а также основную информацию об объекте (например, его имя). Когда вы используете API Kubernetes для создания объекта (напрямую либо через kubectl), соответствующий API-запрос должен включать в теле запроса всю указанную информацию в JSON-формате. В большинстве случаев вы будете передавать kubectl эти данные, записанные в файле .yaml. Тогда инструмент kubectl преобразует их в формат JSON при выполнении запроса к API.

Ниже представлен пример .yaml-файла, в котором заданы обязательные поля и спецификация объекта, необходимая для объекта Deployment в Kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Один из способов создания объекта Deployment с помощью файла .yaml, показанного выше — использовать команду kubectl apply, которая принимает в качестве аргумента файл в формате .yaml. Например:

kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record

Вывод будет примерно таким:

deployment.apps/nginx-deployment created

Обязательные поля

В файле .yaml создаваемого объекта Kubernetes необходимо указать значения для следующих полей:

  • apiVersion — используемая для создания объекта версия API Kubernetes
  • kind — тип создаваемого объекта
  • metadata — данные, позволяющие идентифицировать объект (name, UID и необязательное поле namespace)
  • spec — требуемое состояние объекта

Конкретный формат поля-объекта spec зависит от типа объекта Kubernetes и содержит вложенные поля, предназначенные только для используемого объекта. В справочнике API Kubernetes можно найти формат спецификации любого объекта Kubernetes. Например, формат spec для объекта Pod находится в ядре PodSpec v1, а формат spec для Deployment — в DeploymentSpec v1 apps.

Что дальше

  • Обзор API Kubernetes более подробно объясняет некоторые из API-концепций
  • Познакомиться с наиболее важными и основными объектами в Kubernetes, например, с подами.
  • Узнать подробнее про контролеры в Kubernetes

6.1.4.2 - Управление объектами Kubernetes

В инструменте командной строки kubectl есть несколько разных способов создания и управления объектами Kubernetes. На этой странице рассматриваются различные подходы. Изучите документацию по Kubectl для получения подробной информации по управлению объектами с помощью Kubectl.

Способы управления

Способ управления Область применения Рекомендуемое окружение Количество поддерживаемых авторов Трудность изучения
Императивные команды Активные объекты Проекты в стадии разработки 1+ Низкая
Императивная конфигурация объекта Отдельные файлы Продакшен-проекты 1 Средняя
Декларативная конфигурация объекта Директории или файлы Продакшен-проекты 1+ Сложная

Императивные команды

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

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

Примеры

Запустите экземпляр контейнера nginx, посредством создания объекта Deployment:

kubectl run nginx --image nginx

То же самое, но с другим синтаксисом:

kubectl create deployment nginx --image nginx

Плюсы и минусы

Преимущества по сравнению с конфигурацией объекта:

  • Простые команды, которые легко выучить и запомнить.
  • Для применения изменений в кластер нужно только выполнить команды.

Недостатки по сравнению с конфигурацией объекта:

  • Команды не интегрированы с процессом проверки (обзора) изменений.
  • У команд нет журнала с изменениями.
  • Команды не дают источник записей, за исключением активных объектов.
  • Команды не содержат шаблон для создания новых объектов.

Императивная конфигурация объекта

В случае использования императивной конфигурации объекта команде kubectl устанавливают действие (создание, замена и т.д.), необязательные флаги и как минимум одно имя файла. Файл должен содержать полное определение объекта в формате YAML или JSON.

Посмотрите Справочник API для получения более подробной информации про определения объекта.

Примеры

Создать объекты, определенные в конфигурационном файле:

kubectl create -f nginx.yaml

Удалить объекты, определенные в двух конфигурационных файлах:

kubectl delete -f nginx.yaml -f redis.yaml

Обновить объекты, определенные в конфигурационном файле, перезаписав текущую конфигурацию:

kubectl replace -f nginx.yaml

Плюсы и минусы

Преимущества по сравнению с императивными командами:

  • Конфигурация объекта может храниться в системе управления версиями, такой как Git.
  • Конфигурация объекта может быть интегрирована с процессами проверки изменений и логирования.
  • Конфигурация объекта предусматривает шаблон для создания новых объектов.

Недостатки по сравнению с императивными командами:

  • Конфигурация объекта требует наличие общего представления об схеме объекта.
  • Конфигурация объекта предусматривает написание файла YAML.

Преимущества по сравнению с декларативной конфигурацией объекта:

  • Императивная конфигурация объекта проще и легче для понимания.
  • Начиная с Kubernetes 1.5, конфигурация императивных объектов стала лучше и совершеннее.

Недостатки по сравнению с декларативной конфигурацией объекта:

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

Декларативная конфигурация объекта

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

Примеры

Обработать все конфигурационные файлы объектов в директории configs и создать либо частично обновить активные объекты. Сначала можно выполнить diff, чтобы посмотреть, какие изменения будут внесены, и только после этого применить их:

kubectl diff -f configs/
kubectl apply -f configs/

Рекурсивная обработка директорий:

kubectl diff -R -f configs/
kubectl apply -R -f configs/

Плюсы и минусы

Преимущества по сравнению с императивной конфигурацией объекта:

  • Изменения, внесенные непосредственно в активные объекты, будут сохранены, даже если они не отражены в конфигурационных файлах.
  • Декларативная конфигурация объекта лучше работает с директориями и автоматически определяет тип операции (создание, частичное обновление, удаление) каждого объекта.

Недостатки по сравнению с императивной конфигурацией объекта:

  • Декларативную конфигурацию объекта сложнее отладить и понять, когда можно получить неожиданные результаты.
  • Частичные обновления с использованием различий приводит к сложным операциям слияния и исправления.

Что дальше

6.1.4.3 - Имена и идентификаторы объектов

Каждый объект в кластере имеет уникальное имя для конкретного типа ресурса. Кроме этого, у каждого объекта Kubernetes есть собственный уникальный идентификатор (UID) в пределах кластера.

Например, в одном и том же пространстве имён может быть только один Pod-объект с именем myapp-1234, и при этом существовать объект Deployment с этим же названием myapp-1234.

Для создания пользовательских неуникальных атрибутов у Kubernetes есть метки и аннотации.

Имена

Клиентская строка, предназначенная для ссылки на объект в URL-адресе ресурса, например /api/v1/pods/some-name.

Указанное имя может иметь только один объект определённого типа. Но если вы удалите этот объект, вы можете создать новый с таким же именем

Ниже перечислены три типа распространённых требований к именам ресурсов.

Имена поддоменов DNS

Большинству типов ресурсов нужно указать имя, используемое в качестве имени поддомена DNS в соответствии с RFC 1123. Соответственно, имя должно:

  • содержать не более 253 символов
  • иметь только строчные буквенно-цифровые символы, '-' или '.'
  • начинаться с буквенно-цифрового символа
  • заканчивается буквенно-цифровым символом

Имена меток DNS

Некоторые типы ресурсов должны соответствовать стандарту меток DNS, который описан в RFC 1123. Таким образом, имя должно:

  • содержать не более 63 символов
  • содержать только строчные буквенно-цифровые символы или '-'
  • начинаться с буквенно-цифрового символа
  • заканчивается буквенно-цифровым символом

Имена сегментов пути

Определённые имена типов ресурсов должны быть закодированы для использования в качестве сегмента пути. Проще говоря, имя не может быть "." или "..", а также не может содержать "/" или "%".

Пример файла манифеста пода nginx-demo.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

Уникальные идентификаторы

Уникальная строка, сгенерированная самим Kubernetes, для идентификации объектов.

У каждого объекта, созданного в течение всего периода работы кластера Kubernetes, есть собственный уникальный идентификатор (UID). Он предназначен для выяснения различий между событиями похожих сущностей.

Уникальные идентификатор (UID) в Kubernetes — это универсальные уникальные идентификаторы (известные также как Universally Unique IDentifier, сокращенно UUID). Эти идентификаторы стандартизированы под названием ISO/IEC 9834-8, а также как ITU-T X.667.

Что дальше

6.1.4.4 - Пространства имён

Kubernetes поддерживает несколько виртуальных кластеров в одном физическом кластере. Такие виртуальные кластеры называются пространствами имён.

Причины использования нескольких пространств имён

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

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

Пространства имён — это способ разделения ресурсов кластера между несколькими пользователями (с помощью квоты ресурсов).

По умолчанию в будущих версиях Kubernetes объекты в одном и том же пространстве имён будут иметь одинаковую политику контроля доступа.

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

Использование пространств имён

Создание и удаление пространств имён описаны в руководстве администратора по пространствам имён.

Просмотр пространств имён

Используйте следующую команду, чтобы вывести список существующих пространств имён в кластере:

kubectl get namespace
NAME          STATUS    AGE
default       Active    1d
kube-system   Active    1d
kube-public   Active    1d

По умолчанию в Kubernetes определены три пространства имён:

  • default — пространство имён по умолчанию для объектов без какого-либо другого пространства имён.
  • kube-system — пространство имён для объектов, созданных Kubernetes
  • kube-public — создаваемое автоматически пространство имён, которое доступно для чтения всем пользователям (включая также неаутентифицированных пользователей). Как правило, это пространство имён используется кластером, если некоторые ресурсы должны быть общедоступными для всего кластера. Главная особенность этого пространства имён — оно всего лишь соглашение, а не требование.

Определение пространства имён для отдельных команд

Используйте флаг --namespace, чтобы определить пространство имён только для текущего запроса.

Примеры:

kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>

Определение пространства имён для всех команд

Можно определить пространство имён, которое должно использоваться для всех выполняемых команд kubectl в текущем контексте.

kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Проверка
kubectl config view --minify | grep namespace:

Пространства имён и DNS

При создании сервиса создаётся соответствующая ему DNS-запись. Эта запись вида <service-name>.<namespace-name>.svc.cluster.local означает, что если контейнер использует только <service-name>, то он будет локальным сервисом в пространстве имён. Это позволит применять одну и ту же конфигурацию в нескольких пространствах имен (например, development, staging и production). Если нужно обращаться к другим пространствам имён, то нужно использовать полностью определенное имя домена (FQDN).

Объекты без пространства имён

Большинство ресурсов Kubernetes (например, поды, сервисы, контроллеры репликации и другие) расположены в определённых пространствах имён. При этом сами ресурсы пространства имён не находятся ни в других пространствах имён. А такие низкоуровневые ресурсы, как узлы и persistentVolumes, не принадлежат ни одному пространству имён.

Чтобы посмотреть, какие ресурсы Kubernetes находятся в пространстве имён, а какие — нет, используйте следующие команды:

# Ресурсы в пространстве имён
kubectl api-resources --namespaced=true

# Ресурсы, не принадлежавшие ни одному пространству имён
kubectl api-resources --namespaced=false

Что дальше

6.1.4.5 - Метки и селекторы

Метки — это пары ключ-значение, которые добавляются к объектам, как поды. Метки предназначены для идентификации атрибутов объектов, которые имеют значимость и важны для пользователей, но при этом не относятся напрямую к основной системе. Метки можно использовать для группировки и выбора подмножеств объектов. Метки могут быть добавлены к объектам во время создания и изменены в любое время после этого. Каждый объект может иметь набор меток в виде пары ключ-значение. Каждый ключ должен быть уникальным в рамках одного и того же объекта.

"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

Метки используются при получении и отслеживании объектов и в веб-панелях и CLI-инструментах. Любая неидентифицирующая информация должна быть записана в аннотации.

Причины использования

Метки позволяют пользователям гибко сопоставить их организационные структуры с системными объектами, не требуя от клиентов хранить эти соответствия.

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

Примеры меток:

  • "release" : "stable", "release" : "canary"
  • "environment" : "dev", "environment" : "qa", "environment" : "production"
  • "tier" : "frontend", "tier" : "backend", "tier" : "cache"
  • "partition" : "customerA", "partition" : "customerB"
  • "track" : "daily", "track" : "weekly"

Это всего лишь примеры часто используемых меток; конечно, вы можете использовать свои собственные. Помните о том, что ключ метки должна быть уникальной в пределах одного объекта.

Синтаксис и набор символов

Метки представляют собой пары ключ-значение. Разрешенные ключи метки имеют два сегмента, разделённые слешем (/): префикс (необязательно) и имя. Сегмент имени обязателен и должен содержать не более 63 символов, среди которых могут быть буквенно-цифровые символы ([a-z0-9A-Z]), а также дефисы (-), знаки подчеркивания (_), точки (.). Префикс не обязателен, но он быть поддоменом DNS: набор меток DNS, разделенных точками (.), общей длиной не более 253 символов, за которыми следует слеш (/).

Если префикс не указан, ключ метки считается закрытым для пользователя. Компоненты автоматизированной системы (например, kube-scheduler, kube-controller-manager, kube-apiserver, kubectl или другие сторонние), которые добавляют метки к объектам пользователя, должны указывать префикс.

Префиксы kubernetes.io/ и k8s.io/ зарезервированы для использования основными компонентами Kubernetes.

Например, ниже представлен конфигурационный файл объекта Pod с двумя метками environment: production и app: nginx:

apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels:
    environment: production
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

Селекторы меток

В отличие от имен и идентификаторов, метки не гарантируют уникальность. Поэтому мы предполагаем, что многие объекты будут иметь одинаковые метки.

С помощью селектора меток клиент/пользователь может идентифицировать набор объектов. Селектор меток — основное средство группировки в Kubernetes.

В настоящее время API поддерживает два типа селекторов: на равенстве и на наборе. Селектор меток может состоять из нескольких условий, разделенных запятыми. В таком случае все условия должны быть выполнены, поэтому запятая-разделитель работает как логический оператор И (&&).

Работа пустых или неопределённых селекторов зависит от контекста. Типы API, которые использует селекторы, должны задокументировать это поведение.

Условие равенства

Условия равенства или неравенства позволяют отфильтровать объекты по ключам и значениям меток. Сопоставляемые объекты должны удовлетворять всем указанным условиям меток, хотя при этом у объектов также могут быть заданы другие метки. Доступны три оператора: =,==,!=. Первые два означают равенство (и являются всего лишь синонимами), а последний оператор определяет неравенство. Например:

environment = production
tier != frontend

Первый пример выбирает все ресурсы с ключом environment, у которого значение указано production. Последний получает все ресурсы с ключом tier без значения frontend, а также все ресурсы, в которых нет метки с ключом tier. Используя оператор запятой можно совместить показанные два условия в одно, запросив ресурсы, в которых есть значение метки production и исключить frontend: environment=production,tier!=frontend.

С помощью условия равенства в объектах Pod можно указать, какие нужно выбрать ресурсы. Например, в примере ниже объект Pod выбирает узлы с меткой "accelerator=nvidia-tesla-p100".

apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "registry.k8s.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

Условие набора

Условие меток на основе набора фильтрует ключи в соответствии с набором значений. Поддерживаются три вида операторов: in, notin и exists (только идентификатор ключа). Например:

environment in (production, qa)
tier notin (frontend, backend)
partition
!partition

В первом примере выбираются все ресурсы с ключом environment и значением production или qa. Во втором примере выбираются все ресурсы с ключом tier и любыми значениями, кроме frontend и backend, а также все ресурсы без меток с ключом tier. Третий пример выбирает все ресурсы, включая метку с ключом partition (с любым значением). В четвертом примере выбираются все ресурсы без метки с ключом partition (с любым значением). Как и логический оператор И работает разделитель в виде запятой. Таким образом, фильтрация ресурсов по ключу partition (вне зависимости от значения) и ключу environment с любым значением, кроме qa, можно получить с помощью следующего выражения: partition,environment notin (qa). Селектор меток на основе набора — основная форма равенства, поскольку environment=production то же самое, что и environment in (production); аналогично, оператор != соответствует notin.

Условия набора могут использоваться одновременно с условия равенства. Например, так: partition in (customerA, customerB),environment!=qa.

API

Фильтрация LIST и WATCH

Операции LIST и WATCH могут использовать параметр запроса, чтобы указать селекторы меток фильтрации наборов объектов. Есть поддержка обоих условий (строка запроса URL ниже показывается в исходном виде):

  • Условия на основе равенства: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
  • Условия на основе набора: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29

Указанные выше формы селектора меток можно использовать для просмотра или отслеживания ресурсов через REST-клиент. Например, apiserver с kubectl, который использует условие равенства:

kubectl get pods -l environment=production,tier=frontend

Либо используя условия на основе набора:

kubectl get pods -l 'environment in (production),tier in (frontend)'

Как уже показывалось, условия набора дают больше возможностей. Например, в них можно использовать подобие оператора И:

kubectl get pods -l 'environment in (production, qa)'

Либо можно воспользоваться исключающим сопоставлением с помощью оператора notin:

kubectl get pods -l 'environment,environment notin (frontend)'

Установка ссылок в API-объекты

Некоторые объекты Kubernetes, такие как services и replicationcontrollers, также используют селекторы меток для ссылки на наборы из других ресурсов, например, подов.

Service и ReplicationController

Набор подов, на которые указывает service, определяется через селектор меток. Аналогичным образом, количество подов, которыми должен управлять replicationcontroller, также формируются с использованием селектора меток.

Селекторы меток для обоих объектов записываются в словарях файлов формата json и yaml, при этом поддерживаются только селекторы с условием равенства:

"selector": {
    "component" : "redis",
}

Или:

selector:
    component: redis

Этот селектор (как в формате json, так и в yaml) эквивалентен component=redis или component in (redis).

Ресурсы, поддерживающие условия набора

Новые ресурсы, такие как Job, Deployment, ReplicaSet и DaemonSet, также поддерживают условия набора.

selector:
  matchLabels:
    component: redis
  matchExpressions:
    - {key: tier, operator: In, values: [cache]}
    - {key: environment, operator: NotIn, values: [dev]}

matchLabels — словарь пар {key,value}. Каждая пара {key,value} в словаре matchLabels эквивалентна элементу matchExpressions, где поле key — "key", поле operator — "In", а массив values содержит только "value". matchExpressions представляет собой список условий селектора пода. В качестве операторов могут быть In, NotIn, Exists и DoesNotExist. В случае использования In и NotIn должны заданы непустые значения. Все условия, как для matchLabels, так и для matchExpressions, объединяются с помощью логического И, поэтому при выборке объектов все они должны быть выполнены.

Выбор наборов узлов

Один из вариантов использования меток — возможность выбора набора узлов, в которых может быть развернут под. Смотрите документацию про выбор узлов, чтобы получить дополнительную информацию.

6.1.4.6 - Аннотации

Аннотации Kubernetes можно использовать для добавления собственных метаданных к объектам. Такие клиенты, как инструменты и библиотеки, могут получить эти метаданные.

Добавление метаданных к объектам

Вы можете использовать метки или аннотации для добавления метаданных к объектам Kubernetes. Метки можно использовать для выбора объектов и для поиска коллекций объектов, которые соответствуют определенным условиям. В отличие от них аннотации не используются для идентификации и выбора объектов. Метаданные в аннотации могут быть маленькими или большими, структурированными или неструктурированными, кроме этого они включать символы, которые не разрешены в метках.

Аннотации, как и метки, являются коллекциями с наборами пар ключ-значение:

"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

Некоторые примеры информации, которая может быть в аннотациях:

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

  • Информация о сборке, выпуске или образе, например, метка времени, идентификаторы выпуска, ветка git, номера PR, хеши образов и адрес реестра.

  • Ссылки на репозитории логирования, мониторинга, аналитики или аудита.

  • Информация о клиентской библиотеке или инструменте, которая может использоваться при отладке (например, имя, версия и информация о сборке).

  • Информация об источнике пользователя или инструмента/системы, например, URL-адреса связанных объектов из других компонентов экосистемы.

  • Небольшие метаданные развертывания (например, конфигурация или контрольные точки).

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

  • Инструкции от конечных пользователей по исправлению работы или использования нестандартной функциональности.

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

Синтаксис и набор символов

Аннотации представляют собой пары ключ-значение. Разрешенные ключи аннотации имеют два сегмента, разделённые слешем (/): префикс (необязательно) и имя. Сегмент имени обязателен и должен содержать не более 63 символов, среди которых могут быть буквенно-цифровые символы([a-z0-9A-Z]), а также дефисы (-), знаки подчеркивания (_), точки (.). Префикс не обязателен, но он быть поддоменом DNS: набор меток DNS, разделенных точками (.), общей длиной не более 253 символов, за которыми следует слеш (/).

Если префикс не указан, ключ аннотации считается закрытым для пользователя. Компоненты автоматизированной системы (например, kube-scheduler, kube-controller-manager, kube-apiserver, kubectl или другие сторонние), которые добавляют аннотации к объектам пользователя, должны указывать префикс.

Префиксы kubernetes.io/ и k8s.io/ зарезервированы для использования основными компонентами Kubernetes.

Например, ниже представлен конфигурационный файл объекта Pod с аннотацией imageregistry: https://hub.docker.com/:


apiVersion: v1
kind: Pod
metadata:
  name: annotations-demo
  annotations:
    imageregistry: "https://hub.docker.com/"
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

Что дальше

Узнать подробнее про метки и селекторы.

6.1.4.7 - Селекторы полей

Селекторы полей позволяют выбирать ресурсы Kubernetes, исходя из значения одного или нескольких полей ресурсов. Ниже приведены несколько примеров запросов селекторов полей:

  • metadata.name=my-service
  • metadata.namespace!=default
  • status.phase=Pending

Следующая команда kubectl выбирает все Pod-объекты, в которых значение поля status.phase равно Running:

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

Поддерживаемые поля

Доступные селекторы полей зависят от типа ресурса Kubernetes. У всех типов ресурсов есть поля metadata.name и metadata.namespace. При использовании несуществующего селекторов полей приведёт к возникновению ошибки. Например:

kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"

Поддерживаемые операторы

Можно использовать операторы =, == и != в селекторах полей (= и == — синонимы). Например, следующая команда kubectl выбирает все сервисы Kubernetes, не принадлежавшие пространству имен default:

kubectl get services  --all-namespaces --field-selector metadata.namespace!=default

Составные селекторы

Аналогично метки и другим селекторам, несколько селекторы полей могут быть объединены через запятую. Приведенная ниже команда kubectl выбирает все Pod-объекты, у которых значение поле status.phase, отличное от Running, а поле spec.restartPolicy имеет значение Always:

kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always

Множественные типы ресурсов

Можно использовать селекторы полей с несколькими типами ресурсов одновременно. Команда kubectl выбирает все объекты StatefulSet и Services, не включенные в пространство имен default:

kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default

6.1.4.8 - Рекомендуемые метки

Вы можете визуализировать и управлять объектами Kubernetes не только с помощью kubectl и панели управления. С помощью единого набора меток можно единообразно описывать объекты, что позволяет инструментам согласованно работать между собой.

В дополнение к существующим инструментам, рекомендуемый набор меток описывают приложения в том виде, в котором они могут быть получены.

Метаданные сосредоточены на понятии приложение. Kubernetes — это не платформа как услуга (PaaS), поэтому не закрепляет формальное понятие приложения. Вместо этого приложения являются неформальными и описываются через метаданные. Определение приложения довольно расплывчатое.

Общие метки и аннотации используют один и тот же префикс: app.kubernetes.io. Метки без префикса являются приватными для пользователей. Совместно используемый префикс гарантирует, что общие метки не будут влиять на пользовательские метки.

Метки

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

Ключ Описание Пример Тип
app.kubernetes.io/name Имя приложения mysql string
app.kubernetes.io/instance Уникальное имя экземпляра приложения wordpress-abcxzy string
app.kubernetes.io/version Текущая версия приложения (например, семантическая версия, хеш коммита и т.д.) 5.7.21 string
app.kubernetes.io/component Имя компонента в архитектуре database string
app.kubernetes.io/part-of Имя основного приложения, частью которого является текущий объект wordpress string
app.kubernetes.io/managed-by Инструмент управления приложением helm string

Для демонстрации этих меток, рассмотрим следующий объект StatefulSet:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
    app.kubernetes.io/managed-by: helm

Приложения и экземпляры приложений

Одно и то же приложение может быть установлено несколько раз в кластер Kubernetes, в ряде случаев — в одинаковое пространство имен. Например, WordPress может быть установлен более одного раза, тогда каждый из сайтов будет иметь собственный установленный экземпляр WordPress.

Имя приложения и имя экземпляра хранятся по отдельности. Например, WordPress имеет ключ app.kubernetes.io/name со значением wordpress, при этом у него есть имя экземпляра, представленное ключом app.kubernetes.io/instance со значением wordpress-abcxzy. Такой механизм позволяет идентифицировать как приложение, так и экземпляры приложения. У каждого экземпляра приложения должно быть уникальное имя.

Примеры

Следующие примеры показывают разные способы использования общих меток, поэтому они различаются по степени сложности.

Простой сервис без состояния

Допустим, у нас есть простой сервис без состояния, развернутый с помощью объектов Deployment и Service. Следующие два фрагмента конфигурации показывают, как можно использовать метки в самом простом варианте.

Объект Deployment используется для наблюдения за подами, на которых запущено приложение.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

Объект Service используется для открытия доступа к приложению.

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

Веб-приложение с базой данных

Рассмотрим случай немного посложнее: веб-приложение (WordPress), которое использует базу данных (MySQL), установленное с помощью Helm. В следующих фрагментов конфигурации объектов отображена отправная точка развертывания такого приложения.

Следующий объект Deployment используется для WordPress:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: wordpress
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "4.9.4"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: server
    app.kubernetes.io/part-of: wordpress
...

Объект Service используется для открытия доступа к WordPress:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: wordpress
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "4.9.4"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: server
    app.kubernetes.io/part-of: wordpress
...

MySQL открывается в виде StatefulSet с метаданными как для самого приложения, так и основного (родительского) приложения, к которому принадлежит СУБД:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: mysql-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
...

Объект Service предоставляет MySQL в составе WordPress:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: mysql-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
...

Вы заметите, что StatefulSet и Service MySQL содержат больше информации о MySQL и WordPress.

6.2 - Кластерная Архитектура

Архитектурные концепции, лежащие в основе Kubernetes.

6.2.1 - Узлы

Kubernetes запускает ваши приложения, помещая контейнеры в Поды для запуска на Узлах (Nodes). В зависимости от кластера, узел может быть виртуальной или физической машиной. Каждый узел содержит сервисы, необходимые для запуска Подов, управляемых control plane (управляющим слоем).

Обычно у вас есть несколько узлов в кластере; однако в среде обучения или среде с ограниченными ресурсами у вас может быть только один.

Компоненты на узле включают kubelet, среду выполнения контейнера и kube-proxy.

Управление

Существует два основных способа добавления Узлов в API сервер:

  1. Kubelet на узле саморегистрируется в управляющем слое
  2. Вы или другой пользователь вручную добавляете объект Узла

После того как вы создадите объект Узла или kubelet на узле самозарегистируется, управляющий слой проверяет, является ли новый объект Узла валидным (правильным). Например, если вы попробуете создать Узел при помощи следующего JSON манифеста:

{
  "kind": "Node",
  "apiVersion": "v1",
  "metadata": {
    "name": "10.240.79.157",
    "labels": {
      "name": "my-first-k8s-node"
    }
  }
}

Kubernetes создает внутри себя объект Узла (представление). Kubernetes проверяет, что kubelet зарегистрировался на API сервере, который совпадает со значением поля metadata.name Узла. Если узел здоров (если все необходимые сервисы запущены), он имеет право на запуск Пода. В противном случае этот узел игнорируется для любой активности кластера до тех пор, пока он не станет здоровым.

Имя объекта Узла должно быть валидным именем поддомена DNS.

Саморегистрация Узлов

Когда kubelet флаг --register-node имеет значение true (по умолчанию), то kubelet будет пытаться зарегистрировать себя на API сервере. Это наиболее предпочтительная модель, используемая большинством дистрибутивов.

Для саморегистрации kubelet запускается со следующими опциями:

  • --kubeconfig - Путь к учетным данным для аутентификации на API сервере.

  • --cloud-provider - Как общаться с облачным провайдером, чтобы прочитать метаданные о себе.

  • --register-node - Автоматически зарегистрироваться на API сервере.

  • --register-with-taints - Зарегистрировать узел с приведенным списком ограничений (taints) (разделенных запятыми <key>=<value>:<effect>).

    Ничего не делает, если register-node - false.

  • --node-ip - IP-адрес узла.

  • --node-labels - Метки для добавления при регистрации узла в кластере (смотрите ограничения для меток, установленные плагином согласования (admission plugin) NodeRestriction).

  • --node-status-update-frequency - Указывает, как часто kubelet отправляет статус узла мастеру.

Когда режим авторизации Узла и плагин согласования NodeRestriction включены, kubelet'ы имеют право только создавать/изменять свой собственный ресурс Узла.

Ручное администрирование узла

Вы можете создавать и изменять объекты узла используя kubectl.

Когда вы хотите создать объекты Узла вручную, установите kubelet флаг --register-node=false.

Вы можете изменять объекты Узла независимо от настройки --register-node. Например, вы можете установить метки на существующем Узле или пометить его не назначаемым.

Вы можете использовать метки на Узлах в сочетании с селекторами узла на Подах для управления планированием. Например, вы можете ограничить Под, иметь право на запуск только на группе доступных узлов.

Маркировка узла как не назначаемого предотвращает размещение планировщиком новых подов на этом Узле, но не влияет на существующие Поды на Узле. Это полезно в качестве подготовительного шага перед перезагрузкой узла или другим обслуживанием.

Чтобы отметить Узел не назначаемым, выполните:

kubectl cordon $NODENAME

Статус Узла

Статус узла содержит следующие данные:

Вы можете использовать kubectl для просмотра статуса Узла и других деталей:

kubectl describe node <insert-node-name-here>

Каждая секция из вывода команды описана ниже.

Адреса (Addresses)

Использование этих полей варьируется в зависимости от вашего облачного провайдера или конфигурации физических серверов (bare metal).

  • HostName: Имя хоста, сообщаемое ядром узла. Может быть переопределено через kubelet --hostname-override параметр.
  • ExternalIP: Обычно, IP адрес узла, который является внешне маршрутизируемым (доступен за пределами кластера).
  • InternalIP: Обычно, IP адрес узла, который маршрутизируется только внутри кластера.

Условия (Conditions)

Поле conditions описывает статус всех Running узлов. Примеры условий включают в себя:

Условия узла и описание того, когда применяется каждое условие.
Условие Узла Описание
Ready True если узел здоров и готов принять поды, False если узел нездоров и не принимает поды, и Unknown если контроллер узла не получал информацию от узла в течение последнего периода node-monitor-grace-period (по умолчанию 40 секунд)
DiskPressure True если присутствует давление на размер диска - то есть, если емкость диска мала; иначе False
MemoryPressure True если существует давление на память узла - то есть, если памяти на узле мало; иначе False
PIDPressure True если существует давление на процессы - то есть, если на узле слишком много процессов; иначе False
NetworkUnavailable True если сеть для узла настроена некорректно, иначе False

Состояние узла представлено в виде JSON объекта. Например, следующая структура описывает здоровый узел:

"conditions": [
  {
    "type": "Ready",
    "status": "True",
    "reason": "KubeletReady",
    "message": "kubelet is posting ready status",
    "lastHeartbeatTime": "2019-06-05T18:38:35Z",
    "lastTransitionTime": "2019-06-05T11:41:27Z"
  }
]

Если значение параметра Status для условия Ready остается Unknown или False дольше чем период pod-eviction-timeout(аргумент, переданный в kube-controller-manager), то все Поды на узле планируются к удалению контроллером узла. По умолчанию таймаут выселения пять минут. В некоторых случаях, когда узел недоступен, API сервер не может связаться с kubelet на узле. Решение об удалении подов не может быть передано в kubelet до тех пор, пока связь с API сервером не будет восстановлена. В то же время поды, которые запланированы к удалению, могут продолжать работать на отделенном узле.

Контроллер узла не будет принудительно удалять поды до тех пор, пока не будет подтверждено, что они перестали работать в кластере. Вы можете видеть, что поды, которые могут работать на недоступном узле, находятся в состоянии Terminating или Unknown. В тех случаях, когда Kubernetes не может сделать вывод из основной инфраструктуры о том, что узел окончательно покинул кластер, администратору кластера может потребоваться удалить объект узла вручную. Удаление объекта узла из Kubernetes приводит к удалению всех объектов Подов, запущенных на узле, с API сервера и освобождает их имена.

Контроллер жизненного цикла узла автоматически создает ограничения (taints), которые представляют собой условия. Планировщик учитывает ограничения Узла при назначении Пода на Узел. Поды так же могут иметь допуски (tolerations), что позволяет им сопротивляться ограничениям Узла.

Смотрите раздел Ограничить Узлы по Условию для дополнительной информации.

Емкость и Выделяемые ресурсы (Capacity and Allocatable)

Описывает ресурсы, доступные на узле: CPU, память и максимальное количество подов, которые могут быть запланированы на узле.

Поля в блоке capacity указывают общее количество ресурсов, которые есть на Узле. Блок allocatable указывает количество ресурсов на Узле, которые доступны для использования обычными Подами.

Вы можете прочитать больше о емкости и выделяемых ресурсах, изучая, как зарезервировать вычислительные ресурсы на Узле.

Информация (Info)

Описывает общую информацию об узле, такую как версия ядра, версия Kubernetes (версии kubelet и kube-proxy), версия Docker (если используется) и название ОС. Эта информация собирается Kubelet'ом на узле.

Контроллер узла

Контроллер узла является компонентом управляющего слоя Kubernetes, который управляет различными аспектами узлов.

Контроллер узла играет различные роли в жизни узла. Первая - назначение CIDR-блока узлу при его регистрации (если включено назначение CIDR).

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

Третья - это мониторинг работоспособности узлов. Контроллер узла отвечает за обновление условия NodeReady для NodeStatus на ConditionUnknown, когда узел становится недоступным (т.е. контроллер узла по какой-то причине перестает получать сердцебиения (heartbeats) от узла, например, из-за того, что узел упал), и затем позже выселяет все поды с узла (используя мягкое (graceful) завершение) если узел продолжает быть недоступным. (По умолчанию таймауты составляют 40 секунд, чтобы начать сообщать ConditionUnknown, и 5 минут после, чтобы начать выселять поды.)

Контроллер узла проверяет состояние каждого узла каждые --node-monitor-period секунд.

Сердцебиения

Сердцебиения, посылаемые узлами Kubernetes, помогают определить доступность узла.

Существует две формы сердцебиений: обновление NodeStatus и Lease объект. Каждый узел имеет связанный с ним Lease объект в kube-node-lease namespace. Lease - это легковесный ресурс, который улучшает производительность сердцебиений узла при масштабировании кластера.

Kubelet отвечает за создание и обновление NodeStatus и Lease объекта.

  • Kubelet обновляет NodeStatus либо когда происходит изменение статуса, либо если в течение настроенного интервала обновления не было. По умолчанию интервал для обновлений NodeStatus составляет 5 минут (намного больше, чем 40-секундный стандартный таймаут для недоступных узлов).
  • Kubelet создает и затем обновляет свой Lease объект каждый 10 секунд (интервал обновления по умолчанию). Lease обновления происходят независимо от NodeStatus обновлений. Если обновление Lease завершается неудачно, kubelet повторяет попытку с экспоненциальным откатом, начинающимся с 200 миллисекунд и ограниченным 7 секундами.

Надежность

В большинстве случаев контроллер узла ограничивает скорость выселения до --node-eviction-rate (по умолчанию 0,1) в секунду, что означает, что он не выселяет поды с узлов быстрее чем с одного узла в 10 секунд.

Поведение выселения узла изменяется, когда узел в текущей зоне доступности становится нездоровым. Контроллер узла проверяет, какой процент узлов в зоне нездоров (NodeReady условие в значении ConditionUnknown или ConditiononFalse) в одно и то же время. Если доля нездоровых узлов не меньше --unhealthy-zone-threshold (по умолчанию 0.55), то скорость выселения уменьшается: если кластер небольшой (т.е. количество узлов меньше или равно --large-cluster-size-threshold - по умолчанию, 50), то выселения прекращаются, в противном случае скорость выселения снижается до --secondary-node-eviction-rate (по умолчанию, 0.01) в секунду.

Причина, по которой эти политики реализуются для каждой зоны доступности, заключается в том, что одна зона доступности может стать отделенной от мастера, в то время как другие остаются подключенными. Если ваш кластер не охватывает несколько зон доступности облачного провайдера, то существует только одна зона доступности (весь кластер).

Основная причина разнесения ваших узлов по зонам доступности заключается в том, что приложения могут быть перенесены в здоровые зоны, когда одна из зон полностью становится недоступной. Поэтому, если все узлы в зоне нездоровы, то контроллер узла выселяет поды с нормальной скоростью --node-eviction-rate. Крайний случай - когда все зоны полностью нездоровы (т.е. в кластере нет здоровых узлов). В таком случае контроллер узла предполагает, что существует некоторая проблема с подключением к мастеру, и останавливает все выселения, пока какое-нибудь подключение не будет восстановлено.

Контроллер узла также отвечает за выселение подов, запущенных на узлах с NoExecute ограничениями, за исключением тех подов, которые сопротивляются этим ограничениям. Контроллер узла так же добавляет ограничения соответствующие проблемам узла, таким как узел недоступен или не готов. Это означает, что планировщик не будет размещать поды на нездоровых узлах.

Емкость узла

Объекты узла отслеживают информацию о емкости ресурсов узла (например, объем доступной памяти и количество CPU). Узлы, которые самостоятельно зарегистрировались, сообщают о своей емкости во время регистрации. Если вы вручную добавляете узел, то вам нужно задать информацию о емкости узла при его добавлении.

Планировщик Kubernetes гарантирует, что для всех Подов на Узле достаточно ресурсов. Планировщик проверяет, что сумма requests от контейнеров на узле не превышает емкость узла. Эта сумма requests включает все контейнеры, управляемые kubelet, но исключает любые контейнеры, запущенные непосредственно средой выполнения контейнера, а также исключает любые процессы, запущенные вне контроля kubelet.

Топология узла

СТАТУС ФИЧИ: Kubernetes v1.16 [alpha]

Если вы включили TopologyManager feature gate, то kubelet может использовать подсказки топологии при принятии решений о выделении ресурсов. Смотрите Контроль Политик Управления Топологией на Узле для дополнительной информации.

Что дальше

6.2.2 - Связь между управляющим слоем и узлом

Этот документ описывает связь между API-сервером и кластером Kubernetes. Цель состоит в том, чтобы позволить пользователям настраивать свою установку для усиления сетевой конфигурации, чтобы кластер мог работать в ненадежной сети (или на полностью общедоступных IP-адресах облачного провайдера).

От узла к управляющему слою

В Kubernetes имеется API шаблон «ступица и спица» (hub-and-spoke). Все используемые API из узлов (или которые запускают pod-ы) завершает apiserver. Ни один из других компонентов управляющего слоя не предназначен для предоставления удаленных сервисов. Apiserver настроен на прослушивание удаленных подключений через безопасный порт HTTPS (обычно 443) с одной или несколькими включенными формами аутентификации клиента.

Должна быть включена одна или несколько форм авторизации, особенно, если разрешены анонимные запросы или ServiceAccount токены.

Узлы должны быть снабжены публичным корневым сертификатом для кластера, чтобы они могли безопасно подключаться к apiserver-у вместе с действительными учетными данными клиента. Хороший подход заключается в том, чтобы учетные данные клиента, предоставляемые kubelet-у, имели форму клиентского сертификата. См. Информацию о загрузке kubelet TLS bootstrapping для автоматической подготовки клиентских сертификатов kubelet.

Pod-ы, которые хотят подключиться к apiserver, могут сделать это безопасно, используя ServiceAccount, чтобы Kubernetes автоматически вводил общедоступный корневой сертификат и действительный токен-носитель в pod при его создании. Служба kubernetes (в пространстве имен default) настроена с виртуальным IP-адресом, который перенаправляет (через kube-proxy) на HTTPS эндпоинт apiserver-а.

Компоненты уровня управления также взаимодействуют с кластером apiserver-а через защищенный порт.

В результате режим работы по умолчанию для соединений от узлов и модулей, работающих на узлах, к управляющему слою по умолчанию защищен и может работать в ненадежных и/или общедоступных сетях.

От управляющего слоя к узлу

Существуют два пути связи управляющего слоя (API-сервера) с узлами. Первый - от apiserver-а до kubelet процесса, который выполняется на каждом узле кластера. Второй - от apiserver к любому узлу, pod-у или службе через промежуточную функциональность apiserver-а.

apiserver в kubelet

Соединение из apiserver-а к kubelet используются для:

  • Извлечения логов с pod-ов.
  • Прикрепление (через kubectl) к запущенным pod-ам.
  • Обеспечение функциональности переадресации портов kubelet.

Эти соединения завершаются на HTTPS эндпоинте kubelet-a. По умолчанию apiserver не проверяет сертификат обслуживания kubelet-ов, что делает соединение подверженным к атаке «человек посередине» (man-in-the-middle) и небезопасным к запуску в ненадежных и/или общедоступных сетях.

Для проверки этого соединения используется флаг --kubelet-certificate-authority чтобы предоставить apiserver-у набор корневых (root) сертификатов для проверки сертификата обслуживания kubelet-ов.

Если это не возможно, используйте SSH-тунелирование между apiserver-ом и kubelet, если это необходимо, чтобы избежать подключения по ненадежной или общедоступной сети.

Наконец, должны быть включены аутентификация или авторизация kubelet для защиты kubelet API.

apiserver для узлов, pod-ов, и служб

Соединения с apiserver к узлу, поду или сервису по умолчанию осуществляются по-обычному HTTP-соединению и поэтому не аутентифицируются, и не шифруются. Они могут быть запущены по защищенному HTTPS-соединению, после добавления префикса https: к имени узла, пода или сервиса в URL-адресе API, но они не будут проверять сертификат предоставленный HTTPS эндпоинтом, как и не будут предоставлять учетные данные клиента. Таким образом, хотя соединение будет зашифровано, оно не обеспечит никаких гарантий целостности. Эти соединения в настоящее время небезопасны для запуска в ненадежных или общедоступных сетях.

SSH-туннели

Kubernetes поддерживает SSH-туннели для защиты путей связи от управляющего слоя к узлам. В этой конфигурации apiserver инициирует SSH-туннель для каждого узла в кластере (подключается к ssh-серверу, прослушивая порт 22) и передает весь трафик предназначенный для kubelet, узлу, pod-у или службе через туннель. Этот туннель гарантирует, что трафик не выводится за пределы сети, в которой работает узел.

SSH-туннели в настоящее время устарели, поэтому вы не должны использовать их, если не знаете, что делаете. Служба подключения является заменой этого канала связи.

Служба подключения

СТАТУС ФИЧИ: Kubernetes v1.18 [beta]

В качестве замены SSH-туннелям, служба подключения обеспечивает прокси TCP-уровня для взаимодействия управляющего слоя с кластером. Служба подключения состоит из двух частей: сервер подключения к сети управляющего слоя и агентов подключения в сети узлов. Агенты службы подключения инициируют подключения к серверу подключения и поддерживают сетевое подключение. После включения службы подключения, весь трафик с управляющего слоя на узлы проходит через эти соединения.

Следуйте инструкциям Задача службы подключения, чтобы настроить службу подключения в кластере.

6.2.3 - Контроллеры

В робототехнике и автоматизации, цикл управления - это непрерывный цикл, который регулирует состояние системы.

Вот один из примеров контура управления: термостат в помещении.

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

Контроллеры в Kubernetes - управляющие циклы, которые отслеживают состояние вашего кластера, затем вносят или запрашивают изменения там, где это необходимо. Каждый контроллер пытается привести текущее состояние кластера ближе к желаемому состоянию.

Шаблон контроллера

Контроллер отслеживает по крайней мере один тип ресурса Kubernetes. Эти объекты имеют поле спецификации, которое представляет желаемое состояние. Контроллер (ы) для этого ресурса несут ответственность за приближение текущего состояния к желаемому состоянию

Контроллер может выполнить это действие сам; чаще всего в Kubernetes, контроллер отправляет сообщения на сервер API которые имеют полезные побочные эффекты. Пример этого вы можете увидеть ниже.

Управление с помощью сервера API

Контроллер Job является примером встроенного контроллера Kubernetes. Встроенные контроллеры управляют состоянием, взаимодействуя с кластером сервера API.

Задание - это ресурс Kubernetes, который запускает Pod, или возможно несколько Pod-ов, выполняющих задачу и затем останавливающихся.

(После планирования, Pod объекты становятся частью желаемого состояния для kubelet).

Когда контроллер задания видит новую задачу, он убеждается что где-то в вашем кластере kubelet-ы на множестве узлов запускают нужное количество Pod-ов для выполнения работы. Контроллер задания сам по себе не запускает никакие Pod-ы или контейнеры. Вместо этого контроллер задания сообщает серверу API о создании или удалении Pod-ов. Другие компоненты в управляющем слое действуют на основе информации (имеются ли новые запланированные Pod-ы для запуска), и в итоге работа завершается.

После того как вы создадите новое задание, желаемое состояние для этого задания будет завершено. Контроллер задания приближает текущее состояние этой задачи к желаемому состоянию: создает Pod-ы, выполняющие работу, которую вы хотели для этой задачи, чтобы задание было ближе к завершению.

Контроллеры также обновляют объекты которые их настраивают. Например: как только работа выполнена для задания, контроллер задания обновляет этот объект задание, чтобы пометить его как Завершенный.

(Это немного похоже на то, как некоторые термостаты выключают свет, чтобы указать, что теперь ваша комната имеет установленную вами температуру).

Прямое управление

В отличие от Задания, некоторым контроллерам нужно вносить изменения в вещи за пределами вашего кластера.

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

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

(На самом деле существует контроллер, который горизонтально масштабирует узлы в вашем кластере.)

Важным моментом здесь является то, что контроллер вносит некоторые изменения, чтобы вызвать желаемое состояние, а затем сообщает текущее состояние обратно на сервер API вашего кластера. Другие контуры управления могут наблюдать за этими отчетными данными и предпринимать собственные действия.

В примере с термостатом, если в помещении очень холодно, тогда другой контроллер может также включить обогреватель для защиты от замерзания. В кластерах Kubernetes управляющий слой косвенно работает с инструментами управления IP-адресами, службами хранения данных, API облачных провайдеров и другими службами для реализации расширения Kubernetes.

Желаемое против текущего состояния

Kubernetes использует систему вида cloud-native и способен справляться с постоянными изменениями.

Ваш кластер может изменяться в любой по мере выполнения работы и контуры управления автоматически устраняют сбой. Это означает, что потенциально Ваш кластер никогда не достигнет стабильного состояния.

Пока контроллеры вашего кластера работают и могут вносить полезные изменения, не имеет значения, является ли общее состояние стабильным или нет.

Дизайн

В качестве принципа своей конструкции Kubernetes использует множество контроллеров, каждый из которых управляет определенным аспектом состояния кластера. Чаще всего конкретный контур управления (контроллер) использует один вид ресурса в качестве своего желаемого состояния и имеет другой вид ресурса, которым он управляет, чтобы это случилось. Например, контроллер для заданий отслеживает объекты заданий (для обнаружения новой работы) и объекты модулей (для выполнения заданий, а затем для того, чтобы видеть, когда работа завершена). В этом случае что-то еще создает задания, тогда как контроллер заданий создает Pod-ы.

Полезно иметь простые контроллеры, а не один монолитный набор взаимосвязанных контуров управления. Контроллеры могут выйти из строя, поэтому Kubernetes предназначен для этого.

Способы запуска контроллеров

Kubernetes поставляется с набором встроенных контроллеров, которые работают внутри kube-controller-manager. Эти встроенные контроллеры обеспечивают важные основные функции.

Контроллер развертывания и контроллер заданий - это примеры контроллеров, которые входят в состав самого Kubernetes («встроенные» контроллеры). Kubernetes позволяет вам запускать устойчивый управляющий слой (control plane), так что в случае отказа одного из встроенных контроллеров работу берет на себя другая часть управляющего слоя.

Вы можете найти контроллеры, которые работают вне управляющего слоя, чтобы расширить Kubernetes. Или, если вы хотите, можете написать новый контроллер самостоятельно. Вы можете запустить свой собственный контроллер в виде наборов Pod-ов, или внешнее в Kubernetes. Что подойдет лучше всего, будет зависеть от того, что делает этот конкретный контроллер.

Что дальше

6.2.4 - Диспетчер облачных контроллеров

СТАТУС ФИЧИ: Kubernetes v1.11 [beta]

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

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

Отделяя логику взаимодействия между Kubernetes и базовой облачной инфраструктурой, компонент cloud-controller-manager позволяет поставщикам облачных услуг выпускать функции в другом темпе по сравнению с основным проектом Kubernetes.

Диспетчер облачных контроллеров спроектирован с использованием механизма плагинов, которые позволяют различным облачным провайдерам интегрировать свои платформы с Kubernetes.

Дизайн

Kubernetes components

Диспетчер облачных контроллеров работает в управляющем слое (control plane) как реплицированный набор процессов (обычно это контейнер в Pod-ах). Каждый диспетчер облачных контроллеров реализует множество контроллеров в единственном процессе.

Функции диспетчера облачных контроллеров

Контроллеры внутри диспетчера облачных контроллеров включают в себя:

Контроллер узла

Контроллер узла отвечает за создание объектов узла при создании новых серверов в вашей облачной инфраструктуре. Контроллер узла получает информацию о работающих хостах внутри вашей арендуемой инфраструктуры облачного провайдера. Контроллер узла выполняет следующие функции:

  1. Инициализация объектов узла для каждого сервера, которые контроллер получает через API облачного провайдера.
  2. Аннотирование и маркировка объектов узла специфичной для облака информацией, такой как регион узла и доступные ему ресурсы (процессор, память и т.д.).
  3. Получение имени хоста и сетевых адресов.
  4. Проверка работоспособности узла. В случае, если узел перестает отвечать на запросы, этот контроллер проверяет с помощью API вашего облачного провайдера, был ли сервер деактивирован / удален / прекращен. Если узел был удален из облака, контроллер удаляет объект узла из вашего Kubernetes кластера.

Некоторые облачные провайдеры реализуют его разделение на контроллер узла и отдельный контроллер жизненного цикла узла.

Контроллер маршрута

Контроллер маршрута отвечает за соответствующую настройку маршрутов в облаке, чтобы контейнеры на разных узлах кластера Kubernetes могли взаимодействовать друг с другом.

В зависимости от облачного провайдера, контроллер маршрута способен также выделять блоки IP-адресов для сети Pod-ов.

Контроллер сервисов

Сервисы интегрируются с компонентами облачной инфраструктуры, такими как управляемые балансировщики нагрузки, IP-адреса, фильтрация сетевых пакетов и проверка работоспособности целевых объектов. Контроллер сервисов взаимодействует с API вашего облачного провайдера для настройки требуемых балансировщиков нагрузки и других компонентов инфраструктуры, когда вы объявляете ресурсы сервисов.

Авторизация

В этом разделе разбирается доступ к различным объектам API, который нужен облачным контроллерам для выполнения своих операций.

Контроллер узла

Контроллер узла работает только с объектом узла. Он требует полного доступа на чтение и изменение объектов узла.

v1/Node:

  • Get
  • List
  • Create
  • Update
  • Patch
  • Watch
  • Delete

Контроллер маршрута

Контроллер маршрута прослушивает создание объектов узла и соответствующим образом настраивает маршруты. Для этого требуется получить доступ к объектам узла.

v1/Node:

  • Get

Контроллер сервисов

Контроллер сервисов прослушивает события Create, Update и Delete объектов служб, а затем соответствующим образом настраивает конечные точки для соответствующих сервисов.

Для доступа к сервисам требуется доступ к событиям List и Watch. Для обновления сервисов требуется доступ к событиям Patch и Update.

Чтобы настроить ресурсы конечных точек для сервисов, требуется доступ к событиям Create, List, Get, Watch и Update.

v1/Service:

  • List
  • Get
  • Watch
  • Patch
  • Update

Другие

Реализация ядра диспетчера облачных контроллеров требует доступ для создания объектов событий, а для обеспечения безопасной работы требуется доступ к созданию сервисных учетных записей (ServiceAccounts).

v1/Event:

  • Create
  • Patch
  • Update

v1/ServiceAccount:

  • Create

RBAC ClusterRole для диспетчера облачных контроллеров выглядит так:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cloud-controller-manager
rules:
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - '*'
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - list
  - patch
  - update
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - persistentvolumes
  verbs:
  - get
  - list
  - update
  - watch
- apiGroups:
  - ""
  resources:
  - endpoints
  verbs:
  - create
  - get
  - list
  - watch
  - update

Что дальше

Администрирование диспетчера облачных контроллеров содержит инструкции по запуску и управлению диспетчером облачных контроллеров.

Хотите знать, как реализовать свой собственный диспетчер облачных контроллеров или расширить проект?

Диспетчер облачных контроллеров использует интерфейсы Go, которые позволяют реализовать подключение из любого облака. В частности, он использует интерфейс CloudProvider, который определен в cloud.go из kubernetes/cloud-provider.

Реализация общих контроллеров, описанных в этом документе (Node, Route, и Service), а также некоторые другие вспомогательные конструкции, вместе с общим интерфейсом облачного провайдера являются частью ядра Kubernetes. Особые реализации для облачных провайдеров находятся вне ядра Kubernetes и реализуют интерфейс CloudProvider.

Дополнительные сведения о разработке плагинов см. в разделе Разработка диспетчера облачных контроллеров.

6.2.5 - Container Runtime Interface (CRI)

Интерфейс CRI позволяет kubelet работать с различными исполняемыми средами контейнеров без необходимости перекомпиляции компонентов кластера.

Исполняемая среда контейнеров должна работать на всех узлах кластера, чтобы kubelet мог запускать Pod'ы и их контейнеры.

Интерфейс Kubernetes Container Runtime Interface (CRI) container Runtime Interface (CRI) — это основной протокол для связи между kubelet'ом и исполняемой средой контейнеров.

Интерфейс Kubernetes Container Runtime Interface (CRI) задает основной gRPC-протокол, на базе которого осуществляется коммуникация между компонентами кластера: kubelet'ом и исполняемой средой.

API

СТАТУС ФИЧИ: Kubernetes v1.23 [stable]

Kubelet выступает в роли клиента при подключении к исполняемой среде через gRPC. Конечные точки ImageService и RuntimeService должны быть доступны в исполняемой среде контейнеров; в kubelet их можно настроить независимо с помощью флагов командной строки --image-service-endpoint и --container-runtime-endpoint.

В Kubernetes v1.31 kubelet предпочитает использовать CRI v1. Если исполняемая среда контейнера не поддерживает v1 CRI, kubelet пытается перейти на более старую поддерживаемую версию. В версии v1.31 kubelet также может работать с CRI v1alpha2, но эта версия считается устаревшей. Если согласовать поддерживаемую версию CRI не удается, узел не регистрируется.

Обновление

При обновлении Kubernetes kubelet автоматически выбирает последнюю версию CRI при перезапуске компонента. Если это не удается, происходит откат, как описано выше. Если повторный вызов gRPC произошел из-за обновления исполняемой среды контейнера, последняя также должна поддерживать первоначально выбранную версию, иначе повторный вызов будет неудачным. Для этого требуется перезапуск kubelet'а.

Что дальше

6.2.6 - Сборщик мусора

Сборщик мусора - это собирательный термин для различных механизмов? используемых Kubernetes для очистки ресурсов кластера. Это позволить очистить ресурсы, такие как:

Владельцы и зависимости

Многие объекты в Kubernetes ссылаются друг на друга через ссылки владельцев. Ссылки владельцев сообщают управляющему слою, какие объекты зависят от других. Kubernetes использует ссылки владельцев, чтобы предоставить управляющему слою и другим API клиентам, возможность очистить связанные ресурсы перед удалением объекта. В большинстве случаев, Kubernetes автоматически управляет ссылками владельцев.

Владелец отличается от меток и селекторов которые также используют некоторые ресурсы. Например, рассмотрим Службу которая создает объект EndpointSlice. Служба использует метки чтобы позволить управляющему слою определить, какие EndpointSlice объекты используются для этой службы. В дополнение к меткам, каждый EndpointSlice управляет ои имени службы, имеет ссылку владельца. Ссылки владельцев помогают различным частям Kubernetes избегать вмешательства в объекты, которые они не контролируют.

Каскадное удаление

Kubernetes проверяет и удаляет объекты, на которые больше нет ссылок владельцев, так же как и pod-ов, оставленных после удаления ReplicaSet. Когда Вы удаляете объект, вы можете контролировать автоматический ли Kubernetes удаляет зависимые объекты автоматически в процессе вызова каскадного удаления. Существует два типа каскадного удаления, а именно:

  • Каскадное удаление Foreground
  • Каскадное удаление Background

Вы так же можете управлять как и когда сборщик мусора удаляет ресурсы, на которые ссылаются владельцы с помощью Kubernetes finalizers.

Каскадное удаление Foreground

В Каскадном удалении Foreground, объект владельца, который вы удаляете, сначала переходить в состояние в процессе удаления. В этом состоянии с объектом-владельцем происходить следующее:

  • Сервер Kubernetes API устанавливает полю объекта metadata.deletionTimestamp время, когда объект был помечен для удаления.
  • Сервер Kubernetes API так же устанавливает метку metadata.finalizersдля поля foregroundDeletion.
  • Объект остается видимым благодаря Kubernetes API пока процесс удаления не завершиться

После того как владелец объекта переходит в состояние прогресса удаления, контроллер удаляет зависимые объекты. После удаления всех зависимых объектов, контроллер удаляет объект владельца. На этом этапе, объект больше не отображается в Kubernetes API.

Во время каскадного удаления foreground, единственным зависимым, которые блокируют удаления владельца, являются те, у кого имеется поле ownerReference.blockOwnerDeletion=true. Чтобы узнать больше. Смотрите Использование каскадного удаления foreground.

Каскадное удаление Background

В каскадном удалении background, сервер Kubernetes API немедленно удаляет владельца объекта, а контроллер очищает зависимые объекты в фоновом режиме. По умолчанию, Kubernetes использует каскадное удаление background, если вы в ручную не используете удаление foreground или не решите отключить зависимые объекты.

Чтобы узнать больше. Смотрите Использование каскадного удаления background.

Осиротевшие зависимости

Когда Kubernetes удаляет владельца объекта, оставшиеся зависимости называются осиротевшими объектами. По умолчанию, Kubernetes удаляет зависимые объекты. Чтобы узнать, как переопределить это поведение смотрите Удаление объектов владельца и осиротевших зависимостей.

Сбор мусора из неиспользуемых контейнеров и образов

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

Чтобы настроить параметры для сборщика мусора для неиспользуемого контейнера и сборки мусора образа, подстройте kubelet использую конфигурационный файл и измените параметры, связанные со сборщиком мусора используя тип ресурса KubeletConfiguration.

Жизненный цикл контейнерных образов Container image lifecycle

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

  • HighThresholdPercent
  • LowThresholdPercent

Использование диска выше настроенного значения HighThresholdPercent запускает сборку мусора, которая удаляет образы в порядке основанном на последнем использовании, начиная с самого старого. Kubelet удаляет образы до тех пор, пока использование диска не достигнет значения LowThresholdPercent.

Сборщик мусора контейнерных образов

Kubelet собирает не используемые контейнеры на основе следующих переменных, которые вы можете определить:

  • MinAge: минимальный возраст, при котором kubelet может начать собирать мусор контейнеров. Отключить, установив значение 0.
  • MaxPerPodContainer: максимальное количество неактивных контейнеров, которое может быть у каждой пары Pod-ов. Отключить, установив значение меньше чем 0.
  • MaxContainers: максимальное количество не используемых контейнеров, которые могут быть в кластере. Отключить, установив значение меньше чем 0.

В дополнение к этим переменным, kubelet собирает неопознанные и удаленные контейнеры, обычно начиная с самого старого.

MaxPerPodContainer и MaxContainer могут потенциально конфликтовать друг с другом в ситуациях, когда требуется максимальное количество контейнеров в Pod-е (MaxPerPodContainer) выйдет за пределы допустимого общего количества глобальных не используемых контейнеров (MaxContainers). В этой ситуации kubelet регулирует MaxPodPerContainer для устранения конфликта. Наихудшим сценарием было бы понизить MaxPerPodContainer да 1 и изгнать самые старые контейнеры. Кроме того, владельцы контейнеров в pod-е могут быть удалены, как только они становятся старше чем MinAge.

Настройка сборщик мусора

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

Что дальше

6.3 - Контейнеры

Технология упаковки приложения вместе с его runtime-зависимостями.

Каждый запускаемый контейнер воспроизводим; стандартизация благодаря включению зависимостей позволяет каждый раз получать одинаковое поведение при запуске.

Контейнеры абстрагируют приложения от базовой инфраструктуры хоста, упрощая развертывание в различных облачных средах или ОС.

Образы контейнеров

Образ контейнера – это готовый к запуску пакет программного обеспечения, содержащий все необходимое для запуска приложения: код, среду исполнения, прикладные и системные библиотеки, а также значения по умолчанию всех важных параметров.

Контейнер по определению неизменяем (immutable): код работающего контейнера невозможно поменять. Чтобы внести правки в контейнеризованное приложение, необходимо собрать новый образ, содержащий эти правки, а затем запустить контейнер на базе обновленного образа.

Исполняемые среды контейнеров

Иcполняемая среда контейнера — это программа, предназначенная для запуска контейнера в Kubernetes.

Kubernetes поддерживает различные среды для запуска контейнеров: Docker, containerd, CRI-O, и любые реализации Kubernetes CRI (Container Runtime Interface).

Что дальше

6.3.1 - Образы

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

Как правило, образ контейнера с приложением предварительно собирается и размещается в реестре, после чего его можно использовать в Pod'е.

На этой странице представлено общее описание концепции контейнерных образов.

Названия образов

Образам контейнеров обычно присваивается имя, намекающее на их функционал и цели, например, pause, example/mycontainer или kube-apiserver. Образы также могут включать имя хоста реестра, например, fictional.registry.example/imagename, и (в некоторых случаях) номер порта, например, fictional.registry.example:10443/imagename.

Если имя хоста реестра не указано, Kubernetes по умолчанию будет использовать публичный реестр Docker.

После имени образа можно добавить тег (как, например, в командах docker и podman). Теги помогают идентифицировать различные версии одной и той же линейки образов.

Теги образов могут состоять из строчных и прописных букв, цифр, знаков подчеркивания (_), точек (.) и дефисов (-). Кроме того, существуют дополнительные правила размещения символов-разделителей (_, - и .) внутри тега. Если тег не указан, Kubernetes по умолчанию использует тег latest.

Обновление образов

При первоначальном создании объекта типа Deployment, StatefulSet, Pod или другого объекта, включающего шаблон Pod'а, политика извлечения всех контейнеров в этом Pod'е будет по умолчанию установлена на IfNotPresent, если иное не указано явно. В рамках этой политики kubelet не извлекает образ, если тот уже присутствует в кэше.

Политика извлечения образов

Политика imagePullPolicy контейнера и тег образа определяют поведение kubelet'а при извлечении (загрузке) данного образа.

Вот список возможных значений imagePullPolicy и их влияние:

IfNotPresent
образ извлекается только в том случае, если он еще не доступен локально.
Always
каждый раз при запуске контейнера kubelet запрашивает дайджест образа в реестре образов контейнеров. Если полученный дайджест полностью совпадает с дайджестом кэшированного образа, kubelet использует кэшированный образ; иначе извлекается и используется образ с полученным дайждестом.
Never
kubelet не пытается скачать образ. Если образ уже присутствует локально, kubelet пытается запустить контейнер; в противном случае запуск завершается неудачей. Для получения более подробной информации обратитесь к разделу о предварительно извлеченных (pre-pulled) образах.

Благодаря семантике кэширования, лежащей в основе механизма поставки образов, даже imagePullPolicy: Always может быть вполне эффективной (при условии, что реестр надежно доступен). Исполняемая среда для контейнера может обнаружить, что слои образов уже имеются на узле и их не нужно скачивать еще раз.

Чтобы убедиться, что Pod всегда использует одну и ту же версию образа контейнера, можно указать дайджест образа вместо тега; для этого замените <image-name>:<tag> на <image-name>@<digest> (например, image@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2).

Изменение кода, к которому привязан некий тег, может привести к тому, что в Pod'ах окажется две версии кода — старая и новая. Дайджест образа однозначно идентифицирует конкретную версию образа, что гарантирует идентичность кода при запуске контейнера с заданным именем образа и дайджестом. Таким образом, изменение кода в реестре уже не может привести к смешению версий.

Существуют сторонние admission-контроллеры, которые модифицируют Pod'ы (и их шаблоны) при создании, из-за чего рабочая нагрузка определяется на основе дайджеста образа, а не тега. Это может быть полезно в случаях, когда необходимо убедиться, что вся рабочая нагрузка использует идентичный код независимо от изменений тегов в реестре.

Политика извлечения образов по умолчанию

Когда информация о новом Pod'е поступает на сервер API, кластер устанавливает поле imagePullPolicy в соответствии со следующими условиями:

  • imagePullPolicy автоматически присваивается значение Always, если поле imagePullPolicy не задано, а тег для образа контейнера имеет значение :latest;
  • imagePullPolicy автоматически присваивается значение Always, если поле imagePullPolicy не задано, а тег для образа контейнера не указан;
  • imagePullPolicy автоматически присваивается значение IfNotPresent, если поле imagePullPolicy не задано, а тег для образа контейнера имеет значение, отличное от :latest.

Обязательное извлечение образов

Для принудительного извлечения образов можно сделать следующее:

  • Установить imagePullPolicy контейнера в Always;
  • Не устанавливать imagePullPolicy и использовать тег :latest для образа; Kubernetes автоматически поменяет политику на Always, получив информацию о Pod'е;
  • Не устанавливать imagePullPolicy и тег образа; Kubernetes автоматически применит политику Always, получив информацию о Pod'е;
  • Включить admission-контроллер AlwaysPullImages.

ImagePullBackOff

При создании kubelet'ом контейнеров для Pod'а может возникнуть ситуация, когда контейнер пребывает в состоянии Waiting из-за ImagePullBackOff.

Статус ImagePullBackOff означает, что контейнер не может запуститься, поскольку у Kubernetes не получается извлечь его образ (например, из-за ошибки в имени или попытки извлечь образ из приватного репозитория без imagePullSecret). BackOff в названии статуса указывает на то, что Kubernetes будет продолжать попытки извлечь образ, постепенно увеличивая интервал между ними.

Так, интервал между попытками будет расти до тех пор, пока не достигнет установленного предела в 300 секунд (5 минут).

Мультиархитектурные образы с индексами

Помимо обычных исполняемых образов реестр контейнеров также может хранить так называемые индексы образов. Индекс образа содержит ссылки на различные манифесты образов, каждый из которых предназначен для определенной архитектуры. Идея здесь в том, чтобы любой пользователь мог получить образ, оптимизированный под конкретную архитектуру, используя его унифицированное, общее для всех архитектур имя (например, pause, example/mycontainer, kube-apiserver).

Сам Kubernetes обычно добавляет суффикс -$(ARCH) к имени образа. Для обратной совместимости также рекомендуется генерировать образы с суффиксами в названиях. Например, универсальный образ pause, содержащий манифест для всех архитектур, рекомендуется дополнить образом pause-amd64 для обратной совместимости со старыми конфигурациями или YAML-файлами, в которых могут быть жестко прописаны образы с суффиксами.

Работа с приватным реестром

Для чтения образов из приватных реестров могут потребоваться соответствующие ключи. Доступ к таким реестрам можно получить следующими способами:

  • Аутентификация на уровне узлов:
    • все Pod'ы имеют доступ ко всем настроенным приватным реестрам;
    • требуется конфигурация узлов администратором кластера;
  • Предварительно извлеченные образы:
    • все Pod'ы могут использовать любые образы, кэшированные на узле;
    • для настройки требуется root-доступ ко всем узлам;
  • imagePullSecrets на уровне Pod'а:
    • доступ к реестру получают только Pod'ы с ключами;
  • Специализированные расширения от вендора/пользователя:
    • в кастомных конфигурациях могут существовать специализированные механизмы аутентификации узлов в реестре контейнеров, реализованные самим пользователем или поставщиком облачных услуг.

Ниже мы подробнее остановимся на каждом из вариантов.

Аутентификация на уровне узлов

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

Пример настройки частного реестра образов контейнеров приводится в упражнении Извлекаем образ из частного реестра. В нем используется частный реестр в Docker Hub.

Интерпретация config.json

Интерпретация config.json отличается в оригинальной Docker-реализации и в Kubernetes. В Docker ключи auths могут указывать только корневые URL, в то время как Kubernetes позволяет использовать URL с подстановками (globbing) и пути с префиксами. То есть config.json, подобный этому, вполне допустим:

{
    "auths": {
        "*my-registry.io/images": {
            "auth": "…"
        }
    }
}

Корневой URL (*my-registry.io) сопоставляется с помощью следующего синтаксиса:

pattern:
    { term }

term:
    '*'         соответствует любой последовательности символов, не являющихся разделителями
    '?'         соответствует любому одиночному символу, не являющемуся разделителем
    '[' [ '^' ] { диапазон символов } ']'
                класс символов (не может быть пустым)
    c           соответствует символу c (c != '*', '?', '\\', '[')
    '\\' c      соответствует символу c

диапазон символов:
    c           соответствует символу c (c != '\\', '-', ']')
    '\\' c      соответствует символу c
    lo '-' hi   соответствует символу c при lo <= c <= hi

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

  • my-registry.io/images
  • my-registry.io/images/my-image
  • my-registry.io/images/another-image
  • sub.my-registry.io/images/my-image
  • a.sub.my-registry.io/images/my-image

kubelet последовательно извлекает образы для каждой обнаруженной учетной записи. Это означает, что config.json может содержать сразу несколько записей:

{
    "auths": {
        "my-registry.io/images": {
            "auth": "…"
        },
        "my-registry.io/images/subpath": {
            "auth": "…"
        }
    }
}

К примеру, если необходимо извлечь образ my-registry.io/images/subpath/my-image, kubelet будет пытаться загрузить его из второго источника, если первый не работает.

Предварительно извлеченные образы

По умолчанию kubelet пытается извлечь каждый образ из указанного реестра. Однако если параметр imagePullPolicy контейнера установлен на IfNotPresent или Never, используется локальный образ (преимущественно или исключительно, соответственно).

Чтобы использовать предварительно извлеченные образы (и не связываться с аутентификацией для доступа к реестру), необходимо убедиться, что они идентичны на всех узлах кластера.

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

При этом у всех Pod'ов будет доступ на чтение всех предварительно извлеченных образов.

Задаем imagePullSecrets на уровне Pod'а

Kubernetes поддерживает указание ключей реестра образов на уровне Pod'а.

Создаем Secret с помощью конфигурационного файла Docker

Для аутентификации в реестре необходимо знать имя пользователя, пароль, имя хоста реестра и адрес электронной почты клиента.

Выполните следующую команду, подставив соответствующие значения вместо параметров, выделенных заглавными буквами:

kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

При наличии файла учетных данных Docker можно импортировать их как Secret'ы Kubernetes вместо команды, приведенной выше.

В разделе Создание Secret'а на основе существующих учетных данных Docker рассказывается, как это можно сделать.

Это особенно удобно в случае нескольких приватных реестров контейнеров, так как kubectl create secret docker-registry создает Secret, который работает только с одним приватным реестром.

Ссылаемся на imagePullSecrets в Pod'е

Теперь можно создавать Pod'ы, ссылающиеся на данный Secret, добавив раздел imagePullSecrets в манифест Pod'а.

Например:

cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: awesomeapps
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey
EOF

cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF

Это необходимо проделать для каждого Pod'а, работающего с приватным репозиторием.

Процесс можно автоматизировать, задав imagePullSecrets в ресурсе ServiceAccount.

Подробные инструкции см. в разделе Добавить ImagePullSecrets в Service Account.

Этот подход можно использовать совместно с файлами .docker/config.json, определяемыми для каждого узла. Учетные данные будут объединены.

Примеры использования

Существует ряд решений для настройки приватных реестров. Вот некоторые распространенные случаи использования и рекомендуемые решения:

  1. Кластер, работающий только со свободными (например, Open Source) образами. Необходимость скрывать образы отсутствует.
    • Используйте общедоступные образы из Docker Hub;
      • Настройка не требуется;
      • Некоторые облачные провайдеры автоматически кэшируют или зеркалируют публичные образы, что повышает доступность и сокращает время их извлечения.
  2. В кластере используются закрытые образы. Они должны быть скрыты для всех за пределами компании, но доступны для всех пользователей кластера.
    • Используйте приватный репозиторий;
      • Может потребоваться ручная настройка на узлах, которым необходим доступ к частному репозиторию;
    • В качестве альтернативы можно завести внутренний приватный реестр с доступом на чтение, скрыв его за сетевым экраном;
      • Настройка Kubernetes не требуется;
    • Используйте сервис для работы с образами, контролирующий доступ к ним;
      • Этот подход лучше работает с автомасштабированием кластера, нежели ручная настройка узлов;
    • Если изменение конфигурации узлов в кластере затруднено, можно использовать imagePullSecrets.
  3. Кластер с несвободными образами, некоторые из которых требуют более строгого контроля доступа.
    • Убедитесь, что AlwaysPullImages admission-контроллер включен. В противном случае у всех Pod'ов потенциально будет доступ ко всем образам;
    • Переместите конфиденциальные данные в Secret вместо того, чтобы упаковывать их в образ.
  4. Кластер категории multi-tenant (многопользовательский), где каждому пользователю требуется собственный приватный репозиторий.
    • Убедитесь, что admission-контроллер AlwaysPullImages включен. В противном случае у всех Pod'ов всех пользователей потенциально будет доступ ко всем образам;
    • Создайте приватный реестр с обязательной авторизацией;
    • Сгенерируйте учетные данные для доступа к реестру для каждого пользователя, поместите их в Secret и добавьте его в пространство имен каждого пользователя;
    • Каждый пользователь должен добавить свой Secret в imagePullSecrets каждого пространства имен.

Если нужен доступ к нескольким реестрам, можно создать по Secret'у для каждого реестра.

Что дальше

6.3.2 - RuntimeClass

СТАТУС ФИЧИ: Kubernetes v1.20 [stable]

На этой странице описывается ресурс RuntimeClass и механизм выбора исполняемой среды.

RuntimeClass позволяет выбрать конфигурацию исполняемой среды для контейнеров. Используется для настройки исполняемой среды в Pod'е.

Мотивация

Разным Pod'ам можно назначать различные RuntimeClass'ы, соблюдая баланс между производительностью и безопасностью. Например, если часть рабочей нагрузки требует высокого уровня информационной безопасности, связанные с ней Pod'ы можно запланировать так, чтобы они использовали исполняемую среду для контейнеров на основе аппаратной виртуализации. Это обеспечит повышенную изоляцию, но потребует дополнительных издержек.

Также можно использовать RuntimeClass для запуска различных Pod'ов с одинаковой исполняемой средой, но с разными настройками.

Подготовка

  1. Настройте реализацию CRI на узлах (зависит от используемой исполняемой среды);
  2. Создайте соответствующие ресурсы RuntimeClass.

1. Настройте реализацию CRI на узлах

Конфигурации, доступные с помощью RuntimeClass, зависят от реализации Container Runtime Interface (CRI). Для настройки определенной реализации CRI обратитесь к соответствующему разделу документации (ниже).

Каждой конфигурации соответствует обработчик, на который ссылается RuntimeClass. Имя обработчика должно соответствовать синтаксису для меток DNS.

2. Создайте соответствующие ресурсы RuntimeClass

К каждой конфигурации, настроенной на шаге 1, должно быть привязано имя обработчика (handler), которое ее идентифицирует. Для каждого обработчика создайте соответствующий объект RuntimeClass.

На данный момент у ресурса RuntimeClass есть только 2 значимых поля: имя RuntimeClass (metadata.name) и обработчик (handler). Определение объекта выглядит следующим образом:

# RuntimeClass определен в API-группе node.k8s.io
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  # Имя, которое ссылается на RuntimeClass
  # ресурс RuntimeClass не включается в пространство имен
  name: myclass 
# Имя соответствующей конфигурации CRI
handler: myconfiguration 

Имя объекта RuntimeClass должно удовлетворять синтаксису для поддоменных имен DNS.

Использование

После того как RuntimeClasses настроены для кластера, использовать их очень просто. Достаточно указать runtimeClassName в спецификации Pod'а. Например:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  runtimeClassName: myclass
  # ...

kubelet будет использовать указанный RuntimeClass для запуска этого Pod'а. Если указанный RuntimeClass не существует или CRI не может запустить соответствующий обработчик, Pod войдет в фазу завершения работы Failed. Полное сообщение об ошибке можно получить, обратившись к соответствующему событию (event).

Если имя runtimeClassName не указано, будет использоваться RuntimeHandler по умолчанию (что эквивалентно поведению, когда функция RuntimeClass отключена).

Настройка CRI

Для получения более подробной информации о настройке исполняемых сред CRI обратитесь к разделу Установка CRI.

containerd

Обработчики исполняемой среды настраиваются в конфигурации containerd в файле /etc/containerd/config.toml. Допустимые обработчики прописываются в разделе runtimes:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]

Дополнительная информация доступна в документации по конфигурации containerd.

CRI-O

Обработчики исполняемой среды настраиваются в файле конфигурации CRI-O (/etc/crio/crio.conf). Допустимые обработчики прописываются в таблице crio.runtime:

[crio.runtime.runtimes.${HANDLER_NAME}]
  runtime_path = "${PATH_TO_BINARY}"

Более подробную информацию см. в документации по конфигурации CRI-O.

Scheduling

СТАТУС ФИЧИ: Kubernetes v1.16 [beta]

Поле scheduling в RuntimeClass позволяет наложить определенные ограничения, гарантировав, что Pod'ы с определенным RuntimeClass'ом будут планироваться на узлы, которые его поддерживают. Если параметр scheduling не установлен, предполагается, что данный RuntimeClass поддерживается всеми узлами.

Чтобы гарантировать, что Pod'ы попадают на узлы, поддерживающие определенный RuntimeClass, эти узлы должны быть связаны общей меткой, которая затем выбирается полем runtimeclass.scheduling.nodeSelector. nodeSelector RuntimeClass'а объединяется с nodeSelector'ом admission-контроллера, на выходе образуя пересечение подмножеств узлов, выбранных каждым из селекторов. Если возникает конфликт, Pod отклоняется.

Если поддерживаемые узлы объединены неким taint'ом, чтобы предотвратить запуск на них Pod'ов с другими RuntimeClass'ами, можно к нужному RuntimeClass'у добавить tolerations. Как и в случае с nodeSelector, tolerations объединяются с tolerations Pod'а admission-контроллера, фактически образуя объединение двух подмножеств узлов с соответствующими tolerations.

Чтобы узнать больше о настройке селектора узлов и tolerations, см. раздел Назначаем Pod'ы на узлы.

Pod Overhead

СТАТУС ФИЧИ: Kubernetes v1.24 [stable]

Можно указать overhead-ресурсы, необходимые для работы Pod'а. Это позволит кластеру (и планировщику) учитывать их при принятии решений о Pod'ах и управлении ресурсами.

В RuntimeClass дополнительные ресурсы, потребляемые Pod'ом, указываются в поле overhead. С помощью этого поля можно указать ресурсы, необходимые Pod'ам с данным RuntimeClass'ом, и гарантировать их учет в Kubernetes.

Что дальше

6.3.3 - Контейнерное окружение

На этой странице описаны ресурсы, доступные для контейнеров в соответствующем окружении.

Контейнерное окружение

Контейнерное окружение Kubernetes предоставляет контейнерам несколько важных ресурсов:

  • Файловую систему, сочетающую в себе образ и один или несколько томов.
  • Информацию о самом контейнере.
  • Информацию о других объектах в кластере.

Информация о контейнере

Hostname контейнера — имя Pod'а, в котором запущен контейнер. Его можно получить с помощью команды hostname или функции gethostname в libc.

Имя Pod'а и его пространство имен можно получить из переменных окружения в Downward API.

Контейнеру также доступны переменные окружения из определения Pod'а, заданные пользователем, а также любые переменные окружения, указанные статически в образе контейнера.

Информация о кластере

Список всех сервисов, активных на момент создания контейнера, доступен этому контейнеру в виде переменных окружения. Этот список ограничен сервисами в пространстве имен, которому принадлежит Pod с данным контейнером, а также сервисами управляющего слоя Kubernetes.

Для сервиса foo, связанного с контейнером bar, определены следующие переменные:

FOO_SERVICE_HOST=<хост, на котором запущен сервис>
FOO_SERVICE_PORT=<порт, на котором запущен сервис>

Сервисы получают выделенные IP-адреса и доступны для контейнера через DNS, если включен аддон DNS.

Что дальше

6.3.4 - Хуки жизненного цикла контейнеров

На этой странице описывается, как контейнеры под управлением kubelet могут использовать механизм хуков для запуска кода, инициированного событиями во время своего жизненного цикла.

Общая информация

Многие платформы для разработки предлагают хуки жизненного цикла компонентов (например, Angular). Kubernetes имеет аналогичный механизм. Хуки позволяют контейнерам оставаться в курсе событий своего жизненного цикла и запускать запакованный в обработчик код при наступлении определенных событий, приводящих к вызову хука.

Хуки контейнеров

В распоряжении контейнеров имеются два хука:

PostStart

Выполняется сразу после создания контейнера. Однако нет гарантии, что хук закончит работу до ENTRYPOINT контейнера. Параметры обработчику не передаются.

PreStop

Вызывается непосредственно перед завершением работы контейнера в результате запроса API или иного события (например, неудачное завершение теста liveness/startup, вытеснение, борьба за ресурсы и т.п.). Вызов хука PreStop завершается неудачно, если контейнер уже находится в прерванном (terminated) или завершенном (completed) состоянии. Кроме того, работа хука должна закончиться до того, как будет отправлен сигнал TERM для остановки контейнера. Отсчет задержки перед принудительной остановкой Pod'а (grace-период) начинается до вызова хука PreStop. Таким образом, независимо от результата выполнения обработчика, контейнер будет остановлен в течение этого grace-периода. Параметры обработчику не передаются.

Более подробное описание поведения при прекращении работы можно найти в разделе Прекращение работы Pod'ов.

Реализации обработчиков хуков

Чтобы контейнер имел доступ к хуку, необходимо реализовать и зарегистрировать обработчик для этого хука. Существует два типа обработчиков хуков, доступных для контейнеров:

  • Exec — Выполняет определенную команду, например, pre-stop.sh, внутри cgroups и пространств имен контейнера. Ресурсы, потребляемые командой, прибавляются к ресурсам, потребляемым контейнером.
  • HTTP — Выполняет HTTP-запрос к определенной конечной точке контейнера.

Выполнение обработчиков хуков

При вызове хука, привязанного к жизненному циклу контейнера, система управления Kubernetes выполняет обработчик в соответствии с типом хука: kubelet отвечает за httpGet и tcpSocket, а exec выполняется в контейнере.

Вызовы обработчиков хуков синхронны в контексте Pod'а, содержащего контейнер. Это означает, что в случае PostStart-хука ENTRYPOINT контейнера и хук запускаются асинхронно. При этом если хук выполняется слишком долго или зависает, контейнер не может достичь состояния Running.

Хуки PreStop не запускаются асинхронно с сигналом на остановку контейнера; хук должен завершить свою работу до отправки сигнала TERM. Если хук PreStop зависнет во время выполнения, Pod будет пребывать в состоянии Terminating до истечения периода terminationGracePeriodSeconds, после чего Kubernetes "убьет" его. Этот grace-период включает как время, которое требуется для выполнения хука PreStop, так и время, необходимое для нормальной остановки контейнера. Например, если terminationGracePeriodSeconds равен 60, работа хука занимает 55 секунд, а контейнеру требуется 10 секунд для нормальной остановки после получения сигнала, то контейнер будет "убит" до того, как сможет нормально завершить свою работу, поскольку terminationGracePeriodSeconds меньше, чем суммарное время (55+10), необходимое для работы хука и остановки контейнера.

Если любой из хуков postStart / preStop завершается неудачей, Kubernetes "убивает" контейнер.

Поэтому обработчики для хуков должны быть максимально простыми. Однако бывают случаи, когда применение "тяжелых" команд оправдано – например, при сохранении состояния перед остановкой контейнера.

Гарантии поставки хука

Хук должен выполниться хотя бы один раз. Это означает, что он может вызываться неоднократно для любого события вроде PostStart или PreStop. Задача по правильной обработке подобных вызовов возложена на сам хук.

Как правило, поставка хука выполняется однократно. Если, например, приемник HTTP-хука не работает и не может принимать трафик, повторная попытка отправки не предпринимается. В редких случаях может происходить двойная поставка. Например, если kubelet перезапустится в процессе доставки хука, тот может быть отправлен повторно.

Отладка обработчиков хуков

Логи обработчиков хуков не отображаются в событиях Pod'а. В случае сбоя обработчика тот транслирует событие. Для PostStart это событие FailedPostStartHook, для PreStop — событие FailedPreStopHook. Чтобы самостоятельно сгенерировать событие FailedPreStopHook, в манифесте lifecycle-events.yaml замените команду для postStart на что-то заведомо невыполнимое (badcommand) и примените его. Если теперь выполнить команду kubectl describe pod lifecycle-demo, вы увидите следующее:

Events:
  Type     Reason               Age              From               Message
  ----     ------               ----             ----               -------
  Normal   Scheduled            7s               default-scheduler  Successfully assigned default/lifecycle-demo to ip-XXX-XXX-XX-XX.us-east-2...
  Normal   Pulled               6s               kubelet            Successfully pulled image "nginx" in 229.604315ms
  Normal   Pulling              4s (x2 over 6s)  kubelet            Pulling image "nginx"
  Normal   Created              4s (x2 over 5s)  kubelet            Created container lifecycle-demo-container
  Normal   Started              4s (x2 over 5s)  kubelet            Started container lifecycle-demo-container
  Warning  FailedPostStartHook  4s (x2 over 5s)  kubelet            Exec lifecycle hook ([badcommand]) for Container "lifecycle-demo-container" in Pod "lifecycle-demo_default(30229739-9651-4e5a-9a32-a8f1688862db)" failed - error: command 'badcommand' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: \"badcommand\": executable file not found in $PATH: unknown\r\n"
  Normal   Killing              4s (x2 over 5s)  kubelet            FailedPostStartHook
  Normal   Pulled               4s               kubelet            Successfully pulled image "nginx" in 215.66395ms
  Warning  BackOff              2s (x2 over 3s)  kubelet            Back-off restarting failed container

Что дальше

6.4 - Рабочие нагрузки

Поймите под, самый маленький развертываемый вычислительный объект в Kubernetes, и абстракции более высокого уровня, которые помогут вам их запускать.

Рабочая нагрузка — это приложение, работающее в Kubernetes. Независимо от того, представляет ли ваша рабочая нагрузка один компонент или несколько, которые работают вместе, в Kubernetes вы запускаете ее внутри набора подов. В Kubernetes под представляет собой набор работающих контейнеров в кластере.

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

Однако, чтобы значительно облегчить жизнь, не нужно непосредственно контролировать каждый под. Вместо этого можно использовать ресурсы рабочей нагрузки, которые управляют набором подов за вас. Эти ресурсы настраивают контроллеры, которые обеспечивают запуск нужного количества модулей нужного типа в соответствии с указанным вами состоянием.

Kubernetes предоставляет несколько встроенных ресурсов для рабочих нагрузок:

  • Деплоймент (Deployment) и ReplicaSet (замена устаревшего ресурса ReplicationController). Deployment хорошо подходит для управления неизменными (stateless) приложениями в кластере, то есть для случаев, когда любой под в деплойменте не содержит изменяемых данных и может быть заменен при необходимости.
  • StatefulSet позволяет запускать один или несколько связанных подов, которые как-то отслеживают состояние (являются stateful). Например, если ваше приложение записывает постоянные данные, вы можете использовать StatefulSet, который сопоставляет каждый под с PersistentVolume. Ваш код, работающий в подах этого StatefulSet, может копировать данные в другие поды в том же StatefulSet, чтобы повысить общую отказоустойчивость.
  • DaemonSet создает поды, которые предоставляют инструменты, которые доступны локально для узлов. Каждый раз, когда вы добавляете в кластер узел, соответствующий спецификации DaemonSet, слой управления (control plane) планирует (т.е. запускает) под с этим DaemonSet на новом узле. Каждый под в DaemonSet выполняет работу, аналогичную работе системного демона на классическом сервере Unix/POSIX. DaemonSet может иметь основополагающее значение для работы вашего кластера, например, в случае плагина для запуска сети кластера (cluster networking). Этот ресурс может помочь управлять узлом или предоставить дополнительные возможности для используемой контейнерной платформы.
  • Job и CronJob предоставляют различные способы запуска задач, которые выполняются до своего завершения, а затем останавливаются. Job используется для задачи, которая выполняется только один раз. Вы можете использовать CronJob для запуска этого же задания несколько раз по расписанию.

В экосистеме вокруг проекта Kubernetes можно найти сторонние ресурсы для рабочих нагрузок, которые предоставляют дополнительные функции. Используя custom resource definition, вы можете добавить сторонний ресурс рабочей нагрузки, если нужно определенное поведение, не являющееся частью стандартного Kubernetes. Например, если вы хотите запустить группу подов для своего приложения, но хотите свернуть работу в случае, когда не все поды доступны (возможно, для распределенной задачи с высокой пропускной способностью), можно реализовать или установить расширение, которое предоставляет эту функцию.

Что дальше

В дополнение к информации о каждом виде API для управления рабочей нагрузкой вы можете прочитать, как выполнять конкретные задачи:

Чтобы узнать о механизмах отделения кода от конфигурации в Kubernetes, посетите раздел Configuration.

Есть два вспомогательных концепта, которые дают представление о том, как Kubernetes управляет подами для приложений:

  • Сборщик мусора (Garbage collection) вычищает объекты из вашего кластера после удаления ресурса-владельца.
  • Контроллер времени существования после завершения (time-to-live after finished controller) удаляет задания (Jobs) по истечении определенного времени с момента их завершения.

После запуска вашего приложения можно сделать его доступным в интернете с помощью Service или, только в случае веб-приложения, используя Ingress.

6.4.1 - Ресурсы рабочей нагрузки

Kubernetes предоставляет несколько встроенных API для декларативного управления рабочими нагрузками и их компонентами.

В конечном счете, приложения работают в качестве контейнеров внутри подов, однако управление каждым подом по отдельности требует больших усилий. Например, если под выходит из строя, вам, вероятно, надо будет запустить новый под, чтобы заменить его. Kubernetes может сделать это за вас.

С помощью Kubernetes API можно создавать объект рабочей нагрузки на более высоком уровне абстракции, чем под, а затем уже слой управления Kubernetes будет автоматически управлять подами, руководствуясь спецификацией этого объекта.

Встроенные API для управления рабочими нагрузками:

Деплоймент (Deployment) (и, косвенно, ReplicaSet) — это наиболее распространенный способ запуска приложения в кластере. Deployment хорошо подходит для управления неизменной (stateless) рабочей нагрузкой в кластере, где любой под в деплойменте не содержит изменяемых данных и может быть заменен при необходимости (Deployments — замена устаревшего ресурса ReplicationController API).

StatefulSet позволяет управлять одним или несколькими подами, в которых работает одно и то же приложение, для случаев, когда все эти поды требуют четкой идентичности (т.е. являются stateful). Это отличается от деплоймента, в котором предполагается, что поды могут быть взаимозаменяемыми. Наиболее распространенное использование StatefulSet — возможность установить связь между его подами и их постоянным хранилищем (persistent storage). Например, можно запустить StatefulSet, который связывает каждый под с PersistentVolume. Если один из подов в StatefulSet выходит из строя, Kubernetes создает заменяющий под, подключенный к тому же PersistentVolume.

DaemonSet создает поды, которые предоставляют локальные инструменты для узлов; пример — драйвер, который позволяет контейнерам на узле получить доступ к системе хранения. DaemonSet используется, когда драйвер или сервис должен быть запущен на определенном узле. Каждый под в DaemonSet выполняет роль, аналогичную системному демону на классическом сервере Unix/POSIX. DaemonSet может иметь основополагающее значение для работы кластера, например, для плагина, позволяющего узлу получить доступ к сети кластера. Он может помочь управлять узлом или предоставить менее важные функции, улучшающие работу используемой контейнерной платформы. DaemonSet'ы (и их поды) можно запускать на каждом узле кластера или только на некоторых из них (например, можно установить драйвер ускорителя GPU только на узлах, на которых установлен GPU).

Job и/или CronJob используются, чтобы определять задачи, которые выполняются по отдельному запуску до их завершения, а затем останавливаются. Job представляет собой разовую задачу, тогда как CronJob повторяется по расписанию.

Другие темы в этом разделе:

6.4.1.1 - CronJob

CronJob запускает одноразовые задания по повторяющемуся расписанию
СТАТУС ФИЧИ: Kubernetes v1.21 [stable]

CronJob создает задания (Jobs), которые повторяются по расписанию.

CronJob предназначен для выполнения регулярных заданий по расписанию, таких как резервное копирование, создание отчетов, и так далее. Один CronJob объект — это как одна строка файла crontab (cron table) в Unix-системе. Он периодически запускает задание по заданному расписанию, составленному в формате формате Cron.

У CronJob'a есть свои ограничения и особенности. Например, при определенных обстоятельствах один CronJob может создавать несколько параллельных заданий. См. раздел Ограничения ниже.

Когда управляющий слой (control plane) создает новые задания и (косвенно) поды для CronJob'а, поле .metadata.name в CronJob является частью основы для наименования этих подов. Имя CronJob должно быть действительным значением поддомена DNS, но это может привести к неожиданным результатам для имен хостов подов. Для наилучшей совместимости имя должно соответствовать более строгим правилам имен меток DNS. Даже если имя является поддоменом DNS, оно не должно превышать 52 символов. Это связано с тем, что контроллер CronJob автоматически добавляет 11 символов к указанному вами имени и существует ограничение на то, что длина имени задания (Job) не должна превышать 63 символа.

Пример

Этот пример манифеста CronJob печатает текущее время и сообщение hello каждую минуту:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

(Выполнение автоматических заданий с помощью CronJob более подробно рассматривает этот пример.)

Написание спецификации CronJob'a

Синтаксис расписания

Поле .spec.schedule является обязательным. Значение этого поля соответствует синтаксису Cron:

# ┌───────────── минута (0 - 59)
# │ ┌───────────── час (0 - 23)
# │ │ ┌───────────── день месяца (1 - 31)
# │ │ │ ┌───────────── месяц (1 - 12)
# │ │ │ │ ┌───────────── день недели (0 - 6) (воскресенье - суббота)
# │ │ │ │ │                                   ИЛИ sun, mon, tue, wed, thu, fri, sat
# │ │ │ │ │
# * * * * *

Например, 0 0 13 * 5 указывает, что задание должно запускаться каждую пятницу в полночь, а также 13 числа каждого месяца в полночь.

Формат также включает расширенные значения шагов "Vixie cron". Как объясняется в инструкции для FreeBSD:

Значения шагов можно использовать в сочетании с диапазонами. Если после диапазона указать /<число>, то это означает пропуск значения числа в диапазоне. Например, 0-23/2 можно использовать, чтобы указать выполнение команды каждый второй час (альтернативой в стандарте V7 является 0,2,4,6,8,10,12,14,16,18,20,22). Шаги также разрешены после звездочки, так что если нужно указать "каждые два часа", можно использовать */2.

Помимо стандартного синтаксиса можно также использовать макросы вроде @monthly:

Запись Описание Эквивалент
@yearly (или @annually) Запускается один раз в год в полночь 1 января 0 0 1 1 *
@monthly Запускается раз в месяц в полночь первого дня месяца 0 0 1 * *
@weekly Запускается раз в неделю в полночь в воскресенье утром 0 0 * * 0
@daily (или @midnight) Запускается один раз в день в полночь 0 0 * * *
@hourly Запускается раз в час в начале часа 0 * * * *

Для создания CronJob-расписания можно также использовать такие веб-инструменты, как crontab.guru.

Шаблон задания

Поле .spec.jobTemplate определяет шаблон для заданий, которые создает CronJob, и является обязательным. Он имеет точно такой же вид, как и Job, за исключением того, что является вложенным и не имеет полей apiVersion и kind. Можно указать типичные метаданные для шаблонных заданий (Jobs), такие как метки или аннотации. О том, как написать .spec для Job, см. Написание спецификации Job.

Дедлайн задержки начала задания

Поле .spec.startingDeadlineSeconds является необязательным. В этом поле задается крайний срок (в целых секундах) для запуска задания (Job), если оно по какой-либо причине не успевает к назначенному времени.

Если дедлайн пропущен, CronJob пропускает этот вызов задания (последующие выполнения по-прежнему запланированы). Например, если задание резервного копирования выполняется дважды в день, можно разрешить ему запускаться с опозданием до 8 часов, но не позже, поскольку резервная копия, сделанная позже, не будет полезной: лучше дождаться следующего запуска по расписанию.

Задания, которые не успели выполниться в установленный срок, Kubernetes рассматривает как неудачные. Если не указать startingDeadlineSeconds для CronJob, то задания не будут иметь дедлайн.

Если поле .spec.startingDeadlineSeconds установлено (не является нулевым), контроллер CronJob измеряет время между моментом, когда задание должно быть создано, и реальным временем. Если разница превышает указанный предел, он пропустит этот вызов задания.

Например, если установлено значение 200, задание может быть создано в период до 200 секунд позже фактического расписания.

Политика параллелизма (concurrency policy)

Поле .spec.concurrencyPolicy также является необязательным. Оно определяет, как обращаться с одновременным выполнением заданий, созданных этим CronJob. В этой спецификации может быть указана только одна из следующих политик параллелизма:

  • Allow (по умолчанию): CronJob разрешает одновременное выполнение заданий.
  • Forbid: CronJob не разрешает одновременное выполнение заданий; если пришло время для выполнения нового задания, а предыдущее еще не завершилось, CronJob пропускает новое задание.
  • Replace: Если пришло время для выполнения нового задания, а предыдущее еще не завершилось, CronJob заменит текущее задание на новое.

Заметьте, что принцип параллелизма применяется только к заданиям, созданным одним и тем же Cronjob'ом. Если есть несколько CronJob'ов, их соответствующие задания всегда могут выполняться одновременно.

Остановка выполнения заданий по расписанию

Можно приостановить выполнение CronJob-заданий, присвоив необязательному полю .spec.suspend значение true. По умолчанию это поле имеет значение false.

Эта настройка не влияет на задания, которые уже были запущены CronJob'ом.

Если установить это поле как true, все последующие выполнения будут приостановлены (они остаются запланированными, но CronJob-контроллер не запускает задания для выполнения), пока вы не отмените приостановку CronJob'a.

Лимиты на историю заданий

Поля .spec.successfulJobsHistoryLimit и .spec.failedJobsHistoryLimit являются необязательными. В этих полях указывается, сколько завершенных и неудачных заданий должно быть сохранено в истории. По умолчанию они установлены на 3 и 1 соответственно. Установка предела в 0 будет означать, что никакие задания соответствующего типа не сохранятся после их завершения.

Другой способ автоматической очистки заданий см. в разделе Автоматическая очистка завершенных заданий.

Часовые пояса

СТАТУС ФИЧИ: Kubernetes v1.27 [stable]

Для CronJob'a, в которых не указан часовой пояс, kube-controller-manager интерпретирует расписания относительно своего локального часового пояса.

Можно указать часовой пояс для CronJob'a, присвоив .spec.timeZone имя действительного часового пояса. Например, установка .spec.timeZone: "Etc/UTC" инструктирует Kubernetes интерпретировать расписание относительно всемирного координированного времени.

База данных часовых поясов из стандартной библиотеки Go включена в бинарные файлы и используется в качестве запасного варианта на случай, если внешняя база данных недоступна в системе.

Ограничения CronJob

Неподдерживаемая спецификация TimeZone

Установка часового пояса с помощью переменных CRON_TZ или TZ в .spec.schedule не поддерживается официально (и никогда не поддерживалась).

Начиная с Kubernetes 1.29, если попытаться задать расписание, включающее спецификацию часового пояса TZ или CRON_TZ, Kubernetes не сможет создать ресурс, выдав ошибку валидации. Обновления для CronJobs, уже использующих TZ или CRON_TZ, будут продолжать выдавать предупреждение клиенту.

Модификация задания CronJob

По своей структуре CronJob содержит шаблон для новых заданий. Если изменить существующее задание CronJob, внесенные изменения будут применены к новым заданиям, которые начнут выполняться после завершения модификации. Задания (и их поды), которые уже были запущены, продолжат выполняться без изменений. То есть CronJob не обновляет существующие задания, даже если они остаются запущенными.

Создание заданий

CronJob создает объект задания (Job) примерно один раз за время выполнения своего расписания. Расписание является приблизительным, поскольку есть определенные обстоятельства, при которых могут быть созданы два задания или не создано ни одного. Kubernetes старается избегать таких ситуаций, но не может полностью предотвратить их. Поэтому задания, которые вы определяете, должны быть идемпотентными.

Если в поле startingDeadlineSeconds задано большое значение или оно не определено (по умолчанию), а также при условии, что concurrencyPolicy имеет значение Allow, задания всегда будут выполняться по крайней мере один раз.

Для каждого задания CronJob контроллер проверяет, сколько расписаний он пропустил за время, прошедшее с последнего расписания до настоящего момента. Если пропущено более 100 расписаний, то задание не запускается и фиксируется ошибка.

Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.

Важно отметить, что если поле startingDeadlineSeconds установлено (не равно nil), контроллер считает, сколько пропущенных заданий произошло с момента значения startingDeadlineSeconds до настоящего момента, а не с момента последнего запланированного задания до настоящего момента. Например, если startingDeadlineSeconds равно 200, контроллер подсчитывает, сколько пропущенных заданий произошло за последние 200 секунд.

Задание CronJob считается пропущенным, если оно не было создано в запланированное время. Например, если для concurrencyPolicy установлено значение Forbid, и CronJob пытался быть запланирован, когда предыдущее расписание еще выполнялось, то он будет считаться пропущенным.

Например, предположим, что задание CronJob настроено на планирование нового задания каждую минуту, начиная с 08:30:00, а его поле поле startingDeadlineSeconds не установлено. Если контроллер CronJob не функционирует с 08:29:00 до 10:21:00, задание не будет запущено, так как количество пропущенных заданий, которые не успели выполнить свое расписание, больше 100.

Чтобы подробнее проиллюстрировать эту концепцию, предположим, что задание CronJob настроено на планирование нового задания каждую одну минуту, начиная с 08:30:00, и его параметр startingDeadlineSeconds установлен на 200 секунд. Если контроллер CronJob вдруг не функционирует в течение того же периода, что и в предыдущем примере (с 08:29:00 по 10:21:00), задание все равно начнется в 10:22:00. Это происходит потому, что контроллер в данном случае проверяет, сколько пропущенных запланированных заданий было за последние 200 секунд (т. е. 3 пропущенных расписания), а не с момента последнего запланированного времени до настоящего момента.

CronJob отвечает только за создание заданий (Jobs), соответствующих его расписанию, а задание, в свою очередь, отвечает за управление подами, которые оно представляет.

Что дальше

6.5 - Планирование, приоритизация и вытеснение

В Kubernetes под планированием понимается поиск подходящих узлов, на которых kubelet сможет запустить Pod'ы. Приоритизация — процесс завершения работы Pod'ов с более низким приоритетом и высвобождения места для Pod'ов с более высоким приоритетом. Вытеснение — это проактивное завершение работы одного или нескольких Pod'ов на узлах с дефицитом ресурсов.

В Kubernetes под планированием понимается поиск узлов, подходящих для размещения Pod'ов так, чтобы kubelet мог их запустить. Приоритизация (упреждение; preemption) — процесс завершения работы Pod'ов с более низким приоритетом с освобождением места для Pod'ов с более высоким приоритетом. Вытеснение (eviction) — завершение работы одного или нескольких Pod'ов на узлах.

Планирование

Завершение работы Pod'ов

Нарушение работы Pod'ов (Pod disruption) — процесс, в ходе которого происходит плановое или внеплановое (принудительное) завершение работы Pod'ов на узлах.

Плановое завершение работы Pod'ов инициируется владельцами приложений или администраторами кластера. Внеплановое завершение работы обычно вызвано непредвиденными обстоятельствами различной природы, например, с недостатком ресурсов на узлах или случайными удалениями.

6.5.1 - Распределение подов по узлам

Можно настроить под так, чтобы тот мог запускаться только на определенном(-ых) узле(-ах) или предпочитал определенную группу узлов. Сделать это можно несколькими способами, при этом все рекомендуемые подходы используют селекторы лейблов для выбора. Зачастую нужды в подобных ограничениях нет; планировщик автоматически размещает поды оптимальным образом (например, распределяет их по узлам, чтобы они не оказались все на одном узле с дефицитом ресурсов). Однако в некоторых обстоятельствах возможность контролировать, куда именно попадет под, может пригодиться. Например, она поможет запланировать под на узел с быстрым SSD-хранилищем или разместить два активно взаимодействующих друг с другом пода в одной зоне доступности.

Для планирования подов на определенные узлы можно использовать любой из методов:

Лейблы узлов

Как и у многих других объектов Kubernetes, у узлов есть лейблы. Их можно навешивать вручную. Kubernetes также навешивает стандартный набор лейблов на все узлы кластера.

Изоляция узла/ограничение его использования

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

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

Admission-плагин NodeRestriction не позволяет kubelet'у устанавливать или изменять лейблы с префиксом node-restriction.kubernetes.io/.

Чтобы использовать этот префикс для изоляции узла:

  1. Убедитесь, что используется авторизатор узлов и включен admission-плагин NodeRestriction.
  2. Добавьте лейблы с префиксом node-restriction.kubernetes.io/ к узлам и используйте их в селекторах узлов. Например, example.com.node-restriction.kubernetes.io/fips=true или example.com.node-restriction.kubernetes.io/pci-dss=true.

nodeSelector

nodeSelector — простейшая рекомендуемая форма настроек выбора узлов. Можно добавить поле nodeSelector в спецификацию пода и перечислить в нем лейблы узлов, которые подходят для развертывания пода. В этом случае Kubernetes будет планировать под только на узлы со всеми указанными лейблами.

Дополнительную информацию см. в разделе Размещение подов на узлах.

Правила совместного/раздельного существования (affinity и anti-affinity)

nodeSelector — самый простой способ развернуть поды на узлах с определенными лейблами. Правила совместного/раздельного существования расширяют типы ограничений, которые можно накладывать. Вот некоторые из их преимуществ:

  • Язык правил affinity/anti-affinity более выразителен. nodeSelector выбирает узлы только со всеми указанными лейблами. Правила affinity/anti-affinity расширяют логику выбора и делают ее более гибкой.
  • Правило может быть мягким (soft) или предпочтительным (preferred). В этом случае планировщик все равно запланирует под, даже если подходящего узла для него не найдется.
  • При планировании пода планировщик может учитывать лейблы других подов, запущенных на узле (или в иной топологической области), а не только лейблы самого узла. Это позволяет формулировать правила, определяющие сосуществование подов на узле.

Правила совместного существования (affinity) бывают двух типов:

  • Правила для узлов (node affinity) работают подобно полю nodeSelector, но более выразительны. Кроме того, можно задавать мягкие правила.
  • Правила для подов (inter-pod affinity и anti-affinity) позволяют при планировании учитывать лейблы других подов.

Правила совместного существования для узлов (node affinity)

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

  • requiredDuringSchedulingIgnoredDuringExecution: Планировщик не может запланировать под, если правило не выполнено. Работает как nodeSelector, но с более выразительным синтаксисом.
  • preferredDuringSchedulingIgnoredDuringExecution: Планировщик пытается найти узел, который соответствует правилу. Если подходящий узел не удается найти, планировщик все равно планирует под.

Задавать правила совместного существования для узлов можно с помощью поля .spec.affinity.nodeAffinity в спецификации пода.

В качестве примера рассмотрим следующую спецификацию пода:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - antarctica-east1
            - antarctica-west1
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:2.0

В этом примере применяются следующие правила:

  • У узла должен быть лейбл с ключом topology.kubernetes.io/zone, и значение этого лейбла должно быть либо antarctica-east1, либо antarctica-west1.
  • Предпочтительно, чтобы у узла был лейбл с ключом another-node-label-key и значением another-node-label-value.

Можно использовать поле operator для указания логического оператора, который Kubernetes будет применять при интерпретации правил. Доступны In, NotIn, Exists, DoesNotExist, Gt и Lt.

Узнать больше о том, как они работают, можно в подразделе Операторы.

NotIn и DoesNotExist позволяют задавать правила раздельного существования (anti-affinity) для узла. Кроме того, можно использовать taint'ы узлов, чтобы "отвадить" поды от определенных узлов.

Дополнительную информацию см. в разделе Размещаем поды на узлы с помощью Node Affinity.

Вес правил совместного существования

Для каждого правила типа preferredDuringSchedulingIgnoredDuringExecution можно указать вес weight в диапазоне от 1 до 100. Найдя несколько узлов, удовлетворяющих всем остальным требованиям для планирования пода, планировщик перебирает предпочтительные правила, которым удовлетворяет узел, и суммирует их веса.

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

В качестве примера рассмотрим следующую спецификацию пода:

apiVersion: v1
kind: Pod
metadata:
  name: with-affinity-anti-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/os
            operator: In
            values:
            - linux
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: label-1
            operator: In
            values:
            - key-1
      - weight: 50
        preference:
          matchExpressions:
          - key: label-2
            operator: In
            values:
            - key-2
  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:2.0

Если правилу preferredDuringSchedulingIgnoredDuringExecution соответствуют два узла (один — с лейблом label-1:key-1, другой — с label-2:key-2), планировщик считает вес weight каждого узла и добавляет его к другим оценкам для этого узла. Под планируется на узел с наивысшей итоговой оценкой.

Правила совместного существования и профили планирования

СТАТУС ФИЧИ: Kubernetes v1.20 [beta]

При настройке нескольких профилей планирования можно связать профиль с правилами совместного существования для узлов (это удобно, когда профиль применяется к определенному набору узлов). Для этого необходимо добавить addedAffinity в поле args плагина NodeAffinity в конфигурации планировщика. Например:

apiVersion: kubescheduler.config.k8s.io/v1beta3
kind: KubeSchedulerConfiguration

profiles:
  - schedulerName: default-scheduler
  - schedulerName: foo-scheduler
    pluginConfig:
      - name: NodeAffinity
        args:
          addedAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
              - matchExpressions:
                - key: scheduler-profile
                  operator: In
                  values:
                  - foo

Правило addedAffinity применяется ко всем подам с полем .spec.schedulerName, имеющим значение foo-scheduler, в дополнение к NodeAffinity, заданному в PodSpec. Таким образом, подходящие для пода узлы должны удовлетворять параметрам addedAffinity и правилам .spec.NodeAffinity пода.

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

Правила совместного/раздельного существования подов

Правила совместного/раздельного существования подов позволяют выбирать узлы для планирования в зависимости от лейблов подов, которые уже на этих узлах работают (вместо лейблов самих узлов).

Алгоритм работы правил совместного/раздельного существования подов можно описать так: "данный под должен (или не должен в случае раздельного (anti-affinity) существования) размещаться на X, если на нем уже работает один или несколько подов, удовлетворяющих правилу Y", где X — топологический домен, например, узел, стойка, зона/регион облачного провайдера и т. п., а Y — правило, которое Kubernetes пытается удовлетворить.

Для задания правил Y используются селекторы лейблов с необязательным связанным списком пространств имен. Для подов в Kubernetes указываются пространства имен, соответственно, их лейблы также оказываются неявно связаны с этими же пространствами имен. Любые селекторы лейблов для лейблов подов должны содержать пространства имен, в которых Kubernetes должен искать эти лейблы.

Топологический домен X задается с помощью topologyKey — ключа для лейбла узла, который система использует для обозначения домена. Примеры см. в разделе Типичные лейблы, аннотации и taint'ы.

Типы правил совместного/раздельного существования подов

По аналогии c правилами для узлов существует два типа правил для подов:

  • requiredDuringSchedulingIgnoredDuringExecution
  • preferredDuringSchedulingIgnoredDuringExecution

Например, с помощью правила совместного существования requiredDuringSchedulingIgnoredDuringExecution можно заставить планировщик размещать поды, относящиеся к разным сервисам, в одной зоне облачного провайдера, поскольку они активно обмениваются данными друг с другом.

Аналогичным образом можно использовать правило раздельного существования preferredDuringSchedulingIgnoredDuringExecution для распределения подов по нескольким зонам облачного провайдера.

Для задания правил совместного существования предназначено поле affinity.podAffinity в спецификации пода.

Для задания правил раздельного существования предназначено поле affinity.podAntiAffinity в спецификации пода.

Планирование группы подов, связанных правилами совместного существования

Если планируемый под — первый в серии подов, связанных правилами совместного существования, он может быть запланирован, если удовлетворит всем остальным правилам совместного существования. Чтобы подтвердить, что этот под — действительно первый, проводится проверка, которая должна показать, что пространство имен и селектор этого пода уникальны в кластере (то есть нет других таких подов). Кроме того, под должен соответствовать своим собственным правилам, а выбранный узел — всем запрошенным топологиям. Это предотвращает тупиковую ситуацию, когда поды не могут запланироваться из-за того, что все они связаны правилами совместного существования.

Пример правил совместного/раздельного существования для пода

Рассмотрим следующую спецификацию пода:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: registry.k8s.io/pause:2.0

В примере задается одно правило совместного существования подов, и одно — раздельного. Для совместного правила используется жесткий тип requiredDuringSchedulingIgnoredDuringExecution, для раздельного — мягкий preferredDuringSchedulingIgnoredDuringExecution.

Правило совместного существования гласит, что планировщик может разместить под на узел, только если тот находится в зоне с одним или более подами с лейблом security=S1. Например, если есть кластер с выделенной зоной, назовем ее "V", состоящей из узлов с лейблом topology.kubernetes.io/zone=V, планировщик может назначить под на любой узел зоны V только если в этой зоне уже есть хотя бы один под с лейблом security=S1. И наоборот, если в зоне V нет подов с лейблом security=S1, планировщик не сможет назначить под на какой-либо из узлов в этой зоне.

Правило раздельного существования гласит, что планировщик при возможности не должен размещать под на узел, если тот находится в зоне с одним или более подами с лейблом security=S2. Например, если есть кластер с выделенной зоной, назовем ее "R", состоящей из узлов с лейблами topology.kubernetes.io/zone=R. Планировщик должен избегать назначать поды на узлы из зоны R, если в ней уже есть по крайней мере один под с лейблом security=S2. Соответственно, если в зоне R нет подов с лейблами security=S2, правило раздельного существования не будет влиять на планирование подов в эту зону.

Больше примеров правил совместного/раздельного существования для подов можно найти в рабочей документации.

Поле operator пода поддерживает значения In, NotIn, Exists и DoesNotExist при задании правил совместного/раздельного существования.

Узнать больше о том, как они работают, можно в подразделе Операторы.

В принципе, topologyKey может быть любым разрешенным лейблом-ключом со следующими исключениями по соображениям производительности и безопасности:

  • При задании правил совместного/раздельного существования для подов пустое поле topologyKey не допускается как для requiredDuringSchedulingIgnoredDuringExecution, так и для preferredDuringSchedulingIgnoredDuringExecution.
  • Для правил раздельного существования типа requiredDuringSchedulingIgnoredDuringExecution admission-контроллер разрешает использовать только kubernetes.io/hostname в качестве topologyKey. Для работы с кастомными топологиями admission-контроллер можно дополнить или совсем отключить его.

В дополнение к labelSelector и topologyKey можно опционально указать список пространств имен, которые должен выбирать labelSelector, с помощью поля namespaces на том же уровне, что labelSelector и topologyKey. Если поле namespaces опущено или пусто, по умолчанию выбирается пространство имен пода, в котором задаются правила совместного/раздельного существования.

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

СТАТУС ФИЧИ: Kubernetes v1.24 [stable]

Подходящие пространства имен также можно выбрать с помощью namespaceSelector, который попытается найти лейбл в наборе пространств имен. Условия совместного существования применяются к пространствам имен, выбранным как селектором namespaceSelector, так и полем namespaces. Обратите внимание, что пустой селектор namespaceSelector ({}) выбирает все пространства имен, в то время как пустой или null-список namespaces и null-селектор namespaceSelector выбирает пространство имен пода, в котором правило задано.

matchLabelKeys

СТАТУС ФИЧИ: Kubernetes v1.31 [beta] (enabled by default: true)

Kubernetes включает необязательное поле matchLabelKeys для правил совместного (раздельного) существования подов. В нем указываются ключи для лейблов, которые должны совпадать с лейблами входящего пода, чтобы правила совместного (раздельного) существования выполнялись.

Ключи используются для поиска значений в лейблах подов; эти ключи-лейблы объединяются (с помощью AND) с ограничениями, задаваемыми с помощью поля labelSelector. Такая комбинированная фильтрация позволяет отобрать набор существующих подов, которые приниматься в расчет при обработке правил совместного (раздельного) существования.

Обычно matchLabelKeys используется вместе с pod-template-hash (задается для подов, которые управляются как часть деплоймента, где значение уникально для каждой ревизии). Использование pod-template-hash в matchLabelKeys позволяет нацеливаться на поды, принадлежащие к той же ревизии, что и входящий под. Таким образом, что скользящее обновление не нарушит правила совместного существования.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: application-server
...
spec:
  template:
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - database
            topologyKey: topology.kubernetes.io/zone
            # При расчете affinity подов учитываются только поды из определенного выката.
            # При обновлении Deployment'а новые поды будут следовать своим собственным правилам совместного существования
            # (если они заданы в новом шаблоне подов)
            matchLabelKeys: 
            - pod-template-hash

mismatchLabelKeys

СТАТУС ФИЧИ: Kubernetes v1.31 [beta] (enabled by default: true)

Kubernetes включает необязательное поле mismatchLabelKeys для определения правил совместного (раздельного) существования подов. В поле указываются ключи для лейблов, которые не должны совпадать с лейблами входящего пода, чтобы правила совместного (раздельного) существования подов удовлетворялись.

Один из примеров использования — размещение подов определенной группы пользователей (tenant'ов) или команды в конкретном топологическом домене (узле, зоне и т. д.). То есть идея в том, чтобы избежать одновременного запуска подов от разных групп пользователей в одном топологическом домене.

apiVersion: v1
kind: Pod
metadata:
  labels:
    # Assume that all relevant Pods have a "tenant" label set
    tenant: tenant-a
...
spec:
  affinity:
    podAffinity:      
      requiredDuringSchedulingIgnoredDuringExecution:
      # следим за тем, чтобы поды, связанные с этим тенантом, попадали на нужный пул узлов
      - matchLabelKeys:
          - tenant
        topologyKey: node-pool
    podAntiAffinity:  
      requiredDuringSchedulingIgnoredDuringExecution:
      # следим за тем, чтобы поды, связанные с этим тенантом, не смогли планироваться на узлы для другого тенанта
      - mismatchLabelKeys:
        - tenant # значение лейбла "tenant" этого пода будет предотвращать
                 # планирование на узлы в пулах, на которых работают поды
                 # другого тенанта
        labelSelector:
          # Должен быть labelSelector, который выбирает поды с лейблом tenant,
          # иначе этот под также будет "ненавидеть" поды из daemonset'ов, например, 
          # те, у которых нет лейбла tenant.
          matchExpressions:
          - key: tenant
            operator: Exists
        topologyKey: node-pool

Другие примеры использования

Правила совместного/раздельного существования для подов особенно удобны, когда используются совместно с абстракциями более высокого уровня, такими как ReplicaSet, StatefulSet, Deployment и т. д. Эти правила позволяют настроить размещение рабочих нагрузок с учетом имеющейся топологии; например, пара связанных подов будет планироваться на один и тот же узел.

Представьте кластер, состоящий из трех узлов. Он используется для запуска веб-приложения и как in-memory-кэш (например, Redis). Предположим, что задержка между веб-приложением и кэшем должна быть минимальной. Правила совместного/раздельного существования для подов позволяют настроить планировщик так, чтобы тот размещал веб-серверы как можно ближе к кэшу.

В приведенном ниже примере конфигурации деплоймента с Redis его реплики получают лейбл app=store. Правило podAntiAffinity запрещает планировщику размещать несколько реплик с лейблом app=store на одном узле. В результате каждый узел получает по отдельной кэш-реплике.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  replicas: 3
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine

Конфигурация деплоймента, приведенная ниже, создает три реплики веб-сервера с лейблом app=web-store. Правило совместного существования предписывает планировщику размещать каждую реплику на узле, на котором уже имеется под с лейблом app=store. В то же время правило раздельного существования запрещает планировщику размещать несколько серверов с лейблом app=web-store на одном узле.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx:1.16-alpine

Развертывание ресурсов в соответствии с приведенными выше конфигурациями приведет к созданию кластера, в котором на каждом узле будет по одному веб-серверу и одной реплике Redis (всего три отдельных узла):

узел 1 узел 2 узел 3
webserver-1 webserver-2 webserver-3
cache-1 cache-2 cache-3

В итоге к каждому инстансу Redis'а, скорее всего, будет обращаться клиент, который работает с ним на том же узле. Подобный подход позволит минимизировать как перекос (дисбаланс нагрузки), так и задержки.

Правила совместного/раздельного существования для подов можно использовать и в других случаях.

См., например, руководство по ZooKeeper. В нем с помощью правил раздельного существования StatefulSet настраивается так, чтобы обеспечить высокую доступность (используется подход, аналогичный тому, что применен выше).

nodeName

Поле nodeName в спецификации пода — более непосредственный способ выбора узлов по сравнению с правилами совместного существования или селектором nodeSelector. Если поле nodeName не пустое, планировщик игнорирует под, а kubelet на узле с соответствующим именем пытается разместить под на этом узле. Приоритет поля nodeName выше, чем селектора nodeSelector или правил совместного/раздельного существования.

Однако у nodeName имеются и некоторые недостатки:

  • Если узел с заданным именем не существует, под не будет запущен. Кроме того, в некоторых случаях он может быть автоматически удален.
  • Если на узле с заданным именем недостаточно ресурсов для работы пода, последний будет остановлен; соответствующая причина (например, OutOfmemory или OutOfcpu) будет указана.
  • В облачных окружениях имена узлов не всегда предсказуемы или стабильны.

Ниже приведен пример спецификации пода с полем nodeName:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: kube-01

Такой под будет работать только на узле с именем kube-01.

Ограничения на топологию распределения подов

С помощью ограничений на топологию распределения (topology spread constraints) можно настроить размещение подов в кластере по failure-доменам, таким как регионы, зоны, узлы, или любым другим заданным топологическим конфигурациям. Это позволяет повысить производительность, ожидаемую доступность или эффективность использования ресурсов.

Дополнительные сведения о принципах их работы читайте в разделе Ограничения на топологию распределения подов.

Операторы

Ниже приведены все логические операторы, которые можно использовать в поле operator для nodeAffinity и podAffinity.

Оператор Действие
In Значение лейбла присутствует в предоставленном наборе строк
NotIn Значение лейбла отсутствует в предоставленном наборе строк
Exists Лейбл с таким ключом существует для объекта
DoesNotExist У объекта не существует лейбла с таким ключом

Следующие операторы могут использоваться только с nodeAffinity.

Оператор Действие
Gt Введенное значение будет обработано как целое число, и это целое число меньше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором
Lt Введенное значение будет обработано как целое число, и это целое число больше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором

Что дальше

6.5.2 - Вытеснение, инициированное через API

Вытеснение, инициированное через API — процесс, при котором с помощью Eviction API создается объект Eviction, который запускает корректное завершение работы Pod'а.

Вытеснение можно инициировать напрямую с помощью Eviction API или программно, используя клиент API-сервера (например, командой kubectl drain). В результате будет создан объект Eviction, который запустит процесс контролируемого завершения работы Pod'а.

Вытеснения, инициированные через API, учитывают настройки PodDisruptionBudget и terminationGracePeriodSeconds.

Создание с помощью API объекта Eviction для Pod'а аналогично выполнению операции DELETE для этого Pod'а, которая контролируется политикой.

Вызов API Eviction

Для доступа к API Kubernetes и создания объекта Eviction можно воспользоваться клиентской библиотекой. Необходимая операция оформляется в виде POST-запроса (см. пример ниже):

{
  "apiVersion": "policy/v1",
  "kind": "Eviction",
  "metadata": {
    "name": "quux",
    "namespace": "default"
  }
}

{
  "apiVersion": "policy/v1beta1",
  "kind": "Eviction",
  "metadata": {
    "name": "quux",
    "namespace": "default"
  }
}

Также можно попытаться выполнить операцию вытеснения, обратившись к API с помощью curl или wget, как показано в следующем примере:

curl -v -H 'Content-type: application/json' https://your-cluster-api-endpoint.example/api/v1/namespaces/default/pods/quux/eviction -d @eviction.json

Как работает вытеснение, инициированное через API

При вытеснении, инициированном через API, сервер API выполняет admission-проверки и отвечает одним из следующих способов:

  • 200 OK: вытеснение разрешено, подресурс Eviction создан, Pod удален (аналогично отправке запроса DELETE на URL Pod'а).
  • 429 Too Many Requests: вытеснение в данный момент не разрешено из-за настроек PodDisruptionBudget. Попытку вытеснения можно повторить позже. Такой ответ также может быть вызван работой механизма по ограничению частоты запросов к API.
  • 500 Internal Server Error: вытесение запрещено из-за неправильной конфигурации; например, несколько PodDisruptionBudget'ов могут ссылаться на один и тот же Pod.

Если Pod, предназначенный для вытеснения, не является частью рабочей нагрузки с настроенным PodDisruptionBudget'ом, сервер API всегда возвращает 200 OK и разрешает вытеснение.

В случае, если вытеснение разрешено, процесс удаления Pod'а выглядит следующим образом:

  1. К ресурсу Pod на сервере API добавляется метка времени удаления, после чего сервер API считает ресурс Pod завершенным (terminated). Ресурс Pod также помечается настроенным grace-периодом.
  2. kubelet на узле, где запущен локальный Pod, замечает, что ресурс Pod помечен на удаление, и приступает к корректному завершению работы локального Pod'а.
  3. Пока kubelet завершает работу Pod'а, управляющий слой удаляет Pod из объектов Endpoint и EndpointSlice. В результате контроллеры больше не рассматривают Pod как валидный объект.
  4. После истечения периода корректного завершения работы (grace-периода) kubelet принудительно завершает работу локального Pod'а.
  5. kubelet передает API-серверу информацию о необходимости удалить ресурс Pod.
  6. Сервер API удаляет ресурс Pod.

Зависшие вытеснения

В некоторых ситуациях сбой приводит к тому, что API Eviction начинает возвращать исключительно ответы 429 или 500. Такое может случиться, если, например, за создание Pod'ов для приложения отвечает ReplicaSet, однако новые Pod'ы не переходят в состояние Ready. Подобное поведение также может наблюдаться в случаях, когда у последнего вытесненного Pod'а слишком долгий период завершения работы (grace-период).

Одно из следующих решений может помочь решить проблему:

  • Прервите или приостановите автоматическую операцию, вызвавшую сбой. Перед повторным запуском операции внимательно изучите сбойное приложение.
  • Подождите некоторое время, затем напрямую удалите Pod из управляющего слоя кластера вместо того, чтобы пытаться удалить его с помощью Eviction API.

Что дальше

6.6 - Администрирование кластера

Lower-level detail relevant to creating or administering a Kubernetes cluster.

Обзор администрирования кластера предназначен для всех, кто создает или администрирует кластер Kubernetes. Это предполагает некоторое знакомство с основными концепциями Kubernetes.

Планирование кластера

См. Руководства в разделе настройка для получения примеров того, как планировать, устанавливать и настраивать кластеры Kubernetes. Решения, перечисленные в этой статье, называются distros.

Прежде чем выбрать руководство, вот некоторые соображения:

  • Вы хотите опробовать Kubernetes на вашем компьютере или собрать много узловой кластер высокой доступности? Выбирайте дистрибутивы, наиболее подходящие для ваших нужд.
  • Будете ли вы использовать размещенный кластер Kubernetes, такой, как Google Kubernetes Engine или разместите собственный кластер?
  • Будет ли ваш кластер в помещении или в облаке (IaaS)? Kubernetes не поддерживает напрямую гибридные кластеры. Вместо этого вы можете настроить несколько кластеров.
  • Если вы будете настраивать Kubernetes в помещении (локально), подумайте, какая сетевая модель подходит лучше всего.
  • Будете ли вы запускать Kubernetes на оборудований "bare metal" или на виртуальных машинах (VMs)?
  • Вы хотите запустить кластер или планируете активно разворачивать код проекта Kubernetes? В последнем случае выберите активно разрабатываемый дистрибутив. Некоторые дистрибутивы используют только двоичные выпуски, но предлагают более широкий выбор.
  • Ознакомьтесь с компонентами необходимые для запуска кластера.

Управление кластером

Обеспечение безопасности кластера

Обеспечение безопасности kubelet

Дополнительные кластерные услуги

6.6.1 - Сертификаты

Чтобы узнать, как генерировать сертификаты для кластера, см. раздел Сертификаты.

6.6.2 - Управление ресурсами

Итак, вы развернули приложение и настроили доступ к нему с помощью сервиса. Что дальше? Kubernetes предоставляет ряд инструментов, помогающих управлять развертыванием приложений, включая их масштабирование и обновление. Среди особенностей, которые мы обсудим более подробно, — конфигурационные файлы и лейблы.

Организация конфигураций ресурсов

Многие приложения требуют создания нескольких ресурсов типа Deployment и Service. Управление ими можно упростить, сгруппировав в один YAML-файл (со строкой "---" в качестве разделителя). Например:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Можно создавать сразу несколько ресурсов:

kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created

Ресурсы будут создаваться в порядке, в котором они описаны в файле. Таким образом, первым лучше всего описать сервис — это позволит планировщику распределять Pod'ы этого сервиса по мере их создания контроллером (контроллерами), например, Deployment'ом.

kubectl apply также может принимать сразу несколько аргументов -f:

kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml

Кроме того, можно указывать директории вместо отдельных файлов или в дополнение ним:

kubectl apply -f https://k8s.io/examples/application/nginx/

kubectl прочитает все файлы с расширениями .yaml, .yml или .json.

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

Также в качестве источника конфигурации можно указать URL — это удобно при создании/настройке с использованием конфигурационных файлов, размещенных на GitHub:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created

Пакетные операции в kubectl

Создание ресурсов — не единственная операция, которую kubectl может выполнять в рамках одной команды. Этот инструмент также способен извлекать имена ресурсов из конфигурационных файлов для выполнения других операций, в частности, для удаления созданных ресурсов:

kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted

В случае двух ресурсов их можно перечислить в командной строке, используя синтаксис вида resource/name:

kubectl delete deployments/my-nginx services/my-nginx-svc

При большем количестве ресурсов удобнее указать селектор (запрос по лейблу) с помощью -l или --selector, который отфильтрует ресурсы по их лейблам:

kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted

Поскольку kubectl выводит имена ресурсов в том же синтаксисе, что и получает, можно выстраивать цепочки операций с помощью $() или xargs:

kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {}
NAME           TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)      AGE
my-nginx-svc   LoadBalancer   10.0.0.208   <pending>     80/TCP       0s

Приведенные выше команды сначала создают ресурсы в разделе examples/application/nginx/, выводят о них информацию в формате -o name (то есть в виде пары resource/name). Затем в результатах производится поиск по "service" (grep), и информация о найденных ресурсах выводится с помощью kubectl get.

Если ресурсы хранятся в нескольких поддиректориях в пределах одной директории, можно рекурсивно выполнять операции и в этих поддиректориях, указав --recursive или -R наряду с флагом --filename, -f.

Предположим, что существует директория project/k8s/development, в которой хранятся все манифесты, необходимые для dev-окружения, организованные по типу ресурсов:

project/k8s/development
├── configmap
│   └── my-configmap.yaml
├── deployment
│   └── my-deployment.yaml
└── pvc
    └── my-pvc.yaml

По умолчанию при выполнении массовых операций над project/k8s/development команда остановится на первом уровне, не обрабатывая поддиректории. К примеру, попытка создать ресурсы, описанные в этой директории, приведет к ошибке:

kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)

Вместо этого следует указать флаг --recursive или -R с флагом --filename, -f:

kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created

Флаг --recursive работает с любыми операциями, принимающими флаг --filename, -f, например: kubectl {create, get, delete, describe, rollout} и т.д.

Флаг --recursive также работает для нескольких аргументов -f:

kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created

В разделе Инструмент командной строки kubectl доступна дополнительная информация о kubectl.

Эффективное использование лейблов

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

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

     labels:
        app: guestbook
        tier: frontend

в то время как у master'а и slave'а Redis будут лейблы tier и, возможно, даже дополнительный лейбл role:

     labels:
        app: guestbook
        tier: backend
        role: master

и

     labels:
        app: guestbook
        tier: backend
        role: slave

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

kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME                           READY     STATUS    RESTARTS   AGE       APP         TIER       ROLE
guestbook-fe-4nlpb             1/1       Running   0          1m        guestbook   frontend   <none>
guestbook-fe-ght6d             1/1       Running   0          1m        guestbook   frontend   <none>
guestbook-fe-jpy62             1/1       Running   0          1m        guestbook   frontend   <none>
guestbook-redis-master-5pg3b   1/1       Running   0          1m        guestbook   backend    master
guestbook-redis-slave-2q2yf    1/1       Running   0          1m        guestbook   backend    slave
guestbook-redis-slave-qgazl    1/1       Running   0          1m        guestbook   backend    slave
my-nginx-divi2                 1/1       Running   0          29m       nginx       <none>     <none>
my-nginx-o0ef1                 1/1       Running   0          29m       nginx       <none>     <none>
kubectl get pods -lapp=guestbook,role=slave
NAME                          READY     STATUS    RESTARTS   AGE
guestbook-redis-slave-2q2yf   1/1       Running   0          3m
guestbook-redis-slave-qgazl   1/1       Running   0          3m

Канареечные развертывания

Еще один сценарий, в котором применение нескольких лейблов как нельзя кстати, — дифференциация развертываний отдельных релизов или конфигураций одного и того же компонента. Как правило, новая версия приложения (указанная с помощью тега образа в шаблоне Pod'а) запускается в так называемом канареечном (canary) развертывании параллельно с предыдущей версией. Далее на нее направляется часть реального production-трафика.

В примере ниже лейбл track помогает различить релизы.

У основного, стабильного релиза он будет иметь значение stable:

     name: frontend
     replicas: 3
     ...
     labels:
        app: guestbook
        tier: frontend
        track: stable
     ...
     image: gb-frontend:v3

У нового релиза фронтенда гостевой книги значение этого лейбла будет другим (canary), чтобы два набора Pod'ов не пересекались:

     name: frontend-canary
     replicas: 1
     ...
     labels:
        app: guestbook
        tier: frontend
        track: canary
     ...
     image: gb-frontend:v4

Чтобы охватить оба набора реплик, сервис фронтенда следует настроить на выбор общего подмножества их лейблов (т.е. опустить лейбл track). В результате трафик будет поступать на обе версии приложения:

  selector:
     app: guestbook
     tier: frontend

При этом число стабильных и канареечных реплик можно менять, регулируя долю production-трафика, которую будет получать каждая версия приложения (три к одному в нашем случае). Убедившись в стабильности новой версии, можно поменять значение ее лейбла track с canary на stable.

Более подробный пример доступен в руководстве по развертыванию Ghost.

Обновление лейблов

Иногда возникает необходимость поменять лейблы у существующих Pod'ов и других ресурсов перед созданием новых. Сделать это можно с помощью команды kubectl label. Например, чтобы промаркировать все Pod'ы NGINX как имеющие отношение к фронтенду, выполните следующую команду:

kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled

Сначала она выберет все Pod'ы с лейблом app=nginx, а затем пометит их лейблом tier=fe. Чтобы просмотреть список этих Pod'ов, выполните:

kubectl get pods -l app=nginx -L tier
NAME                        READY     STATUS    RESTARTS   AGE       TIER
my-nginx-2035384211-j5fhi   1/1       Running   0          23m       fe
my-nginx-2035384211-u2c7e   1/1       Running   0          23m       fe
my-nginx-2035384211-u3t6x   1/1       Running   0          23m       fe

Будут выведены все Pod'ы app=nginx с дополнительным столбцом tier (задается с помощью -L или --label-columns).

Дополнительную информацию можно найти в разделах Лейблы и kubectl label.

Обновление аннотаций

Иногда возникает потребность навесить на ресурсы аннотации. Аннотации — это произвольные неидентифицирующие метаданные для извлечения клиентами API (инструментами, библиотеками и т.п.). Добавить аннотацию можно с помощью команды kubectl annotate. Например:

kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
  annotations:
    description: my frontend running nginx
...

Для получения дополнительной информации обратитесь к разделу Аннотации и описанию команды kubectl annotate.

Масштабирование приложения

Для масштабирования приложения можно воспользоваться инструментом kubectl. Например, следующая команда уменьшит число реплик с 3 до 1:

kubectl scale deployment/my-nginx --replicas=1
deployment.apps/my-nginx scaled

После ее применения количество Pod'ов под управлением соответствующего объекта Deployment сократится до одного:

kubectl get pods -l app=nginx
NAME                        READY     STATUS    RESTARTS   AGE
my-nginx-2035384211-j5fhi   1/1       Running   0          30m

Чтобы система автоматически выбирала необходимое количество реплик NGINX в диапазоне от 1 до 3, выполните следующую команду:

kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled

Теперь количество реплик NGINX будет автоматически увеличиваться и уменьшаться по мере необходимости.

Для получения дополнительной информации см. разделы kubectl scale, kubectl autoscale и horizontal pod autoscaler.

Обновление ресурсов "на месте"

Иногда возникает необходимость внести мелкие обновления в созданные ресурсы, не требующие их пересоздания.

kubectl apply

Хранить конфигурационные файлы рекомендуемтся в системе контроля версий (см. конфигурация как код). В этом случае их можно будет поддерживать и версионировать вместе с кодом ресурсов, которые те конфигурируют. Далее с помощью команды kubectl apply изменения, внесенные в конфигурацию, можно применить к кластеру.

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

kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured

Обратите внимание, что kubectl apply добавляет к ресурсу аннотацию, помогающую отслеживать изменения в конфигурации с момента предыдущего вызова. При вызове kubectl apply проводит трехстороннее сравнение (three-way diff) предыдущей конфигурации, ее текущей и новой версий, которое определяет, какие правки следует внести в ресурс.

На данный момент ресурсы в Kubernetes создаются без данной аннотации, поэтому при первом вызове kubectl apply проведет двустороннее сравнение входных данных и текущей конфигурации ресурса. Кроме того, она не cможет определить, какие свойства, заданные при создании ресурса, требуют удаления (соответственно, не будет их удалять).

При всех последующих вызовах kubectl apply и других команд, меняющих конфигурацию, таких как kubectl replace и kubectl edit, аннотация будет обновляться. В результате kubectl apply сможет проводить трехстороннее сравнение (three-way diff), определяя, какие свойства требуют удаления, и удалять их.

kubectl edit

Ресурсы также можно обновлять с помощью команды kubectl edit:

kubectl edit deployment/my-nginx

По сути, kubectl edit объединяет в себе логику нескольких команд, упрощая жизнь пользователям: сначала она получает (get) ресурс, вызывает текстовый редактор, а затем применяет (apply) обновленную конфигурацию:

kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# внесите правки и сохраните файл

kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured

rm /tmp/nginx.yaml

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

За дополнительной информацией обратитесь к разделу kubectl edit.

kubectl patch

Команда kubectl patch обновляет объекты API "на месте". Она поддерживает форматы JSON patch, JSON merge patch и strategic merge patch. См. разделы Обновление объектов API "на месте" с помощью kubectl patch и kubectl patch.

Обновления, требующие перерыва в работе

Иногда может понадобиться обновить поля ресурса, которые нельзя изменить после инициализации, или возникнет необходимость немедленно внести рекурсивные изменения, например, "починить" сбойные Pod'ы, созданные Deployment'ом. Для этого можно воспользоваться командой replace --force, которая удалит и пересоздаст ресурс. Вот как можно внести правки в исходный файл конфигурации в нашем примере:

kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced

Обновление приложения без перерыва в работе

В какой-то момент возникнет необходимость обновить развернутое приложение. Обычно это делают, указывая новый образ или тег образа, как в приведенном выше сценарии канареечного развертывания. kubectl поддерживает несколько видов обновлений, каждый из которых подходит для разных сценариев.

Ниже будет рассказано, как создавать и обновлять приложения с помощью объектов Deployment.

Предположим, что в кластере используется версия NGINX 1.14.2:

kubectl create deployment my-nginx --image=nginx:1.14.2
deployment.apps/my-nginx created

с тремя репликами (чтобы старые и новые ревизии могли сосуществовать):

kubectl scale deployment my-nginx --current-replicas=1 --replicas=3
deployment.apps/my-nginx scaled

Чтобы перейти на версию 1.16.1, измените значение параметра .spec.template.spec.containers[0].image с nginx:1.14.2 на nginx:1.16.1:

kubectl edit deployment/my-nginx

Вот и все! Deployment декларативно обновит развернутое приложение NGINX "за кулисами". При этом Kubernetes проследит, чтобы число недоступных реплик в каждый момент времени не превышало определенного значения, а также за тем, чтобы количество новых реплик не превышало определенного предела, установленного для желаемого числа Pod'ов. Более подробную информацию об этом можно получить в разделе Deployment.

Что дальше

6.6.3 - Сеть в кластере

Сеть — важная часть Kubernetes, но понять, как именно она работает, бывает непросто. Существует 4 уникальных сетевых проблемы, которые требуют внимнаия:

  1. Высокосвязанные коммуникации между контейнерами: решается организацией коммуникации между Pod'ами и localhost.
  2. Связь Pod'ов друг с другом (Pod-to-Pod): именно ей уделяется основное внимание в этом документе.
  3. Связь Pod'ов с сервисами (Pod-to-Service): подробнее об этом можно почитать в разделе Сервисы.
  4. Связь внешних систем с сервисами (External-to-Service): информация о данных коммуникациях также приведена в разделе Сервисы.

Суть Kubernetes — в организации совместного использования хостов приложениями. Обычно совместное использование подразумевает, что два приложения не могут задействовать одни и те же порты. Создать единую глобальную схему использования портов очень сложно. В результате пользователи рискуют получить сложноустранимые проблемы на уровне кластера.

Динамическое распределение портов значительно усложняет систему: каждое приложение должно уметь принимать порты в виде флагов-параметров, серверы API должны уметь вставлять динамические номера портов в конфигурационные блоки, сервисы должны знать, как найти друг друга и т.п. Вместо того чтобы пытаться разобраться со всем этим, Kubernetes использует иной подход.

Больше узнать о сетевой модели Kubernetes можно в соответствующем разделе.

Реализация сетевой модели Kubernetes

Сетевая модель реализуется средой исполнения для контейнеров на узлах. Наиболее распространенные среды исполнения используют плагины Container Network Interface (CNI) для управления сетью и обеспечения безопаснояти коммуникаций. Существует множество различных плагинов CNI от разных разработчиков. Некоторые из них предлагают только базовые функции, такие как добавление и удаление сетевых интерфейсов. Другие позволяют проводить интеграцию с различныеми системами оркестрации контейнеров, поддерживают запуск нескольких CNI-плагинов/расширенные функции IPAM и т.д.

Неполный список сетевых аддонов, поддерживаемых Kubernetes, приведен на соответствующей странице в разделе "Сеть и сетевая политика".

Что дальше

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

6.6.4 - Архитектура для сбора логов

Логи помогают понять, что происходит внутри приложения. Они особенно полезны для отладки проблем и мониторинга деятельности кластера. У большинства современных приложений имеется тот или иной механизм сбора логов. Контейнерные движки в этом смысле не исключение. Самый простой и наиболее распространенный метод сбора логов для контейнерных приложений задействует потоки stdout и stderr.

Однако встроенной функциональности контейнерного движка или среды исполнения обычно недостаточно для организации полноценного решения по сбору логов.

Например, может возникнуть необходимость просмотреть логи приложения при аварийном завершении работы Pod'а, его вытеснении (eviction) или "падении" узла.

В кластере у логов должно быть отдельное хранилище и жизненный цикл, не зависящий от узлов, Pod'ов или контейнеров. Эта концепция называется сбор логов на уровне кластера.

Архитектуры для сбора логов на уровне кластера требуют отдельного бэкенда для их хранения, анализа и выполнения запросов. Kubernetes не имеет собственного решения для хранения такого типа данных. Вместо этого существует множество продуктов для сбора логов, которые прекрасно с ним интегрируются. В последующих разделах описано, как обрабатывать логи и хранить их на узлах.

Основы сбора логов в Kubernetes

В примере ниже используется спецификация Pod с контейнером для отправки текста в стандартный поток вывода раз в секунду.

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args: [/bin/sh, -c,
            'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']

Запустить его можно с помощью следующей команды:

kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml

Результат будет таким:

pod/counter created

Получить логи можно с помощью команды kubectl logs, как показано ниже:

kubectl logs counter

Результат будет таким:

0: Mon Jan  1 00:00:00 UTC 2001
1: Mon Jan  1 00:00:01 UTC 2001
2: Mon Jan  1 00:00:02 UTC 2001
...

Команда kubectl logs --previous позволяет извлечь логи из предыдущего воплощения контейнера. Если в Pod'е несколько контейнеров, выбрать нужный для извлечения логов можно с помощью флага -c:

kubectl logs counter -c count

Для получения дополнительной информации см. документацию по kubectl logs.

Сбор логов на уровне узла

Сбор логов на уровне узла

Среда исполнения для контейнера обрабатывает и перенаправляет любой вывод в потоки stdout и stderr приложения. Docker Engine, например, перенаправляет эти потоки драйверу журналирования, который в Kubernetes настроен на запись в файл в формате JSON.

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

Важным моментом при сборе логов на уровне узла является их ротация, чтобы логи не занимали все доступное место на узле. Kubernetes не отвечает за ротацию логов, но способен развернуть инструмент для решения этой проблемы. Например, в кластерах Kubernetes, развертываемых с помощью скрипта kube-up.sh, имеется инструмент logrotate, настроенный на ежечасный запуск. Также можно настроить среду исполнения контейнера на автоматическую ротацию логов приложения.

Подробную информацию о том, как kube-up.sh настраивает логирование для образа COS на GCP, можно найти в соответствующем скрипте configure-helper.

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

При выполнении команды kubectl logs (как в примере из раздела про основы сбора логов) kubelet на узле обрабатывает запрос и считывает данные непосредственно из файла журнала. Затем он возвращает его содержимое.

Логи системных компонентов

Существует два типа системных компонентов: те, которые работают в контейнере, и те, которые работают за пределами контейнера. Например:

  • планировщик Kubernetes и kube-proxy выполняются в контейнере;
  • kubelet и среда исполнения контейнера работают за пределами контейнера.

На машинах с systemd среда исполнения и kubelet пишут в journald. Если systemd отсутствует, среда исполнения и kubelet пишут в файлы .log в директории /var/log. Системные компоненты внутри контейнеров всегда пишут в директорию /var/log, обходя механизм ведения логов по умолчанию. Они используют библиотеку для сбора логов klog. Правила сбора логов и рекомендации можно найти в соответствующей документации.

Как и логи контейнеров, логи системных компонентов в директории /var/log необходимо ротировать. В кластерах Kubernetes, созданных с помощью скрипта kube-up.sh, эти файлы настроены на ежедневную ротацию с помощью инструмента logrotate или при достижении 100 МБ.

Архитектуры для сбора логов на уровне кластера

Kubernetes не имеет собственного решения для сбора логов на уровне кластера, но есть общие подходы, которые можно рассмотреть. Вот некоторые из них:

  • использовать агент на уровне узлов (запускается на каждом узле);
  • внедрить в Pod с приложением специальный sidecar-контейнер для сбора логов;
  • отправлять логи из приложения непосредственно в бэкенд.

Использование агента на уровне узлов

Использование агента на уровне узлов

Сбор логов на уровне кластера можно реализовать, запустив node-level-агент на каждом узле. Лог-агент — это специальный инструмент, который предоставляет доступ к логам или передает их бэкенду. Как правило, лог-агент представляет собой контейнер с доступом к директории с файлами логов всех контейнеров приложений на этом узле.

Поскольку лог-агент должен работать на каждом узле, рекомендуется запускать его как DaemonSet.

Сбор логов на уровне узла предусматривает запуск одного агента на узел и не требует изменений в приложениях, работающих на узле.

Контейнеры пишут в stdout и stderr, но без согласованного формата. Агент на уровне узла собирает эти логи и направляет их на агрегацию.

Сбор логов с помощью sidecar-контейнера с лог-агентом

Sidecar-контейнер можно использовать одним из следующих способов:

  • sidecar-контейнер транслирует логи приложений на свой собственный stdout;
  • в sidecar-контейнере работает агент, настроенный на сбор логов из контейнера приложения.

Транслирующий sidecar-контейнер

Sidecar-контейнер с транслирующим контейнером

Настроив sidecar-контейнеры на вывод в их собственные потоки stdout и stderr, можно воспользоваться преимуществами kubelet и лог-агента, которые уже работают на каждом узле. Sidecar-контейнеры считывают логи из файла, сокета или journald. Затем каждый из них пишет логи в собственный поток stdout или stderr.

Такой подход позволяет разграничить потоки логов от разных частей приложения, некоторые из которых могут не поддерживать запись в stdout или stderr. Логика, управляющая перенаправлением логов, проста и не требует значительных ресурсов. Кроме того, поскольку stdout и stderr обрабатываются kubelet'ом, можно использовать встроенные инструменты вроде kubectl logs.

Предположим, к примеру, что в Pod'е работает один контейнер, который пишет логи в два разных файла в двух разных форматах. Вот пример конфигурации такого Pod'а:

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

Не рекомендуется писать логи разных форматов в один и тот же поток, даже если удалось перенаправить оба компонента в stdout контейнера. Вместо этого можно создать два sidecar-контейнера. Каждый из них будет забирать определенный лог-файл с общего тома и перенаправлять логи в свой stdout.

Вот пример конфигурации Pod'а с двумя sidecar-контейнерами:

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-1
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-2
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/2.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

Доступ к каждому потоку логов такого Pod'а можно получить отдельно, выполнив следующие команды:

kubectl logs counter count-log-1

Результат будет таким:

0: Mon Jan  1 00:00:00 UTC 2001
1: Mon Jan  1 00:00:01 UTC 2001
2: Mon Jan  1 00:00:02 UTC 2001
...
kubectl logs counter count-log-2

Результат будет таким:

Mon Jan  1 00:00:00 UTC 2001 INFO 0
Mon Jan  1 00:00:01 UTC 2001 INFO 1
Mon Jan  1 00:00:02 UTC 2001 INFO 2
...

Агент на уровне узла, установленный в кластере, подхватывает эти потоки логов автоматически без дополнительной настройки. При желании можно настроить агент на парсинг логов в зависимости от контейнера-источника.

Обратите внимание: несмотря на низкое использование процессора и памяти (порядка нескольких milliCPU для процессора и пары мегабайт памяти), запись логов в файл и их последующая потоковая передача в stdout может вдвое увеличить нагрузку на диск. Если приложение пишет в один файл, рекомендуется установить /dev/stdout в качестве адресата, нежели использовать подход с транслирующим контейнером.

Sidecar-контейнеры также можно использовать для ротации файлов логов, которые не могут быть ротированы самим приложением. В качестве примера можно привести небольшой контейнер, периодически запускающий logrotate. Однако рекомендуется использовать stdout и stderr напрямую, а управление политиками ротации и хранения оставить kubelet'у.

Sidecar-контейнер с лог-агентом

Sidecar-контейнер с лог-агентом

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

Ниже приведены два файла конфигурации sidecar-контейнера с лог-агентом. Первый содержит ConfigMap для настройки fluentd.

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
data:
  fluentd.conf: |
    <source>
      type tail
      format none
      path /var/log/1.log
      pos_file /var/log/1.log.pos
      tag count.format1
    </source>

    <source>
      type tail
      format none
      path /var/log/2.log
      pos_file /var/log/2.log.pos
      tag count.format2
    </source>

    <match **>
      type google_cloud
    </match>    

Второй файл описывает Pod с sidecar-контейнером, в котором работает fluentd. Pod монтирует том с конфигурацией fluentd.

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-agent
    image: registry.k8s.io/fluentd-gcp:1.30
    env:
    - name: FLUENTD_ARGS
      value: -c /etc/fluentd-config/fluentd.conf
    volumeMounts:
    - name: varlog
      mountPath: /var/log
    - name: config-volume
      mountPath: /etc/fluentd-config
  volumes:
  - name: varlog
    emptyDir: {}
  - name: config-volume
    configMap:
      name: fluentd-config

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

Прямой доступ к логам из приложения

Прямой доступ к логам из приложения

Сбор логов приложения на уровне кластера, при котором доступ к ним осуществляется напрямую, выходит за рамки Kubernetes.

6.6.5 - Логи системных компонентов

Логи системных компонентов регистрируют события, происходящие в кластере, что может быть очень полезно при отладке. Степень детализации логов настраивается. Так, в логах низкой детализации будет содержаться только информация об ошибках внутри компонента, в то время как логи высокой детализации будут содержать пошаговую трассировку событий (доступ по HTTP, изменения состояния Pod'а, действия контроллера, решения планировщика).

Klog

klog — библиотека Kubernetes для сбора логов. Отвечает за генерацию соответствующих сообщений для системных компонентов оркестратора.

Дополнительные сведения о настройке klog можно получить в Справке по CLI.

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

  • --add-dir-header
  • --alsologtostderr
  • --log-backtrace-at
  • --log-dir
  • --log-file
  • --log-file-max-size
  • --logtostderr
  • --one-output
  • --skip-headers
  • --skip-log-headers
  • --stderrthreshold

Вывод всегда будет записываться в stderr независимо от его формата. Перенаправление вывода должно осуществляться компонентом, который вызывает компонент Kubernetes, например, POSIX-совместимой командной оболочкой или инструментом вроде systemd.

Иногда эти опции недоступны — например, в случае контейнера без дистрибутива (distroless) или системной службы Windows. Тогда kube-log-runner можно использовать в качестве обертки вокруг компонента Kubernetes для перенаправления вывода. Его предварительно собранный исполняемый файл включен в некоторые базовые образы Kubernetes под старым именем /go-runner, а в актуальных бинарных релизах архивов с kubernetes-server и kubernetes-node он называется kube-log-runner.

В таблице ниже показаны соответствия между вызовами kube-log-runner и логикой перенаправления командной оболочки:

Использование Оболочка POSIX (например, Bash) kube-log-runner <options> <cmd>
Объединить stderr и stdout, вывести в stdout 2>&1 kube-log-runner (default behavior)
Перенаправить оба потока в файл лога 1>>/tmp/log 2>&1 kube-log-runner -log-file=/tmp/log
Скопировать в файл лога и в stdout 2>&1 | tee -a /tmp/log kube-log-runner -log-file=/tmp/log -also-stdout
Перенаправить только stdout в файл лога >/tmp/log kube-log-runner -log-file=/tmp/log -redirect-stderr=false

Вывод klog

Пример оригинального "родного" формата klog:

I1025 00:15:15.525108       1 httplog.go:79] GET /api/v1/namespaces/kube-system/pods/metrics-server-v0.3.1-57c75779f-9p8wg: (1.512ms) 200 [pod_nanny/v0.0.0 (linux/amd64) kubernetes/$Format 10.56.1.19:51756]

Сообщение может содержать переносы строк:

I1025 00:15:15.525108       1 example.go:79] This is a message
which has a line break.

Структурированное логирование

СТАТУС ФИЧИ: Kubernetes v1.23 [beta]

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

По умолчанию структурированные сообщения форматируются как текст, при этом его формат обратно совместим с традиционным форматом klog:

<klog header> "<message>" <key1>="<value1>" <key2>="<value2>" ...

Пример:

I1025 00:15:15.525108       1 controller_utils.go:116] "Pod status updated" pod="kube-system/kubedns" status="ready"

Строки заключаются в кавычки. Другие значения форматируются с помощью %+v. В результате сообщение может продолжиться на следующей строке в зависимости от типа данных.

I1025 00:15:15.525108       1 example.go:116] "Example" data="This is text with a line break\nand \"quotation marks\"." someInt=1 someFloat=0.1 someStruct={StringField: First line,
second line.}

Контекстное логирование

СТАТУС ФИЧИ: Kubernetes v1.24 [alpha]

Контекстное логирование базируется на структурированном логировании. Речь идет в первую очередь о том, как разработчики используют лог-вызовы: код, основанный на этой концепции, более гибок и поддерживает дополнительные сценарии использования (см. Contextual Logging KEP).

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

В настоящее время за включение контекстного логирования отвечает переключатель функционала StructuredLogging. По умолчанию оно отключено. Соответствующая инфраструктура появилась в версии 1.24 и она не потребовала изменений в компонентах. Команда component-base/logs/example показывает, как использовать новые лог-вызовы и как ведет себя компонент, поддерживающий контекстное логирование.

$ cd $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/component-base/logs/example/cmd/
$ go run . --help
...
      --feature-gates mapStringBool  A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
                                     AllAlpha=true|false (ALPHA - default=false)
                                     AllBeta=true|false (BETA - default=false)
                                     ContextualLogging=true|false (ALPHA - default=false)
$ go run . --feature-gates ContextualLogging=true
...
I0404 18:00:02.916429  451895 logger.go:94] "example/myname: runtime" foo="bar" duration="1m0s"
I0404 18:00:02.916447  451895 logger.go:95] "example: another runtime" foo="bar" duration="1m0s"

Префикс example и foo="bar" были добавлены вызовом функции, которая пишет в лог сообщение runtime и значение duration="1m0s", при этом вносить изменения в эту функцию не потребовалось.

При отключенном контекстном логировании WithValues и WithName ничего не делают, а вызовы журнала проходят через глобальный логгер klog. Соответственно, эта дополнительная информация более не отображается в логе:

$ go run . --feature-gates ContextualLogging=false
...
I0404 18:03:31.171945  452150 logger.go:94] "runtime" duration="1m0s"
I0404 18:03:31.171962  452150 logger.go:95] "another runtime" duration="1m0s"

Логи в формате JSON

СТАТУС ФИЧИ: Kubernetes v1.19 [alpha]

Флаг --logging-format=json переключает формат логов с родного формата klog на JSON. Пример лога в формате JSON (стилистически отформатированном):

{
   "ts": 1580306777.04728,
   "v": 4,
   "msg": "Pod status updated",
   "pod":{
      "name": "nginx-1",
      "namespace": "default"
   },
   "status": "ready"
}

Специальные ключи:

  • ts — временная метка в формате времени Unix (обязательный параметр, float);
  • v — детализация (для общей информации — не для сообщений об ошибках, int);
  • err — ошибка (опциональный параметр, string);
  • msg — сообщение (обязательный параметр, string).

Список компонентов, поддерживающих формат JSON:

Уровень детализации лога

Флаг -v задает степень детализации лога. Увеличение значения увеличивает количество регистрируемых событий. Уменьшение значения уменьшает количество регистрируемых событий. Увеличение детализации приводит к тому, что регистрируются все менее значимые события. При уровне детализации, равном 0, регистрируются только критические события.

Местоположение лога

Существует два типа системных компонентов: те, которые работают в контейнере, и те, которые работают за пределами контейнера. Например:

На машинах с systemd среда исполнения и kubelet пишут в journald. В противном случае ведется запись в файлы .log в директории /var/log. Системные компоненты внутри контейнеров всегда пишут в файлы .log в директории /var/log, обходя механизм логирования по умолчанию. Как и логи контейнеров, логи системных компонентов в /var/log нуждаются в ротации. В кластерах Kubernetes, созданных с использованием скрипта kube-up.sh, ротация логов настраивается с помощью инструмента logrotate. logrotate ротирует логи ежедневно или при достижении ими размера в 100 МБ.

Что дальше

6.6.6 - Типы прокси-серверов в Kubernetes

На этой странице рассказывается о различных типах прокси-серверов, которые используются в Kubernetes.

Прокси-серверы

При работе с Kubernetes можно столкнуться со следующими типами прокси-серверов:

  1. kubectl:

    • работает на локальной машине или в Pod'е;
    • поднимает канал связи от локальной машины к интерфейсу API-сервера Kubernetes;
    • данные от клиента к прокси-серверу передаются по HTTP;
    • данные от прокси к серверу API передаются по HTTPS;
    • отвечает за обнаружение сервера API;
    • добавляет заголовки аутентификации.
  2. Прокси-сервер API:

    • бастион, встроенный в API-сервер;
    • подключает пользователя за пределами кластера к IP-адресам кластера, которые в ином случае могут оказаться недоступными;
    • входит в процессы сервера API;
    • данные от клиента к прокси-серверу передаются по HTTPS (или по HTTP, если сервер API настроен соответствующим образом);
    • данные от прокси-сервера к цели передаются по HTTP или HTTPS в зависимости от настроек прокси;
    • используется для доступа к узлам, Pod'ам или сервисам;
    • при подключении к сервису выступает балансировщиком нагрузки.
  3. kube proxy:

    • работает на каждом узле;
    • обрабатывает трафик UDP, TCP и SCTP;
    • "не понимает" HTTP;
    • выполняет функции балансировщика нагрузки;
    • используется только для доступа к сервисам.
  4. Прокси-сервер/балансировщик нагрузки перед API-сервером(-ами):

    • наличие и тип (например, nginx) определяется конфигурацией кластера;
    • располагается между клиентами и одним или несколькими серверами API;
    • балансирует запросы при наличии нескольких серверов API.
  5. Облачные балансировщики нагрузки на внешних сервисах:

    • предоставляются некоторыми облачными провайдерами (например, AWS ELB, Google Cloud Load Balancer);
    • создаются автоматически для сервисов Kubernetes с типом LoadBalancer;
    • как правило, поддерживают только UDP/TCP;
    • наличие поддержки SCTP зависит от реализации балансировщика нагрузки облачного провайдера;
    • реализация варьируется в зависимости от поставщика облачных услуг.

Пользователи Kubernetes, как правило, в своей работе сталкиваются только с прокси-серверами первых двух типов. За настройку остальных типов обычно отвечает администратор кластера.

Запросы на перенаправления

На смену функциям перенаправления (редиректам) пришли прокси-серверы. Перенаправления устарели.

6.6.7 - Равноправный доступ к API

СТАТУС ФИЧИ: Kubernetes v1.20 [beta]

Контроль за поведением API-сервера Kubernetes в условиях высокой нагрузки — ключевая задача для администраторов кластера. В kube-apiserver имеются некоторые механизмы управления (например, флаги командной строки --max-requests-inflight и --max-mutating-requests-inflight) для ограничения нагрузки на сервер. Они предотвращают наплыв входящих запросов и потенциальный отказ сервера API, но не позволяют гарантировать прохождение наиболее важных запросов в периоды высокой нагрузки.

Функция регулирования приоритета и обеспечения равноправного доступа к API (API Priority and Fairness), или РДА, — отличная альтернатива флагам. Она оптимизирует вышеупомянутые ограничения на максимальное количество запросов. РДА тщательнее классифицирует запросы и изолирует их. Также она поддерживает механизм очередей, который помогает обрабатывать запросы при краткосрочных всплесках нагрузки. Отправка запросов из очередей осуществляется на основе метода организации равноправных очередей, поэтому плохо работающий контроллер не будет мешать работе других (даже с аналогичным уровнем приоритета).

Эта функция предназначена для корректной работы со стандартными контроллерами, которые используют информеры и реагируют на неудачные API-запросы, экспоненциально увеличивая выдержку (back-off) между ними, а также клиентами, устроенными аналогичным образом.

Включение/отключение равноправного доступа к API

Управление РДА осуществляется с помощью переключателя функционала (feature gate); по умолчанию функция включена. В разделе Переключатели функционала приведено их общее описание и способы включения/отключения. В случае РДА соответствующий переключатель называется "APIPriorityAndFairness". Данная функция также включает группу API, при этом: (a) версия v1alpha1 по умолчанию отключена, (b) версии v1beta1 и v1beta2 по умолчанию включены. Чтобы отключить РДА и бета-версии групп API, добавьте следующие флаги командной строки в вызов kube-apiserver:

kube-apiserver \
--feature-gates=APIPriorityAndFairness=false \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta1=false,flowcontrol.apiserver.k8s.io/v1beta2=false \
 # …и остальные флаги, как обычно

Кроме того, версию v1alpha1 группы API можно включить с помощью --runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true.

Флаг командной строки --enable-priority-and-fairness=false отключит функцию равноправного доступа к API, даже если другие флаги ее активировали.

Основные понятия

Функция равноправного доступа к API в своей работе использует несколько базовых понятий/механизмов. Входящие запросы классифицируются по атрибутам с помощью т.н. FlowSchemas, после чего им присваиваются уровни приоритета. Уровни приоритета обеспечивают некоторую степень изоляции, обеспечивая различные пределы параллелизма, предотвращая влияние запросов с разными уровнями приоритета друг на друга. В пределах одного приоритета алгоритм равнодоступного формирования очереди предотвращает взаимное влияние запросов из разных потоков и формирует очередь запросов, снижая число неудачных запросов во время всплесков трафика при приемлемо низкой средней нагрузке.

Уровни приоритета

Без включенного равноправного доступа к API управление общим параллелизмом в API-сервере осуществляется флагами --max-requests-inflight и --max-mutating-requests-inflight для kube-apiserver. При включенном равноправном доступе к API пределы параллелизма, заданные этими флагами, суммируются, а затем сумма распределяется по настраиваемому набору уровней приоритета. Каждому входящему запросу присваивается определенный уровень приоритета, причем каждый уровень приоритета может отправлять только такое количество параллельных запросов, которое прописано в его конфигурации.

Конфигурация по умолчанию, например, предусматривает отдельные уровни приоритета для запросов на выборы лидера, запросов от встроенных контроллеров и запросов от Pod'ов. Это означает, что Pod, ведущий себя некорректно и переполняющий API-сервер запросами, не сможет помешать выборам лидера или оказать влияние на действия встроенных контроллеров.

Очереди

Каждый уровень приоритета может включать большое количество различных источников трафика. Во время перегрузки важно предотвратить негативное влияние одного потока запросов на остальные (например, в идеале один сбойный клиент, переполняющий kube-apiserver своими запросами, не должен оказывать заметного влияния на других клиентов). Для этого при обработке запросов с одинаковым уровнем приоритета используется алгоритм равнодоступной очереди. Каждый запрос приписывается к потоку, который идентифицируется по имени соответствующей FlowSchema и дифференциатору потока: пользователю-источнику запроса, пространству имен целевого ресурса или пустым значением. Система старается придать примерно равный вес запросам в разных потоках с одинаковым уровнем приоритета. Для раздельной обработки различных инстансов контроллеры с большим их числом должны аутентифицироваться под разными именами пользователей.

Распределив запрос в некоторый поток, РДА приписывает его к очереди. Этот процесс базируется на методе, известном как shuffle sharding (тасование между шардами), который относительно эффективно изолирует потоки низкой интенсивности от потоков высокой интенсивности с помощью очередей.

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

Запросы-исключения

Некоторые запросы считаются настолько важными, что на них не распространяется ни одно из ограничений, налагаемых этой функцией. Механизм исключений не позволяет ошибочно настроенной конфигурации управления потоком полностью вывести сервер API из строя.

Ресурсы

API управления потоками включает в себя два вида ресурсов. PriorityLevelConfigurations определяет доступные классы изоляции, долю доступного бюджета параллелизма, которая выделяется для каждого класса, и позволяет выполнять тонкую настройку работы с очередями. FlowSchema используется для классификации отдельных входящих запросов, сопоставляя каждый из них с одной из конфигураций PriorityLevelConfiguration. Кроме того, существует версия v1alpha1 данной группы API, с аналогичными Kinds с теми же синтаксисом и семантикой.

PriorityLevelConfiguration

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

Пределы параллелизма для PriorityLevelConfigurations указываются не в виде абсолютного количества запросов, а в виде "долей параллелизма" (concurrency shares). Совокупный объем ресурсов API-сервера, доступных для параллелизма, распределяется между существующими PriorityLevelConfigurations пропорционально этим долям. Администратор кластера может увеличить или уменьшить совокупный объем трафика на сервер, просто перезапустив kube-apiserver с другим значением --max-requests-inflight (или --max-mutating-requests-inflight). В результате пропускная способность каждой PriorityLevelConfigurations возрастет (или снизится) соразмерно ее доле.

Поле type спецификации PriorityLevelConfiguration определяет судьбу избыточных запросов, когда их объем, отнесенный к одной PriorityLevelConfiguration, превышает ее допустимый уровень параллелизма. Тип Reject означает, что избыточный трафик будет немедленно отклонен с ошибкой HTTP 429 (Too Many Requests). Тип Queue означает, что запросы, превышающие пороговое значение, будут поставлены в очередь, при этом для балансировки прогресса между потоками запросов будут использоваться методы тасования между шардами и равноправных очередей.

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

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

  • Увеличение длины очереди (queueLengthLimit) позволяет выдерживать большие всплески трафика без потери запросов за счет увеличения задержек и повышенного потребления памяти.

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

Ниже приведена таблица с различными конфигурациями, показывающая вероятность того, что "мышь" (поток низкой интенсивности) будет раздавлена "слонами" (потоками высокой интенсивности) в зависимости от числа "слонов" при тасовании потоков между шардами. Скрипт для расчета таблицы доступен по ссылке.

Конфигурации shuffle sharding
handSize Число очередей 1 слон 4 слона 16 слонов
12 32 4.428838398950118e-09 0.11431348830099144 0.9935089607656024
10 32 1.550093439632541e-08 0.0626479840223545 0.9753101519027554
10 64 6.601827268370426e-12 0.00045571320990370776 0.49999929150089345
9 64 3.6310049976037345e-11 0.00045501212304112273 0.4282314876454858
8 64 2.25929199850899e-10 0.0004886697053040446 0.35935114681123076
8 128 6.994461389026097e-13 3.4055790161620863e-06 0.02746173137155063
7 128 1.0579122850901972e-11 6.960839379258192e-06 0.02406157386340147
7 256 7.597695465552631e-14 6.728547142019406e-08 0.0006709661542533682
6 256 2.7134626662687968e-12 2.9516464018476436e-07 0.0008895654642000348
6 512 4.116062922897309e-14 4.982983350480894e-09 2.26025764343413e-05
6 1024 6.337324016514285e-16 8.09060164312957e-11 4.517408062903668e-07

FlowSchema

FlowSchema сопоставляется со входящими запросами; по результатам данного действия тем приписывается определенный уровень приоритета. Каждый входящий запрос по очереди проверяется на соответствие каждой FlowSchema, начиная с тех, у которых наименьшее численное значение matchingPrecedence (т.е., логически наивысший приоритет). Проверка ведется до первого совпадения.

Схема FlowSchema подходит определенному запросу, если хотя бы одно из ее правил (rules) подходит ему. В свою очередь, правило соответствует запросу, если ему соответствует хотя бы один из его субъектов (subjects) и хотя бы одно из его правил resourceRules или nonResourceRules (в зависимости от того, является ли входящий запрос ресурсным или нересурсным URL).

Для поля name в субъектах (subjects) и полей verbs, apiGroups, resources, namespaces и nonResourceURLs в ресурсных и нересурсных правилах может быть указан универсальный символ *, который будет соответствовать всем значениям для данного поля, фактически исключая его из рассмотрения.

Параметр distinguisherMethod.type схемы FlowSchema определяет, как запросы, соответствующие этой схеме, будут разделяться на потоки. Он может быть либо ByUser (в этом случае один запрашивающий пользователь не сможет лишить других пользователей ресурсов), либо ByNamespace (в этом случае запросы на ресурсы в одном пространстве имен не смогут помешать запросам на ресурсы в других пространствах имен), либо он может быть пустым (или distinguisherMethod может быть опущен) (в этом случае все запросы, соответствующие данной FlowSchema, будут считаться частью одного потока). Правильный выбор для определенной FlowSchema зависит от ресурса и конкретной среды.

Значения по умолчанию

kube-apiserver поддерживает два вида объектов конфигурации РДА: обязательные и рекомендуемые.

Обязательные объекты конфигурации

Четыре обязательных объекта конфигурации отражают защитное поведение, встроенное в серверы. Оно реализуется независимо от этих объектов; параметры последних просто его отражают.

  • Обязательный уровень приоритета exempt используется для запросов, которые вообще не подчиняются контролю потока: они всегда будут доставляться немедленно. Обязательная FlowSchema exempt относит к этому уровню приоритета все запросы из группы system:masters. При необходимости можно задать другие FlowSchemas, которые будут наделять другие запросы данным уровнем приоритета.

  • Обязательный уровень приоритета catch-all используется в сочетании с обязательной FlowSchema catch-all, гарантируя, что каждый запрос получит какую-либо классификацию. Как правило, полагаться на эту универсальную конфигурацию не следует. Рекомендуется создать свои собственные универсальные FlowSchema и PriorityLevelConfiguration (или использовать опциональный уровень приоритета global-default, доступный по умолчанию). Поскольку предполагается, что обязательный уровень приоритета catch-all будет использоваться редко, его доля параллелизма невысока, кроме того, он не ставит запросы в очередь.

Опциональные объекты конфигурации

Опциональные объекты FlowSchemas и PriorityLevelConfigurations образуют оптимальную конфигурацию по умолчанию. При желании их можно изменить и/или создать дополнительные объекты конфигурации. Если велика вероятность высокой нагрузки на кластер, следует решить, какая конфигурация будет работать лучше всего.

Опциональная конфигурация группирует запросы по шести уровням приоритета:

  • Уровень приоритета node-high предназначен для проверки здоровья узлов.

  • Уровень приоритета system предназначен для запросов от группы system:nodes, не связанных с состоянием узлов, а именно: от kubelet'ов, которые должны иметь возможность связываться с сервером API для планирования рабочих нагрузок.

  • Уровень приоритета leader-election предназначен для запросов на выборы лидера от встроенных контроллеров (в частности, запросы на объекты типа Endpoint, ConfigMap или Lease, поступающие от пользователей system:kube-controller-manager или system:kube-scheduler и служебных учетных записей в пространстве имен kube-system). Их важно изолировать от другого трафика, поскольку сбои при выборе лидеров приводят к перезагрузкам контроллеров. Соответственно, новые контроллеры потребляют трафик, синхронизируя свои информеры.

  • Уровень приоритета workload-high предназначен для прочих запросов от встроенных контроллеров.

  • Уровень приоритета workload-low предназначен для запросов от остальных учетных записей служб, которые обычно включают все запросы от контроллеров, работающих в Pod'ах.

  • Уровень приоритета global-default обрабатывает весь остальной трафик, например, интерактивные команды kubectl, выполняемые непривилегированными пользователями.

Опциональные FlowSchemas служат для направления запросов на вышеуказанные уровни приоритета и здесь не перечисляются.

Обслуживание обязательных и опциональных объектов конфигурации

Каждый kube-apiserver самостоятельно обслуживает обязательные и опциональные объекты конфигурации, используя стратегию начальных/периодических проходов. Таким образом, в ситуации с серверами разных версий может возникнуть пробуксовка (thrashing) из-за разного представления серверов о правильном содержании этих объектов.

Каждый kube-apiserver выполняет начальный проход по обязательным и опциональным объектам конфигурации, а затем периодически (раз в минуту) обходит их.

Для обязательных объектов обслуживание заключается в проверке того, что объект существует и имеет надлежащую спецификацию (spec). Сервер не разрешает создавать или обновлять объекты со spec, которая не соответствует его защитному поведению.

Обслуживание опциональных объектов конфигурации предусматривает возможность переопределения их спецификации (spec). Кроме того, удаление носит непостоянный характер: объект будет восстановлен в процессе обслуживания. Если опциональный объект конфигурации не нужен, его не нужно удалять, но достаточно настроить spec'и так, чтобы последствия были минимальными. Обслуживание опциональных объектов также рассчитано на поддержку автоматической миграции при выходе новой версии kube-apiserver, при этом вероятны конфликты (thrashing), пока группировка серверов остается смешанной.

Обслуживание опционального объекта конфигурации предусматривает его создание — с рекомендуемой спецификацией сервера — если тот не существует. В то же время, если объект уже существует, поведение при обслуживании зависит от того, кто им управляет — kube-apiserver'ы или пользователи. В первом случае сервер гарантирует, что спецификация объекта соответствует рекомендуемой; во втором случае спецификация не анализируется.

Чтобы узнать, кто управляет объектом, необходимо найти аннотацию с ключом apf.kubernetes.io/autoupdate-spec. Если такая аннотация существует и ее значение равно true, то объект контролируется kube-apiserver'ами. Если аннотация существует и ее значение равно false, объект контролируется пользователями. Если ни одно из этих условий не выполняется, выполняется обращение к metadata.generation объекта. Если этот параметр равен 1, объект контролируется kube-apiserver'ами. В противном случае объект контролируют пользователи. Эти правила были введены в версии 1.22, и использование metadata.generation обусловлено переходом от более простого предыдущего поведения. Пользователи, желающие контролировать опциональный объект конфигурации, должны убедиться, что его аннотация apf.kubernetes.io/autoupdate-spec имеет значение false.

Обслуживание обязательного или опционального объекта конфигурации также предусматривает проверку наличия у него аннотации apf.kubernetes.io/autoupdate-spec, которая позволяет понять, контролируют ли его kube-apiserver'ы.

Обслуживание также предусматривает удаление объектов, которые не являются ни обязательными, ни опциональными, но имеют аннотацию apf.kubernetes.io/autoupdate-spec=true.

Освобождение проверок работоспособности от параллелизма

Опциональная конфигурация не предусматривает особого отношения к health check-запросам на kube-apiserver'ы от их локальных kubelet'ов. В данном случае обычно используется защищенный порт, но учетные данные не передаются. В опциональной конфигурации такие запросы относятся к FlowSchema global-default и соответствующему уровню приоритета global-default, где другой трафик может мешать их прохождению.

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

apiVersion: flowcontrol.apiserver.k8s.io/v1beta3
kind: FlowSchema
metadata:
  name: health-for-strangers
spec:
  matchingPrecedence: 1000
  priorityLevelConfiguration:
    name: exempt
  rules:
  - nonResourceRules:
    - nonResourceURLs:
      - "/healthz"
      - "/livez"
      - "/readyz"
      verbs:
      - "*"
    subjects:
    - kind: Group
      group:
        name: system:unauthenticated

Диагностика

Каждый HTTP-ответ от сервера API с включенной функцией РДА содержит два дополнительных заголовка: X-Kubernetes-PF-FlowSchema-UID и X-Kubernetes-PF-PriorityLevel-UID. В них указываются схема потока и уровень приоритета соответственно. Имена объектов API не включаются в эти заголовки на случай, если запрашивающий пользователь не обладает правами на их просмотр, поэтому при отладке можно использовать команду типа:

kubectl get flowschemas -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
kubectl get prioritylevelconfigurations -o custom-columns="uid:{metadata.uid},name:{metadata.name}"

чтобы привязать UID к именам для FlowSchemas и PriorityLevelConfigurations.

Наблюдаемость

Метрики

При включении функции равноправного доступа к API kube-apiserver начинает экспортировать дополнительные метрики. Их мониторинг помогает выявить негативное влияние (throttling) текущей конфигурации на важный трафик или найти неэффективные рабочие нагрузки, которые вредят здоровью системы.

  • apiserver_flowcontrol_rejected_requests_total — вектор-счетчик (кумулятивный с момента запуска сервера) запросов, которые были отклонены, с разбивкой по лейблам flow_schema (указывает на FlowSchema у запросов, попавших под соответствие), priority_level (уровень приоритета, который был присвоен этим запросам) и reason. Лейбл reason будет иметь одно из следующих значений:

    • queue-full — в очереди уже слишком много запросов;
    • concurrency-limit — PriorityLevelConfiguration настроена на отклонение, а не на постановку в очередь избыточных запросов;
    • time-out — запрос все еще находился в очереди, когда истек его лимит ожидания.
  • apiserver_flowcontrol_dispatched_requests_total — вектор-счетчик (кумулятивный с момента запуска сервера) запросов, которые начали выполняться, сгруппированный по лейблам flow_schema (указывает на FlowSchema у запросов, попавших под соответствие) и priority_level (уровень приоритета, который был присвоен этим запросам).

  • apiserver_current_inqueue_requests — вектор предыдущего максимума числа запросов в очереди, сгруппированных по лейблу request_kind, значение которого mutating или readOnly. Эти максимумы описывают наибольшее число, наблюдавшееся в последнем завершенном односекундном окне. Они дополняют более старый вектор apiserver_current_inflight_requests, который показывает максимум активно обслуживаемых запросов в последнем окне.

  • apiserver_flowcontrol_read_vs_write_request_count_samples — вектор-гистограмма наблюдений за тогда-текущим количеством запросов с разбивкой по лейблам phase (принимает значения waiting и executing) и request_kind (принимает значения mutating и readOnly). Наблюдения проводятся периодически с высокой частотой. Каждое наблюдаемое значение представляет собой число в диапазоне от 0 до 1, равное отношению числа запросов к соответствующему ограничению на их количество (ограничение длины очереди в случае ожидания и лимит параллелизма в случае выполнения).

  • apiserver_flowcontrol_read_vs_write_request_count_watermarks — вектор-гистограмма максимумов или минимумов количества запросов (число запросов, деленное на соответствующее ограничение) с разбивкой по лейблам phase (принимает значения waiting и executing) и request_kind (принимает значения mutating и readOnly); лейбл mark принимает значения high и low. Минимумы и максимумы собираются в окнах, ограниченных временем, когда наблюдение было добавлено в apiserver_flowcontrol_read_vs_write_request_count_samples. Эти экстремумы помогают определить разброс диапазона значений, наблюдавшийся в разных сэмплах.

  • apiserver_flowcontrol_current_inqueue_requests — gauge-вектор, содержащий количество стоящих в очереди (не выполняющихся) запросов в каждый момент с разбивкой по лейблам priority_level и flow_schema.

  • apiserver_flowcontrol_current_executing_requests — gauge-вектор, содержащий количество исполняемых (не ожидающих в очереди) запросов в каждый момент с разбивкой по лейблам priority_level и flow_schema.

  • apiserver_flowcontrol_request_concurrency_in_use — gauge-вектор, содержащий количество занятых мест в каждый момент с разбивкой по лейблам priority_level и flow_schema.

  • apiserver_flowcontrol_priority_level_request_count_samples — вектор-гистограмма наблюдений за текущим-на-тот-момент количеством запросов с разбивкой по лейблам phase (принимает значения waiting и executing) и priority_level. Каждая гистограмма получает наблюдения, сделанные периодически, вплоть до последней активности соответствующего рода. Наблюдения проводятся с высокой частотой. Каждое наблюдаемое значение представляет собой число в диапазоне от 0 до 1, равное отношению числа запросов к соответствующему ограничению на их количество (ограничение длины очереди в случае ожидания и лимит параллелизма в случае выполнения).

  • apiserver_flowcontrol_priority_level_request_count_watermarks — вектор-гистограмма максимумов или минимумов количества запросов с разбивкой по лейблам phase (принимает значения waiting и executing) и priority_level; лейбл mark принимает значения high и low. Минимумы и максимумы собираются в окнах, ограниченных временем, когда наблюдение было добавлено в apiserver_flowcontrol_priority_level_request_count_samples. Эти экстремумы показывают диапазон значений, наблюдавшийся в разных сэмплах.

  • apiserver_flowcontrol_priority_level_seat_count_samples — вектор-гистограмма наблюдений за использованием лимита параллелизма для уровня приоритета с разбивкой по priority_level. Использование — отношение (количество занятых мест) / (предел параллелизма). Метрика учитывает все стадии выполнения (как обычную, так и дополнительную задержку в конце записи для покрытия соответствующей работы по уведомлению) всех запросов, кроме WATCHes; для этих запросов учитывается только начальная стадия по доставке уведомлений о ранее существующих объектах. Каждая гистограмма в векторе также помечена лейблом phase: executing (количество мест для фазы ожидания не ограничено). Каждая гистограмма получает наблюдения, сделанные периодически, вплоть до последней активности соответствующего рода. Наблюдения производятся с высокой частотой.

  • apiserver_flowcontrol_priority_level_seat_count_watermarks — вектор-гистограмма минимумов и максимумов использования предела параллелизма для уровня приоритета с разбивкой по priority_leve и mark (принимает значения high и low). Каждая гистограмма в векторе также помечена лейблом phase: executing (для фазы ожидания предел на места отсутствует). Максимумы и минимумы собираются в окнах, ограниченных временем, когда наблюдение было добавлено в apiserver_flowcontrol_priority_level_seat_count_samples. Эти экстремумы помогают определить разброс диапазона значений, наблюдавшийся в разных сэмплах.

  • apiserver_flowcontrol_request_queue_length_after_enqueue — вектор-гистограмма длины очереди для очередей с разбивкой по лейблам priority_level и flow_schema как выборки по поставленным в очередь запросам. Каждый запрос при постановке в очередь вносит один сэмпл в гистограмму, сообщая о длине очереди сразу после добавления запроса. Обратите внимание, что это дает иную статистику, чем при объективном исследовании.

  • apiserver_flowcontrol_request_concurrency_limit — gauge-вектор, содержащий вычисленный лимит параллелизма (основанный на общем лимите параллелизма сервера API и долях параллелизма PriorityLevelConfigurations), с разбивкой по лейблу priority_level.

  • apiserver_flowcontrol_request_wait_duration_seconds — вектор-гистограмма времени ожидания запросов в очереди с разбивкой по лейблам flow_schema (указывает, какая схема соответствует запросу), priority_level (указывает, к какому уровню был отнесен запрос) и execute (указывает, начал ли запрос выполняться).

  • apiserver_flowcontrol_request_execution_seconds — вектор-гистограмма времени, затраченного на выполнение запросов, с разбивкой по по лейблам flow_schema (указывает, какая схема соответствует запросу) и priority_level (указывает, к какому уровню был отнесен запрос).

  • apiserver_flowcontrol_watch_count_samples — вектор-гистограмма количества активных запросов WATCH, относящихся к данной записи, с разбивкой по flow_schema и priority_level.

  • apiserver_flowcontrol_work_estimated_seats — вектор-гистограмма количества предполагаемых мест (максимум начального и конечного этапа выполнения), связанных с запросами, с разбивкой по flow_schema и priority_level.

  • apiserver_flowcontrol_request_dispatch_no_accommodation_total — вектор-счетчик количества событий, которые в принципе могли бы привести к отправке запроса, но не привели из-за отсутствия доступного параллелизма, с разбивкой по flow_schema и priority_level. Соответствующими событиями являются поступление запроса и завершение запроса.

Отладочные endpoint'ы

При включении функции равноправного доступа к API kube-apiserver предоставляет следующие дополнительные пути на своих HTTP[S]-портах.

  • /debug/api_priority_and_fairness/dump_priority_levels — список всех уровней приоритета и текущее состояние каждого из них. Получить его можно следующим образом:

    kubectl get --raw /debug/api_priority_and_fairness/dump_priority_levels
    

    Вывод выглядит примерно так:

    PriorityLevelName, ActiveQueues, IsIdle, IsQuiescing, WaitingRequests, ExecutingRequests,
    workload-low,      0,            true,   false,       0,               0,
    global-default,    0,            true,   false,       0,               0,
    exempt,            <none>,       <none>, <none>,      <none>,          <none>,
    catch-all,         0,            true,   false,       0,               0,
    system,            0,            true,   false,       0,               0,
    leader-election,   0,            true,   false,       0,               0,
    workload-high,     0,            true,   false,       0,               0,
    
  • /debug/api_priority_and_fairness/dump_queues — список всех очередей и их текущее состояние. Получить его можно следующим образом:

    kubectl get --raw /debug/api_priority_and_fairness/dump_queues
    

    Вывод выглядит примерно так:

    PriorityLevelName, Index,  PendingRequests, ExecutingRequests, VirtualStart,
    workload-high,     0,      0,               0,                 0.0000,
    workload-high,     1,      0,               0,                 0.0000,
    workload-high,     2,      0,               0,                 0.0000,
    ...
    leader-election,   14,     0,               0,                 0.0000,
    leader-election,   15,     0,               0,                 0.0000,
    
  • /debug/api_priority_and_fairness/dump_requests — список всех запросов, которые в настоящее время ожидают в очереди. Получить его можно следующим образом:

    kubectl get --raw /debug/api_priority_and_fairness/dump_requests
    

    Вывод выглядит примерно так:

    PriorityLevelName, FlowSchemaName, QueueIndex, RequestIndexInQueue, FlowDistingsher,       ArriveTime,
    exempt,            <none>,         <none>,     <none>,              <none>,                <none>,
    system,            system-nodes,   12,         0,                   system:node:127.0.0.1, 2020-07-23T15:26:57.179170694Z,
    

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

    Более подробный список можно получить с помощью следующей команды:

    kubectl get --raw '/debug/api_priority_and_fairness/dump_requests?includeRequestDetails=1'
    

    Вывод выглядит примерно так:

    PriorityLevelName, FlowSchemaName, QueueIndex, RequestIndexInQueue, FlowDistingsher,       ArriveTime,                     UserName,              Verb,   APIPath,                                                     Namespace, Name,   APIVersion, Resource, SubResource,
    system,            system-nodes,   12,         0,                   system:node:127.0.0.1, 2020-07-23T15:31:03.583823404Z, system:node:127.0.0.1, create, /api/v1/namespaces/scaletest/configmaps,
    system,            system-nodes,   12,         1,                   system:node:127.0.0.1, 2020-07-23T15:31:03.594555947Z, system:node:127.0.0.1, create, /api/v1/namespaces/scaletest/configmaps,
    

Что дальше

Для получения подробной информации о функции равноправного доступа к API см. предложение по улучшению (KEP). Предложения и запросы функционала принимаются через SIG API Machinery или в специализированном канале Slack.

6.6.8 - Установка дополнений

Надстройки расширяют функциональность Kubernetes.

На этой странице перечислены некоторые из доступных надстроек и ссылки на соответствующие инструкции по установке.

Сеть и сетевая политика

  • ACI обеспечивает интегрированную сеть контейнеров и сетевую безопасность с помощью Cisco ACI.
  • Antrea работает на уровне 3, обеспечивая сетевые службы и службы безопасности для Kubernetes, используя Open vSwitch в качестве уровня сетевых данных.
  • Calico Calico поддерживает гибкий набор сетевых опций, поэтому вы можете выбрать наиболее эффективный вариант для вашей ситуации, включая сети без оверлея и оверлейные сети, с или без BGP. Calico использует тот же механизм для обеспечения соблюдения сетевой политики для хостов, модулей и (при использовании Istio и Envoy) приложений на уровне сервисной сети (mesh layer).
  • Canal объединяет Flannel и Calico, обеспечивая сеть и сетевую политику.
  • Cilium - это плагин сети L3 и сетевой политики, который может прозрачно применять политики HTTP/API/L7. Поддерживаются как режим маршрутизации, так и режим наложения/инкапсуляции, и он может работать поверх других подключаемых модулей CNI.
  • CNI-Genie позволяет Kubernetes легко подключаться к выбору плагинов CNI, таких как Calico, Canal, Flannel, Romana или Weave.
  • Contrail, основан на Tungsten Fabric, представляет собой платформу для виртуализации мультиоблачных сетей с открытым исходным кодом и управления политиками. Contrail и Tungsten Fabric интегрированы с системами оркестрации, такими как Kubernetes, OpenShift, OpenStack и Mesos, и обеспечивают режимы изоляции для виртуальных машин, контейнеров/подов и рабочих нагрузок без операционной системы.
  • Flannel - это поставщик оверлейной сети, который можно использовать с Kubernetes.
  • Knitter - это плагин для поддержки нескольких сетевых интерфейсов Kubernetes подов.
  • Multus - это плагин Multi для работы с несколькими сетями в Kubernetes, который поддерживает большинство самых популярных CNI (например: Calico, Cilium, Contiv, Flannel), в дополнение к рабочим нагрузкам основанных на SRIOV, DPDK, OVS-DPDK и VPP в Kubernetes.
  • OVN-Kubernetes - это сетевой провайдер для Kubernetes основанный на OVN (Open Virtual Network), реализация виртуальной сети, появившийся в результате проекта Open vSwitch (OVS). OVN-Kubernetes обеспечивает сетевую реализацию на основе наложения для Kubernetes, включая реализацию балансировки нагрузки и сетевой политики на основе OVS.
  • OVN4NFV-K8S-Plugin - это подключаемый модуль контроллера CNI на основе OVN для обеспечения облачной цепочки сервисных функций (SFC), несколько наложенных сетей OVN, динамического создания подсети, динамического создания виртуальных сетей, сети поставщика VLAN, сети прямого поставщика и подключаемого к другим Multi Сетевые плагины, идеально подходящие для облачных рабочих нагрузок на периферии в сети с несколькими кластерами.
  • NSX-T плагин для контейнера (NCP) обеспечивающий интеграцию между VMware NSX-T и контейнерами оркестраторов, таких как Kubernetes, а так же интеграцию между NSX-T и контейнеров на основе платформы CaaS/PaaS, таких как Pivotal Container Service (PKS) и OpenShift.
  • Nuage - эта платформа SDN, которая обеспечивает сетевое взаимодействие на основе политик между Kubernetes подами и не Kubernetes окружением, с отображением и мониторингом безопасности.
  • Romana - это сетевое решение уровня 3 для сетей подов, которое также поддерживает NetworkPolicy API. Подробности установки Kubeadm доступны здесь.
  • Weave Net предоставляет сеть и обеспечивает сетевую политику, будет работать на обеих сторонах сетевого раздела и не требует внешней базы данных.

Обнаружение служб

  • CoreDNS - это гибкий, расширяемый DNS-сервер, который может быть установлен в качестве внутрикластерного DNS для подов.

Визуализация и контроль

  • Dashboard - это веб-интерфейс панели инструментов для Kubernetes.

Инфраструктура

  • KubeVirt - это дополнение для запуска виртуальных машин в Kubernetes. Обычно работает на bare-metal кластерах.

Legacy Add-ons

В устаревшем каталоге cluster/addons задокументировано несколько других дополнений.

Ссылки на те, в хорошем состоянии, должны быть здесь. Пул реквесты приветствуются!

7 - Руководства

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

Основы

Конфигурирование

Приложения без состояния

Приложения с состоянием

Кластеры

Сервисы

Что дальше

Если вы хотите создать руководство самостоятельно, обратитесь к странице Использование шаблонов страниц, чтобы узнать информацию и посмотреть шаблоны для составления руководств.

7.1 - Привет, Minikube

Это руководство демонстрирует, как запустить простое приложение в Kubernetes с помощью minikube. Для этого используется образ контейнера с NGINX, который выводит обратно текст всех запросов.

Цели

  • Развернуть простое приложение в minikube.
  • Запустить приложение.
  • Посмотреть логи приложения.

Подготовка к работе

Руководство подразумевает, что вы уже настроили minikube. См. документацию minikube start для инструкций по его установке.

Вам также потребуется установить kubectl. См. Установку и настройку kubectl для инструкций по его установке.

Создание кластера minikube

minikube start

Запуск панели (dashboard)

Откройте панель Kubernetes. Это можно сделать двумя способами:

Откройте новый терминал и запустите:

# Запустите в новом терминале и не закрывайте его.
minikube dashboard

Теперь можно вернуться к терминалу, где вы запускали minikube start.

Если вы не хотите, чтобы minikube запускал веб-браузер, выполните команду dashboard с флагом --url. В этом случае minikube выведет URL, который вы можете открыть в любом браузере.

Откройте новый терминал и запустите:

# Запустите в новом терминале и не закрывайте его.
minikube dashboard --url

Теперь можно вернуться к терминалу, где вы запускали minikube start.

Создание деплоймента

Под Kubernetes — это группа из одного или более контейнеров, связанных друг с другом для удобного администрирования и организации сети. В данном руководстве под включает в себя один контейнер. Деплоймент (Deployment) в Kubernetes проверяет здоровье пода и перезагружает контейнер пода в случае, если он прекратил работу. Деплойменты — рекомендуемый способ создания и масштабирования подов.

  1. Используйте команду kubectl create для создания деплоймента, который будет управлять подом. Под запустит контейнер с указанным Docker-образом.

    # Запуск тестового образа контейнера с веб-сервером
    kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port=8080
    
  2. Посмотреть информацию о Deployment:

    kubectl get deployments
    

    Вывод будет примерно следующим:

    NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    hello-node   1         1         1            1           1m
    
  3. Посмотреть информацию о поде:

    kubectl get pods
    

    Вывод будет примерно следующим:

    NAME                          READY     STATUS    RESTARTS   AGE
    hello-node-5f76cf6ccf-br9b5   1/1       Running   0          1m
    
  4. Посмотреть события кластера:

    kubectl get events
    
  5. Посмотреть конфигурацию kubectl:

    kubectl config view
    

Создание сервиса

По умолчанию под доступен только при обращении по его внутреннему IP-адресу внутри кластера Kubernetes. Чтобы сделать контейнер hello-node доступным вне виртуальной сети Kubernetes, необходимо представить под как сервис Service Kubernetes.

  1. Сделать под доступным для публичного интернета можно с помощью команды kubectl expose:

    kubectl expose deployment hello-node --type=LoadBalancer --port=8080
    

    Флаг --type=LoadBalancer показывает, что сервис должен быть виден вне кластера.

    Код приложения в тестовом образе прослушивает только TCP-порт 8080. Если вы сделали приложение доступным по другому порту командой kubectl expose, клиенты не смогут подключиться к этому порту.

  2. Посмотреть только что созданный сервис:

    kubectl get services
    

    Вывод будет примерно следующим:

    NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    hello-node   LoadBalancer   10.108.144.78   <pending>     8080:30369/TCP   21s
    kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          23m
    

    Для облачных провайдеров, поддерживающих балансировщики нагрузки, для доступа к сервису будет предоставлен внешний IP адрес. В Minikube тип LoadBalancer делает сервис доступным при обращении с помощью команды minikube service.

  3. Выполните следующую команду:

    minikube service hello-node
    

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

Активация дополнений

В minikube есть набор встроенных дополнений (addons), которые могут быть включены, выключены и открыты в локальном окружении Kubernetes.

  1. Отобразить текущие поддерживаемые дополнения:

    minikube addons list
    

    Вывод будет примерно следующим:

    addon-manager: enabled
    dashboard: enabled
    default-storageclass: enabled
    efk: disabled
    freshpod: disabled
    gvisor: disabled
    heapster: disabled
    helm-tiller: disabled
    ingress: disabled
    ingress-dns: disabled
    logviewer: disabled
    metrics-server: disabled
    nvidia-driver-installer: disabled
    nvidia-gpu-device-plugin: disabled
    registry: disabled
    registry-creds: disabled
    storage-provisioner: enabled
    storage-provisioner-gluster: disabled
    
  2. Включить дополнение, например, metrics-server:

    minikube addons enable metrics-server
    

    Вывод:

    metrics-server was successfully enabled
    
  3. Посмотреть Pod и Service, которые вы только что создали:

    kubectl get pod,svc -n kube-system
    

    Вывод будет примерно следующим:

    NAME                                        READY     STATUS    RESTARTS   AGE
    pod/coredns-5644d7b6d9-mh9ll                1/1       Running   0          34m
    pod/coredns-5644d7b6d9-pqd2t                1/1       Running   0          34m
    pod/metrics-server-67fb648c5                1/1       Running   0          26s
    pod/etcd-minikube                           1/1       Running   0          34m
    pod/influxdb-grafana-b29w8                  2/2       Running   0          26s
    pod/kube-addon-manager-minikube             1/1       Running   0          34m
    pod/kube-apiserver-minikube                 1/1       Running   0          34m
    pod/kube-controller-manager-minikube        1/1       Running   0          34m
    pod/kube-proxy-rnlps                        1/1       Running   0          34m
    pod/kube-scheduler-minikube                 1/1       Running   0          34m
    pod/storage-provisioner                     1/1       Running   0          34m
    
    NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
    service/metrics-server         ClusterIP   10.96.241.45    <none>        80/TCP              26s
    service/kube-dns               ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP       34m
    service/monitoring-grafana     NodePort    10.99.24.54     <none>        80:30002/TCP        26s
    service/monitoring-influxdb    ClusterIP   10.111.169.94   <none>        8083/TCP,8086/TCP   26s
    
  4. Отключить metrics-server:

    minikube addons disable metrics-server
    

    Вывод будет примерно следующим:

    metrics-server was successfully disabled
    

Очистка

Теперь вы можете освободить ресурсы, созданные в кластере:

kubectl delete service hello-node
kubectl delete deployment hello-node

Остановите кластер minikube:

minikube stop

Удалите виртуальную машину minikube (опционально):

minikube delete

Если вы планируете использовать minikube в дальнейшем, чтобы больше узнать про Kubernetes, удалять инструмент не нужно.

Что дальше

7.2 - Основы Kubernetes

Основы Kubernetes

В данном руководстве вы познакомитесь с основами системы оркестрации кластеров Kubernetes. Каждый модуль содержит краткую справочную информацию по основной функциональности и концепциям Kubernetes, а также включает интерактивные онлайн-уроки. С их помощью вы научитесь самостоятельно управлять простым кластером и контейнеризированными приложениями, которые были в нём развернуты.

Пройдя интерактивные уроки, вы узнаете, как:

  • развёртывать контейнеризированное приложение в кластер;
  • масштабировать развёртывание;
  • обновить контейнеризированное приложение на новую версию ПО;
  • отлаживать контейнеризированное приложение.

Чем может Kubernetes помочь вам?

От современных веб-сервисов пользователи ожидают, что приложения будут доступны 24/7, а разработчики — развёртывать новые версии приложений по нескольку раз в день. Контейнеризация направлена на достижение этой цели, поскольку позволяет выпускать и обновлять приложения без простоев. Kubernetes гарантирует, что ваши контейнеризованные приложения будет запущены где угодно и когда угодно, вместе со всеми необходимыми для их работы ресурсами и инструментами. Kubernetes — это готовая к промышленному использованию платформа с открытым исходным кодом, разработанная на основе накопленного опыта Google по оркестровке контейнеров и вобравшая в себя лучшие идеи от сообщества.


7.2.1 - Создание кластера

7.2.1.1 - Использование minikube для создания кластера

Узнайте, что такое кластер Kubernetes. Узнайте, что такое minikube. Запустите Kubernetes-кластер.

Цели

  • Узнать, что такое кластер Kubernetes
  • Узнать, что такое minikube
  • Запустить кластер Kubernetes

Кластеры Kubernetes

Задача Kubernetes заключается в координации кластера компьютеров, работающего как одно целое. Абстрактные объекты в Kubernetes позволяют развертывать контейнеризированные приложения в кластер, не привязывая их к отдельным машинам. Для использования этой новой модели развертывания, приложения должны быть подготовлены так, чтобы они не зависели от конкретных хостов, т.е. они должны быть упакованы в контейнеры. Приложения в контейнерах более гибки и доступны, чем в предыдущих моделях развертывания, когда приложения устанавливались непосредственно на конкретные машины в виде пакетов, тесно связанных с хостом. Kubernetes автоматизирует распределение и выполнение контейнеров приложений для запуска в кластере более эффективным образом. Kubernetes — это платформа с открытым исходным кодом, готовая к промышленной эксплуатации.

Кластер Kubernetes состоит из двух типов ресурса:

  • Мастер (ведущий узел) управляет кластером
  • Рабочие узлы — машины, на которых выполняются приложения

Краткое содержание:

  • Кластер Kubernetes
  • Minikube

Kubernetes — платформа с открытым исходным кодом промышленного уровня, которая управляет размещением (планированием) и запуском контейнеров приложений в пределах компьютерных кластеров и между ними.


Схема кластера


Мастер отвечает за управление кластером. Мастер координирует все процессы в кластере, такие как планирование выполнения приложений, сохранение требуемого состояния приложений, а также их масштабирование и обновление.

Узел — это виртуальная машина или физический компьютер, который выполняет роль рабочего узла в кластере Kubernetes. У каждого узла есть Kubelet — агент, управляющий узлом и взаимодействующий с ведущим узлом Kubernetes. Узел также имеет инструменты для выполнения контейнерных операций, например, Docker или rkt. Кластер Kubernetes в промышленном окружении должен состоять как минимум из трёх узлов.

Ведущие узлы управляют кластером и узлами, которые используются для запуска приложений.

При развертывании приложений в Kubernetes вы сообщаете ведущему узлу запускать контейнеры приложений. Ведущий узел планирует выполнение контейнеров на узлах кластера. Узлы взаимодействуют с ведущим узлом посредством API Kubernetes, который предлагает ведущий узел. Кроме этого, конечные пользователи могут напрямую использовать API Kubernetes для работы с кластером.

Kubernetes-кластер может быть развернут на физических или виртуальных машинах. Чтобы начать работать с Kubernetes, можно использовать minikube. Minikube — это упрощённая реализация Kubernetes, которая создает виртуальную машину на вашем локальном компьютере и разворачивает простой кластер с одним узлом. Minikube доступен для Linux, macOS и Windows. В CLI-инструмент minikube встроены все необходимые функции для инициализации кластера и работы с ним, включая запуск, остановку, просмотр состояния и удаление кластера.

Теперь, когда вы знаете больше о том, что такое Kubernetes, перейдите к руководству Привет, minikube на своём компьютере.

7.2.2 - Развёртывание приложения

7.2.2.1 - Использование kubectl для развёртывания приложения

Узнайте про деплойменты приложения. Разверните первое приложение в Kubernetes с помощью kubectl.

Цели

  • Узнать про деплойменты приложения
  • Развернуть первое приложение в Kubernetes с помощью kubectl

Deployments в Kubernetes

Как только вы запустили кластер Kubernetes, вы можете развернуть на нём свои контейнеризированные приложения. Для этого вам нужно создать деплоймент (Deployment). Deployment в Kubernetes определяет, как создавать и обновлять экземпляры вашего приложения. После создания деплоймента control plane в Kubernetes запланирует запуск экземпляров приложения на отдельных узлах в кластере.

После того, как экземпляры приложения были созданы, контроллер деплойментов Kubernetes будет непрерывно отслеживать их. Если узел, на котором размещен экземпляр, вышёл из строя или был удалён, контроллер деплойментов заменит этот экземпляр экземпляром на другом узле в кластере. Этот процесс представляет собой механизм самовосстановления, обеспечивающий работу кластера в случае возникновения аппаратных неисправностей либо технических работ.

До того, как появились системы оркестровки, для запуска приложений обычно использовались установочные скрипты, которые не перезапускались после сбоя компьютера. Создавая экземпляры приложений и поддерживая их работу на нескольких узлах, деплойменты Kubernetes используют принципиально другой подход к управлению приложениями.

Краткое содержание:

  • Деплойменты
  • Kubectl

Deployment отвечает за создание и обновление экземпляров приложения


Развёртывание вашего первого приложения на Kubernetes


Вы можете создавать и управлять деплойментами через консольный инструмент Kubernetes под названием kubectl. Kubectl использует Kubernetes API для работы с кластером. В этом модуле вы узнаете про наиболее используемые команды kubectl, необходимые для создания деплойментов, которые будут запускать приложения в кластере Kubernetes.

При создании развертывания нужно указать образ контейнера приложения и количество запущенных реплик. Впоследствии эти параметры можно изменить. В модулях 5 и 6 рассказывается про масштабирование и обновление деплойментов.

Чтобы приложение запускалось в Kubernetes, оно должно быть упаковано в один из поддерживаемых форматов контейнеров

Для своего первого деплоймента возьмём приложение hello-node, упакованное в Docker-контейнер и использующее NGINX, чтобы выводить на экран все запросы. (Если вы ещё не пробовали создавать приложение hello-node и деплоить контейнер с ним, можете сначала выполнить инструкции из руководства "Привет, Minikube").

Вам также потребуется установленная утилита kubectl. По вопросам её инсталляции см. Установку инструментов.

Теперь, когда понятие деплойментов вам знакомо, давайте задеплоим первое приложение!


Основы kubectl

Общий формат команд kubectl выглядит так: kubectl действие ресурс

Эта команда выполнит указанное действие (например, create, describe или delete) с указанным ресурсом (например, node или deployment). Можно воспользоваться справкой через флаг --help после подкоманды, чтобы получить дополнительные сведения о возможных параметрах (например: kubectl get nodes --help).

Убедитесь, что kubectl настроена на подключение к вашему кластеру, выполнив команду kubectl version.

Убедитесь, что kubectl установлена и вы можете увидеть версию и у клиента, и у сервера.

Чтобы увидеть список узлов кластера, выполните команду kubectl get nodes.

Вы увидите доступные узлы. Позже Kubernetes выберет, куда задеплоить ваше приложение, руководствуясь данными о доступных узлах.

Деплой приложения

Давайте развернём первое приложение в Kubernetes с помощью команды kubectl create deployment. Для этого потребуется указать имя деплоймента и путь к образу приложения (используйте полный URL репозитория для образов, которые располагаются вне Docker Hub).

kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

Отлично! Создав этот Deployment, вы только что развернули первое приложение. Команда привела к выполнению следующих действий:

  • поиск подходящего узла, на котором можно запустить экземпляр приложения (у нас доступен только 1 узел);
  • планирование (размещение) приложения для запуска на этом узле;
  • настройка кластера на повторное размещение экземпляра на новом узле, когда это потребуется.

Чтобы увидеть список деплойментов, выполните команду kubectl get deployments:

kubectl get deployments

Вы увидите, что есть 1 деплоймент, в котором запущен единственный экземпляр приложения. Этот экземпляр работает в контейнере на узле кластера.

Просмотр приложения

Поды, которые запущены внутри Kubernetes, работают в частной, изолированной сети. По умолчанию они видны для других подов и сервисов того же Kubernetes-кластера, однако не за пределами этой сети. Когда мы используем утилиту kubectl, мы взаимодействуем с нашим приложением через API-эндпоинт.

О других возможностях сделать приложение доступным вне кластера Kubernetes мы расскажем позже, в разделе Открытие доступа к приложению.

Команда kubectl proxy создаст прокси, который перенаправляет взаимодействие в частную сеть, доступную в рамках кластера. Во время своей работы прокси не выводит никаких сообщений, а остановить его можно нажатием на control-C.

Для запуска прокси потребуется открыть второе окно с терминалом.

kubectl proxy

Теперь у нас есть соединение между хостом (терминалом) и Kubernetes-кластером. Прокси обеспечивает прямой доступ к API из терминала.

Через эндпоинт от прокси можно увидеть все API. Например, с помощью curl мы можем напрямую через API узнать версию:

curl http://localhost:8001/version

Сервер API автоматически создаст эндпоинт для каждого пода в соответствии с именем пода, который будет также доступен через прокси.

Для начала узнаем имя пода и сохраним его в переменной окружения POD_NAME:

export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME

Теперь получим доступ к поду через проксированный API, выполнив команду:

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

Чтобы новый деплоймент был доступен без использования прокси, потребуется сервис (объект Service), о котором будет рассказано в следующих разделах.

Когда всё готово, переходите к разделу Просмотр подов и узлов.

7.2.3 - Изучение приложения

7.2.3.1 - Просмотр подов и узлов

Узнайте, как диагностировать проблемы с Kubernetes-приложениями с помощью kubectl get, kubectl describe, kubectl logs и kubectl exec.

Цели

  • Узнать про поды Kubernetes
  • Узнать про узлы Kubernetes
  • Научиться диагностировать развёрнутые приложения

Поды Kubernetes

После того, как вы создали Deployment в модуле 2, Kubernetes создал под (Pod), в котором был размещён экземпляр вашего приложения. Под — это абстрактный объект Kubernetes, представляющий собой группу из одного или нескольких контейнеров приложения (например, Docker) и совместно используемых ресурсов для этих контейнеров. Ресурсами могут быть:

  • общее хранилище (тома);
  • сеть (уникальный IP-адрес кластера);
  • информация о том, как запускать каждый контейнер, например, версия образа контейнера или используемые номера портов.

Под представляет специфичный для приложения "логический хост" и может содержать разные контейнеры приложений, которые в общем и целом тесно связаны. Например, в поде может размещаться как контейнер с приложением на Node.js, так и другой контейнер, который получает некоторые данные для их дальнейшей публикации на веб-сервере Node.js. Все контейнеры в поде имеют одни и те же IP-адрес и пространство портов, всегда размещаются и планируются для выполнения на одном и том же узле.

Поды — неделимая единица в платформе Kubernetes. При создании деплоймента в Kubernetes создаются поды с контейнерами внутри (вместо того, чтобы непосредственно создавать контейнеры). Каждый объект Pod связан с узлом (Node), на котором он размещён, и остаётся там до окончания работы (согласно стратегии перезапуска) либо удаления. В случае неисправности узла такой же под будет запланирован для запуска на других доступных узлах кластера.

Краткое содержание:

  • Поды
  • Узлы
  • Основные команды kubectl

Под (Pod) — группа из одного или нескольких контейнеров приложений (например, Docker) и их общих хранилищ (томов), IP-адреса и информации о том, как их запускать.


Схема подов


Узлы

Под всегда работает в узле (Node). Узел — это рабочая машина в Kubernetes, которая в зависимости от кластера может быть либо виртуальной, либо физической. Каждый узел управляется компонентом под названием control plane. Узел может содержать несколько подов, которые control plane автоматически размещает ("планирует" для запуска) на разные узлы кластера. Автоматическое планирование (распределение подов по узлам) control plane учитывает доступные ресурсы на каждом узле.

В каждом узле Kubernetes как минимум работает:

  • Kubelet — процесс, отвечающий за взаимодействие между control plane и узлом; он управляет подами и запущенными контейнерами на рабочей машине.
  • Среда выполнения контейнера (вроде Docker), отвечающая за получение (загрузку) образа контейнера из реестра, распаковку контейнера и запуск приложения.

Контейнеры должны запускаться вместе в пределах одного пода только в случаях, когда они тесно связаны и должны совместно использовать ресурсы (например, диск).


Схема узла


Диагностика с помощью kubectl

В модуле 2 вы использовали инструмент командной строки kubectl. В этом (третьем) модуле вы продолжите его использовать, но для получения информации о развернутых приложениях и окружениях, в которых они работают. Наиболее распространенные операции выполняются с использованием следующих команд kubectl:

  • kubectl get — вывод списка ресурсов;
  • kubectl describe — вывод подробной информации о ресурсе;
  • kubectl logs — вывод логов контейнера в поде;
  • kubectl exec — выполнение команды в контейнере пода.

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

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

Узел — рабочая машина в Kubernetes, которая может быть как виртуальной, так и физической (в зависимости от используемого кластера). На одном узле могут быть запущены несколько подов.

Проверка конфигурации приложения

Давайте проверим, что приложение, которое мы развернули ранее, работает. Воспользуемся командой kubectl get и посмотрим на существующие поды:

kubectl get pods

Если работающих подов нет, подождите несколько секунд и выведите их список снова. Как только увидите работающий под, следуйте инструкциям ниже.

Теперь, чтобы увидеть, какие контейнеры находятся внутри этого пода и какие образы использовались при сборке этих контейнеров, выполним команду kubectl describe pods:

kubectl describe pods

Здесь можно увидеть подробности о контейнере пода: IP-адрес, используемые порты и список событий, относящихся к жизненному циклу пода.

У подкоманды describe подробный вывод. В частности, он затрагивает концепции, которые мы ещё не рассматривали, но не волнуйтесь — они станут понятнее в дальнейшем.

Примечание: подкоманду describe можно использовать для получения информации о многих примитивах Kubernetes, включая узлы (Nodes), поды (Pods) и деплойменты (Deployments). Вывод describe предназначен для чтения человеком, не для использования в скриптах.

Просмотр приложения в терминале

Вспомним, что поды работают в изолированной, частной сети, поэтому нам нужен прокси для доступа к ним — так мы сможем производить отладку и взаимодействовать с ними. Для этого мы во втором терминале воспользуемся командой kubectl proxy, чтобы запустить прокси. Откройте новое окно терминала и выполните:

kubectl proxy

Теперь мы снова получим имя пода и обратимся к нему через прокси. Чтобы получить имя пода и записать его в переменную окружения POD_NAME, выполним:

export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo Name of the Pod: $POD_NAME

Чтобы увидеть вывод приложения, выполним запрос через curl:

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

Здесь URL указывает на маршрут к API пода.

Просмотр логов контейнера

Всё, что обычное приложение отправляет в стандартный вывод (standard output), становится логами контейнера в поде. Получить эти логи можно с помощью команды kubectl logs:

kubectl logs "$POD_NAME"

Примечание: указывать название контейнера не требуется, потому что в данном поде у нас единственный контейнер.

Выполнение команд в контейнере

Когда под запущен и работает, в его контейнерах можно выполнять команды. Для этого воспользуемся подкомандой exec и передадим имя пода в качестве параметра. Выведем список переменных окружения в контейнере:

kubectl exec "$POD_NAME" -- env

Вновь отметим, что название контейнера можно не указывать, поскольку в этом поде у нас единственный контейнер.

Далее запустим Bash-сессию в контейнере пода:

kubectl exec -ti $POD_NAME -- bash

Откроется консоль в контейнере, в котором работает NodeJS-приложение. Исходный код приложения находится в файле server.js:

cat server.js

Также можно убедиться, что приложение запущено и работает, обратившись к нему через curl:

curl http://localhost:8080

Примечание: мы здесь использовали localhost, поскольку выполняли команду внутри пода NodeJS. Если у вас не получается подключиться к localhost:8080, проверьте, что запускали команду kubectl exec, а сейчас вызываете команду из пода.

Чтобы закрыть подключение к контейнеру, введите exit.

Когда всё готово, переходите к разделу Создание сервиса для открытия доступа к приложению.

7.2.4 - Открытие доступа к приложению

7.2.4.1 - Создание сервиса для открытия доступа к приложению

Узнайте о сервисах в Kubernetes. Разберитесь, какое отношение к сервисам имеют лейблы и селекторы. Сделайте приложение доступным вне кластера Kubernetes.

Цели

  • Узнать о сервисах в Kubernetes
  • Разобраться, какое отношение к сервисам имеют лейблы и селекторы
  • Сделать приложение доступным вне кластера Kubernetes

Обзор сервисов Kubernetes

Под — это расходный материал в Kubernetes. У них есть свой жизненный цикл. Когда рабочий узел прекращает работу, запущенные поды в узле также уничтожаются. После этого ReplicaSet попытается автоматически вернуть кластер обратно в требуемое состояние, создавая новые поды, чтобы поддержать работоспособность приложения. Другим примером жизни и смерти подов может служить бэкенд для обработки изображений с 3 репликами. Поскольку это взаимозаменяемые реплики, они не влияют на фронтенд-часть, даже если под был уничтожен и пересоздан. Тем не менее, каждый под в кластере Kubernetes имеет уникальный IP-адрес — даже под на одном и том же узле. Поэтому необходим способ автоматической координации изменений между подами, чтобы приложения продолжали функционировать.

Сервис (Service) в Kubernetes — это абстрактный объект, который определяет логический набор подов и политику доступа к ним. Сервисы создают слабую связь между подами, которые от них зависят. Сервис создаётся в формате YAML (рекомендуемый формат) или JSON, как и все остальные объекты в Kubernetes. Как правило, набор подов для сервиса определяется селектором лейблов (label selector) — ниже будет описано, в каких случаях может понадобиться сервис без указания селектора (selector) в его спецификации.

Хотя у каждого пода есть уникальный IP-адрес, эти IP-адреса не доступны за пределами кластера без использования сервиса. Сервисы позволяют приложениям принимать трафик. Сервисы могут быть по-разному открыты, в зависимости от значения поля type, указанного в спецификации сервиса:

  • ClusterIP (по умолчанию) — открывает доступ к сервису по внутреннему IP-адресу в кластере. Этот тип делает сервис доступным только внутри кластера;
  • NodePort — открывает сервис на том же порту каждого выбранного узла в кластере с помощью NAT. Делает сервис доступным вне кластера через <NodeIP>:<NodePort>. Является надмножеством ClusterIP.
  • LoadBalancer — создает внешний балансировщик нагрузки в текущем облаке (если это поддерживается) и назначает фиксированный внешний IP-адрес для сервиса. Является надмножеством NodePort.
  • ExternalName — открывает доступ к сервису по содержимому поля externalName (например, foo.bar.example.com), возвращая запись CNAME с его значением. При этом прокси не используется. Для этого типа требуется версия kube-dns 1.7+ или CoreDNS 0.0.8+.

Более подробно узнать о различных типах сервисах можно в руководстве Использование IP-порта источника. Также изучите Подключение приложений к сервисам.

Кроме этого, обратите внимание, что в некоторых случаях в сервисах не определяется selector в спецификации. Сервис без selector не будет создавать соответствующий эндпоинт (Endpoint). Таким образом, пользователь может вручную определить эндпоинты для сервиса. Ещё один возможный сценарий создания сервиса без селектора — это строгое использование type: ExternalName.

Краткое содержание

  • Открытие внешнего трафика для подов
  • Балансировка нагрузки трафика между подов
  • Использование лейблов

Сервис Kubernetes (Service) — это уровень абстракции, который определяет логический набор подов, перенаправляет внешний трафик, балансирует нагрузку и реализует service discovery для этих подов.


Сервисы и лейблы

Сервис направляет трафик через набор подов. Сервисы — это абстракция, позволяющая взаимозаменять поды Kubernetes без ущерба для работы приложения. Сервисы в Kubernetes находят и маршрутизируют трафик между зависимыми подами (это могут быть фронтенд- и бэкенд-компоненты приложения).

Сервисы для выбора набора подов используют лейблы и селекторы. Лейблы — пары ключ-значение, добавленные к объектам; например, они могут использоваться чтобы:

  • идентифицировать объекты для окружений разработки, тестирования и production;
  • встроить теги версии;
  • классифицировать объекты через теги.


Лейблы могут добавляться во время создания объектов или после этого. Они также могут быть изменены в любое время. Теперь давайте откроем доступ к приложению с помощью создания сервиса и добавим лейблы.

Создание нового сервиса

Давайте убедимся, что приложение работает. Воспользуемся командой kubectl get и посмотрим на существующие поды:

kubectl get pods

Если работающих подов нет, объекты из предыдущих разделов руководства была удалены. В таком случае вернитесь и повторно создайте деплоймент по инструкциям из раздела Использование kubectl для развёртывания приложения. После этого подождите несколько секунд и повторно запросите список подов. Как только увидите работающий под, можно следовать инструкциям ниже.

Далее посмотрим на список уже имеющихся сервисов в кластере:

kubectl get services

У нас есть сервис под названием kubernetes. Его по умолчанию создаёт minikube при запуске кластера. Чтобы создать новый сервис и сделать его доступным для внешних пользователей, воспользуемся командой expose с указанием типа сервиса NodePort в качестве параметра.

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

Попробуем подкоманду get services ещё раз:

kubectl get services

Теперь у нас есть сервис под названием kubernetes-bootcamp. Мы можем увидеть, что у этого сервиса уникальный cluster-IP, внутренний порт и external-IP (IP соответствующего узла).

Чтобы выяснить, какой порт был открыт для внешнего мира (для сервиса со спецификацией type: NodePort), выполним подкоманду describe service:

kubectl describe services/kubernetes-bootcamp

Объявим переменную окружения NODE_PORT, в которую запишем значение назначенного порта узла:

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"

Теперь можно проверить, что приложение доступно вне кластера, с помощью curl, IP-адреса узла и порта, проброшенного вовне:

curl http://"$(minikube ip):$NODE_PORT"

Получим ответ от сервера. Сервис доступен внешнему миру.

Шаг 2: использование лейблов

Deployment автоматически создаёт лейбл для пода. Подкоманда describe deployment покажет его название (key):

kubectl describe deployment

Воспользуемся этим лейблом при выводе списка подов. Для этого вызовем команду kubectl get pods с флагом -l и нужными значениями лейблов в качестве параметра:

kubectl get pods -l app=kubernetes-bootcamp

То же самое можно делать при выводе списка сервисов:

kubectl get services -l app=kubernetes-bootcamp

Получим имя пода и запишем его в переменную окружения POD_NAME:

export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Name of the Pod: $POD_NAME"

Чтобы добавить новый лейбл, воспользуемся подкомандой label, для которой укажем тип объекта, имя объекта и значение нового лейбла:

kubectl label pods "$POD_NAME" version=v1

Новый лейбл добавится к поду (мы зафиксировали версию приложения для этого пода), а мы сможем убедиться в этом с помощью команды describe pod:

kubectl describe pods "$POD_NAME"

Как видно, лейбл добавился к нашему поду. Теперь мы можем получить список всех подов, использующих новый лейбл:

kubectl get pods -l version=v1

Наш под будет в этом списке.

Удаление сервиса

Чтобы удалить сервис, воспользуйтесь подкомандой delete service. В ней могут указываться и лейблы:

kubectl delete service -l app=kubernetes-bootcamp

Убедитесь, что сервис удалился:

kubectl get services

Вывод подтвердит, что сервис был удалён. Убедиться в том, что удалился соответствующий маршрут для внешнего трафика, можно через curl к доступному ранее IP и порту:

curl http://"$(minikube ip):$NODE_PORT"

Так можно убедиться, что приложение более недоступно снаружи кластера. Проверить, что приложение всё ещё работает, можно через curl, который будет выполнен внутри пода:

kubectl exec -ti $POD_NAME -- curl http://localhost:8080

Мы увидим, что приложение запущено. Оно функционирует, потому что за его работу отвечает деплоймент (Deployment). Чтобы остановить приложение, потребуется также удалить и его деплоймент.

Когда всё готово, переходите к разделу Запуск нескольких экземпляров приложения.

7.2.5 - Масштабирование приложения

7.2.5.1 - Запуск нескольких экземпляров приложения

Отмасштабируйте существующее приложение вручную с помощью kubectl.

Цели

  • Научиться масштабировать приложение с kubectl

Масштабирование приложения

В предыдущих модулях мы создали деплоймент (Deployment), а затем открыли к нему публичный доступ через сервис (Service). Деплоймент создал только один под, в котором работает наше приложение. По мере увеличения трафика необходимо будет промасштабировать приложение, чтобы оно могло справиться с возросшим потоком пользователей.

Если вы не работали с предыдущими разделами документации, начните с использования minikube для создания кластера.

Масштабирование осуществляется за счёт изменения количества реплик в развёртывании.

Краткое содержание:

  • Масштабирование деплоймента

Количество экземпляров можно указать прямо при создании деплоймента, используя параметр --replicas команды kubectl create deployment


Обзор темы масштабирования


В случае масштабирования деплоймента создаются новые поды, которые распределяются по узлам с доступными ресурсами. Масштабирование увеличит количество подов в соответствии с новым требуемым состоянием. Kubernetes также поддерживает автоматическое масштабирование подов, но эта тема не рассматривается в данном уроке. Кроме этого, возможно масштабирование до нуля: в таком случае завершается работа всех подов в деплойменте.

При запуске нескольких экземпляров приложения нужно правильно распределить трафик между ними. У сервисов есть встроенный балансировщик нагрузки, который распределяет сетевой трафик на все поды деплоймента, доступного извне. Сервисы постоянно отслеживают запущенные поды через их эндпоинты (endpoints), чтобы направлять трафик только на доступные поды.

Масштабирование выполняется с помощью изменения количества реплик в деплойменте.


Если у вас есть несколько работающих экземпляров приложения, можно выполнять плавающие обновления (rolling updates) без простоев. С ними мы познакомимся в следующем модуле. А пока перейдём к терминалу и промасштабируем наше приложение.

Масштабирование деплоймента

Для вывода списка депойментов воспользуйтесь подкомандой get deployments: kubectl get deployments

Вывод будет примерно следующим:

               NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
               kubernetes-bootcamp   1/1     1            1           11m
               

У нас должен быть 1 под. Если его нет, выполните команду ещё раз. Вывод показывает следующую информацию:

  • NAME — названия деплойментов (Deployments) в кластере.
  • READY — соотношение CURRENT/DESIRED для его экземпляров (реплик).
  • UP-TO-DATE — количество реплик, которые были обновлены до желаемого состояния.
  • AVAILABLE — количество реплик, доступных для пользователей.
  • AGE — сколько времени приложение было запущено.

Чтобы увидеть ReplicaSet, созданные деплойментом, выполните: kubectl get rs

Обратите внимание, что название ReplicaSet всегда форматируется как [DEPLOYMENT-NAME]-[RANDOM-STRING]. Последний фрагмент генерируется случайным образом и использует pod-template-hash в качестве seed-значения.

Этот вывод будет содержать два важных столбца:

  • DESIRED — желаемое количество экземпляров (реплик) приложения. Это значение вы определяете, когда создаёте деплоймент.
  • CURRENT — количество реплик, которые работают в настоящий момент.

Далее отмасштабируем деплоймент до 4 реплик. Для этого воспользуемся командой kubectl scale, для которой укажем тип объекта (деплоймент), его название и количество желаемых экземпляров:

kubectl scale deployments/kubernetes-bootcamp --replicas=4

Снова выведем список деплойментов с помощью get deployments:

kubectl get deployments

Изменение применилось: теперь доступны 4 экземпляра приложения. Далее проверим, изменилось ли количество подов:

kubectl get pods -o wide

Теперь у нас 4 пода с разными IP-адресами. Это изменение было зафиксировано в логе событий деплоймента. Убедиться в этом можно подкомандой describe:

kubectl describe deployments/kubernetes-bootcamp

В выводе этой команды тоже видно, что теперь у нас 4 реплики.

Балансировка нагрузки

Проверим, что сервис балансирует трафик. Чтобы узнать внешний IP-адрес и порт, воспользуемся командой describe service, с которой уже познакомились в предыдущем модуле:

kubectl describe services/kubernetes-bootcamp

Объявим переменную окружения NODE_PORT со значением порта нашего узла:

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"

echo NODE_PORT=$NODE_PORT

Далее обратимся через curl к проброшенному IP-адресу и порту. Выполните эту команду много раз:

curl http://"$(minikube ip):$NODE_PORT"

Каждый раз мы будем попадать на разный под. Это означает, что балансировка нагрузки работает.

Масштабирование вниз

Чтобы уменьшить деплоймент до 2 реплик, снова обратимся к подкоманде scale:

kubectl scale deployments/kubernetes-bootcamp --replicas=2

С помощью подкоманды get deployments выведем список деплойментов, чтобы убедиться, что изменение применилось:

kubectl get deployments

Количество реплик уменьшилось до 2. Выведем список подов с get pods:

kubectl get pods -o wide

Так мы убедимся, что работа 2 подов была остановлена.

Когда всё готово, переходите к разделу Выполнение плавающего обновления.

7.2.6 - Обновление приложения

7.2.6.1 - Выполнение плавающего обновления

Выполнение плавающего обновления с помощью kubectl.

Цели

  • Выполнить плавающее обновление с помощью kubectl

Обновление приложения

Пользователи надеются, что приложения будут работать круглосуточно, а разработчики в свою очередь хотят развёртывать новые версии приложений по несколько раз в день. В Kubernetes это возможно благодаря механизму плавающих обновлений (rolling updates). Плавающие обновления позволяют обновить деплойменты без простоев, шаг за шагом заменяя старые поды на новые. Новые поды будут запущены на узлах, имеющих достаточно ресурсов.

В предыдущем модуле мы промасштабировали приложение до нескольких экземпляров. Это необходимо сделать, чтобы иметь возможность обновлять приложение, не влияя на его доступность. По умолчанию максимальное количество подов, которое может быть недоступно во время обновления, и максимальное количество новых подов, которое можно создать, равны 1. Эти две опции могут быть определены в абсолютном значении (числа) или относительном соотношении (проценты). В Kubernetes обновления версионируются, поэтому любое обновление деплоймента можно откатить до предыдущей (стабильной) версии.

Краткое содержание:

  • Обновление приложения

Плавающие обновления последовательно заменяют экземпляры подов на новые, тем самым позволяя обновить деплойменты без простоев


Обзор плавающих обновлений


Подобно масштабированию приложения, если деплоймент доступен извне, при обновлении сервис будет балансировать трафик только между доступными подами. Доступный под — это экземпляр, который может быть запущен для пользователей приложения.

С помощью плавающих обновлений можно:

  • переводить приложение из одного окружения в другое (через обновления образа контейнера);
  • откатываться к предыдущим версиям;
  • осуществлять непрерывную интеграцию и непрерывную доставку приложений без простоев.

Если деплоймент был открыт наружу, в процессе обновления сервис будет балансировать трафик только на доступные поды.


В инструкциях ниже мы обновим приложение до новой версии и потом откатим его обратно.


Обновление версии приложения

Чтобы получить список деплойментов, выполните подкоманду get deployments: kubectl get deployments

Для списка подов — подкоманду get pods:

kubectl get pods

Чтобы увидеть версию текущего образа в приложении, воспользуйтесь подкомандой describe pods и посмотрите на поле Image:

kubectl describe pods

Чтобы обновить версию образа приложения до v2, воспользуемся подкомандой set image, для которой укажем имя деплоймента и новую версию нужного образа:

kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2

Эта команда перевела деплоймент на использование другого образа для приложения и инициировала плавающее обновление. Статус новых и старых подов (т. е. тех, которые будут остановлены) можно проверить с помощью подкоманды get pods:

kubectl get pods

Шаг 2: валидация обновления

Во-первых, убедимся, что приложение работает. Доступный извне IP-адрес и порт узнаем с помощью команды describe service:

kubectl describe services/kubernetes-bootcamp

Объявим переменную окружения NODE_PORT со значением порта нашего узла:

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"

Далее обратимся через curl к проброшенному IP и порту:

curl http://"$(minikube ip):$NODE_PORT"

Каждый раз при вызове этой команды curl вам будет попадаться другой под. Обратите внимание, что все поды теперь работают с последней версией приложения (v2).

Проверить статус обновления можно также с помощью подкоманды rollout status:

kubectl rollout status deployments/kubernetes-bootcamp

Увидеть текущую версию образа приложения можно подкомандой describe pods:

kubectl describe pods

В поле Image у этого вывода убедитесь, что запущена последняя версия образа (v2).

Откат обновления

Выполним ещё одно обновление и попробуем развернуть образ, тегированный как v10:

kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10

Вызовем get deployments, чтобы увидеть статус деплоймента:

kubectl get deployments

Обратите внимание, что вывод показывает недостаток желаемого количества доступных подов. Обратимся к подкоманде get pods, чтобы вывести полный список подов:

kubectl get pods

Здесь обратите внимание, что некоторые поды перешли в статус ImagePullBackOff.

Чтобы получить больше информации о проблеме, выполните подкоманду describe pods:

kubectl describe pods

В разделе Events вывода по проблемным подам можно увидеть, что новая версия образа (v10) не существует в репозитории.

Чтобы откатить деплоймент к последней работающей версии, воспользуйтесь подкомандой rollout undo:

kubectl rollout undo deployments/kubernetes-bootcamp

Команда rollout undo откатывает деплоймент к предыдущему известному состоянию (к образу v2). Обновления версионируются, поэтому можно откатиться к любому предыдущему известному состоянию деплоймента.

С помощью подкоманды get pods выведем список подов еще раз:

kubectl get pods

Четыре пода работают. Проверить, какие версии образа развёрнуты в этих подах, можно подкомандой describe pods:

kubectl describe pods

Деплоймент снова использует стабильную версию приложения (v2). Откат произошёл успешно.

Не забудьте очистить содержимое вашего локального кластера:

kubectl delete deployments/kubernetes-bootcamp services/kubernetes-bootcamp

8 - Ссылки

Этот раздел документации Kubernetes содержит ссылки.

Ссылки API

Клиентские библиотеки API

Для вызова API Kubernetes из языка программирования вы можете использовать клиентские библиотеки. Официально поддерживаемые клиентские библиотеки:

Ссылки CLI

  • kubectl - Основной инструмент CLI для запуска команд и управления кластерами Kubernetes.
  • JSONPath - Документация по синтаксису использования выражений JSONPath с kubectl.
  • kubeadm - Инструмент CLI для легкого разворачивания защищенного кластера Kubernetes.
  • kubefed - Инструмент CLI для помощи в администрировании федеративных кластеров.

Ссылки на конфигурации

  • kubelet - Основной агент ноды, который работает на каждой ноде. Kubelet принимает набор PodSpecs и гарантирует, что описанные контейнеры работают исправно.
  • kube-apiserver - REST API, который проверяет и настраивает данные для объектов API, таких, как модули, службы, контроллеры и репликации.
  • kube-controller-manager - Демон, который встраивает основные контрольные циклы, поставляемые с Kubernetes.
  • kube-proxy - Может выполнять простую пересылку запросов TCP/UDP или циклическую переадресацию TCP/UDP через набор бекендов.
  • kube-scheduler - Планировщик, который управляет доступностью, производительностью и хранилищем.
  • federation-apiserver - Сервер API для федеративных кластеров.
  • federation-controller-manager - Демон, который встраивает основные контрольные циклы, поставляемые с Kubernetes.

Дизайн документация

Архив документации по дизайну для функциональности Kubernetes. Начните с Архитектуры Kubernetes и Обзора дизайна Kubernetes.

8.1 - Стандартизированный глоссарий

8.2 - kubectl CLI

8.2.1 - Обзор kubectl

Kubectl — это инструмент командной строки для управления кластерами Kubernetes. kubectl ищет файл config в директории $HOME/.kube. Вы можете указать другие файлы kubeconfig, установив переменную окружения KUBECONFIG или флаг --kubeconfig.

На этой странице рассматривается синтаксис kubectl, описаны командные операции и приведены распространённые примеры. Подробную информацию о каждой команде, включая все поддерживаемые в ней флаги и подкоманды, смотрите в справочной документации kubectl. Инструкции по установке находятся на странице Установка и настройка kubectl.

Синтаксис

Используйте следующий синтаксис для выполнения команд kubectl в терминале:

kubectl [command] [TYPE] [NAME] [flags]

где command, TYPE, NAME и flags:

  • command: определяет выполняемую операцию с одним или несколькими ресурсами, например, create, get, describe, delete.

  • TYPE: определяет тип ресурса. Типы ресурсов не чувствительны к регистру, кроме этого вы можете использовать единственную, множественную или сокращенную форму. Например, следующие команды выведут одно и то же.

    ```shell
    kubectl get pod pod1
    kubectl get pods pod1
    kubectl get po pod1
    ```
    
  • NAME: определяет имя ресурса. Имена чувствительны к регистру. Если имя не указано, то отображаются подробности по всем ресурсам, например, kubectl get pods.

    При выполнении операции с несколькими ресурсами можно выбрать каждый ресурс по типу и имени, либо сделать это в одном или нескольких файлов:

    • Выбор ресурсов по типу и имени:

      • Сгруппировать ресурсы, если все они одного типа: TYPE1 name1 name2 name<#>.
        Пример: kubectl get pod example-pod1 example-pod2

      • Выбор нескольких типов ресурсов по отдельности: TYPE1/name1 TYPE1/name2 TYPE2/name3 TYPE<#>/name<#>.
        Пример: kubectl get pod/example-pod1 replicationcontroller/example-rc1

    • Выбор ресурсов по одному или нескольким файлов: -f file1 -f file2 -f file<#>

      • Используйте YAML вместо JSON, так как YAML удобнее для пользователей, особенно в конфигурационных файлах.
        Пример: kubectl get pod -f ./pod.yaml
  • flags: определяет дополнительные флаги. Например, вы можете использовать флаги -s или --server, чтобы указать адрес и порт API-сервера Kubernetes.

Если вам нужна помощь, выполните команду kubectl help.

Операции

В следующей таблице приведены краткие описания и общий синтаксис всех операций kubectl:

Операция Синтаксис Описание
annotate kubectl annotate (-f FILENAME | TYPE NAME | TYPE/NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--overwrite] [--all] [--resource-version=version] [flags] Добавить или обновить аннотации одного или нескольких ресурсов.
api-versions kubectl api-versions [flags] Вывести доступные версии API.
apply kubectl apply -f FILENAME [flags] Внести изменения в конфигурацию ресурса из файла или потока stdin.
attach kubectl attach POD -c CONTAINER [-i] [-t] [flags] Подключиться к запущенному контейнеру либо для просмотра потока вывода, либо для работы с контейнером (stdin).
autoscale kubectl autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU] [flags] Автоматически промасштабировать набор подов, управляемых контроллером репликации.
cluster-info kubectl cluster-info [flags] Показать информацию о главном узле и сервисах в кластере.
config kubectl config SUBCOMMAND [flags] Изменить файлы kubeconfig. Подробные сведения смотрите в отдельных подкомандах.
create kubectl create -f FILENAME [flags] Создать один или несколько ресурсов из файла или stdin.
delete kubectl delete (-f FILENAME | TYPE [NAME | /NAME | -l label | --all]) [flags] Удалить ресурсы из файла, потока stdin, либо с помощью селекторов меток, имен, селекторов ресурсов или ресурсов.
describe kubectl describe (-f FILENAME | TYPE [NAME_PREFIX | /NAME | -l label]) [flags] Показать подробное состояние одного или нескольких ресурсов.
diff kubectl diff -f FILENAME [flags] Diff file or stdin against live configuration (BETA)
edit kubectl edit (-f FILENAME | TYPE NAME | TYPE/NAME) [flags] Отредактировать и обновить определение одного или нескольких ресурсов на сервере, используя редактор по умолчанию.
exec kubectl exec POD [-c CONTAINER] [-i] [-t] [flags] [-- COMMAND [args...]] Выполнить команду в контейнере пода.
explain kubectl explain [--recursive=false] [flags] Посмотреть документацию по ресурсам. Например, поды, узлы, сервисы и т.д.
expose kubectl expose (-f FILENAME | TYPE NAME | TYPE/NAME) [--port=port] [--protocol=TCP|UDP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type] [flags] Создать Kubernetes-сервис из контроллера репликации, сервиса или пода.
get kubectl get (-f FILENAME | TYPE [NAME | /NAME | -l label]) [--watch] [--sort-by=FIELD] [[-o | --output]=OUTPUT_FORMAT] [flags] Вывести один или несколько ресурсов.
label kubectl label (-f FILENAME | TYPE NAME | TYPE/NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--overwrite] [--all] [--resource-version=version] [flags] Добавить или обновить метки для одного или нескольких ресурсов.
logs kubectl logs POD [-c CONTAINER] [--follow] [flags] Вывести логи контейнера в поде.
patch kubectl patch (-f FILENAME | TYPE NAME | TYPE/NAME) --patch PATCH [flags] Обновить один или несколько полей ресурса, используя стратегию слияния патча.
port-forward kubectl port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N] [flags] Переадресовать один или несколько локальных портов в под.
proxy kubectl proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix] [flags] Запустить прокси для API Kubernetes.
replace kubectl replace -f FILENAME Заменить ресурс из файла или потока stdin.
rolling-update kubectl rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC) [flags] Выполните плавающее обновление, постепенно заменяя указанный контроллер репликации и его поды.
run kubectl run NAME --image=image [--env="key=value"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [flags] Запустить указанный образ в кластере.
scale kubectl scale (-f FILENAME | TYPE NAME | TYPE/NAME) --replicas=COUNT [--resource-version=version] [--current-replicas=count] [flags] Обновить размер указанного контроллера репликации.
version kubectl version [--client] [flags] Отобразить версию Kubernetes, запущенного на клиенте и сервере.

Примечание: подробную информацию о командных операциях смотрите в справочную документацию kubectl.

Типы ресурсов

В следующей таблице перечислены все доступные типы ресурсов вместе с сокращенными аббревиатурами.

(Это актуальный вывод команды kubectl api-resources с версии Kubernetes 1.13.3.)

Resource Name Short Names API Group Namespaced Resource Kind
bindings true Binding
componentstatuses cs false ComponentStatus
configmaps cm true ConfigMap
endpoints ep true Endpoints
limitranges limits true LimitRange
namespaces ns false Namespace
nodes no false Node
persistentvolumeclaims pvc true PersistentVolumeClaim
persistentvolumes pv false PersistentVolume
pods po true Pod
podtemplates true PodTemplate
replicationcontrollers rc true ReplicationController
resourcequotas quota true ResourceQuota
secrets true Secret
serviceaccounts sa true ServiceAccount
services svc true Service
mutatingwebhookconfigurations admissionregistration.k8s.io false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io false ValidatingWebhookConfiguration
customresourcedefinitions crd, crds apiextensions.k8s.io false CustomResourceDefinition
apiservices apiregistration.k8s.io false APIService
controllerrevisions apps true ControllerRevision
daemonsets ds apps true DaemonSet
deployments deploy apps true Deployment
replicasets rs apps true ReplicaSet
statefulsets sts apps true StatefulSet
tokenreviews authentication.k8s.io false TokenReview
localsubjectaccessreviews authorization.k8s.io true LocalSubjectAccessReview
selfsubjectaccessreviews authorization.k8s.io false SelfSubjectAccessReview
selfsubjectrulesreviews authorization.k8s.io false SelfSubjectRulesReview
subjectaccessreviews authorization.k8s.io false SubjectAccessReview
horizontalpodautoscalers hpa autoscaling true HorizontalPodAutoscaler
cronjobs cj batch true CronJob
jobs batch true Job
certificatesigningrequests csr certificates.k8s.io false CertificateSigningRequest
leases coordination.k8s.io true Lease
events ev events.k8s.io true Event
ingresses ing extensions true Ingress
networkpolicies netpol networking.k8s.io true NetworkPolicy
poddisruptionbudgets pdb policy true PodDisruptionBudget
podsecuritypolicies psp policy false PodSecurityPolicy
clusterrolebindings rbac.authorization.k8s.io false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io false ClusterRole
rolebindings rbac.authorization.k8s.io true RoleBinding
roles rbac.authorization.k8s.io true Role
priorityclasses pc scheduling.k8s.io false PriorityClass
csidrivers storage.k8s.io false CSIDriver
csinodes storage.k8s.io false CSINode
storageclasses sc storage.k8s.io false StorageClass
volumeattachments storage.k8s.io false VolumeAttachment

Опции вывода

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

Форматирование вывода

Стандартный формат вывода всех команд kubectl представлен в понятном для человека текстовом формате. Чтобы вывести подробности в определенном формате можно добавить флаги -o или --output к команде kubectl.

Синтаксис

kubectl [command] [TYPE] [NAME] -o <output_format>

В зависимости от операции kubectl поддерживаются следующие форматы вывода:

Выходной формат Описание
-o custom-columns=<spec> Вывести таблицу с использованием списка пользовательских столбцов, разделённого запятыми.
-o custom-columns-file=<filename> Вывести таблицу с использованием шаблона с пользовательскими столбцами в файле <filename>.
-o json Вывести API-объект в формате JSON.
-o jsonpath=<template> Вывести поля, определенные в выражении jsonpath.
-o jsonpath-file=<filename> Вывести поля, определённые в выражении jsonpath из файла <filename>.
-o name Вывести только имя ресурса.
-o wide Вывести в текстовом формате с дополнительной информацией. Для подов отображается имя узла.
-o yaml Вывести API-объект в формате YAML
Пример

В данном примере следующая команда выводит подробную информацию по указанному поду в виде объекта в YAML-формате:

kubectl get pod web-pod-13je7 -o yaml

Примечание: подробную информацию о доступных форматах вывода в определенной команде смотрите в справочной документации kubectl.

Пользовательские столбцы

Для определения пользовательских столбцов и вывода в таблицу только нужных данных, можно использовать опцию custom-columns. Вы можете определить пользовательские столбцы в самой опции, либо сделать это в файле шаблона: -o custom-columns=<spec> или -o custom-columns-file=<filename>.

Примеры

Столбцы указаны в самой команде:

kubectl get pods <pod-name> -o custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion

Столбцы указаны в файле шаблона:

kubectl get pods <pod-name> -o custom-columns-file=template.txt

где файл template.txt содержит следующее:

NAME          RSRC
metadata.name metadata.resourceVersion

Результат выполнения любой из показанной выше команды:

NAME           RSRC
submit-queue   610995

Получение вывода с сервера

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

Эта функциональность включена по умолчанию, начиная с kubectl 1.11 и выше. Чтобы отключить ее, добавьте флаг --server-print=false в команду kubectl get.

Примеры

Для вывода информации о состоянии пода, используйте следующую команду:

kubectl get pods <pod-name> --server-print=false

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

NAME       READY     STATUS              RESTARTS   AGE
pod-name   1/1       Running             0          1m

Сортировка списка объектов

Для вывода объектов в виде отсортированного списка в терминал используется флаг --sort-by к команде kubectl. Для сортировки объектов нужно указать любое числовое или строковое поле в флаге --sort-by. Для определения поля используйте выражение jsonpath.

Синтаксис

kubectl [command] [TYPE] [NAME] --sort-by=<jsonpath_exp>
Пример

Чтобы вывести список подов, отсортированных по имени, выполните команду ниже:

kubectl get pods --sort-by=.metadata.name

Примеры: распространенные операции

Посмотрите следующие примеры, чтобы ознакомиться с часто используемыми операциями kubectl:

kubectl apply - Внести изменения или обновить ресурс из файла или потока stdin.

# Создать сервис из определения в example-service.yaml.
kubectl apply -f example-service.yaml

# Создать контроллер репликации из определения в example-controller.yaml.
kubectl apply -f example-controller.yaml

# Создать объекты, которые определены в файлах с расширением .yaml, .yml или .json в директории <directory>.
kubectl apply -f <directory>

kubectl get - Вывести один или несколько ресурсов.

# Вывести все поды в текстовом формате вывода.
kubectl get pods

# Вывести все поды в текстовом формате вывода и включить дополнительную информацию (например, имя узла).
kubectl get pods -o wide

# Вывести контроллер репликации с указанным именем в текстовом формате вывода. Совет: вы можете использовать сокращенный псевдоним 'rc' вместо 'replicationcontroller'.
kubectl get replicationcontroller <rc-name>

# Вывести все контроллеры репликации и сервисы вместе в текстовом формате вывода.
kubectl get rc,services

# Вывести все наборы демонов в текстовом формате вывода.
kubectl get ds

# Вывести все поды, запущенные на узле server01
kubectl get pods --field-selector=spec.nodeName=server01

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

# Показать информацию об узле с именем <node-name>.
kubectl describe nodes <node-name>

# Показать подробности пода <pod-name>.
kubectl describe pods/<pod-name>

# Показать подробности всех подов, управляемые контроллером репликации <rc-name>.
# Обратите внимание: любые поды, созданные контроллером репликации, имеют префикс с именем контроллера репликации.
kubectl describe pods <rc-name>

# Показать подробности по всем подам
kubectl describe pods

kubectl delete - Удалить ресурсы из файла, потока stdin или с помощью селекторов меток, имена, селекторов ресурсов или имен ресурсов.

# Удалить под по типу и имени, указанных в файле pod.yaml.
kubectl delete -f pod.yaml

# Удалить все поды и сервисы с именем метки <label-name>.
kubectl delete pods,services -l name=<label-name>

# Удалить все поды, включая неинициализированные.
kubectl delete pods --all

kubectl exec - Выполнить команду в контейнере пода.

# Получить вывод от запущенной команды 'date' в поде <pod-name>. По умолчанию отображается вывод из первого контейнера.
kubectl exec <pod-name> date

# Получить вывод из запущенной команды 'date' в контейнере <container-name> пода <pod-name>.
kubectl exec <pod-name> -c <container-name> date

# Получить интерактивный терминал (TTY) и запустить /bin/bash в поде <pod-name>. По умолчанию отображается вывод из первого контейнера.
kubectl exec -ti <pod-name> /bin/bash

kubectl logs - Вывести логи контейнера в поде.

# Возвращает текущие логи в поде <pod-name>.
kubectl logs <pod-name>

# Вывод логов в поде <pod-name> в режиме реального времени. Это похоже на команду 'tail -f' Linux.
kubectl logs -f <pod-name>

Примеры: создание и использование плагинов

Посмотрите следующие примеры, чтобы ознакомиться с тем, как писать и использовать плагины kubectl:

# Плагин может быть на на любом языке, а сам исполняемый файл должен начинается с префикса "kubectl-".
cat ./kubectl-hello
#!/bin/bash

# Этот плагин выводит строку "hello world"
echo "hello world"

# Сделать плагин исполняемым
sudo chmod +x ./kubectl-hello

# Переместить его в директорию из PATH
sudo mv ./kubectl-hello /usr/local/bin

# Плагин дял kubectl создан и "установлен".
# Воспользоваться плагином можно через kubectl, вызвав его подобно обычной команды.
kubectl hello
hello world
# "Отмена установки" плагина происходит через удаление его файла из директории в PATH.
sudo rm /usr/local/bin/kubectl-hello

Посмотреть все доступные плагины kubectl можно с помощью подкоманды kubectl plugin list:

kubectl plugin list
The following kubectl-compatible plugins are available:

/usr/local/bin/kubectl-hello
/usr/local/bin/kubectl-foo
/usr/local/bin/kubectl-bar
# Эта команда также может сообщить, что плагин является неисполняемым,
# либо что плагин переопределен другими плагинами

sudo chmod -x /usr/local/bin/kubectl-foo
kubectl plugin list
The following kubectl-compatible plugins are available:

/usr/local/bin/kubectl-hello
/usr/local/bin/kubectl-foo
  - warning: /usr/local/bin/kubectl-foo identified as a plugin, but it is not executable
/usr/local/bin/kubectl-bar

error: one plugin warning was found

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

cat ./kubectl-whoami
#!/bin/bash

# Этот плагин использует команду `kubectl config` для вывода
# информации о текущем пользователе из текущего выбранного контекста
kubectl config view --template='{{ range .contexts }}{{ if eq .name "'$(kubectl config current-context)'" }}Current user: {{ .context.user }}{{ end }}{{ end }}'

Выполнение этого плагина генерирует вывод, содержащий пользователя для текущего выбранного контекста в файле KUBECONFIG:

# Сделать файл исполняемым
sudo chmod +x ./kubectl-whoami

# Перенести файл в директорию из PATH
sudo mv ./kubectl-whoami /usr/local/bin

kubectl whoami
Current user: plugins-user

Чтобы узнать больше о плагинах, изучите пример CLI-плагина.

Что дальше

Начните использовать команды kubectl.

8.2.2 - Поддержка JSONPath

Kubectl поддерживает шаблон JSONPath.

Шаблон JSONPath состоит из выражений JSONPath, заключенных в фигурные скобки {}. Kubectl использует JSONPath-выражения для фильтрации по определенным полям в JSON-объекте и форматирования вывода. В дополнение к оригинальному синтаксису шаблона JSONPath, допустимы следующие функции и синтаксис:

  1. Внутри выражений JSONPath текстовые значения заключайте в двойные кавычки.
  2. Используйте операторы range, end, конечные операторы для перебора списков.
  3. Используйте отрицательные индексы срезов для перехода на предыдущий элемент в списке. Отрицательные индексы не "зацикливаются" в списке и работают пока истинно выражение -index + listLength >= 0.

Все примеры ниже будут ориентироваться на следующий JSON-объект:

{
  "kind": "List",
  "items":[
    {
      "kind":"None",
      "metadata":{"name":"127.0.0.1"},
      "status":{
        "capacity":{"cpu":"4"},
        "addresses":[{"type": "LegacyHostIP", "address":"127.0.0.1"}]
      }
    },
    {
      "kind":"None",
      "metadata":{"name":"127.0.0.2"},
      "status":{
        "capacity":{"cpu":"8"},
        "addresses":[
          {"type": "LegacyHostIP", "address":"127.0.0.2"},
          {"type": "another", "address":"127.0.0.3"}
        ]
      }
    }
  ],
  "users":[
    {
      "name": "myself",
      "user": {}
    },
    {
      "name": "e2e",
      "user": {"username": "admin", "password": "secret"}
    }
  ]
}
Функция Описание Пример Результат
text обычный текст kind is {.kind} kind is List
@ текущий объект {@} то же, что и ввод
. или [] оператор выбора по ключу {.kind}, {['kind']} или {['name\.type']} List
.. рекурсивный спуск {..name} 127.0.0.1 127.0.0.2 myself e2e
* шаблон подстановки. Получение всех объектов {.items[*].metadata.name} [127.0.0.1 127.0.0.2]
[start:end:step] оператор индексирования {.users[0].name} myself
[,] оператор объединения {.items[*]['metadata.name', 'status.capacity']} 127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]
?() фильтрация {.users[?(@.name=="e2e")].user.password} secret
range, end перебор списка {range .items[*]}[{.metadata.name}, {.status.capacity}] {end} [127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]]
'' интерпретируемая в кавычках строка {range .items[*]}{.metadata.name}{'\t'}{end} 127.0.0.1 127.0.0.2

Примеры использования kubectl и JSONPath-выражений:

kubectl get pods -o json
kubectl get pods -o=jsonpath='{@}'
kubectl get pods -o=jsonpath='{.items[0]}'
kubectl get pods -o=jsonpath='{.items[0].metadata.name}'
kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'status.capacity']}"
kubectl get pods -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.startTime}{"\n"}{end}'

8.2.3 - kubectl

Краткое описание

kubectl управляет кластерами Kubernetes.

Более подробная информация по ссылке: https://kubernetes.io/ru/docs/reference/kubectl/overview/

kubectl [flags]

Опции

--add-dir-header
Если true, добавляет директорию файла в заголовок
--alsologtostderr
Логировать в стандартный поток ошибок, а также в файлы
--application-metrics-count-limit int     По умолчанию: 100
Максимальное количество сохраняемых метрик приложения (на каждый контейнер)
--as string
Имя пользователя, от которого будет выполняться операция
--as-group stringArray
Группа, от которой будет выполняться операция, этот флаг можно использовать неоднократно, чтобы указать несколько групп.
--azure-container-registry-config string
Путь к файлу, который содержит информацию с конфигурацией реестра контейнера Azure.
--boot-id-file string     По умолчанию: "/proc/sys/kernel/random/boot_id"
Разделенный запятыми список файлов для проверки boot-id. Используйте первый существующий.
--cache-dir string     По умолчанию: "$HOME/.kube/http-cache"
Директория HTTP-кеша по умолчанию
--certificate-authority string
Путь к файлу сертификата для центра сертификации
--client-certificate string
Путь к файлу клиентского сертификата для TLS
--client-key string
Путь к файлу клиентского ключа для TLS
--cloud-provider-gce-l7lb-src-cidrs cidrs     По умолчанию: 130.211.0.0/22,35.191.0.0/16
Открыть CIDR в брандмауэре GCE для прокси трафика L7 LB и проверки работоспособности
--cloud-provider-gce-lb-src-cidrs cidrs     По умолчанию: 130.211.0.0/22,209.85.152.0/22,209.85.204.0/22,35.191.0.0/16
Открыть CIDR в брандмауэре GCE для прокси трафика L4 LB и проверки работоспособности
--cluster string
Имя используемого кластера kubeconfig
--container-hints string     По умолчанию: "/etc/cadvisor/container_hints.json"
Путь к файлу подсказок контейнера
--containerd string     По умолчанию: "/run/containerd/containerd.sock"
Конечная точка containerd
--containerd-namespace string     По умолчанию: "k8s.io"
Пространство имени containerd
--context string
Имя контекста kubeconfig
--default-not-ready-toleration-seconds int     По умолчанию: 300
Указывает tolerationSeconds для допущения notReady:NoExecute, которое по умолчанию добавляется к каждому поду, у которого не установлено такое допущение.
--default-unreachable-toleration-seconds int     По умолчанию: 300
Указывает tolerationSeconds для допущения unreachable:NoExecute, которое по умолчанию добавляется к каждому поду, у которого не установлено такое допущение.
--disable-root-cgroup-stats
Отключить сбор статистики корневой группы (Cgroup)
--docker string     По умолчанию: "unix:///var/run/docker.sock"
docker endpoint
--docker-env-metadata-whitelist string
Список ключей переменных окружения, разделенный запятыми, которые необходимо собрать для Docker-контейнеров
--docker-only
В дополнение к корневой статистике уведомлять только о Docker-контейнерах
--docker-root string     По умолчанию: "/var/lib/docker"
УСТАРЕЛО: корень docker считывается из информации docker (запасной вариант, по умолчанию: /var/lib/docker)
--docker-tls
Использовать TLS для подключения к Docker
--docker-tls-ca string     По умолчанию: "ca.pem"
Путь к доверенному CA
--docker-tls-cert string     По умолчанию: "cert.pem"
Путь к клиентскому сертификату
--docker-tls-key string     По умолчанию: "key.pem"
Путь к приватному ключу
--enable-load-reader
Включить считыватель нагрузки процессора
--event-storage-age-limit string     По умолчанию: "default=0"
Максимальный период времени для хранения события (по каждому типу). Значение флага — список из ключей и значений, разделенные запятыми, где ключи — это типы событий (например: создание, oom) либо "default", а значение — длительность. По умолчанию флаг применяется ко всем неуказанным типам событий
--event-storage-event-limit string     По умолчанию: "default=0"
Максимальное количество событий для хранения (по каждому типу). Значение флага — список из ключей и значений, разделенные запятыми, где ключи — это типы событий (например: создание, oom) либо "default", а значение — целое число. По умолчанию флаг применяется ко всем неуказанным типам событий
--global-housekeeping-interval duration     По умолчанию: 1m0s
Интервал между глобальными служебными операциями (housekeepings)
-h, --help
Получить справочную информацию по команде kubectl
--housekeeping-interval duration     По умолчанию: 10s
Интервал между служебными операциями (housekeepings) контейнера
--insecure-skip-tls-verify
Если true, значит сертификат сервера не будет проверяться на достоверность. Это сделает подключения через HTTPS небезопасными.
--kubeconfig string
Путь к файлу kubeconfig для использования в CLI-запросах.
--log-backtrace-at traceLocation     По умолчанию: :0
При логировании указанной строки (file:N), сгенерировать трассировку стека
--log-cadvisor-usage
Записывать ли в журнал использование контейнера cAdvisor
--log-dir string
Если указан, хранить лог-файлы в этой директории.
--log-file string
Если указан, использовать этот лог-файл
--log-file-max-size uint     По умолчанию: 1800
Установить максимальный размер файла лог-файла (в Мб). Если значение равно 0, максимальный размер файла не ограничен.
--log-flush-frequency duration     По умолчанию: 5s
Максимальное количество секунд между очисткой лог-файлов
--logtostderr     По умолчанию: true
Вывод логов в стандартный поток ошибок вместо сохранения их в файлы
--machine-id-file string     По умолчанию: "/etc/machine-id,/var/lib/dbus/machine-id"
Список файлов, разделенных запятыми, для проверки machine-id. Используйте первый существующий.
--match-server-version
Убедиться, что версия сервера соответствует версии клиента
-n, --namespace string
Указать область пространства имен для данного запроса CLI
--password string
Пароль для базовой аутентификации на API-сервере
--profile string     По умолчанию: "none"
Имя профиля. Может быть одним из перечисленных значений: none|cpu|heap|goroutine|threadcreate|block|mutex
--profile-output string     По умолчанию: "profile.pprof"
Имя файла для записи профиля.
--request-timeout string     По умолчанию: "0"
Время ожидания перед тем, как перестать ожидать ответ от сервера. Значения должны содержать соответствующую единицу времени (например, 1s, 2m, 3h). Нулевое значение означает, что у запросов нет тайм-аута.
-s, --server string
Адрес и порт API-сервера Kubernetes
--skip-headers
Если true, не отображать заголовки в сообщениях лога.
--skip-log-headers
Если true, не отображать заголовки при открытии лог-файлов.
--stderrthreshold severity     По умолчанию: 2
Логи указанного уровня серьёзности или выше выводить в поток stderr
--storage-driver-buffer-duration duration     По умолчанию: 1m0s
Буферизировать запись в драйвере хранилища в течение указанного времени, и сохранять в файловом хранилище в виде одной транзакции
--storage-driver-db string     По умолчанию: "cadvisor"
Имя базы данных
--storage-driver-host string     По умолчанию: "localhost:8086"
Хост и порт базы данных, записанный в формате host:port
--storage-driver-password string     По умолчанию: "root"
Пароль к базе данных
--storage-driver-secure
Использовать безопасное соединение с базой данных
--storage-driver-table string     По умолчанию: "stats"
Имя таблицы
--storage-driver-user string     По умолчанию: "root"
Имя пользователя базы данных
--token string
Аутентификационный (bearer) токен для аутентификации на API-сервере
--update-machine-info-interval duration     По умолчанию: 5m0s
Интервал между обновлениями информации о машине.
--user string
Имя пользователя для kubeconfig
--username string
Имя пользователя для базовой аутентификации на API-сервере
-v, --v Level
Номер уровня серьёзности логирования
--version version[=true]
Вывод версии команды
--vmodule moduleSpec
Список, разделённый запятыми, в виде настроек pattern=N для фильтрации лог-файлов

См. также

  • kubectl annotate - Обновить аннотации ресурса.
  • kubectl api-resources - Вывести доступные API-ресурсы на сервере.
  • kubectl api-versions - Вывести доступные API-версии на сервере в виде "group/version".
  • kubectl apply - Внести изменения в конфигурацию ресурса из файла или потока stdin.
  • kubectl attach - Присоединиться к запущенному контейнеру.
  • kubectl auth - Проверить разрешение на выполнение определённых действий.
  • kubectl autoscale - Автоматически масштабировать Deployment, ReplicaSet или ReplicationController.
  • kubectl certificate - Изменить сертификаты ресурсов.
  • kubectl cluster-info - Показать информацию по кластеру.
  • kubectl completion - Вывод кода автодополнения указанной командной оболочки (bash или zsh).
  • kubectl config - Изменить файлы kubeconfig.
  • kubectl convert - Конвертировать конфигурационные файлы в различные API-версии.
  • kubectl cordon - Отметить узел как неназначаемый.
  • kubectl cp - Копировать файлы и директории в/из контейнеров.
  • kubectl create - Создать ресурс из файла или потока stdin.
  • kubectl delete - Удалить ресурсы из файла, потока stdin, либо с помощью селекторов меток, имен, селекторов ресурсов или ресурсов.
  • kubectl describe - Показать подробную информацию о конкретном ресурсе или группе ресурсов.
  • kubectl diff - Сравнить действующую версию с новой (применяемой).
  • kubectl drain - Вытеснить узел для подготовки к эксплуатации.
  • kubectl edit - Отредактировать ресурс на сервере.
  • kubectl exec - Выполнить команду в контейнере.
  • kubectl explain - Получить документацию ресурсов.
  • kubectl expose - Создать новый сервис Kubernetes из контроллера репликации, сервиса, развёртывания или пода.
  • kubectl get - Вывести один или несколько ресурсов.
  • kubectl kustomize - Собрать ресурсы kustomization из директории или URL-адреса.
  • kubectl label - Обновить метки ресурса.
  • kubectl logs - Вывести логи контейнера в поде.
  • kubectl options - Вывести список флагов, применяемых ко всем командам.
  • kubectl patch - Обновить один или несколько полей ресурса, используя стратегию слияния патча.
  • kubectl plugin - Команда для работы с плагинами.
  • kubectl port-forward - Переадресовать один или несколько локальных портов в под.
  • kubectl proxy - Запустить прокси на API-сервер Kubernetes.
  • kubectl replace - Заменить ресурс из определения в файле или потоке stdin.
  • kubectl rollout - Управление плавающим обновлением ресурса.
  • kubectl run - Запустить указанный образ в кластере.
  • kubectl scale - Задать новый размер для Deployment, ReplicaSet или Replication Controller.
  • kubectl set - Конфигурировать ресурсы в объектах.
  • kubectl taint - Обновить ограничения для одного или нескольких узлов.
  • kubectl top - Показать информацию по использованию системных ресурсов (процессор, память, диск).
  • kubectl uncordon - Отметить узел как назначаемый.
  • kubectl version - Вывести информацию о версии клиента и сервера.
  • kubectl wait - Экспериментально: ожидать выполнения определенного условия в одном или нескольких ресурсах.

8.2.4 - kubectl для пользователей Docker

Вы можете использовать инструмент командной строки kubectl в Kubernetes для работы с API-сервером. Если вы знакомы с инструментом командной строки Docker, то использование kubectl не составит проблем. Однако команды docker и kubectl отличаются. В следующих разделах показана подкоманда docker и приведена эквивалентная команда в kubectl.

docker run

Для развёртывания nginx и открытия доступа к объекту Deployment используйте команду kubectl run.

docker:

docker run -d --restart=always -e DOMAIN=cluster --name nginx-app -p 80:80 nginx
55c103fa129692154a7652490236fee9be47d70a8dd562281ae7d2f9a339a6db
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
55c103fa1296        nginx               "nginx -g 'daemon of…"   9 seconds ago       Up 9 seconds        0.0.0.0:80->80/tcp   nginx-app

kubectl:

# запустить под, в котором работает nginx
kubectl create deployment --image=nginx nginx-app
deployment "nginx-app" created
# add env to nginx-app
kubectl set env deployment/nginx-app  DOMAIN=cluster
deployment.apps/nginx-app env updated
# открыть порт, чтобы иметь доступ к сервису
kubectl expose deployment nginx-app --port=80 --name=nginx-http
service "nginx-http" exposed

С помощью kubectl можно создать объект Deployment, чтобы убедиться, что N подов, запущены под nginx, где N — это количество реплик, указанных в спецификации (по умолчанию — 1). Вы также можете создать сервис с селектором, соответствующим меткам подов. Для получения дополнительной информации перейдите на страницу Use a Service to Access an Application in a Cluster.

По умолчанию образы запускаются в фоновом режиме, аналогично команде docker run -d .... Для запуска в центральном (интерактивном) режиме используйте команду ниже:

kubectl run [-i] [--tty] --attach <name> --image=<image>

В отличие от docker run ..., если вы укажете --attach, то присоедините stdin, stdout and stderr. Нельзя проконтролировать, какие потоки прикрепляются (docker -a ...). Чтобы отсоединиться от контейнера, воспользуетесь комбинацией клавиш Ctrl+P, а затем Ctrl+Q.

Так как команда kubectl run запускает развёртывание для контейнера, то оно начнет перезапускаться, если завершить прикрепленный процесс по нажатию Ctrl+C, в отличие от команды docker run -it. Для удаления объекта Deployment вместе с подами, необходимо выполнить команду kubectl delete deployment <name>.

docker ps

Посмотреть, что сейчас запущено можно с помощью команды kubectl get.

docker:

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                     PORTS                NAMES
14636241935f        ubuntu:16.04        "echo test"              5 seconds ago        Exited (0) 5 seconds ago                        cocky_fermi
55c103fa1296        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute          0.0.0.0:80->80/tcp   nginx-app

kubectl:

kubectl get po
NAME                        READY     STATUS      RESTARTS   AGE
nginx-app-8df569cb7-4gd89   1/1       Running     0          3m
ubuntu                      0/1       Completed   0          20s

docker attach

Чтобы присоединить процесс, который уже запущен в контейнере, используйте команду kubectl attach.

docker:

docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
55c103fa1296        nginx               "nginx -g 'daemon of…"   5 minutes ago       Up 5 minutes        0.0.0.0:80->80/tcp   nginx-app
docker attach 55c103fa1296
...

kubectl:

kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE
nginx-app-5jyvm   1/1       Running   0          10m
kubectl attach -it nginx-app-5jyvm
...

Для отсоединения его от контейнера используйте сочетания клавиш Ctrl+P и Ctrl+Q.

docker exec

Для выполнения команды в контейнере используйте команду kubectl exec.

docker:

docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
55c103fa1296        nginx               "nginx -g 'daemon of…"   6 minutes ago       Up 6 minutes        0.0.0.0:80->80/tcp   nginx-app
docker exec 55c103fa1296 cat /etc/hostname
55c103fa1296

kubectl:

kubectl get po
NAME              READY     STATUS    RESTARTS   AGE
nginx-app-5jyvm   1/1       Running   0          10m
kubectl exec nginx-app-5jyvm -- cat /etc/hostname
nginx-app-5jyvm

Примеры с командной оболочкой

docker:

docker exec -ti 55c103fa1296 /bin/sh
# exit

kubectl:

kubectl exec -ti nginx-app-5jyvm -- /bin/sh
# exit

Для получения дополнительной информации обратитесь к странице Get a Shell to a Running Container.

docker logs

Для отслеживания логов в потоки stdout/stderr запущенного процесса используйте команду kubectl logs.

docker:

docker logs -f a9e
192.168.9.1 - - [14/Jul/2015:01:04:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.35.0" "-"
192.168.9.1 - - [14/Jul/2015:01:04:03 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.35.0" "-"

kubectl:

kubectl logs -f nginx-app-zibvs
10.240.63.110 - - [14/Jul/2015:01:09:01 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"
10.240.63.110 - - [14/Jul/2015:01:09:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"

Есть небольшая разница между подами и контейнерами: по умолчанию поды не прекращают выполнение, если их процессы завершаются. Вместо этого поды перезапускают процесс. Это похоже на опцию --restart=always в Docker, только с одной большой разницей. В Docker вывод каждого вызова процесса объединяется, в отличие от Kubernetes, где каждый вызов является отдельным. Для просмотра вывода предыдущего запуска в Kubernetes, используйте команду ниже:

kubectl logs --previous nginx-app-zibvs
10.240.63.110 - - [14/Jul/2015:01:09:01 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"
10.240.63.110 - - [14/Jul/2015:01:09:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"

Для получения дополнительной информации обратитесь к странице Logging Architecture.

docker stop и docker rm

Для завершения и удаления запущенного процесса используйте команду kubectl delete.

docker:

docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
a9ec34d98787        nginx               "nginx -g 'daemon of"  22 hours ago        Up 22 hours         0.0.0.0:80->80/tcp, 443/tcp   nginx-app
docker stop a9ec34d98787
a9ec34d98787
docker rm a9ec34d98787
a9ec34d98787

kubectl:

kubectl get deployment nginx-app
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-app    1/1     1            1           2m
kubectl get po -l app=nginx-app
NAME                         READY     STATUS    RESTARTS   AGE
nginx-app-2883164633-aklf7   1/1       Running   0          2m
kubectl delete deployment nginx-app
deployment "nginx-app" deleted
kubectl get po -l app=nginx-app
# Return nothing

docker login

В kubectl нет прямого аналога команды docker login. Если вы планируете использовать Kubernetes с приватным реестром, изучите страницу Using a Private Registry.

docker version

Для получения версии клиента и сервера используйте команду kubectl version.

docker:

docker version
Client version: 1.7.0
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 0baf609
OS/Arch (client): linux/amd64
Server version: 1.7.0
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 0baf609
OS/Arch (server): linux/amd64

kubectl:

kubectl version
Client Version: version.Info{Major:"1", Minor:"6", GitVersion:"v1.6.9+a3d1dfa6f4335", GitCommit:"9b77fed11a9843ce3780f70dd251e92901c43072", GitTreeState:"dirty", BuildDate:"2017-08-29T20:32:58Z", OpenPaasKubernetesVersion:"v1.03.02", GoVersion:"go1.7.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"6", GitVersion:"v1.6.9+a3d1dfa6f4335", GitCommit:"9b77fed11a9843ce3780f70dd251e92901c43072", GitTreeState:"dirty", BuildDate:"2017-08-29T20:32:58Z", OpenPaasKubernetesVersion:"v1.03.02", GoVersion:"go1.7.5", Compiler:"gc", Platform:"linux/amd64"}

docker info

Для получения разной информации про окружение и конфигурации перейдите в раздел kubectl cluster-info.

docker:

docker info
Containers: 40
Images: 168
Storage Driver: aufs
 Root Dir: /usr/local/google/docker/aufs
 Backing Filesystem: extfs
 Dirs: 248
 Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.13.0-53-generic
Operating System: Ubuntu 14.04.2 LTS
CPUs: 12
Total Memory: 31.32 GiB
Name: k8s-is-fun.mtv.corp.google.com
ID: ADUV:GCYR:B3VJ:HMPO:LNPQ:KD5S:YKFQ:76VN:IANZ:7TFV:ZBF4:BYJO
WARNING: No swap limit support

kubectl:

kubectl cluster-info
Kubernetes master is running at https://203.0.113.141
KubeDNS is running at https://203.0.113.141/api/v1/namespaces/kube-system/services/kube-dns/proxy
kubernetes-dashboard is running at https://203.0.113.141/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy
Grafana is running at https://203.0.113.141/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
Heapster is running at https://203.0.113.141/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy
InfluxDB is running at https://203.0.113.141/api/v1/namespaces/kube-system/services/monitoring-influxdb/proxy

8.2.5 - Команды kubectl

Справочник команд kubectl

8.2.6 - Шпаргалка по kubectl

Смотрите также: обзор Kubectl и руководство по JsonPath.

Эта команда представляет собой обзор команды kubectl.

kubectl - Шпаргалка

Автодополнение ввода для Kubectl

BASH

source <(kubectl completion bash) # настройка автодополнения в текущую сессию bash, предварительно должен быть установлен пакет bash-completion .
echo "source <(kubectl completion bash)" >> ~/.bashrc # добавление автодополнения autocomplete постоянно в командную оболочку bash.

Вы также можете использовать короткий псевдоним для kubectl, который можно интегрировать с автодополнениями:

alias k=kubectl
complete -F __start_kubectl k

ZSH

source <(kubectl completion zsh)  # настройка автодополнения в текущую сессию zsh
echo "[[ $commands[kubectl] ]] && source <(kubectl completion zsh)" >> ~/.zshrc # add autocomplete permanently to your zsh shell

Контекст и конфигурация kubectl

Установка того, с каким Kubernetes-кластером взаимодействует kubectl и изменяет конфигурационную информацию. Подробную информацию о конфигурационном файле смотрите на странице Authenticating Across Clusters with kubeconfig.

kubectl config view # показать объединённые настройки kubeconfig

# использовать несколько файлов kubeconfig одновременно и посмотреть объединённую конфигурацию из этих файлов
KUBECONFIG=~/.kube/config:~/.kube/kubconfig2

kubectl config view

# получить пароль для пользователя e2e
kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}'

kubectl config view -o jsonpath='{.users[].name}'    # показать первого пользователя
kubectl config view -o jsonpath='{.users[*].name}'   # получить список пользователей
kubectl config get-contexts                          # показать список контекстов
kubectl config current-context                       # показать текущий контекст (current-context)
kubectl config use-context my-cluster-name           # установить my-cluster-name как контекст по умолчанию

# добавить новую конфигурацию для кластера в kubeconf с базовой аутентификацией
kubectl config set-credentials kubeuser/foo.kubernetes.com --username=kubeuser --password=kubepassword

# сохранить пространство имен для всех последующих команд kubectl в этом контексте.
kubectl config set-context --current --namespace=ggckad-s2

# установить контекст, используя имя пользователя и пространство имен.
kubectl config set-context gce --user=cluster-admin --namespace=foo \
  && kubectl config use-context gce

kubectl config unset users.foo                       # удалить пользователя foo

Apply

apply управляет приложениями с помощью файлов, которые определяют ресурсы Kubernetes. Выполните команду kubectl apply для создания и обновления ресурсов. Это рекомендуемый способ управления приложениями Kubernetes в промышленном окружении. Смотрите Kubectl Book.

Создание объектов

Манифесты Kubernetes могут быть определены в YAML или JSON. Можно использовать расширение файла .yaml, .yml и .json

kubectl apply -f ./my-manifest.yaml            # создать ресурсы
kubectl apply -f ./my1.yaml -f ./my2.yaml      # создать ресурсы из нескольких файлов
kubectl apply -f ./dir                         # создать ресурсы из всех файлов манифеста в директории
kubectl apply -f https://git.io/vPieo          # создать ресурсы из URL-адреса
kubectl create deployment nginx --image=nginx  # запустить один экземпляр nginx
kubectl explain pods                           # посмотреть документацию по манифестам подов

# Создать несколько YAML-объектов из stdin
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: busybox-sleep
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - sleep
    - "1000000"
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox-sleep-less
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - sleep
    - "1000"
EOF

# Создать секрет с несколькими ключами
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: $(echo -n "s33msi4" | base64 -w0)
  username: $(echo -n "jane" | base64 -w0)
EOF

Просмотр и поиск ресурсов

# Get-команды с основном выводом
kubectl get services                          # Вывести все сервисы в пространстве имён
kubectl get pods --all-namespaces             # Вывести все поды во всех пространств имён
kubectl get pods -o wide                      # Вывести все поды в текущем пространстве имён с подробностями
kubectl get deployment my-dep                 # Вывести определённое развёртывание
kubectl get pods                              # Вывести все поды в пространстве имён
kubectl get pod my-pod -o yaml                # Получить информацию по поду в формате YAML

# Посмотреть дополнительные сведения команды с многословным выводом
kubectl describe nodes my-node
kubectl describe pods my-pod

# Вывести сервисы, отсортированные по имени
kubectl get services --sort-by=.metadata.name

# Вывести поды, отсортированные по количеству перезагрузок
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'

# Вывести постоянные тома (PersistentVolumes), отсортированные по емкости
kubectl get pv --sort-by=.spec.capacity.storage

# Получить метку версии всех подов с меткой app=cassandra
kubectl get pods --selector=app=cassandra -o \
  jsonpath='{.items[*].metadata.labels.version}'

# Получить все рабочие узлы (с помощью селектора исключаем узлы с меткой 'node-role.kubernetes.io/master')
kubectl get node --selector='!node-role.kubernetes.io/master'

# Получить все запущенные поды в пространстве имён
kubectl get pods --field-selector=status.phase=Running

# Получить внешние IP-адреса (ExternalIP) всех узлов
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}'

# Вывести имена подов, принадлежащие к определённому RC
# Использование команды "jq" помогает упросить поиск в jsonpath, подробнее смотрите на сайте https://stedolan.github.io/jq/
sel=${$(kubectl get rc my-rc --output=json | jq -j '.spec.selector | to_entries | .[] | "\(.key)=\(.value),"')%?}
echo $(kubectl get pods --selector=$sel --output=jsonpath={.items..metadata.name})

# Показать метки всех подов (или любого другого объекта Kubernetes, которым можно прикреплять метки)
kubectl get pods --show-labels

# Получить готовые узлы
JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}' \
 && kubectl get nodes -o jsonpath="$JSONPATH" | grep "Ready=True"

# Вывод декодированных секретов без внешних инструментов
kubectl get secret my-secret -o go-template='{{range $k,$v := .data}}{{"### "}}{{$k}}{{"\n"}}{{$v|base64decode}}{{"\n\n"}}{{end}}'

# Вывести все секреты, используемые сейчас в поде.
kubectl get pods -o json | jq '.items[].spec.containers[].env[]?.valueFrom.secretKeyRef.name' | grep -v null | sort | uniq

# Вывести все идентификаторы (containerID) контейнеров инициализации (initContainers) во всех подах.
# Это полезно при очистке остановленных контейнеров, не удаляя при этом контейнеры инициализации.
kubectl get pods --all-namespaces -o jsonpath='{range .items[*].status.initContainerStatuses[*]}{.containerID}{"\n"}{end}' | cut -d/ -f3

# Вывести события, отсортированные по временной метке
kubectl get events --sort-by=.metadata.creationTimestamp

# Сравнить текущее состояние кластера с состоянием, в котором находился бы кластер в случае применения манифеста.
kubectl diff -f ./my-manifest.yaml

Обновление ресурсов

Начиная с версии 1.11 подкоманда rolling-update была удалена (см. CHANGELOG-1.11.md), поэтому вместо неё используйте rollout.

kubectl set image deployment/frontend www=image:v2               # Плавающее обновление контейнеров "www" развёртывания "frontend", обновление образа
kubectl rollout history deployment/frontend                      # Проверить историю развёртывания, включая ревизии.
kubectl rollout undo deployment/frontend                         # Откатиться к предыдущему развёртыванию
kubectl rollout undo deployment/frontend --to-revision=2         # Откатиться к определённой ревизии
kubectl rollout status -w deployment/frontend                    # Отслеживать статус плавающего развёртывания "frontend" до его завершения
kubectl rollout restart deployment/frontend                      # Перезапуск плавающего развёртывания "frontend"


# Объявлено устаревшим, начиная с версии 1.11
kubectl rolling-update frontend-v1 -f frontend-v2.json           # (устарело) Плавающее обновление подов frontend-v1
kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2  # (устарело) Изменить имя ресурса и обновить образ
kubectl rolling-update frontend --image=image:v2                 # (устарело) Обновить образ подов frontend
kubectl rolling-update frontend-v1 frontend-v2 --rollback        # (устарело) Отменить выполняющееся обновление

cat pod.json | kubectl replace -f -                              # Заменить под из определения в JSON-файле, переданного в поток stdin

# Принудительно заменить, удалить, а затем пересоздать ресурс. Это приведет к простою приложения
kubectl replace --force -f ./pod.json

# Создать сервис с реплицированным nginx на порту 80, который подключается к контейнерам на порту 8000.
kubectl expose rc nginx --port=80 --target-port=8000

# Обновить версию (метку) образа пода из одного контейнера single до v4
kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f -

kubectl label pods my-pod new-label=awesome                      # Добавить метку
kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq       # Добавить аннотацию
kubectl autoscale deployment foo --min=2 --max=10                # Автоматически масштабировать развёртывание "foo" в диапазоне от 2 до 10 подов

Обновление ресурсов

# Обновить часть узла
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'

# Обновить образ контейнера; необходимо указать spec.containers[*].name, чтобы произвести слияние
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'

# Обновить образ контейнера через json-патч с позиционными массивами
kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'

# Удалить развертывание livenessProbe через json-патч с позиционными массивами
kubectl patch deployment valid-deployment  --type json   -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]'

# Добавить нового элемента в позиционный массив
kubectl patch sa default --type='json' -p='[{"op": "add", "path": "/secrets/1", "value": {"name": "whatever" } }]'

Редактирование ресурсов

Вы можете отредактировать API-ресурс в любом редакторе.

kubectl edit svc/docker-registry                      # Отредактировать сервис docker-registry
KUBE_EDITOR="nano" kubectl edit svc/docker-registry   # Использовать другой редактор

Масштабирование ресурсов

kubectl scale --replicas=3 rs/foo                                 # Масштабирование набора реплик (replicaset) 'foo' до 3
kubectl scale --replicas=3 -f foo.yaml                            # Масштабирование ресурса в "foo.yaml" до 3
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql  # Если количество реплик в развёртывании mysql равен 2, масштабировать его до 3
kubectl scale --replicas=5 rc/foo rc/bar rc/baz                   # Масштабирование нескольких контроллеров репликации до 5

Удаление ресурсов

kubectl delete -f ./pod.json                                              # Удалить под по типу и имени в pod.json
kubectl delete pod,service baz foo                                        # Удалить поды и сервисы с одноимёнными именам "baz" и "foo"
kubectl delete pods,services -l name=myLabel                              # Удалить поды и сервисы с именем метки myLabel
kubectl -n my-ns delete pod,svc --all                                     # Удалить все поды и сервисы в пространстве имен my-ns
# Удалить все поды, соответствующие pattern1 или pattern2 в awk
kubectl get pods  -n mynamespace --no-headers=true | awk '/pattern1|pattern2/{print $1}' | xargs  kubectl delete -n mynamespace pod

Работа с запущенными подами

kubectl logs my-pod                                 # вывести логи пода (в stdout)
kubectl logs -l name=myLabel                        # вывести логи пода с меткой myLabel (в stdout)
kubectl logs my-pod --previous                      # вывести логи пода (в stdout) по предыдущему экземпляру контейнера
kubectl logs my-pod -c my-container                 # вывести логи контейнера пода (в stdout, при работе с несколькими контейнерами)
kubectl logs -l name=myLabel -c my-container        # вывести логи пода с меткой myLabel (в stdout)
kubectl logs my-pod -c my-container --previous      # вывести логи контейнера пода (в stdout, при работе с несколькими контейнерами) по предыдущему экземпляру контейнера
kubectl logs -f my-pod                              # вывести логи пода в режиме реального времени (в stdout)
kubectl logs -f my-pod -c my-container              # вывести логи контейнера пода в режиме реального времени (в stdout, при работе с несколькими контейнерами)
kubectl logs -f -l name=myLabel --all-containers    # вывести логи всех подов с меткой myLabel (в stdout)
kubectl run -i --tty busybox --image=busybox -- sh  # запустить под как интерактивную оболочку
kubectl run nginx --image=nginx --restart=Never -n
mynamespace                                         # Запустить под nginx в заданном пространстве имён
kubectl run nginx --image=nginx --restart=Never     # Запустить под nginx и записать его спецификацию в файл pod.yaml
--dry-run -o yaml > pod.yaml

kubectl attach my-pod -i                            # Прикрепить к запущенному контейнеру
kubectl port-forward my-pod 5000:6000               # Переадресовать порт 5000 в локальной машине на порт 6000 в поде my-pod
kubectl exec my-pod -- ls /                         # Выполнить команду в существующем поде (в случае одного контейнера).
kubectl exec my-pod -c my-container -- ls /         # Выполнить команду в существующем поде (в случае нескольких контейнеров)
kubectl top pod POD_NAME --containers               # Показать метрики по заданному поду вместе с его контейнерами

Работа с узлами и кластером

kubectl cordon my-node                                                # Отметить узел my-node как неназначаемый
kubectl drain my-node                                                 # Вытеснить узел my-node, чтобы подготовиться к эксплуатации
kubectl uncordon my-node                                              # Отметить узел my-node как назначаемый
kubectl top node my-node                                              # Показать метрики по заданному узлу
kubectl cluster-info                                                  # Показать адреса главного узла и сервисов
kubectl cluster-info dump                                             # Вывести состояние текущего кластера в stdout
kubectl cluster-info dump --output-directory=/path/to/cluster-state   # Вывести состояние текущего кластера в /path/to/cluster-state

# Если ограничение с заданным ключом и проявлением уже существует, его значение будет заменено указанным
kubectl taint nodes foo dedicated=special-user:NoSchedule

Типы ресурсов

Вывести все поддерживаемые типы ресурсов, включая API-группу, флаг namespaced (организован ли ресурс в пространство имён или нет) и Kind:

kubectl api-resources

Другие варианты команды для анализа API-ресурсов:

kubectl api-resources --namespaced=true      # Все ресурсы с пространством имён
kubectl api-resources --namespaced=false     # Все ресурсы без пространства имён
kubectl api-resources -o name                # Все ресурсы с простым выводом  (только имя ресурса)
kubectl api-resources -o wide                # Все ресурсы с расширенным (с неограниченной длинной) выводом
kubectl api-resources --verbs=list,get       # Все ресурсы, которые поддерживают глаголы запроса "list" и "get"
kubectl api-resources --api-group=extensions # Все ресурсы в API-группе "extensions"

Форматирование вывода

Для вывода подробной информации в окно терминала в определенном формате, добавьте флаг -o (или --output) в команду kubectl, которая поддерживает форматирование.

Формат вывода Описание
-o=custom-columns=<spec> Вывод таблицы из списка пользовательских столбцов через запятую
-o=custom-columns-file=<filename> Вывод таблицы из списка пользовательских столбцов, определённых в файле <filename>
-o=json Вывод API-объекта в формате JSON
-o=jsonpath=<template> Вывод полей, определённых в выражении jsonpath
-o=jsonpath-file=<filename> Вывод полей, определённых в выражении jsonpath из файла <filename>
-o=name Вывод только имена ресурсов
-o=wide Вывод дополнительную информации в обычном текстовом формате, в случае подов отображается имя узла
-o=yaml Вывод API-объекта в формате YAML

Уровни детальности вывода и отладки в Kubectl

Уровни детальности вывода Kubectl регулируются с помощью флагов -v или --v, за которыми следует целое число, представляющее уровни логирования. Общие соглашения по логированию Kubernetes и связанные с ними уровни описаны здесь.

Уровень детальности Описание
--v=0 Как правило, используется чтобы всегда видеть, что происходит
--v=1 Достаточный уровень логирования по умолчанию, если вам не нужна большая детальность.
--v=2 Полезная информация про стабильное состояние сервиса и важные сообщения логов, которые могут связаны со значительными изменениями в системе. Это рекомендуемый уровень логирования по умолчанию для большинства систем.
--v=3 Расширенная информация об изменениях.
--v=4 Уровень детальности для отладки.
--v=6 Показать запрашиваемые ресурсы.
--v=7 Показать заголовки HTTP-запросов.
--v=8 Показать содержимое HTTP-запросов.
--v=9 Показать содержимого HTTP-запроса в полном виде.

Что дальше

8.3 - Проблемы и безопасность Kubernetes

8.3.1 - Трекер задач (Issues) Kubernetes

Чтобы сообщить о проблеме в области безопасности, воспользуйтесь процедурой раскрытия информации о безопасности Kubernetes.

Механизм GitHub Issues позволяет работать с кодом Kubernetes и отслеживать активные задачи.

Связанные с безопасностью анонсы публикуются в рассылке kubernetes-security-announce@googlegroups.com.

8.3.2 - Общие сведения о безопасности Kubernetes и раскрытии информации

На этой странице приводятся общие сведения о безопасности Kubernetes и раскрытии информации, имеющей к ней отношение.

Анонсы в области безопасности

Информация о проблемах в области безопасности и ключевых изменениях API доступна в рассылке kubernetes-security-announce.

Сообщить об уязвимости

Мы искренне признательны исследователям в области безопасности и пользователям, которые передают информацию об уязвимостях в Open Source-сообщество Kubernetes. Все отчеты тщательно изучаются группой добровольцев сообщества.

Чтобы создать отчет, отправьте свою уязвимость в Bug Bounty-программу Kubernetes. Это позволит отследить и обработать уязвимость в стандартные сроки.

Также можно оправить стандартное письмо об ошибках Kubernetes с описанием проблемы с безопасностью и ее подробностями в закрытый список security@kubernetes.io.

Письмо можно зашифровать, используя GPG-ключи членов Комитета по безопасности. Шифрование с использованием GPG НЕ является обязательным.

Когда следует сообщать об уязвимости

  • Вы думаете, что обнаружили уязвимость в безопасности Kubernetes.
  • Вы не уверены, как именно уязвимость повлияет на Kubernetes.
  • Вы думаете, что обнаружили уязвимость в другом проекте, от которого зависит работа Kubernetes.
    • Если у проекта имеется собственный регламент регистрации и раскрытия информации об уязвимостях, пожалуйста, следуйте ему и пишите сразу в проект.

Когда НЕ следует сообщать об уязвимости

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

Реагирование на уязвимости в области безопасности

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

Любая информация об уязвимостях, переданная Комитету по реагированию на угрозы безопасности, остается внутри проекта Kubernetes и не передается в другие проекты, если только этого не требуется для устранения проблемы.

Автору отчета будет сообщено о результатах триажа и дальнейших шагах по подготовке исправления и планированию релиза.

Сроки раскрытия информации

Дата публичного раскрытия согласовывается Комитетом по реагированию на угрозы безопасности Kubernetes и автором отчета об уязвимости. Мы предпочитаем полностью раскрывать информацию об обнаруженной проблеме сразу после того, как станет понятно, какие шаги необходимо предпринять для устранения ее последствий. Разумно отложить раскрытие информации, если проблема или порядок дальнейших шагов не до конца понятны, решение плохо протестировано или необходима координация действий вендоров. Срок раскрытия информации варьируется от незамедлительного (особенно если она уже широко известна) до нескольких недель. Для "простых" уязвимостей с момента подачи отчета до даты раскрытия обычно проходит около 7 дней. Комитет по реагированию на угрозы безопасности сохраняет последнее слово при определении даты раскрытия информации.

8.3.3 - Официальный CVE-фид

СТАТУС ФИЧИ: Kubernetes v1.27 [beta]

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

Проект Kubernetes публикует фиды с анонсами проблем в области безопасности в формате JSON и RSS, доступные для автоматического считывания. Доступ к ним можно получить, выполнив следующие команды:

Ссылка на JSON-формат

curl -Lv https://k8s.io/docs/reference/issues-security/official-cve-feed/index.json

Ссылка на RSS-формат

curl -Lv https://k8s.io/docs/reference/issues-security/official-cve-feed/feed.xml
Официальный список Kubernetes CVE (последнее обновление: 21 нояб. 2024 22:38:10 UTC)
CVE ID Описание проблемы CVE GitHub Issue URL
CVE-2024-10220 Arbitrary command execution through gitRepo volume #128885
CVE-2024-9594 VM images built with Image Builder with some providers use default credentials during builds #128007
CVE-2024-9486 VM images built with Image Builder and Proxmox provider use default credentials #128006
CVE-2024-7646 Ingress-nginx Annotation Validation Bypass #126744
CVE-2024-5321 Incorrect permissions on Windows containers logs #126161
CVE-2024-3744 azure-file-csi-driver discloses service account tokens in logs #124759
CVE-2024-3177 Bypassing mountable secrets policy imposed by the ServiceAccount admission plugin #124336
CVE-2023-5528 Insufficient input sanitization in in-tree storage plugin leads to privilege escalation on Windows nodes #121879
CVE-2023-5044 Code injection via nginx.ingress.kubernetes.io/permanent-redirect annotation #126817
CVE-2023-5043 Ingress nginx annotation injection causes arbitrary command execution #126816
CVE-2022-4886 ingress-nginx path sanitization can be bypassed #126815
CVE-2023-3955 Insufficient input sanitization on Windows nodes leads to privilege escalation #119595
CVE-2023-3893 Insufficient input sanitization on kubernetes-csi-proxy leads to privilege escalation #119594
CVE-2023-3676 Insufficient input sanitization on Windows nodes leads to privilege escalation #119339
CVE-2023-2431 Bypass of seccomp profile enforcement #118690
CVE-2023-2728 Bypassing policies imposed by the ImagePolicyWebhook and bypassing mountable secrets policy imposed by the ServiceAccount admission plugin #118640
CVE-2023-2727 Bypassing policies imposed by the ImagePolicyWebhook and bypassing mountable secrets policy imposed by the ServiceAccount admission plugin #118640
CVE-2023-2878 secrets-store-csi-driver discloses service account tokens in logs #118419
CVE-2022-3294 Node address isn't always verified when proxying #113757
CVE-2022-3162 Unauthorized read of Custom Resources #113756
CVE-2022-3172 Aggregated API server can cause clients to be redirected (SSRF) #112513
CVE-2021-25749 `runAsNonRoot` logic bypass for Windows containers #112192
CVE-2021-25748 Ingress-nginx `path` sanitization can be bypassed with newline character #126814
CVE-2021-25746 Ingress-nginx directive injection via annotations #126813
CVE-2021-25745 Ingress-nginx `path` can be pointed to service account token file #126812
CVE-2021-25742 Ingress-nginx custom snippets allows retrieval of ingress-nginx serviceaccount token and secrets across all namespaces #126811
CVE-2021-25741 Symlink Exchange Can Allow Host Filesystem Access #104980
CVE-2021-25737 Holes in EndpointSlice Validation Enable Host Network Hijack #102106
CVE-2021-3121 Processes may panic upon receipt of malicious protobuf messages #101435
CVE-2021-25735 Validating Admission Webhook does not observe some previous fields #100096
CVE-2020-8554 Man in the middle using LoadBalancer or ExternalIPs #97076
CVE-2020-8566 Ceph RBD adminSecrets exposed in logs when loglevel >= 4 #95624
CVE-2020-8565 Incomplete fix for CVE-2019-11250 allows for token leak in logs when logLevel >= 9 #95623
CVE-2020-8564 Docker config secrets leaked when file is malformed and log level >= 4 #95622
CVE-2020-8563 Secret leaks in kube-controller-manager when using vSphere provider #95621
CVE-2020-8557 Node disk DOS by writing to container /etc/hosts #93032
CVE-2020-8559 Privilege escalation from compromised node to cluster #92914
CVE-2020-8558 Node setting allows for neighboring hosts to bypass localhost boundary #92315
CVE-2020-8555 Half-Blind SSRF in kube-controller-manager #91542
CVE-2020-10749 IPv4 only clusters susceptible to MitM attacks via IPv6 rogue router advertisements #91507
CVE-2019-11254 kube-apiserver Denial of Service vulnerability from malicious YAML payloads #89535
CVE-2020-8552 apiserver DoS (oom) #89378
CVE-2020-8551 Kubelet DoS via API #89377
CVE-2020-8553 ingress-nginx auth-type basic annotation vulnerability #126818
CVE-2019-11251 kubectl cp symlink vulnerability #87773
CVE-2018-1002102 Unvalidated redirect #85867
CVE-2019-11255 CSI volume snapshot, cloning and resizing features can result in unauthorized volume data access or mutation #85233
CVE-2019-11253 Kubernetes API Server JSON/YAML parsing vulnerable to resource exhaustion attack #83253
CVE-2019-11250 Bearer tokens are revealed in logs #81114
CVE-2019-11248 /debug/pprof exposed on kubelet's healthz port #81023
CVE-2019-11249 Incomplete fixes for CVE-2019-1002101 and CVE-2019-11246, kubectl cp potential directory traversal #80984
CVE-2019-11247 API server allows access to custom resources via wrong scope #80983
CVE-2019-11245 container uid changes to root after first restart or if image is already pulled to the node #78308
CVE-2019-11243 rest.AnonymousClientConfig() does not remove the serviceaccount credentials from config created by rest.InClusterConfig() #76797
CVE-2019-11244 `kubectl:-http-cache=<world-accessible dir>` creates world-writeable cached schema files #76676
CVE-2019-1002100 json-patch requests can exhaust apiserver resources #74534
CVE-2018-1002105 proxy request handling in kube-apiserver can leave vulnerable TCP connections #71411
CVE-2018-1002101 smb mount security issue #65750
CVE-2018-1002100 Kubectl copy doesn't check for paths outside of it's destination directory. #61297
CVE-2017-1002102 atomic writer volume handling allows arbitrary file deletion in host filesystem #60814
CVE-2017-1002101 subpath volume mount handling allows arbitrary file access in host filesystem #60813
CVE-2017-1002100 Azure PV should be Private scope not Container scope #47611
CVE-2017-1000056 PodSecurityPolicy admission plugin authorizes incorrectly #43459

Список автоматически обновляется с заметной, но небольшой задержкой (от нескольких минут до нескольких часов) с момента анонса CVE до момента его появления в этом фиде.

В качестве источника используется набор GitHub Issues, отфильтрованный по контролируемому и ограниченному лейблу official-cve-feed. Исходные данные хранятся в бакете Google Cloud, право на запись в который есть только у небольшого числа доверенных представителей сообщества.

9 - Участие в документации Kubernetes

Если вы хотите внести свой вклад в документацию или сайт Kubernetes, мы будем рады вашей помощи! Любой может принять участие в проекте, независимо от того, знакомы ли вы с проектом или нет, кроме этого не имеет значения кто вы — разработчик, обычный пользователь или всего лишь тот, кто терпеть не может опечаток.

С деталями о содержании и стиле документации Kubernetes вы можете ознакомиться в Documentation style overview.

Типы участников документации

  • Член организации Kubernetes, который подписал CLA и уже поработал в проекте определённое время. Перейдите на страницу Членство в сообществе, чтобы узнать что нужно для вступления в организацию.
  • Рецензент документации SIG — член организации Kubernetes, который занимался проверкой пулреквестов в документацию и поэтому был добавлен в соответствующую группу на GitHub, и кроме того является ответственным за файлы, перечисленные в OWNERS в репозитории GitHub.
  • Утверждающий документации SIG — участник с хорошей репутацией, который продемонстрировал неизменную приверженность проекту. Утверждающий может принимать пулреквесты и публиковать контент от имени организации Kubernetes. Утверждающие также могут быть представителями документации SIG в более крупном сообществе Kubernetes. Некоторые из обязанностей утверждающего документации SIG, такие как организация нового выпуска, требуют огромного количество времени.

Способы участия в документации

Этот список разделен на то, что может делать каждый, что могут делать члены организации Kubernetes, и то, что требует более высокого уровня доступа и знания процессов документации SIG. Со временем постоянное участие в проекте поможет вам понять некоторые средства и организационные решения, которые уже были приняты.

Это не полный список способов поучаствовать в документации Kubernetes, зато он должен помочь вам начать работу.

  • Любой человек
    • Добавление реализуемых задач
  • Член
    • Улучшение существующей документации
    • Предложение идей по улучшению документации в Slack или в списке рассылки документации SIG
    • Улучшение доступности документации
    • Составление рекомендаций к пулреквестам в документацию
    • Написание постов в блоге или примеров использования продукта
  • Рецензент
    • Документирование новых функциональных возможностей
    • Сортировка и маркировка задач
    • Анализ пулреквестов
    • Создание диаграмм, графических ресурсов и встраиваемых скринкастов и/или видео
    • Локализация
    • Участие в других репозиториях в качестве представителя документации
    • Редактирование пользовательских строк в коде
    • Улучшение комментариев в коде, Godoc
  • Утверждающий
    • Публикация материалов участников, проверяя и объединяя пулреквесты
    • Участие в команде по выпуску новых версий Kubernetes в качестве представителя документации
    • Внесение предложений по улучшению руководства по стилю оформлению
    • Внесение предложений по улучшению в тесты документации
    • Внесение предложений по улучшению в сайт Kubernetes website или другие инструменты

Дополнительные способы участия

9.1 - Участие для начинающих

Если вы хотите поучаствовать в работе над документацией Kubernetes, эта страница и связанные с ней темы могут помочь вам начать работу. Вам не нужно быть разработчиком или техническим писателем, чтобы внести вклад в документацию или улучшить сайт Kubernetes! Все, что вам нужно для тем на этой странице, это учетная запись на GitHub и браузер.

Если вы ищете информацию про участие в репозиториях, связанным с кодом Kubernetes, обратитесь к руководству сообщества Kubernetes.

Основные сведения про документацию

Документация Kubernetes написана на Markdown, обработана и развернута при помощи Hugo. Исходные файлы находятся на GitHub по адресу https://github.com/kubernetes/website. Основная часть документации хранится в директории /content/en/docs/. Часть справочной документации автоматически генерируется из скриптов в директории update-imported-docs/.

Вы можете создавать новые задачи, редактировать содержимое и проверять изменения от других участников, — всё это доступно с сайта GitHub. Вы также можете использовать встроенный в GitHub поиск и историю коммитов.

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

Участие в документации SIG

Документация Kubernetes поддерживается специальной группой (Special Interest Group, SIG) под названием SIG Docs. Мы общаемся с помощью канала Slack, списка рассылки и еженедельных видеозвонков. Будем рады новым участникам. Для получения дополнительной информации обратитесь к странице Участие в SIG Docs.

Руководящие принципы по содержанию

Сообщество SIG Docs разработало правила, которые касаются разрешенных видов контента в документации Kubernetes. Посмотрите руководство по содержанию документации для определения того, допустим ли контент, который вы хотите добавить. Задать вопросы про допустимый контент можно в Slack-канале #sig-docs.

Правила оформления

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

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

Шаблоны страниц

Мы используем шаблоны страниц, чтобы управлять представление наших страниц документации. Разберитесь как работают эти шаблоны, ознакомившись с разделом Использование шаблонов страниц.

Макрокоды Hugo

Документация Kubernetes с помощью Hugo конвертируется из формата разметки Markdown в HTML. Мы используем встроенные макрокоды Hugo, а также некоторые из своих собственных, созданных специально для документации Kubernetes. Посетите страницу Нестандартные макрокоды Hugo, чтобы узнать, как их использовать.

Мультиязычность

Исходные файлы документации доступны на нескольких языках в директории /content/. Каждый язык имеет свою собственную директорию с двухбуквенным кодом, определенным стандартомISO 639-1 standard. Например, исходники документации для английского языка хранится в директории /content/en/docs/.

Более подробную информацию про участие в работе над документацией на нескольких языках "Localize content" в промежуточном руководстве по добавлению.

Если вы заинтересованы в переводе документации на новый язык, посмотрите раздел "Локализация".

Создание хороших заявок

Любой, у кого есть аккаунт на GitHub, может создать заявку (issue, или отчет об ошибке) в документации Kubernetes. Если вы заметили какую-либо какую-либо ошибку, даже если вы не знаете, как её исправить, откройте ишью. Но не делайте этого, если нашли небольшую ошибку, например, опечатку, которую вы при желании можете исправить самостоятельно. В этом случае можете исправить ее вместо того, чтобы писать об этом.

Как создать заявку

  • Для существующей страницы

    Если заметили проблему на существующей странице в документации Kubernetes, перейдите в конец страницы и нажмите кнопку Create an Issue. Если вы ещё не авторизованы в GitHub, сделайте это. После этого откроется страница с форма для создания нового запроса в GitHub с уже предварительно заполненным полями.

    При помощи разметки Markdown опишите как можно подробнее, что хотите. Там, где вы видите пустые квадратные скобки ([ ]), проставьте x между скобками. Если у вас есть предлагаемое решение проблемы, напишите его.

  • Запросить новую страницу

    Если вы хотите добавить что-то новое, но вы не уверены, на какую страницу документации это сделать или считаете, что новая информация не вписывается в существующие страницы, всё равно создайте ишью. Вы можете либо перейти на страницу документации, куда, по вашему мнению, нужно добавить новую информацию и создать заявку прямо с этой страницы, либо перейти по адресу https://github.com/kubernetes/website/issues/new/ и написать что вы хотите там.

Как заполнить хорошую заявку

Чтобы нам самим убедиться, что понимаем вас правильно, помните следующее:

  • Используйте шаблон ишью и заполните его как можно подробнее.
  • Четко изложите суть вашего проблемы, как она сказывается на пользователях.
  • Как можно меньше ограничьте охват изменений в вашей заявке. Задачи с большим объемом работы разбейте на более мелкие. Например, "Fix the security docs" не является проблемой, требующей немедленного решения, зато заявка с заголовком "Add details to the 'Restricting network access' topic", вероятно, такой является.
  • Если проблема связана с другой заявкой или пулреквестом, вы можете указать сослаться на них, либо по его полному URL-адресу, либо по их номеру с #. Например, Introduced by #987654.
  • Будьте уважительны и избегайте жалоб. Например, заголовок ишью "The docs about X suck" явно не несёт ничего полезного или чтобы на него реагировали. Нормы поведения также применяется к общению в GitHub-репозиториях Kubernetes.

Участие в дискуссиях SIG Docs

Команда SIG Docs общается следующими способами:

Улучшение существующего текста

Чтобы улучшить текущее содержимое документации, вам нужно открыть пулреквест (pull request, PR) после того, как вы сделаете копию (fork) оригинального репозитория. Эти два термина относятся к GitHub. Для начала работы, которая показана в этом разделе, вам не нужно знать всё про эти понятия, так как вы всё можете делать в своём браузере. Когда вы перейдете к продвинутому руководству участника документации, тогда вам понадобиться пополнить свои знания Git.

Примечание. Разработчики кода Kubernetes. Если вы документируете новую функцию для предстоящего выпуска Kubernetes, ваш процесс будет немного другим. См. Документирование функции для руководства по процессу и информации о сроках.

Подписание CLA-соглашения CNCF

Прежде чем внести вклад в код или документацию Kubernetes, вам обязательно следует прочитать руководство для участников и подписать лицензионное соглашение участника (Contributor License Agreement, CLA). Не переживайте — подписание не займет много времени!

Поиск задач для работы

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

Если вы хотите ещё не определились с тем, над чем хотите поработать, перейдите по адресу https://github.com/kubernetes/website/issues и найдите ишью с меткой good first issue (вы можете использовать эту ссылку для быстрого поиска). Прочитайте комментарии, чтобы убедиться что нет открытого пулреквеста для решения текущей ишью, а также, что никто другой не оставил комментарий, что он работает над этой задачей в последнее время (как правило, 3 дня). Добавьте комментарий, что вы хотели бы заняться решением этой задачи.

Выбор правильной ветки в Git

Самым важный момент в создании пулреквестов — это выбор нужной ветки для вашей работы. Используйте эти рекомендации, чтобы принять верное решение:

  • Используйте ветку master для исправления ошибок в текущей документации, либо чтобы улучшить существующий текст.
  • Используйте ветку master для документирования функциональности в текущей версии Kubernetes, для которой отсутствовала документация. Прежде всего вам нужно написать документацию на английском языке, а затем команды по переводам подхватят это изменение, чтобы актуализировать перевод.
  • Если вы работаете над переводом, вам нужно следовать соглашению в этой конкретной локализации. Чтобы понять это, вы можете другие пулреквесты (подсказка: is:pr is:merged label:language/xx)
    • Некоторые команды локализации работают с пулреквестами, которые ориентированы на ветку master
    • Другие команды локализации работают с рядом долговечных веток, периодически сливая их в ветку master. Такая ветка именуется как dev-<version>-<language code>.<team milestone>, например, dev-release-1.31-ja.1.
  • Если вы пишете или обновляете документацию к выпуску грядущего изменения, то вам необходимо знать мажорную и минорную версию Kubernetes, в которой это изменение впервые появится.
    • Например, если переключатель возможностей (feature gates) JustAnExample должен измениться с альфа-версии на бета-версию в следующей минорной версии, вам необходимо знать номер этой версии.
    • Найдите ветку выпуска, названную для этой версии. Например, функциональность, которая изменились в выпуске vrelease-1.31, будет документирована в ветке dev-release-1.31.

Если вы все еще не уверены, какую ветку выбрать, спросите в Slack-канале #sig-docs или посетите еженедельную встречу SIG Docs, чтобы внести ясность.

Отправка пулреквеста

Следуйте описанным ниже шагам, чтобы создать пулреквест для улучшения документации Kubernetes.

  1. На странице, которую вы хотите отредактировать, щелкните на иконку карандаша в правом верхнем углу. Откроется новая страница на GitHub с небольшой подсказкой.

  2. Если вы ранее не делали копию репозитория документации Kubernetes, вам будет предложено это сделать. Создайте копию репозитория под своим логином GitHub, а не в организации, в которой вы состоите. URL-адрес копии репозитория будет выглядит как https://github.com/<username>/website, в случае у вас нет репозитория с таким же названием.

    Поскольку у вас нет доступа к оригинальному репозиторию и соответственно вы не можете отправлять напрямую изменения в основную ветку, вам нужно сделать копию репозитория Kubernetes.

  3. Откроется редактор GitHub для редактирования исходного файла в формате Markdown. Внесите свои изменения. Под редактором заполните форму Propose file change. Первое поле — краткое содержание вашего сообщения коммита, оно должно содержать не более 50 символов. Второе поле является необязательным, в нём вы можете подробно расписать суть ваших изменений.

    Нажмите на кнопку Propose file change. Изменения в файле записываются в виде коммита в новой ветке вашей копии репозитория, которая автоматически будет иметь имя что-то вроде patch-1.

  4. На следующей странице вам будут показаны различия в вашей ветке (поля выбора head fork и compare) с текущим состоянием оригинального репозитория (base fork) в основной ветке (base) (по умолчанию ветка master в репозитории kubernetes/website). Вы можете выбрать другое значение в полях выбора, но не делайте этого сейчас. Сравните различия и если всё верно, нажмите кнопку Create pull request.

  5. Отобразится форма с заголовком Open a pull request. Название пулреквеста будет содержать краткое описание из сообщения коммита, хотя вы можете изменить его при необходимости. В описании пулреквеста будет остальная информация из сообщения коммита (если оно есть) и небольшой шаблон с текстом. Прочитайте текст шаблона и сделайте то, что там описано, а затем удалите этот шаблонный текст. Если вы добавите в описание пулреквест fixes #<000000> или closes #<000000>, где #<000000> - номер связанной заявки, то GitHub автоматически закроет указанную заявку при слиянии пулреквеста. Оставьте флажок Allow edits from maintainers отмеченным. Нажмите на кнопку Create pull request.

    Поздравляем! Ваш пулреквест добавлен в список пулреквестов.

    Через несколько минут вы сможете просмотреть версию сайта с изменениями в вашем пулреквесте. Перейдите в низ страницы пулреквеста на вкладке Conversation и там нажмите на ссылку Details рядом с проверкой deploy/netlify. По умолчанию она откроется в текущей вкладке.

  6. Ожидайте, когда проверят ваш пулреквест. Как правило, рецензенты выбираются авматоматически ботом k8s-ci-robot. Если рецензент попросил изменить пулреквест, вы можете сделать это, если перейдёте на вкладку Files changed и щёлкните на иконку с карандашом на любом изменённом файле в вашем пулреквесте. Сохранение измененного файла оформляется в виде нового коммита в ветке, указанной в пулреквесте. Если вы ожидаете новую проверку изменений от рецензента, заранее попросите его об этом не более одного раза в 7 дней. Вы также можете зайти в Slack-канал #sig-docs — это хорошее место, где можно попросить проверку пулреквеста.

  7. Если ваши изменения одобрены, то рецензент объединяет соответствующий пулреквест. Через несколько минут вы сможете сможете увидеть его в действии на сайте Kubernetes.

Это только один из способов отправить пулреквест. Если вы уже опытный пользователь Git и GitHub, вы можете вносить изменения, используя локальный GUI-клиент или Git из терминала вместо того, чтобы использовать интерфейс GitHub для этого. Некоторые основы использования Git-клиента из командной строки обсуждаются в руководстве для продвинутого участника.

Просмотр пулреквестов в документацию

Новички документации могут обозревать пулреквесты. Вы можете изучить кодовую базу и завоевать доверие к себе со стороны коллег-участников. Документация на английском — это первоисточник содержимого. Мы общаемся на английском языке во время еженедельных встреч и в объявлениях сообщества. Владение английским языком может быть разным, поэтому используйте простой и прямой язык в своих обзорах пулреквестов. Полезные обзоры фокусируются как на мелких деталях, так и на потенциальном влиянии изменений.

Обзоры не носят «обязательный характер», это означает, что только ваша проверка не приведет к слиянию пулреквеста. Тем не менее, это не делает ваши обзоры бесполезными. Даже только просмотр изменений в пулреквеста поможет вам понять как происходит рабочий процесс, какие могут быть трудности и проблемы. Перед проверкой пулреквестов ознакомьтесь с руководством по содержанию и руководством по оформлению, чтобы узнать, каким должен быть содержимое и как оно должно быть оформлено..

Рекомендации

  • Будьте вежливы, внимательны и помогайте другим
  • Не забывайте отмечать также положительные стороны пулреквеста
  • Будьте чутким и думайте, как ваши комментарии могут быть восприняты
  • Проявите добрые намерения и задавайте уточняющие вопросы
  • Опытным участникам: помогайте новым участникам, их работа требует глаз да глаз

Поиск и проверка пулреквеста

  1. Перейдите по URL-адресу https://github.com/kubernetes/website/pulls. Вы увидите список всех пулреквестов в репозиторий сайта Kubernetes и его документации.

  2. По умолчанию открываются открытые пулреквесты (статус open), поэтому вы не увидите закрытых или принятых пулреквестов. Рекомендуется добавить дополнительный фильтр cncf-cla: yes, а также для вашей первой проверки пулреквеста неплохо применить ещё и size/S и size/XS. Метка с размером назначается автоматически в зависимости от количества изменённых строк кода в пулреквесте. Вы можете применить фильтры, используя поля выбора в верхней части страницы, либо воспользоваться этой ссылкой для просмотра небольших пулреквестов. Все фильтры объединены в логическое AND, поэтому у вас не получиться искать по меткам size/XS и size/S одновременно.

  3. Перейдите на вкладку Files changed. Посмотрите изменения, внесенные в PR, а также изучите любые связанные задачи (если есть). Если вы видите ошибку, неточность или хотите внести улучшение, то наведите курсор на строку и щелкните на появившийся символ +.

    Вы можете написать комментарий, после чего нажать на кнопку Add single comment или Start a review. Как правило, лучше начать проверку (review), поскольку тогда вы сможете оставить несколько комментариев и уведомить автора PR только после завершения рецензирования, вместо того, чтобы упоминать его в каждом комментарии.

  4. После окончания разбора пулреквеста, нажмите на кнопку Review changes вверху страницы. Вы можете подвести краткий итог своей проверки и выполнить одно из действий: просто прокомментировать, одобрить или запросить изменения. Новым участникам нужно всегда только комментировать (кнопка Comment) пулреквесты.

Спасибо за обзор пулреквеста! Если вы новенький в проекте, рекомендуется попросить кого-нибудь оценить ваш обзор пулреквеста. Slack-канал #sig-docs — отличное место для этого.

Написание постов в блоге

Любой может написать пост в блоге и отправить его на рассмотрение. Посты блога не должны носит коммерческий характер и должны отражать опыт, который может широко применён в сообществе Kubernetes.

Чтобы заявить о посте вы можете отправить его, используя форму блога Kubernetes, либо же выполнить следующие действия.

  1. Подпишите CLA, если вы еще этого не сделали.
  2. Изучите разметку Markdown у текущих постов блога в репозитории сайта.
  3. Напишите свою статью в вашем любимом текстовом редакторе.
  4. По ссылке из второго шага нажмите на кнопку Create new file. Скопируйте из своего редактора текст и вставьте в многострочное поле. Назовите файл так, чтобы он соответствовал предлагаемому заголовку статьи в блоге, но не указывайте дату в имени файла. Рецензенты блога будут работать с вами над окончательным именем файла и датой публикации записи.
  5. Когда вы сохраните файл, начнётся описанный выше процесс принятия пулреквеста в GitHub.
  6. Рецензент блога рассмотрит вашу статью и вместе с вами будет работать над ее улучшением. Когда запись в блоге будет одобрена, будет известна дата публикации вашей статьи.

Отправка примеров использования

В примерах использования показывается, как организации используют Kubernetes для решения собственных реальных проблем. Они написаны в сотрудничестве с маркетинговой командой Kubernetes, которой занимается CNCF.

Ознакомьтесь с существующими примерами использования. Воспользуйтесь формой добавления нового примера использования Kubernetes, чтобы поделиться своим опытом.

Что дальше

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

9.2 - Участие для продвинутых

1

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

Теперь, когда вы уже знаете кое-что и приняли участие в документации Kubernetes, как описано в теме Участие для начинающих, вы можете пойти ещё дальше. Далее пойдут задачи, предусматривающие наличие и желание получить глубокие знания по следующим темам:

  • Концепции Kubernetes
  • Рабочие процессы документации Kubernetes
  • Поиск нужной информации о будущих возможностях Kubernetes
  • Сильные аналитические навыки в целом

Эти задачи не такие последовательные, как задачи для начинающих. Поэтому мы не ожидаем, что кто-то в одиночку будет постоянно заниматься всеми ими.

Знакомство с Prow

Prow — это система CI/CD, использующая Kubernetes, которая выполняет задания с пулреквестами (PR). Prow с помощью команд, похожих на те, что есть в чатботах, даёт возможность обрабатывать действия в организации Kubernetes на GitHub. Вы можете выполнять целый ряд действий, такие как добавление и удаление меток, закрытие заявок и назначение утверждающего. Введите Prow-команду в поле для комментария в формате /<command-name>. Некоторые популярные команды:

  • /lgtm (looks good to me): добавляет метку lgtm, которая сообщает, что рецензент проверил PR
  • /approve: одобряет PR так, чтобы он мог быть принят (эта команда работает только для утверждающих)
  • /assign: назначает проверяющего на PR
  • /close: закрывает ишью или PR
  • /hold: добавляет метку do-not-merge/hold, которая означает, что PR не может быть автоматически принят
  • /hold cancel: удаляет метку do-not-merge/hold

Детально изучите список команд Prow, прежде чем начать проверять PR или сортировать ишью.

Проверка пулреквестов

Каждую неделю утверждающий доброволец документации сортирует и просматривает пулреквесты и заявки. Такой человек называется "PR Wrangler" на неделю. Расписание ведется с помощью планировщика PR Wrangler. Чтобы поучаствовать в этом списке, посетите еженедельную встречу SIG Docs. Даже если вас не выбрали дежурным по PR на текущую неделю, вы все равно можете проверять пулреквесты (PR), которые еще не были детально просмотрены.

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

Мы хотим, чтобы пулреквесты принимались и публиковались как можно быстрее. Чтобы документация оставалась точной и актуальной, каждый PR должен проверяться людьми, понимающие суть темы, а также теми, кто имеет опыт написания отличной документации.

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

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

Поиск пулреквестов для проверки

Чтобы посмотреть все открытые пулреквесты, перейдите на вкладку Pull Requests в GitHub-репозитории. PR можно проверять только, если он соответствует всем перечисленным ниже критериям:

  • Имеет метку cncf-cla:yes
  • Не содержит надписи WIP в описании
  • Не имеет тег с фразой do-not-merge
  • Нет конфликтов для слияния
  • Сделан в правильную ветку (обычно это master, за исключением, если PR не относится к невыпущенной ещё функциональности)
  • Не проверялся ещё детально другим проверяющим документации (то же самое касается и остальных технических рецензентов), если только этот человек явно не обратился за вашей помощью. В частности, не рекомендуется добавлять много новых комментариев после других циклов рассмотрения PR.

Если PR не имеет условия для проверки, можно оставить комментарий, чтобы сообщить автору о текущих проблемах и предложить помочь решить их. Если автор пулреквеста был оповещён о проблемах и не устранил их в течение нескольких недель или месяцев, то рано или поздно такой PR будет закрыт.

Если вы новичок в проверке пулреквестов или у вас недостаточно времени и возможностей, попробуйте поискать PR с тегом size/XS или size/S. Размер пулреквеста автоматически определяется по количеству изменённых строк в PR.

Рецензенты и утверждающие

В репозитории сайта Kubernetes работа построена иначе, чем в других репозиториях Kubernetes, когда речь идет о роли рецензентов и утверждающих. Для получения дополнительной информации об обязанностях рецензентов и утверждающих см. Участие в SIG Docs. Ниже вы найдете краткий обзор.

  • Рецензент проверяет содержание пулреквеста для соблюдения технической точности. Рецензент даёт понять, что PR технически точен, оставляя комментарий с /lgtm к PR.

  • Утверждающий проверяет содержание запроса на предмет качества и соответствия рекомендациям SIG Docs, приведенным в руководствах по содержанию и оформлению. Только люди, указанные в качестве утверждающих в файле OWNERS, могут одобрить PR. Чтобы одобрить PR, оставьте комментарий /approve к PR.

PR объединяется, когда у него есть комментарий /lgtm от кого-либо из организации Kubernetes и комментарий /approve от утверждающего в группе sig-docs-maintainers, если он не удерживается, а автор PR подписал CLA.

Проверка PR

  1. Изучите описание PR вместе с указанными ишью и ссылками, если они есть. Кратковременные мимолетные обзоры иногда могут наносит больше вреда, чем пользы, поэтому убедитесь, что вы обладаете нужными знаниями, чтобы сделать содержательный обзор.

  2. Если кто-то другой может лучше всего проверит определенный PR, упомяните этого человека, добавив комментарий /assign @<github-username>. Если вы обратились за технической проверкой к человеку, который не занимается документацией, но при этом вы хотите сами посмотреть PR как участник группы документации, то не стесняйтесь это делать.

  3. Перейдите на вкладку Files changed. Посмотрите на все изменённые строки. Удалённый текст выделен красным, а строки с ним начинаются с символа -. Добавленный текст отмечен зелёным фоном, а строки с ним начинаются с символа +. Внутри строки фактически измененный контент имеет чуть более темный зеленый фон, чем остальная часть строки.

    • В частности, если в PR есть сложное форматирование или он изменяет CSS, JavaScript или другие элементы сайта, вы можете просмотреть сайт, сгенерированный с этими изменениями в PR. Перейдите на вкладку Conversation и нажмите ссылку Details в проверке deploy/netlify в нижней части страницы. По умолчанию ссылка открывается в текущей вкладке браузера, поэтому чтобы потерять частичный отзыв, откройте ссылку в новой вкладке. Вернитесь на вкладку Files changed, чтобы продолжить проверку пулреквеста.

    • Убедитесь, что PR соответствует правилам содержания и оформления; если что-то не так, укажите на этом со ссылкой на раздел в руководстве.

    • Если у вас есть вопрос или вы хотите прокомментировать определённое изменение, наведите курсор мыши на строку и кликните на появившуюся сине-белую кнопку с иконкой +. Напишите свой комментарий и нажмите на кнопку Start a review.

    • Если вам нужно оставить больше одного комментария, сделайте это по аналогии с предыдущим шагом.

    • По соглашению, если вы видите небольшую проблему, не имеющей отношение к основному назначению PR, например, опечатку или лишний пробел, вы можете сообщить о ней, начав комментарий с nit:, чтобы автор знал, что это незначительная ошибка. Хотя это не означает, что автор пулреквеста может проигнорировать такие проблемы.

    • Когда вы всё проверили или у вас не осталось комментариев, прокрутите в верхнюю часть страницы и нажмите на кнопку Review changes. Далее кликните либо на Comment или Request Changes. Напишите краткий итог вашей проверки и добавьте соответствующие Prow-команды по одной на каждой строке в поле Review Summary. SIG Docs следует процессу проверки кода Kubernetes. Все ваши комментарии будут отправлены автору PR в виде одного уведомления.

      • Если вы считаете, что PR в хорошем состоянии, чтобы его принять, добавьте команду /approve в резюме вашей проверки.

      • Если PR не нуждается в дополнительном техническом рассмотрении, добавьте ещё команду /lgtm.

      • Если PR требуется дополнительный технический обзор, добавьте команду /assign и после неё укажите логин человека на GitHub, который должен сделать технический анализ. Посмотрите на поле рецензентов во вступительной (фронтальной) части вверху данного Markdown-файла, чтобы выяснить, кто может провести технический разбор пулреквеста.

      • Чтобы заблокировать слияние PR, используйте команду /hold. Она добавит метку do-not-merge/hold.

      • Если в PR нет конфликтов и есть метки lgtm и approve (и нет метки hold), то он автоматически объединиться.

      • Если PR имеет метки lgtm и/или approve, и появляются новые изменения, эти метки будут автоматически удалены.

        Посмотрите список доступных команд, которые можно использовать в PR.

    • Если вы ранее выбрали нажали на Request changes и затем автор PR решил все указанные проблемы, вы можете обновить статус проверки либо на вкладке Files changed, либо в нижней части вкладки Conversation. Обязательно укажите команду /approve и при необходимости выберите технических рецензентов, чтобы можно было объединить PR.

Редактирование PR другого человека

Добавление комментариев в PR — полезное дело, но могут быть случаи, когда нужно сделать коммит в пулреквест другого человека, а не просто оставить свой отзыв.

Не поддавайтесь желанию выполнить работу за другого человека, если только он явно не попросит вас об этом или вы не захотите оживить давно заброшенный PR. Хотя это может быть быстрее в краткосрочной плане, но это лишает человека возможности внести собственный вклад.

Используемый процесс зависит от того, нужно ли вам отредактировать файл, который уже изменен в PR, либо вам нужно отредактировать файл, который в PR не участвовал.

Вы не можете отредактировать чужой PR, если выполняется одно из условий:

  • Если автор PR отправил свою ветку непосредственно в репозиторий https://github.com/kubernetes/website/, то только рецензент с правом отправки изменений напрямую в репозиторий может вносить изменения в PR. Авторам следует открыть PR из ветки в своей копии репозитория.
  • Если автор PR явно запретил редактирование утверждающими, вы не сможете внести изменения в его PR, пока он не изменит эту настройку.

Если файл уже изменён в PR

Этот метод использует интерфейс GitHub. Вы можете использовать командную строку, если вам комфортнее работать в ней, даже если вам нужно изменить файл, который ранее редактировался в PR.

  1. Перейдите на вкладку Files changed.
  2. Прокрутите к блоку с файлом, который вы хотите отредактировать и нажмите на иконку с карандашом.
  3. Внесите изменения, напишите сообщение коммита в соответствующем поле под текстовым редактором и нажмите Commit changes.

После этого ваш коммит отправляется в ветку из PR (скорее всего, в копию репозитория автора), и теперь отображается в PR, а ваши изменения отражаются на вкладке Files changed. Оставьте комментарий, чтобы автор PR знал, что вы что-то сделали в PR.

Если автор использует командную строку, а не сайт GitHub для работы с этим PR, он должен получить изменения со своей копии репозитория и перебазировать свою локальную ветку на ветку своей копии, прежде чем заниматься своим PR.

Если файл ещё не был изменён в PR

Если необходимо внести изменения в файл, который не был отредактирован в рамках конкретного PR, нужно использовать командную строку. Вам придётся по душе такой метод, если вы предпочитаете использовать терминал вместо использования сайта GitHub.

  1. Узнайте URL-адрес копии репозитория автора пулреквеста. Вы можете найти его в нижней части вкладки Conversation. Найдите текст Add more commits by pushing to. Первая ссылка после этой надписи ведет на ветку, а вторая ссылка — на саму копию репозитория. Скопируйте вторую ссылку. Запомните название ветки, пригодится впоследствии.

  2. Добавьте копию репозитория как новый удаленный репозиторий. В терминале перейдите в директорию своей копии репозитория. Придумайте имя для удаленного репозитория (например, по имени логина автора на GitHub) и добавьте его, используя следующую команду:

    git remote add <name> <url-of-fork>
    
  3. Получите информацию о добавленном удаленном репозитории. Это действие не затронет локальные файлы, а только загрузит в вашу копии репозитория информацию о другой копии (например, ветки и теги).

    git remote fetch <name>
    
  4. Перейдите в ветку, полученную с удаленного репозитория. Эта команда не получится, если у вас локально уже есть ветка с таким же именем.

    git checkout <branch-from-PR>
    
  5. Внесите изменения и добавьте их через git add, а затем зафиксируйте их.

  6. Отправьте изменения в удаленный репозиторий автора.

    git push <remote-name> <branch-name>
    
  7. Откройте снова сайт GitHub и обновите страницу PR. Вы увидите ваши изменения. Добавьте комментарий для автора, чтобы он был в курсе, что вы изменили его PR.

Если автор использует командную строку, а не интерфейс на GitHub для работы над PR, ему нужно получить новые изменения из своей копии репозитоии и перебазировать свою локальную ветку на ветку своей копии репозитории, прежде чем снова заниматься собственным PR.

Работа из локальной копии

В случае изменений нескольких файлов, либо добавлением новых или перемещением старых, лучше работать из локальной копии Git-репозитория на компьютере, нежели чем использовать для этого GitHub. Следующие инструкции используют командую утилиту git, которая предполагается, что она уже установлена на вашем компьютере. Вы можете воспользоваться ими даже, если пользуетесь графическим Git-клиента.

Клонирование репозитория

Вам нужно только один раз клонировать репозиторий на каждом компьютере, на котором вы работаете с документацией Kubernetes.

  1. Создайте копию репозитория kubernetes/website на GitHub. В браузере перейдите по https://github.com/kubernetes/website и нажмите на кнопку Fork. После нескольких секунд вы будете автоматически перенаправлены на URL-адрес вашей копии, которая будет иметь следующий вид: https://github.com/<github_username>/website.

  2. В окне термина используйте команду git clone для получения копии репозитория.

    git clone git@github.com/<github_username>/website
    

    После выполнения этой команды в текущей рабочей директории появится новая директория website с содержимым вашего репозитория на GitHub. В данном случае удаленный репозиторий origin будет ссылаться на вашу копию репозитория.

  3. Перейдите в новую директорию website. Добавьте новый удалённый репозиторий kubernetes/website под именем upstream.

    cd website
    
    git remote add upstream https://github.com/kubernetes/website.git
    
  4. Проверьте ваши репозитории origin и upstream.

    git remote -v
    

    Output is similar to:

    origin	git@github.com:<github_username>/website.git (fetch)
    origin	git@github.com:<github_username>/website.git (push)
    upstream	https://github.com/kubernetes/website.git (fetch)
    upstream	https://github.com/kubernetes/website.git (push)
    

Работа в локальном репозитории

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

  • Для общих улучшений существующего контента создайте собственную ветку от ветки master.
  • Для добавления нового контента про функциональность, которая уже есть в текущих версиях Kubernetes, начните с ветки master.
  • В случае большой и длительной работы, над которой будут трудиться несколько участников SIG Docs, например, реорганизация контента, создайте отдельную ветку, специально предназначенной для этого.
  • Для нового контента про будущие, но ещё не выпущенные версии Kubernetes, работайте в ветке предварительного выпуска, созданной специально для этой версии Kubernetes.

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

После того, как вы определили, с какой ветви начать свою работу (или на какой ветке будет базироваться ваша работа, если говорить в терминологии Git), следуйте определённому ниже рабочему процессу, чтобы ваша работа оставалась актуальной.

  1. Когда вы работаете локально, есть три разные копии репозитория: local, upstream и origin. Получите данные по удалённым репозиториям origin и upstream. Эта команда очистит кеш удаленных репозиториях без фактического изменения каких-либо из копии.

    git fetch origin
    git fetch upstream
    

    Этот рабочий процесс отличается от того, который определен в сообществе GitHub. Здесь вам не нужно объединять вашу локальную копию master из репозитория upstream/master, прежде чем отправлять изменения в вашу копию. Этот шаг не требуется в kubernetes/website, потому что ваша ветка базируется на репозитории upstream.

  2. Создайте локальную рабочую ветку из наиболее подходящей ветки upstream-репозитория: upstream/dev-1.xx для разработчиков в конкретных версиях или upstream/master для всех остальных участников. В этом примере предполагается, что вы будете работать с ветки upstream/master. Так как ваша локальная ветка master не настроена для отслеживания изменений с upstream/master на предыдущем шаге, поэтому вам нужно явно создать свою ветку от upstream/master.

    git checkout -b <my_new_branch> upstream/master
    
  3. После переключения на новую ветку можно начать в ней работать в текстовом редакторе. Используйте команду git status , чтобы посмотреть измененные файлы.

  4. Когда вы закончите работу, зафиксируйте изменения. Сначала выполните команду git status, чтобы увидеть, какие изменения будут добавлены в коммит. В выводе этой команды есть две важные секции: Changes staged for commit и Changes not staged for commit. Файлы в последней секции, рядом с которыми есть надпись modified или untracked, необходимо добавить, если вы хотите, чтобы они попали в коммит. Для каждого файла, который нужно добавить, используйте команду git add.

    git add example-file.md
    

    Когда все изменённые файлы добавлены, зафиксируйте их с помощью команды git commit:

    git commit -m "Your commit message"
    
  5. При желании вы можете посмотреть, как ваши изменения будут выглядеть на сайте, если запустите сайт на вашей машине с помощью команды hugo. Посмотрите раздел Просмотр ваших изменений локально. Кроме этого, вы увидите свои изменения после создания пулреквеста.

  6. Перед тем, как открывать пулреквест с вашими изменениями вам для начала отправить в ветку удаленного репозитория, чем в данном случае является origin.

    git push origin <my_new_branch>
    

    Технически вы можете не указать имя ветки в команде push, но корректное выполнение команды в таком случае зависит от используемой версии Git. Результаты будут более ожидаемыми, если вы напишите название ветки.

  7. Перейдите по адресу https://github.com/kubernetes/website в вашем браузере. GitHub определит и укажет вам, что вы загрузили новую ветку в свою копию, и поэтому предложит создать пулреквест. Заполните шаблон запроса.

    • Название должно быть не длиннее 50 символов и отражать краткий итог изменений.
    • Подробное описание должно содержать больше информации про исправление, включая строку типа Fixes #12345, если пулреквест решает проблему на GitHub. Это приведет к автоматическому закрытию указанной ишью после принятия пулреквеста.
    • Вы можете добавить метки или другие метаданные и назначить рецензентов. Смотрите страницу Сортировка и классификация ишью.

    Нажмите на кнопку Create pull request.

  8. Начнут выполняться автоматические тесты в зависимости от состояния сайта с вашими изменениями. Если какой-либо из тестов завершился неудачно, нажмите на ссылку Details для получения дополнительной информации. Если тест Netlify прошёл успешно, по ссылке Details вы можете найти предварительную версию сайта Kubernetes с внесенными вашими изменениями. Именно на ней рецензенты будут проверять ваши изменения.

  9. Если вам необходимо что-то дополнить, изменить пулреквест в соответствии с выполненной проверкой, либо изменить текст коммита, вы можете использовать команду ниже.

    git commit -a --amend
    
    • -a: зафиксировать все изменения
    • --amend: изменить предыдущий коммит вместо создания нового

    Откроется текстовый редактор, чтобы вы могли отредактировать сообщение коммита, если это нужно.

    Если вы используете git commit -m, как в шаге 4, вы сделаете новый коммит, а не измените исходный (предыдущий) коммит. Создание нового коммита означает, что вам нужно объединить свои коммиты до того, прежде чем пулреквест может быть объединен.

    Следуйте инструкциям в шаге 6, чтобы отправить новый коммит в удаленный репозиторий. После этого новое изменение отобразится в пулреквесте, а дальше снова запустятся тесты, а также произойдет новая сборка предварительной версии сайта на Netlify с последними изменениями.

  10. Если рецензент изменяет файлы в вашем пулреквесте, вам нужно получить новые изменения в вашей локальной копии, до того как снова начать что-то делать. Используйте команды ниже, чтобы обновить свою ветку (предполагается, что ветка уже получена с вашей копии репозитория).

    git fetch origin
    git rebase origin/<your-branch-name>
    

    После перебазирования вам нужно добавить флаг --force-with-lease, чтобы принудительно отправить новые изменения в ветке на вашу копию.

    git push --force-with-lease origin <your-branch-name>
    
  11. Может возникнуть конфликт, если кто-то, как и вы, изменил те же части файла в ветке, из которой была создана ваша ветка. Если пулреквест показывает, что есть конфликты, которые нужно разрешить, вы можете сделать это либо на сайте GitHub, либо исправить их локально.

    Сначала выполните шаг 10, чтобы актуализировать локальную ветку в соответствии с веткой в удаленном репозитории.

    Затем обновите репозиторий upstream и перебазируйте вашу ветку на ту, с которой она была создана, в данном случае это upstream/master.

    git fetch upstream
    git rebase upstream/master
    

    Если есть конфликты, которые Git не может разрешить автоматически, вы можете увидеть конфликтующие файлы с помощью команды git status. Отредактируйте каждый конфликтующий файл: найдите в них маркеры конфликта >>>, <<< и ===. Разрешение конфликта происходит путём удаления указанных маркеров конфликта. После это нужно добавить измененные файлы с помощью команды git add <filename> и продолжить перебазирование ветки, используя команду git rebase --continue. Когда всё зафиксировано в репозитории и не осталось неразрешенных конфликтов, команда git status покажет, что вы вышли из состояния перебазирования ветки и нет изменений для фиксации. На этом этапе вам осталось принудительно отправить ветку в свою копию репозитория, после чего на странице пулреквеста не должны быть конфликты.

  12. Если у вашего PR отображаются несколько сделанных коммитов после редактирования предыдущих коммитов, вам следует объединить эти несколько коммитов в один коммит, чтобы PR мог быть объединен. Проверить количество коммитов можно на вкладке Commits на странице PR или выполнив git log в терминале. Объединение коммитов (Squashing commits) — это одна из форм перебазирования.

```bash
git rebase -i HEAD~<number_of_commits>
```

Ключ `-i` сообщает git, что вы хотите сделать перебазирование в интерактивном режиме. В этом режиме вы сможете выбрать для git, какие коммиты нужно объединить в один. Например, в вашей ветке есть 3 коммита:

```
12345 commit 4 (2 minutes ago)
6789d commit 3 (30 minutes ago)
456df commit 2 (1 day ago)
```

Вам нужно объединить свои последние три коммита в один-единственный.

```
git rebase -i HEAD~3
```

Эта команда откроет редактор с таким содержимым:

```
pick 456df commit 2
pick 6789d commit 3
pick 12345 commit 4
```

Измените `pick` на `squash` у тех коммитов, которые вы хотите объединить, и проверьте, что коммит с выбранным `pick` находится сверху.

```
pick 456df commit 2
squash 6789d commit 3
squash 12345 commit 4
```

Сохраните и закройте редактор. Затем отправьте объединённый коммит в репозитории с помощью команды `git push --force-with-lease origin <branch_name>`.

Если у вас возникли проблемы с разрешением конфликтов или вы долго не можете что-то разрешить, что связано с вашим пулреквестом, обратитесь за помощью в Slack-канал #sig-docs или в список рассылки kubernetes-sig-docs.

Просмотр изменений локально

Если вы ещё не готовы создать пулреквесты, но при этом хотите посмотреть, как будет выглядеть сайт с вашими изменениями, то можете собрать и запустить образ Docker, чтобы сгенерировать всю документацию и открыть ее на своем компьютере.

  1. Соберите образ локально:

    make docker-image
    
  2. После того. как образ kubernetes-hugo собран, вы можете использовать его для запуска сайта:

    make docker-serve
    
  3. В адресной строке браузера введите вставьте адрес localhost:1313. Hugo будет следить за изменениями файловой системы и пересобирать сайт по мере необходимости.

  4. Чтобы остановить локальный сайт Hugo, откройте снова терминал и введите Ctrl+C или просто закройте окно с терминалом.

  1. Установите версию Hugo, которая указана в файле website/netlify.toml.

  2. В терминале перейдите в корневую директорию вашей копии документации Kubernetes и введите следующую команду:

    hugo server
    
  3. В адресной строке браузера скопируйте localhost:1313.

  4. Чтобы остановить локальный сайт Hugo, откройте снова терминал и введите Ctrl+C или просто закройте окно с терминалом.

Сортировка и классификация ишью

Люди в SIG Docs отвечают только за сортировку и классификацию ишью, связанных с документацией. Вопросы и проблемы общего характера также хранятся в репозитории kubernetes/website.

Что вы делаете, когда сортируете ишью:

  • Проверить ишью
    • Убедитесь, что ишью связана с документацией сайта. Некоторые заявки можно быстро закрыть, ответив на вопрос или указав автору на ресурс. Подробности смотрите в разделе Заявки с помощью или отчёты об ошибке в коде.
    • Рассмотрите, насколько обоснованной является заявка. Добавьте метку triage/needs-information, если в ишью описано мало подробностей, чтобы ее можно было начать решать, либо если шаблон был неправильно заполнен. Закройте заявку, если она имеет метки lifecycle/stale и triage/needs-information.
  • Добавьте метку с приоритетом (см. руководство по сортировке заявок, где подробно определены метки)
    • priority/critical-urgent - заниматься нужно прямо сейчас
    • priority/important-soon - нужно выполнить в течение 3 months
    • priority/important-longterm - нужно сделать в течение 6 months
    • priority/backlog - решение можно быть отложено на неопределенный срок indefinitely; самый низкий приоритет; делать, когда будут свободны ресурсы
    • priority/awaiting-more-evidence - указание, что это возможно хорошая задача, которую нужно иметь на виду
  • Дополнительно вы можете добавить метку help или good first issue, если определенная заявка может быть решена человеком, мало знакомым с Kubernetes или SIG Docs. В качестве руководства обратитесь к файлу Help Wanted and Good First Issue Labels.
  • При желании примите сами участие в ишью и отправьте PR для ее решения (в частности если она может быстро разрешена или вы ранее выполняли нечто подобное).

С помощью этого фильтра можно найти заявки, которые необходимо отсортировать.

Если у вас есть вопросы о про сортировку, спросите в Slack-канале #sig-docs или в списке рассылки kubernetes-sig-docs.

Добавление и удаление меток

Для добавления метки нужен комментарий, содержащий что-то вроде /<label-to-add> или /<label-category> <label-to-add>. Метка уже должна быть создана в репозитории. Если вы попытаетесь добавить несуществующую метку, команда проигнорируется.

Примеры:

  • /triage needs-information
  • /priority important-soon
  • /language ja
  • /help
  • /good-first-issue
  • /lifecycle frozen

Для удаления метки нужен комментарий с /remove-<label-to-remove> или /remove-<label-category> <label-to-remove>.

Примеры:

  • /remove-triage needs-information
  • /remove-priority important-soon
  • /remove-language ja
  • /remove-help
  • /remove-good-first-issue
  • /remove-lifecycle frozen

Список всех меток, используемых в Kubernetes, находится здесь. Не все метки используются группой SIG Docs.

Дополнительные сведения о метках

  • Ишью может иметь несколько ярлыков.
  • Некоторые метки в своём имени содержат слеш для группировки, это своего рода "подметки". Например, существует множество меток sig/, например, sig/cli и sig/api-machinery (полный список).
  • Некоторые метки добавляются автоматически, в зависимости от метаданных файлов из ишью, либо от используемых в комментариях команд со слешем, а также от указанной информации в описании.
  • Новые метки могут добавляться вручную человеком, который сортировкой ишью (либо тем, кто создает ишью).
    • kind/bug, kind/feature и kind/documentation: баг (bug) — это проблема в текущем контенте или в функциональности, а возможность (feature) — запрос на добавление нового контента или функциональности. Метка kind/documentation используется редко.
    • Метки language/ja, language/ko и похожие языковые метки добавляются, если ишью относится к локализованному контенту.

Жизненный цикл ишью

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

lifecycle/stale: после 90 дней бездействия ишью автоматически помечается как устаревшая (stale). Такая заявка будет автоматически закрыта, если эта метка не будет удалена с помощью команды /remove-lifecycle stale.

lifecycle/frozen: заявка с данной меткой не будет считаться устаревшей после 90 дней отсутствия активности. Пользователь вручную добавляет эту метку к заявкам, которые должны оставаться открытыми значительно дольше 90 дней, например, у ишью с меткой priority/important-longterm.

Обработка специальных типов ишью

Мы встречаем перечисленные ниже типы заявкой достаточно часто, поэтому расписали, как их обрабатывать.

Дублирование заявок

Если для какой-нибудь проблемы есть одна или несколько открытых заявок, решение этой проблемы должно быть вынесено в одну заявку. Вам нужно решить, какую заявку оставить открытой (либо вовсе открыть новую ишью), перенести всю соответствующую информацию и указать связанные заявки. Затем для всех остальных похожих заявок добавьте метку с triage/duplicate и закройте их. Наличие только одной-единственной заявки поможет уменьшить путаницу и избежать дублирования работы над одной и той же проблемой.

Заявки про неработающие ссылки

В зависимости от того, где сообщается о неработающей ссылке, для решения этой проблемы требуются различные действия. Неработающие ссылки в API и документации Kubectl — это заявки, связанные с автоматизацией и поэтому их нужно отмечать меткой /priority critical-urgent, пока проблема не будет полностью проанализирована. Все остальные неработающие ссылки — это ишью, которым нужно заниматься вручную, поэтому им нужно добавить метку /priority important-longterm.

Заявки, связанные с блогом

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

Заявки с помощью или отчёты об ошибке в коде

Некоторые открытые заявки — это проблемы с основным кодом или просьбы с помощью, когда что-то (например, учебное руководство) не работает. Для заявок, не имеющих отношение к документации, закройте её, проставив метку kind/support и добавив комментарий с ресурсами, где можно найти помощь (Slack, Stack Overflow) и при необходимости укажите, где нужно открыть заявку, чтобы сообщить об ошибке в функциональности (вероятно, репозиторий kubernetes/kubernetes отлично подойдет для этого).

Пример ответа на запрос о помощи:

This issue sounds more like a request for support and less
like an issue specifically for docs. I encourage you to bring
your question to the `#kubernetes-users` channel in
[Kubernetes slack](http://slack.k8s.io/). You can also search
resources like
[Stack Overflow](http://stackoverflow.com/questions/tagged/kubernetes)
for answers to similar questions.

You can also open issues for Kubernetes functionality in
 https://github.com/kubernetes/kubernetes.

If this is a documentation issue, please re-open this issue.

Пример ответа на сообщение об ошибке в коде:

This sounds more like an issue with the code than an issue with
the documentation. Please open an issue at
https://github.com/kubernetes/kubernetes/issues.

If this is a documentation issue, please re-open this issue.

Добавление документации для новой функциональности

Каждый мажорный выпуск Kubernetes несет в себе новую функциональность, для большей части из которой нужно написать хоть краткую документацию, чтобы показать людям, как её использовать.

Зачастую SIG-группа, ответственная за новую функциональность, представляют черновик документацию в виде пулреквеста в соответствующую ветку выпуска в репозитории kubernetes/website, а кто-то из команды SIG Docs могут сделать вычитку или отредактировать черновик напрямую.

Поиск информации о новой функциональности

Чтобы узнать о будущей функциональности, посетите еженедельную встречу sig-release (см. страницу Сообщество, чтобы быть в курсе предстоящих собраний) и отслеживайте документацию к новому релизу в репозитории kubernetes/sig-release. Каждый выпуск имеет поддиректорию в директории /sig-release/tree/master/releases/. Каждая директорию содержит график выхода новой версии, черновик с примечаниями к выпуску, а также документ, в котором перечислена команда, занимающаяся новым выпуском.

  • График выпуска содержит ссылки на все другие документы, встречи, протоколы собраний и этапы, связанные с выпуском. Он также содержит информацию о целях и сроках выпуска, а также о любых специальных процессах, используемых этом выпуске. В нижней части документа определены несколько терминов, связанных с выпуском.

    Этот документ также содержит ссылку на лист отслеживания функциональности — это "официальный" способ узнать про новую функциональность, запланированной в выпуске.

  • В документе команды выпуска указано, кто какую роль занимает. Если непонятно, с кем можно поговорить об определенной функциональности или вы хотите что-то спросить, то либо посетите встречу по этому выпуску, чтобы задать свой вопрос, либо обратитесь к руководителю.

  • Черновик примечаний к выпуску — хорошая отправная точка, где можно узнать чуть больше о конкретной функциональности, изменениях, устаревших возможностях и в целом что-то ещё о выпуске. Содержимое может обновляться до конца цикла выпуска, поэтому будьте начеку.

Лист отслеживания функциональности

В списке отслеживания функциональности для данного выпуска Kubernetes перечислена вся функциональность, запланированная для выпуска. Каждая строка содержит название возможности, ссылку на основную заявку GitHub, уровень стабильности (Alpha, Beta или Stable), группу SIG и ответственного лица за её реализацию, информацию про документацию, черновик примечания для выпуска, а также указание, была ли функциональность уже принята. Имейте в виду следующее:

  • Функциональность в состоянии Beta и Stable обычно имеет более высокий приоритет по сравнению с версией Alpha.
  • Трудно протестировать (и, следовательно, написать документацию) функциональности, которая не ещё принята или,по крайней мере, считается полнофункциональной в своем PR.
  • Определение, нужна ли документировать функциональности, производится вручную, и даже если у функциональности нет метки, что ей нужна документация, это не означает, это действительно так.

Документирование функциональности

Как отмечалось выше, черновик документации для новой функциональности обычно предлагается SIG-группой, ответственной за реализацию новой функциональности. Это означает, вы в данном случае будете больше наблюдающим (куратором) в данной функциональности, нежели чем полноценным автором документации для неё.

После того, как вы выбрали функциональность для документирования/наблюдения, заявите об этом в Slack-канале #sig-docs, на еженедельной встрече sig-docs или напрямую в PR, отправленном SIG. Если вам дали добро, вы можете редактировать PR, используя один из способов, указанных в разделе Редактирование PR другого человека.

Если вам нужно написать новую тему, полезны следующие ссылки:

Члены SIG, участвующие в документировании новой функциональности

Если вы участник SIG-группы, кто разрабатывает новую функциональность для Kubernetes, вам нужно работать с документацией SIG, чтобы убедиться, что на момент новой версии написана документация для этой функциональности. Проверьте электронную таблицу с отслеживанием функциональности или присоединитесь в Slack-канал #sig-release, чтобы узнать информацию о сроках выхода. Некоторые крайние сроки касательно документации:

  • Docs deadline - Open placeholder PRs: откройте пулреквест в ветку release-X.Y в репозитории kubernetes/website с небольшим коммитом, который вы позже измените. Используйте команду Prow /milestone X.Y, чтобы назначить PR соответствующему этапу. Это уведомляет человека, который занимается документацией и ответственный за этот выпуск, что выходит документация для новой функциональности. Если функциональность не нуждается в каких-либо изменениях документации, убедитесь, что команда sig-release знает об этом, написав им сообщение в Slack-канале #sig-release. Если для функциональности нужна документация, но PR для этого ещё не создан, функциональность может быть удалена из этапа.
  • Docs deadline - PRs ready for review: теперь ваш PR должен содержать первый черновик документации для вашей функциональности. Не беспокойтесь о форматировании или всяких улучшениях. Просто опишите, что делает эта функциональность и как ее использовать. Участник из группы документации, управляющий выпуском новой версии, будет работать вместе с вами, чтобы подготовить контент для публикации. Если вашей функциональности нужна документация и первого черновика с документацией до сих пор нет, эта функциональность может быть удалена из этапа.
  • Docs complete - All PRs reviewed and ready to merge: если ваш PR еще не был объединен в ветку release-X.Y к заданному крайнему сроку, обратитесь за помощью к человеку, ответственному за выпуск новой версии. Если вашей функциональности требуется документация, но она ещё не сделана, функциональность может быть удалена из этапа.

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

Участие к других репозиториях

В проекте Kubernetes более 50 самостоятельных репозиториев. Многие из этих репозиториев хранят код или контент, который можно рассматривать как документацию, например, справочный текст для пользователях, сообщения об ошибках, пользовательский текст в справочниках API или даже комментарии кода.

Если вы видите текст и не знаете, откуда он берётся, вы можете использовать поиск GitHub по репозиториям организации Kubernetes, чтобы выяснить, где встречается этот текст. Это поможет вам определиться с тем, куда создать заявку или PR.

У каждого репозитория могут быть определены собственные процессы и правила. До того как открыть проблему или отправить PR, изучите файлы README.md, CONTRIBUTING.md и code-of-conduct.md в репозитории, если они есть.

Большинство репозиториев используют шаблоны для заявок и PR. Просмотрите некоторые открытые заявки и PR, чтобы понять, как устроена работа. Обязательно как можно более подробно заполните шаблоны при открытии заявок или PR.

Локализация контента

Английский является основным языком документации Kubernetes, однако мы хотим, чтобы у людей была возможность читать документацию на своём родном языке. Если вам комфортно писать на другом языке, особенно в теме программного обеспечения, вы можете помочь перевести документацию Kubernetes или помочь с существующим переводом. Посмотрите страницу Локализация и задайте вопрос в списке рассылки kubernetes-sig-docs или в канале #sig-docs на Slack, если вы хотите помочь.

Работа с локализованным контентом

Старайтесь соблюдать эти рекомендации по работе с переведенным контентом:

  • В PR должны быть изменения касающиеся только одного языка.

    В каждом языке есть собственные рецензенты и утверждающие.

  • Рецензентам: убедитесь, что PR содержат изменения только на одном языке.

    Если PR изменяет файлы на нескольких языках, попросите автора открыть отдельные PR для каждого языка.

Что дальше

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

9.3 - Существенный вклад

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

Дежурный по PR на неделю

Утверждающие группы SIG Docs регулярно по очереди становятся дежурными по PR в репозитории и поэтому участвуют в графике ротации PR-дежурного на неделю.

В обязанности дежурного по PR входят:

  • Ежедневно проверять открытые пулреквесты для контроля качества и соблюдения рекомендаций по оформлению и содержимому.
    • В первую очередь просматривайте самые маленькие пулреквесты (size/XS), и только потом беритесь за самые большие (size/XXL).
    • Проверяйте столько пулреквестов, сколько сможете.
  • Проследите, что CLA подписан каждым участником.
    • Помогайте новым участникам подписать CLA.
    • Используйте этот скрипт, чтобы автоматически напомнить участникам, не подписавшим CLA, подписать его.
  • Оставить свое мнение о предложенных изменениях и поспособствовать в проведении технического обзора от членов других SIG-групп.
    • Предложить исправления для измененного контента в PR.
    • Если вы хотите убедиться в правильности контента, прокомментируйте PR и задайте уточняющие вопросы.
    • Добавьте нужные метки с sig/.
    • Если нужно, то назначьте рецензентов из секции reviewers: в верхней части файла.
    • Добавьте метки Docs Review и Tech Review для установки статуса проверки PR.
    • Добавьте метку Needs Doc Review или Needs Tech Review для пулреквестов, которые ещё не были проверены.
    • Добавьте метку Doc Review: Open Issues или Tech Review: Open Issues для пулреквестов, которые были проверены и требуют дополнительную информацию и выполнение действия перед слиянием.
    • Добавьте метки /lgtm и /approve для пулреквестов, которые могут быть приняты.
  • Объедините пулреквесты, если они готовы, либо закройте те, которые не могут быть приняты.
  • Ежедневно отсортируйте и пометьте новые заявки. Обратитесь к странице Участие для опытных для получения информации по использованию метаданных SIG Docs.

Полезные ссылки на GitHub для дежурных

Следующие ссылки помогут при дежурстве. После обработки заявок по трём первым ссылкам, как правило, список пулреквестов для проверки сократится. По указанным ссылкам вы найдете PR только в английскую версию, предназначенные для слияния в ветку master (кроме последней ссылки).

  • Нет CLA, нет права на слияние: напомните участнику подписать CLA. Если об этом уже напомнил и бот, и человек, то закройте PR и напишите автору, что он может открыть свой PR после подписания CLA. Не проверяйте PR, если их авторы не подписали CLA!
  • Требуется LGTM: если нужна проверка с технической точки зрения, попросите её провести одного из рецензентов, которого предложил бот. Если требуется просмотр пулреквеста со стороны группы документации или вычитка, то предложите изменения, либо сами измените PR, чтобы ускорить процесс принятия пулреквеста.
  • Имеет LGTM, нужно одобрение со стороны группы документации: выясните, нужно ли внести какие-либо дополнительные изменения или обновления, чтобы принять PR. Если по вашему мнению PR готов к слиянию, оставьте комментарий с текстом /approve.
  • Быстрые результаты: если маленький PR направлен в основную ветку и не имеет условий для объединения (поменяйте "XS" в метке с размером при работе с другими пулреквестами [XS, S, M, L, XL, XXL]).
  • Вне основной ветки: если PR отправлен в ветку dev-, значит он предназначается для будущего выпуска. Убедитесь, что release meister знает об этом, добавив комментарий с /assign @<meister's_github-username>. Если он направлен в старую ветку, помогите автору PR изменить на более подходящую ветку.

Когда закрывать пулреквесты

Обзоры и одобрения — это только один из способов, позволяющих держать список PR коротким и актуальным. Закрытие пулреквестов — альтернативный метод для этого.

  • Можете закрыть любой PR, если CLA-соглашение не было подписано в течение двух недель. Авторы PR могут повторно открыть PR после подписания CLA, так что это безопасный способ убедиться, что ничто не будет объединено без подписанного CLA.

  • Закройте любой PR, если автор не отреагировал на комментарии или проверки в течение 2 или более недель.

Не бойтесь закрывать пулреквесты. Участники с лёгкостью могут открыть и возобновить незаконченную работу. Зачастую уведомление о закрытии стимулирует автора возобновить и завершить свою работу до конца.

Чтобы закрыть пулреквест, оставьте комментарий /close в PR.

Внесение улучшений

Члены SIG Docs могут предлагать улучшения.

Если вы давно начали работать над документацией Kubernetes, у вас наверняка появились какие-нибудь идеи по улучшению руководства по оформлению, руководства по содержанию, набору инструментов, который используется для создания документации, стилизации сайта, процессов проверки и объединения пулреквестов. Для максимальной открытости подобные типы предложений по улучшению должны обсуждаться на встречи SIG Docs или в списке рассылки kubernetes-sig-docs. Помимо этого, это поможет разъяснить, как всё устроено в данный момент, и объяснить, почему так было принято, прежде чем предлагать радикальные изменения. Самый быстрый способ узнать ответы на вопросы о том, как в настоящее время работает документация, это задать их в канале #sig-docs в официальном Slack.

Когда обсуждение состоялось, а SIG-группа согласилась с желаемым результатом, вы можете работать над предлагаемыми изменениями наиболее приемлемым способом. Например, обновление руководства по оформлению или функциональности сайта может включать открытие пулреквеста, а изменение, связанное с тестированием документации, может предполагать взаимодействие с sig-testing.

Координация документации по выпуску Kubernetes

Утверждающие SIG Docs могут координировать документацию для выпуска Kubernetes.

Каждый выпуск Kubernetes координируется командой людей, участвующих в специальной группе (Special Interest Group, SIG) sig-release. Другие члены команды в данном выпуске включают в себя общего руководителя выпуском, а также представителей sig-pm, sig-testing и др. Чтобы узнать больше о процессах выпуска версий Kubernetes, обратитесь к https://github.com/kubernetes/sig-release.

Представитель SIG Docs для данного выпуска координирует следующие задачи:

  • Мониторинг электронной таблицы с отслеживанием функциональности на наличие новых или измененных возможностей, затрагивающих документацию. Если документация для определенной функциональности не будет готова к выпуску, возможно, она не попадет в выпуск.
  • Регулярное посещение встречи sig-release и обновление информации о статусе документации к выпуску.
  • Проверка и вычитка документации по функциональности, подготовленной SIG-группой, ответственной за реализацию этой функциональности.
  • Объединение связанных с выпуском пулреквестов и поддержка Git-ветки выпуска.
  • Консультирование других участников SIG Docs, которые хотят научиться выполнять эту роль в будущем. Это называется сопровождение (shadowing).
  • Публикация изменений в документации, связанные с выпуском при размещении артефактов.

Координация выпуска обычно занимает 3-4 месяца, а обязанности распределяются между утверждающими SIG Docs.

Амбассадор нового участника

Утверждающие SIG Docs могут выступать в качестве амбассадоров новых участников.

Амбассадоры новых участников работают бок о бок, чтобы поприветствовать новых участников SIG Docs, предлагать PR новым участникам и консультировать новых участников в их собственных PR.

Обязанности амбассадоров новых участников включают в себя:

  • Отвечать на вопросы новых участников в Slack-канале Kubernetes #sig-docs.
  • Совместно работать с дежурным по PR, чтобы определять заявки, которые подойдут для решения новыми участниками.
  • Консультировать новых участников в их PR.
  • Помогать новым участникам в создании более сложных PR, чтобы они могли стать членами Kubernetes.
  • Оказывать содействие участникам на их пути становления членом в Kubernetes.

Текущие амбассадоры новых участников объявляются на каждом собрании SIG Docs и на канале #sig-docs в Kubernetes.

Поддержка нового участника

Рецензенты SIG Docs могут содействовать новым участникам в членстве организации.

Если участник сделал 5 значительных пулреквестов в один или несколько репозиториев Kubernetes, он имеет право на членство в организации Kubernetes. Членство участника должно быть поддержано двумя спонсорами, которые уже являются рецензентами.

Новые участники документации могут найти спонсоров в канале #sig-docs в Slack Kubernetes или в списке рассылки SIG Docs. Если вы осознали полезность работы автора заявки на членство, вы добровольно можете поддержать (спонсировать) его. Когда они подадут заявку на членство, отреагируйте на заявку "+1" и напишите подробный комментарий о том, почему вы считаете, что кандидат отлично вписывается в члены организации Kubernetes.

Сопредседатель SIG

Утверждающие SIG Docs могут быть сопредседателями SIG Docs.

Требования

Сопредседатели должны соответствовать следующим требованиям:

  • Быть утверждающими SIG Docs не меньше 6 месяцев.
  • Руководить выпуском документации Kubernetes или сопроводить два выпуска.
  • Понимать рабочие процессы и инструменты SIG Docs: git, Hugo, локализация, блог.
  • Понимать, как другие SIG-группы и репозитории Kubernetes влияют на рабочий процесс SIG Docs, включая: команды в k/org, процессы в k/community, плагины в k/test-infra и роль SIG Architecture.
  • Уделять не менее 5 часов в неделю (но зачастую больше) в течение как минимум 6 месяцев для выполнения обязанностей.

Обязанности

Роль сопредседателя посвящена в основном одной из задач: сопредседатели управляют процессом и политикой, планируют и проводят собрания, назначают дежурных по PR и, как правило, делают то, что никто больше не хочет делать, для увеличения количества участников.

Обязанности включают в себя:

  • Сосредоточить группу SIG Docs на достижении максимального счастья для разработчиков через отличную документацию.
  • Быть примером соблюдения норм поведения сообщества и контролировать их выполнение членами SIG.
  • Изучать и внедрять передовые практики для SIG-группы, обновляя рекомендации по участию.
  • Планировать и проверять встречи SIG: еженедельные обновления информации, ежеквартальные ретроспективные/плановые совещания и многое другое.
  • Планирование и проведение спринтов по документации на мероприятиях KubeCon и других конференциях.
  • Набирать персонал и выступать в поддержку CNCF и его платиновых партнеров, включая Google, Oracle, Azure, IBM и Huawei.
  • Поддерживать нормальную работу SIG.

Проведение продуктивных встреч

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

Соблюдайте нормы поведения сообщества:

  • Привлекайте самый широкий круг участников к дискуссии и уважительно общайтесь между собой, стараясь никого не обидеть.

Сформулируйте четкую повестку дня:

  • Определите конкретную цель встречи.
  • Опубликуйте программу дня заранее.

Для еженедельных встреч скопируйте примечания из предыдущей недели в раздел "Past meetings".

Работайте вместе для создания точных примечания:

  • Запишите обсуждение встречи.
  • Подумайте над тем, чтобы делегировать роль стенографиста кому-нибудь другому.

Определяйте решения по пунктам повестки четко и точно:

  • Записывайте решения по пунктам, кто будет ими заниматься и ожидаемую дату завершения.

Руководите обсуждением, когда это необходимо:

  • Если обсуждение выходит за пределы повестки дня, снова обратите внимание участников на обсуждаемую тему.
  • Найдите место для различных стилей ведения обсуждения, не отвлекаясь от темы обсуждения и уважая время людей.

Уважайте время людей:

  • Начинайте и заканчивайте встречи своевременно.

Используйте Zoom эффективно:

Исполнение роли ведущего в Zoom

Запись встреч на Zoom

Когда вам потребуется начать запись, нажмите пункт с надписью Record to Cloud.

Если нужно остановить запись, нажмите на кнопку Stop.

Запись автоматически загрузится на YouTube.

9.4 - Обзор оформления документации

Темы в этом разделе содержат рекомендации по написанию, форматированию и организации контента, а также охватывают настройку Hugo в контексте документации Kubernetes.

9.4.1 - Руководство по оформлению документации

На этой странице вы найдёте рекомендации по оформлению написания документации Kubernetes. Это рекомендации, а не правила. Используйте здравый смысл и не стесняйтесь предлагать изменения в этот документ в виде пулреквеста.

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

Язык

Документация Kubernetes была переведена на несколько языков (см. README-файлы локализаций).

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

Правила форматирования документации

Используйте верблюжью нотацию для написания объектов API

Когда вы указываете имя API-объекта, используйте те же самые прописные и строчные буквы так, как они записаны в имени объекта. Как правило, имена объектов API написаны с использованием верблюжьей нотации.

Не разделяйте имя объекта API на отдельные слова. Например, пишите PodTemplateList, а не Pod Template List.

Указывая имена API-объектов, не добавляйте к ним слово "объект", за исключением случаев, когда это только ухудшает читаемость.

Можно делать и нельзя - Объекты API
Можно Нельзя
В Pod два контейнера. В поде два контейнера.
Deployment отвечает за ... Объект Deployment отвечает за ...
PodList — это список Pod. Pod List — это список подов.
Два ContainerPorts ... Два объекта ContainerPort ...
Два объекта ContainerStateTerminated ... Два ContainerStateTerminated ...

Используйте угловые скобки для заполнителей

Используйте угловые скобки для заполнителей. Сообщите читателю, что означает заполнитель.

  1. Отобразить информацию о Pod:

     kubectl describe pod <pod-name> -n <namespace>
    

    Если пространство имён пода равняется default, вы можете опустить параметр '-n'.

Используйте полужирное начертание для элементов пользовательского интерфейса

Можно делать и нельзя - Элементы интерфейса в полужирном начертании
Можно Нельзя
Нажмите на Fork. Нажмите на "Fork".
Выберите Other. Выберите "Other".

Используйте курсивное начертание для определения или включения новых терминов

Можно делать и нельзя - Используйте курсивное начертание для новых терминов
Можно Нельзя
Кластер — это набор узлов ... "Кластер" — это набор узлов ...
Эти компоненты формируют управляющий слой. Эти компоненты формируют управляющий слой.

Оформляйте как код имена файлов, директории и пути

Можно делать и нельзя - Оформляйте как код имена файлов, директории и пути
Можно Нельзя
Откройте файл envars.yaml. Откройте файл envars.yaml.
Перейдите в директорию /docs/tutorials. Перейдите в директорию /docs/tutorials.
Откройте файл /_data/concepts.yaml file. Откройте файл /_data/concepts.yaml.

Используйте международные правила для пунктуации внутри кавычек

Можно делать и нельзя - Используйте международные правила для пунктуации внутри кавычек
Можно Нельзя
события записываются с соответствующей "стадией". события записываются с соответствующей "стадией."
Копия называется "fork". Копия называется "fork."

Форматирование с использованием однострочного кода

Используйте оформление кода для встроенного кода и команд

Для однострочного (встроенного) блока кода в HTML-документе используйте тег <code>. В файле Markdown используйте обратную кавычку (`).

Можно делать и нельзя - Use code style for inline code and commands
Можно Нельзя
Команда kubectl run создает Deployment. Команда "kubectl run" создает Deployment.
Для декларативного управления используйте kubectl apply. Для декларативного управления используйте "kubectl apply".
Заключите примеры кода в тройные обратные кавычки. (```) Заключите примеры кода с использованием любого другого синтаксиса.
Используйте одинарные обратные кавычки для выделения встроенного кода. Например, var example = true. Используйте две звездочки (**) или подчёркивание (_) для выделения встроенного кода. Например, var example = true.
Используйте тройные обратные кавычки до и после многострочного блока кода для отдельных блоков кода. Используйте многострочные блоки кода для создания диаграмм, блок-схем или т.д.
Используйте понятные имена переменных с соответствующим контекстом. Используйте имена переменных, такие как 'foo', 'bar' и 'baz', которые не имеют смысла и которым не хватает контекста.
Удаляйте завершающие пробелы в коде. Добавляйте конечные пробелы в код там, где они необходимо, поскольку программа для чтения с экрана также будет зачитывать пробелы.

Имена полей объектов и пространства имён оформляйте как код

Можно делать и нельзя - Имена полей объектов и пространства имён оформляйте как код
Можно Нельзя
Задайте значение для поля replicas в конфигурационном файле. Задайте значение для поля "replicas" в конфигурационном файле.
Значением поля exec является объект ExecAction. Значением поля "exec" является объект ExecAction.
Запустите процесс как Daemonset в пространстве имен kube-system. Запустите процесс как Daemonset в пространстве имен kube-system.

Имена компонентов и командного инструмента оформляйте как код

Можно делать и нельзя - Имена компонентов и командного инструмента оформляйте как код
Можно Нельзя
kubelet сохраняет стабильность узла. kubelet сохраняет стабильность узла.
kubectl обрабатывает поиск и аутентификацию на сервере API. kubectl обрабатывает поиск и аутентификацию на apiserver.
Запустите процесс с использованием сертификата kube-apiserver --client-ca-file=FILENAME. Запустите процесс с использованием сертификата kube-apiserver --client-ca-file=FILENAME.

Начинайте предложение с имени инструмента или компонента

Можно делать и нельзя - Начинайте предложение с имени инструмента или компонента
Можно Нельзя
The kubeadm tool bootstraps and provisions machines in a cluster. kubeadm tool bootstraps and provisions machines in a cluster.
The kube-scheduler is the default scheduler for Kubernetes. kube-scheduler is the default scheduler for Kubernetes.

Используйте общее описание вместо имени компонента

Можно делать и нельзя - Используйте общее описание вместо имени компонента
Можно Нельзя
Сервер Kubernetes API следует спецификации OpenAPI. apiserver следует спецификации OpenAPI.
Агрегированные API-интерфейсы — вспомогательные API-серверы. Агрегированные API-интерфейсы — вспомогательные APIServers.

Cтроковые и целочисленные значения полей пишите в обычном стиле

Для значений полей типа string или integer используйте обычный стиль без кавычек.

Можно делать и нельзя - Cтроковые и целочисленные значения полей пишите в обычном стиле
Можно Нельзя
Задайте значение для поля imagePullPolicy как Always. Задайте значение для поля imagePullPolicy как "Always".
Задайте значение для поля image как nginx:1.8. Задайте значение для поляimage как nginx:1.8.
Задайте значение для поля replicas как 2. Задайте значение для поля replicas как 2.

Форматирование фрагментов кода

Не добавляйте символ приглашения командной строки

Можно делать и нельзя - Не добавляйте символ приглашения командной строки
Можно Нельзя
kubectl get pods $ kubectl get pods

Отделяйте команды от вывода

Убедитесь, что Pod работает на выбранном вами узле:

kubectl get pods --output=wide

Вывод будет примерно таким:

NAME     READY     STATUS    RESTARTS   AGE    IP           NODE
nginx    1/1       Running   0          13s    10.200.0.4   worker0

Версионирование примеров Kubernetes

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

Если информация зависит от версии, необходимо определить версию Kubernetes в секции prerequisites шаблона задачи или шаблона руководства. После сохранения страницы секция prerequisites отобразится в отдельном блоке с заголовком Подготовка к работе.

Для указания версии Kubernetes для страницы задачи или руководства в фронтальную часть файла добавьте поле min-kubernetes-server-version.

Если YAML-пример определён в отдельном файле, поищите и просмотрите темы, которые ссылаются на него. Убедитесь, что темы с подключённым YAML-файлом содержат соответствующую информацию о версии. Если ни одна из тем не использует какой-либо YAML-файл подумайте над тем, чтобы удалить его вместо того, чтобы обновления.

Например, если вы пишете руководство, предназначенное для использования с версией Kubernetes 1.8, фронтальная часть вашего Markdown-файла должен выглядеть примерно так:

---
title: <your tutorial title here>
min-kubernetes-server-version: v1.8
---

В примерах кода и конфигурации не добавляйте комментарии про альтернативные версии. Убедитесь в том, чтобы в комментариях ваших примеров не содержались некорректные сведения, такие как ниже:

apiVersion: v1 # в более ранних версиях...
kind: Pod
...

Словарь Kubernetes.io

Список специфичных для Kubernetes терминов и слов, которые будут регулярно встречаться по всему сайту.

Словарь Kubernetes.io
Термин Пример использования
Kubernetes Kubernetes всегда должен начинаться с заглавной буквы.
Docker Docker всегда должен начинаться с заглавной буквы.
SIG Docs SIG Docs, а не SIG-DOCS или другие варианты.
On-premises On-premises or On-prem rather than On-premise or other variations.

Макрокоды

Макрокоды Hugo помогают создавать разного рода обращений к читателю. Наша документация поддерживает три разных макрокода для этого: примечание {{< note >}}, предостережение {{< caution >}} и предупреждение {{< warning >}}.

  1. Заключите текст в открывающий и закрывающий макрокод.

  2. Используйте следующий синтаксис для определения стиля:

    {{< note >}}
    Вам не нужно указывать надпись; макрокод автоматически добавит её. (Примечание:, Предостережение:, и т.д.)
    {{< /note >}}
    

Результат:

Примечание

Используйте {{< note >}} для выделения подсказки или части информации, которая может быть полезна для ознакомления.

Например:

{{< note >}}
Вы _также_ можете использовать Markdown внутри этих выносок.
{{< /note >}}

Результат:

Вы можете использовать {{< note >}} в списке:

1. Используйте макрокод примечания в списке

1. Второй пункт с добавленным блоком примечания

   {{< note >}}
   Макрокоды предупреждения, предостережения и примечания, добавленные в списки, должны содержать отступ в четыре пробела. Смотрите раздел [Распространённые проблемы с шорткодами](#распространённые-проблемы-с-шорткодами).
   {{< /note >}}

1. Третий пункт в списке

1. Четвертый пункт в списке

Результат:

  1. Используйте макрокод примечания в списке

  2. Второй пункт с добавленным блоком примечания

  3. Третий пункт в списке

  4. Четвертый пункт в списке

Предостережение

Используйте {{< caution >}}, чтобы обратить внимание к важной информации, которая поможет избежать подводных камней.

Например:

{{< caution >}}
Оформление выноски применяется только к строке, следующей после тега выше.
{{< /caution >}}

Результат:

Предупреждение

Используйте {{< warning >}} для обозначения предупреждающей информации или такой, которую чрезвычайно важно соблюдать.

Например:

{{< warning >}}
Острожно.
{{< /warning >}}

Результат:

Распространённые проблемы с шорткодами

Упорядоченные списки

Макрокоды сбросят нумерацию в нумерованных списках, если вы не добавите отступ в четыре пробела перед уведомлением и тегом.

Например:

1. Разогреть духовку до 350˚F

1. Подготовить тесто и вылить её в формочку для выпечки.
   {{< note >}}Для лучшего результата смажьте формочку.{{< /note >}}

1. Выпекать 20-25 minutes или пока тесто не зарумянится.

Результат:

  1. Разогреть духовку до 350˚F

  2. Подготовить тесто и вылить её в формочку для выпечки.

  3. Выпекать 20-25 minutes или пока тесто не зарумянится.

Выражения для вставок

Макрокоды внутри include-выражений нарушит процесс сборки. Поэтому они должны быть вставлены в родительский документ до и после вызова include. Например:

{{< note >}}
{{< include "task-tutorial-prereqs.md" >}}
{{< /note >}}

Элементы Markdown

Переносы строк

Добавляйте одну новую строку для разделения содержимого таких блоков, как заголовки, списки, изображения, многострочный код и т.д. Исключение составляют заголовки второго уровня, которые должны быть разделены двумя переводами строки. Заголовки второго уровня следуют за первым уровнем (или названием страницы). Две пустые строки помогает лучше наглядно представить общую структуру содержимого в редакторе кода.

Заголовки

Люди, просматривающие документацию, могут использовать программу чтения с экрана или другую вспомогательную технологию (Assistive technologies, AT). Программы чтения с экрана — устройства вывода, которые выводят элементы на странице по очереди. Если на странице много текста, вы можете использовать заголовки, чтобы придать странице внутреннюю структуру. Хорошая структура страницы помогает всем читателям легко перемещаться по странице или выбрать интересующие темы.

Можно делать и нельзя - Заголовки
Можно Нельзя
Обновите заголовок в фронтальной части страницы или записи блога. Используйте заголовок первого уровня, так как Hugo автоматически преобразует название страницы в фронтальной части в заголовок первого уровня.
Используйте упорядоченные заголовки, чтобы сформировать общее представление о содержании страницы. Используйте заголовки с уровня 4 по 6, если только это только в этом нет необходимости. Если текст настолько подробный, возможно, его нужно разделить на отдельные статьи.
Используйте знак решётки или хеша (#) для всех видов контента, кроме записей блога. Используйте подчеркивание (--- или ===) для обозначения заголовков первого уровня.
Начинайте с большой буквы только первое слово в заголовке. Например, Расширение kubectl с помощью плагинов Пишите с заглавной буквы все слова в заголовке. Например, Расширение Kubectl С Помощью Плагинов

Параграфы

Можно делать и нельзя - Параграфы
Можно Нельзя
Проследите за тем, чтобы в одном абзаце было не более 6 предложений. Добавить к первом абзацу отступ с пробелами. Например, ⋅⋅⋅Три пробела перед абзацем образуют отступ.
Используйте три дефиса (---) для создания горизонтальной черты. Используйте горизонтальные линии для обозначения конца в содержании абзаца. Например, смена места в истории или переход темы в разделе. Используйте горизонтальные линии для оформления.

Ссылки

Можно делать и нельзя - Ссылки
Можно Нельзя
Указывайте ссылки, которые передают суть содержания, на который они ссылаются. Например: "Некоторые порты открыты на ваших машинах. Смотрите раздел Проверка необходимых портов, чтобы получить дополнительную информацию". Используйте двусмысленные термины, такие как "нажмите сюда". Например: Некоторые порты открыты на ваших машинах. Смотрите этот раздел, чтобы получить дополнительную информацию".
Указывайте ссылки в стиле Markdown: [текст ссылки](URL). Например: [Макрокоды Hugo](/docs/contribute/style/hugo-shortcodes/#table-captions) отобразится как Макрокоды Hugo. Указывайте ссылки в формате HTML: <a href="/media/examples/link-element-example.css" target="_blank">Ознакомьтесь с нашим руководством!</a> или добавляйте ссылки, которые открываются в новых вкладках или окнах. Например: [example website](https://example.com){target="_blank"}

Списки

Сгруппируйте пункты в списке так, чтобы они были связаны друг с другом и следовали в определённом порядке, либо чтобы они сохраняли взаимосвязь между несколькими элементами. Когда программа чтения с экрана встречает нумерованный или неупорядоченный список, пользователю будет проинформирован, что существует группа из элементов списка. Затем пользователь может использовать клавиши-стрелки для перемещения между разными элементами в списке. Навигационные ссылки по сайту также могут быть помечены как элементы списка; в конечном счёте, все они просто группа связанных ссылок.

  • Заканчивайте каждый элемент в списке точкой, если один или несколько элементов в списке являются законченными предложениями. Как правило, для согласованности либо все элементы должны быть целыми предложениями, либо ни один из них.

  • Используйте цифру один (1.) для упорядоченных списков.

  • Используйте (+), (*) или (-) для неупорядоченных списков.

  • Добавьте пустую строку после каждого списка.

  • Во вложенных списках добавьте отступ в четыре пробела (например, ⋅⋅⋅⋅).

  • Элементы списка могут содержать несколько абзацев. Каждый последующий абзац в элементе списка должен иметь отступ в четыре пробела или один символ табуляции.

Таблицы

Семантическая цель таблицы данных состоит в представлении данных в табличном виде. Пользователи с нормальным зрением могут бегло просмотреть таблицу, однако программа для чтения с экрана сканирует таблицу построчно. Заголовок таблицы используется для создания информативного заголовка для табличных данных. Инструменты вспомогательных технологий (Assistive technologies, AT) используют элемент заголовка HTML-таблицы, чтобы идентифицировать для пользователей, какие на странице есть таблицы.

  • Добавьте подписи к таблицам с помощью соответствующих макрокодов Hugo.

Рекомендации по написанию контента

В этом разделе перечислены рекомендации для написания ясного, лаконичного и единообразного текста документации.

Используйте настоящее время

Можно делать и нельзя - Используйте настоящее время
Можно Нельзя
Эта команда запускает прокси. Эта команда запустит прокси.

Исключение: используйте будущее или прошедшее время, если требуется передать правильный смысл.

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

Можно делать и нельзя - Используйте действительный залог
Можно Нельзя
Вы можете изучить API с помощью браузера. API можно изучить с помощью браузера.
В файле YAML определяется количество реплик. Количество реплик определяется в файле YAML.

Исключение: используйте страдательный залог, если в действительном залоге получается неудачная формулировка.

Используйте простой и понятный язык

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

Можно делать и нельзя - Используйте простой и понятный язык
Можно Нельзя
Чтобы создать ReplicaSet, ... Для того чтобы создать a ReplicaSet, ...
Смотрите конфигурационный файл. Пожалуйста, смотрите конфигурационный файл.
Посмотрите Pods. С помощью следующей команды мы посмотрим Pods.

Обращайтесь к читателю на "вы"

Можно делать и нельзя - Обращайтесь к читателю на вы
Можно Нельзя
Вы можете создать Deployment с помощью ... Мы создадим Deployment с помощью ...
В предыдущем выводе вы можете увидеть ... В предыдущем выводе мы можем увидеть ...

Избегайте использования латинских фраз

Вместо латинских аббревиатур используйте соответствующие выражения на английском.

Можно делать и нельзя - Избегайте использования латинских фраз
Можно Нельзя
For example, ... e.g., ...
That is, ... i.e., ...

Исключение: используйте "etc." вместо "et cetera".

Ошибки, которые следует избегать

Избегайте использования "мы"

Использование "мы" в предложении может сбить с толку, так так неясно, кто под этим "мы" подразумевается (имеется ли в виду сам читатель при этом).

Можно делать и нельзя - Избегайте использования мы
Можно Нельзя
Версия 1.4 включает в себя ... В версии 1.4 мы добавили ...
Kubernetes представляет новую возможность для ... Мы представляем новую возможность ...
На этой странице вы узнаете, как использовать Pods. На этой странице мы познакомимся с Pods.

Избегайте жаргона и идиомы

Некоторые читатели говорят на английском как на втором языке. Избегайте жаргона и идиом, чтобы облегчить им понимание.

Можно делать и нельзя - Избегайте жаргона и идиомы
Можно Нельзя
Internally, ... Under the hood, ...
Create a new cluster. Turn up a new cluster.

Избегайте выражений о будущем

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

Избегайте выражений, которые могут потерять актуальность

Избегайте таких слов, как "в настоящее время" и "новый". Новая функциональность в настоящее время не будет таковой через несколько месяцев.

Можно делать и нельзя - Избегайте выражений, которые могут потерять актуальность
Можно Нельзя
В версии 1.4 ... В текущей версии ...
Функциональность Federation предоставляет ... Новая функциональность Federation предоставляет ...

Что дальше

9.4.2 - Руководство по содержанию документации

Эта страница содержит рекомендации по добавлению контента в документацию Kubernetes. Если у вас есть вопросы по поводу допустимого контента, обратитесь к каналу #sig-docs в Slack Kubernetes и задайте свои вопросы! Поступайте на своё усмотрение и не стесняйтесь вносить изменения в этот документ через пулреквест.

Для получения дополнительной информации о создании нового контента для документации Kubernetes следуйте инструкциям в руководстве по оформлению.

Участие в контенте

Документация Kubernetes включает содержимое из оригинального репозитория kubernetes/website. Документация Kubernetes находится в директории kubernetes/website/content/<language_code>/docs, большая часть которой относится к проекту Kubernetes. Документация Kubernetes может также включать содержимое их проектов в GitHub-организациях kubernetes и kubernetes-sigs, если у этих проектов нет собственной документации. Всегда можно ссылаться на действующие проекты kubernetes, kubernetes-sigs и (CNCF) в документации Kubernetes, но перелинковка с продуктами определённого разработчика не допускается. Проверьте списки проектов CNCF (Graduated/Incubating, Sandbox, Archived), если вы не уверены в статусе CNCF проекта

Контент, полученный из двух источников

Документация Kubernetes не содержит дублированный контент, полученный из разных мест (так называемый контент из двух источников). Контент из двух источников требует дублирования работы со стороны мейнтейнеров проекта и к тому же быстро теряет актуальность. Перед добавлением контента, задайте себе вопрос:

  • Новая информация относится к действующему проекту CNCF или проекту в организациях на GitHub kubernetes или kubernetes-sigs?
    • Если да, то:
      • У этого проекта есть собственная документация?
        • если да, то укажите ссылку на документацию проекта в документации Kubernetes.
        • если нет, добавьте информацию в репозиторий проекта (если это возможно), а затем укажите ссылку на неё в документации Kubernetes.
    • Если нет, то:
      • Остановитесь!
        • Добавление информации о продуктах от других разработчиков не допускается.
        • Не разрешено ссылаться на документацию и сайты сторонних разработчиков.

Разрешенная и запрещённая информация

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

  1. Инструкции по установке или эксплуатации Kubernetes, которые не связаны с проектами Kubernetes.

    • Разрешено:
      • Ссылаться на документацию CNCF-проекта или на проект в GitHub-организациях kubernetes или kubernetes-sigs.
        • Пример: для установки Kubernetes в процессе обучения нужно обязательно установить и настроить minikube, а также сослаться на соответствующую документацию minikube.
      • Добавление инструкций для проектов в организации kubernetes или kubernetes-sigs, если по ним нет инструкций.
        • Пример: добавление инструкций по установке и решению неполадок kubeadm.
    • Запрещено:
      • Добавление информации, которая дублирует документацию в другом репозитории.
        • Примеры:
          • Добавление инструкций по установке и настройке minikube; Minikube имеет собственную документацию, которая включают эти инструкции.
          • Добавление инструкций по установке Docker, CRI-O, containerd и других окружений для выполнения контейнеров в разных операционных системах.
          • Добавление инструкций по установке Kubernetes в промышленных окружениях, используя разные проекты:
            • Kubernetes Rebar Integrated Bootstrap (KRIB) — это проект стороннего разработчика, поэтому всё содержимое находится в репозитории разработчика.
            • У проекта Kubernetes Operations (kops) есть инструкции по установке и руководства в GitHub-репозитории.
            • У проекта Kubespray есть собственная документация.
      • Добавление руководства, в котором объясняется, как выполнить задачу с использованием продукта определенного разработчика или проекта с открытым исходным кодом, не являющиеся CNCF-проектами или проектом в GitHub-организациях kubernetes, или kubernetes-sigs.
      • Добавление руководства по использованию CNCF-проекта или проекта в GitHub-организациях kubernetes или kubernetes-sigs, если у проекта есть собственная документация.
  2. Подробное описание технических аспектов по использованию стороннего проекта (не Kubernetes) или как этот проект разработан.

    Добавление такого типа информации в документацию Kubernetes не допускается.

  3. Информация стороннему проекту.

    • Разрешено:
      • Добавление краткого введения о CNCF-проекте или проекте в GitHub-организациях kubernetes или kubernetes-sigs; этот абзац может содержать ссылки на проект.
    • Запрещено:
      • Добавление информации по продукту определённого разработчика.
      • Добавление информации по проекту с открытым исходным кодом, который не является CNCF-проектом или проектом в GitHub-организациях kubernetes или kubernetes-sigs.
      • Добавление информации, дублирующего документацию из другого проекта, независимо от оригинального репозитория.
        • Пример: добавление документации для проекта Kubernetes in Docker (KinD) в документацию Kubernetes.
  4. Только ссылки на сторонний проект.

    • Разрешено:
      • Ссылаться на проекты в GitHub-организациях kubernetes и kubernetes-sigs.
        • Пример: добавление ссылок на документацию проекта Kubernetes in Docker (KinD), который находится в GitHub-организации kubernetes-sigs.
      • Добавление ссылок на действующие CNCF-проекты.
        • Пример: добавление ссылок на документацию проекта Prometheus; Prometheus — это действующий проект CNCF.
    • Запрещено:
      • Ссылаться на продукты стороннего разработчика.
      • Ссылаться на прекращенные проекты CNCF.
      • Ссылаться на недействующие проекты в организациях GitHub в kubernetes и kubernetes-sigs.
      • Ссылаться на проекты с открытым исходным кодом, которые не являются проектами CNCF или не находятся в организациях GitHub kubernetes, или kubernetes-sigs.
  5. Содержание учебных курсов.

    • Разрешено:
    • Запрещено:
      • Ссылаться на учебные онлайн-курсы, не относящиеся к CNCF, Linux Foundation или Linux Academy; документация Kubernetes не содержит ссылок на сторонний контент.
        • Пример: добавление ссылок на учебные руководства или курсы Kubernetes на Medium, KodeKloud, Udacity, Coursera, learnk8s и т.д.
      • Ссылаться на руководства определённых разработчиков вне зависимости от обучающей организации.

Если у вас есть вопросы по поводу допустимого контента, присоединяйтесь к каналу #sig-docs в Slack Kubernetes!

Что дальше

9.4.3 - Написание новой темы

На этой странице показано, как создать новую тему для документации Kubernetes.

Подготовка к работе

Создайте копию репозитория документации Kubernetes, как описано в разделе Участие для начинающих.

Выбор типы страницы

Перед написанием новой темы, выберите тип страницы, который бы лучше всего подходил под ваш текст:

Правила выбора типа страницы
Тип Описание
Концепция Страница концепции объясняет некоторые аспекты Kubernetes. Например, страницы концепции может описывать объект Deployment в Kubernetes и разъяснить, какую роль он играет после развертывания, масштабирования и обновления приложения. Как правило, страницы концепций не включают последовательности шагов, а вместо этого содержат ссылки на задачи или руководства. В качестве примера концептуальной темы посмотрите страницу Nodes.
Задача На странице задачи показывается, как сделать что-то одно конкретное, главным образом с помощью короткой последовательности шагов. Страница задачи может быть короткой или длинной, если она остаётся сконцентрированной на одном аспекте. На странице задач можно сочетать краткие объяснения с необходимыми шагами для выполнения, однако если вам нужно дать подробное пояснение, вам следует сделать это в концептуальной теме. Смежные задачи и концептуальные темы должны быть связаны друг с другом. В качестве примера короткой страницы задачи посмотрите Configure a Pod to Use a Volume for Storage. Пример длинной страницы задачи смотрите Configure Liveness and Readiness Probes
Руководство На странице руководства показано, как сделать что-то более крупнее одной-единственной задачи. В руководстве может быть несколько последовательностей шагов, которые читатели могут реально выполнить по ходу чтения страницы. Либо на странице руководства могут приведены объяснения связанных частей кода. Например, руководство может содержать разбор примера кода. Руководство может включать в себя краткие объяснения связанной функциональности Kubernetes, но при они этом должны ссылаться на сопутствующие концептуальные темы, где можно узнать подробнее про конкретные возможности.

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

Выбор заголовка и имени файла a title and filename

Подберите заголовок, содержащий такие ключевые слова, по которым вы могли его найти в поисковике. Имя файла должно создаваться из слов в заголовке, написанных через дефис. Например, для темы с заголовком Using an HTTP Proxy to Access the Kubernetes API имя файла будет http-proxy-access-api.md. Вам не нужно указывать "kubernetes" в имени файла, потому что слово "kubernetes" уже есть в полном URL-адресе темы, например:

   /docs/tasks/access-kubernetes-api/http-proxy-access-api/

Добавление заголовка темы в фронтальную часть

В фронтальную часть файла вашей темы поместите поле заголовка title. Фронтальная часть — YAML-блок, который находится тремя дефисами в самом верху страницы. Например:

---
title: Using an HTTP Proxy to Access the Kubernetes API
---

Выбор директории

В зависимости от типа вашей страницы поместите новый файл в одну из следующую поддиректорию:

  • /content/en/docs/tasks/
  • /content/en/docs/tutorials/
  • /content/en/docs/concepts/

Вы можете поместить файл в имеющуюся поддиректорию либо создать новую.

Добавление темы в оглавлении

Оглавление динамически генерируется исходя из структуры директорий документации. Корневые директории в /content/en/docs/ создают навигацию с основными ссылками, где у каждой поддиректории есть записи в оглавлении.

В каждой поддиректории есть файл _index.md, представляющий собой "главную" страницу всего содержимого этой поддиректории. В файле _index.md не нужно применять шаблон. В нём находится обзор содержания тем в поддиректории.

Другие файлы в директории по умолчанию сортируются в алфавитном порядке. Такой порядок сортировки редко устраивает. Для управления такой относительной сортировкой тем в поддиректории, определите ключ weight: с целым числом в фронтальной части файла. Как правило, мы используем значения, кратные 10, чтобы оставить про запас для будущих страниц. Например, тема с весом 10 будет отображаться перед темой с весом 20.

Вставка кода в тему

Если вы хотите добавить код в тему, вы можете встроить код из файла напрямую, используя синтаксис блока кода в Markdown. Такой способ рекомендуется использовать в следующих случаев (это не исчерпывающий список):

  • В вашем коде показывается вывод такой команды, как kubectl get deploy mydeployment -o json | jq '.status'.
  • Ваш код недостаточно универсален, чтобы пользователи могли его попробовать сами. В качестве примера можно привести пример YAML-файла для создания Pod, который зависит от конкретной реализации FlexVolume.
  • Ваш код — это не готовый пример, потому что он предзначен для выделения части большего файла. Например, при описании способов настройки PodSecurityPolicy по определённым причинам вы можете включить небольшой фрагмент напрямую в файле темы.
  • Ваш код по разным причинам не подходит для тестирования пользователями. Например, если вы описываете, как новый атрибут должен добавляться к ресурсу с помощью команды kubectl edit, то вы можете добавить короткий пример, показывающий только добавляемый атрибут.

Добавление кода из другого файла

Другой способ добавить код в вашу тему — создать новый полноценный файл с примером (или группу файлов примеров), а затем из вашей темы подключить этот пример. Используйте этот метод, чтобы включить универсальный и повторно используемый пример YAML-файла, который читатель может проверить сам.

При добавлении нового отдельного файла примера, например, в формате YAML, поместите код в одну из директорий <LANG>/examples/, где <LANG> — язык темы. В вашем файле темы используйте макрокод codenew:

{{% codenew file="<RELPATH>/my-example-yaml>" %}}

где <RELPATH> — это путь к включаемому файлу относительно директории examples. Следующий макрокод Hugo ссылается на YAML-файл по пути /content/en/examples/pods/storage/gce-volume.yaml.

{{% codenew file="pods/storage/gce-volume.yaml" %}}

Демонстрация создания API-объекта из конфигурационного файла

Если вам нужно показать, как создать объект API из файла конфигурации, поместите файл конфигурации в одну из директорий в <LANG>/examples.

В вашей теме укажите эту команду:

kubectl create -f https://k8s.io/examples/pods/storage/gce-volume.yaml

В качестве примера темы, в которой используется этот метод, смотрите Running a Single-Instance Stateful Application.

Добавление изображений в тему

Поместите файлы изображений в директорию /images. Предпочтительный формат изображения — SVG.

Что дальше

9.4.4 - Использование шаблонов страниц

При добавлении новых тем воспользуйтесь одним из перечисленных ниже шаблонов. Это регламентирует пользовательское восприятие определённой страницы.

Шаблоны страниц находятся в директории layouts/partials/templates репозитория kubernetes/website.

Шаблон концепции

Страница концепции объясняет некоторые аспекты Kubernetes. Например, страницы концепции может описывать объект Deployment в Kubernetes и разъяснить какую роль он играет после развертывания, масштабирования и обновления приложения. Как правило, страницы концепций не включают последовательности шагов, и вместо этого содержат ссылки на задачи или руководства.

Для написания новой страницы концепции в директории /content/en/docs/concepts создайте поддиректорию с Markdown-файлом со следующим требованиями:

  • Во фронтальной части YAML этой страницы определите поле content_type: concept.

  • В теле страницы укажите переменные capture и любые другие, которые вы хотите включить:

    Переменная Обязательна?
    overview да
    body да
    whatsnext нет

    Тело страницы будет выглядеть следующим образом (удалите все необязательные capture-блоки, если они вам не понадобятся):

    {{% capture overview %}}
    
    {{% /capture %}}
    
    {{% capture body %}}
    
    {{% /capture %}}
    
    {{% capture whatsnext %}}
    
    {{% /capture %}}
    
  • Заполните каждый раздел информацией. Следуйте этим рекомендациям:

    • Структурируйте контент с помощью заголовков H2 и H3.
    • В блоке overview одним абзацем сформируйте контекст темы.
    • В блоке body объясните суть концепции.
    • В блоке whatsnext сформируйте ненумерованный список тем (до 5), к которым нужно обратиться, чтобы получить дополнительную информацию о концепции.

Annotations — это готовый пример шаблона концепции. Кстати, текущая страница использует шаблон концепции.

Шаблон задачи

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

Для написания новой страницы задачи в директории /content/en/docs/tasks создайте поддиректорию с Markdown-файлом со следующим требованиями:

  • Во фронтальной части YAML этой страницы определите поле content_type: task.

  • В теле страницы укажите переменные capture и любые другие, которые вы хотите включить:

    Переменная Обязательна?
    overview да
    prerequisites да
    steps нет
    discussion нет
    whatsnext нет

    Тело страницы будет выглядеть следующим образом (удалите все необязательные capture-блоки, если они вам не нужны):

    {{% capture overview %}}
    
    {{% /capture %}}
    
    {{% capture prerequisites %}}
    
    {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
    
    {{% /capture %}}
    
    {{% capture steps %}}
    
    {{% /capture %}}
    
    {{% capture discussion %}}
    
    {{% /capture %}}
    
    {{% capture whatsnext %}}
    
    {{% /capture %}}
    
  • Заполните каждый блок информацией. Следуйте этим рекомендациям:

    • Используйте по минимуму заголовков H2 (с двумя ведущими символами #). У самих разделов заголовок формируется автоматически по заданному шаблону.
    • В блоке overview обозначьте контекст для всей темы.
    • В блоке prerequisites используйте ненумерованные списки, где это возможно. Добавьте дополнительные предварительные условия ниже include. Предварительные условия по умолчанию содержат пункт про наличие работающего кластера.
    • В блоке steps используйте нумерованные списки.
    • В блоке discussion подробно распишите информацию, описанную в разделе steps.
    • В блоке whatsnext сформируйте ненумерованный список тем (до 5), которые могут быть интересны читателю в качестве дополнительного чтения.

Пример готовой темы, в которой используется шаблон задачи — Using an HTTP proxy to access the Kubernetes API.

Шаблон руководства

На странице руководства показывается, как выполнить что-то более крупнее одной-единственной задачи. Как правило, страницы руководства поделена на несколько разделов, в каждом из которых есть последовательность шагов. Например, руководство может включать анализ примера кода, демонстрирующий определенную возможность Kubernetes. Руководства могут содержать поверхностные объяснения и одновременно включать ссылки на соответствующие концептуальные темы для получения углубленных знаний.

Для написания новой страницы задачи в директории /content/en/docs/tutorials создайте поддиректорию с Markdown-файлом со следующим требованиями:

  • Во фронтальной части YAML этой страницы определите поле content_type: tutorial.

  • В теле страницы укажите переменные capture и любые другие, которые вы хотите включить:

    Переменная Обязательна?
    overview да
    prerequisites да
    objectives да
    lessoncontent да
    cleanup нет
    whatsnext нет

    Тело страницы будет выглядеть следующим образом (удалите все необязательные capture-блоки, если они вам не понадобятся):

    {{% capture overview %}}
    
    {{% /capture %}}
    
    {{% capture prerequisites %}}
    
    {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
    
    {{% /capture %}}
    
    {{% capture objectives %}}
    
    {{% /capture %}}
    
    {{% capture lessoncontent %}}
    
    {{% /capture %}}
    
    {{% capture cleanup %}}
    
    {{% /capture %}}
    
    {{% capture whatsnext %}}
    
    {{% /capture %}}
    
  • Заполните каждый блок информацией. Следуйте этим рекомендациям:

    • Используйте по минимуму заголовков H2 (с двумя ведущими символами #). У самих разделов заголовок формируется автоматически по заданному шаблону.
    • В блоке overview обозначьте контекст для всей темы.
    • В блоке prerequisites используйте ненумерованные списки, где это возможно. Добавьте дополнительные предварительные условия ниже include. Предварительные условия по умолчанию содержат пункт про наличие работающего кластера.
    • В блоке objectives используйте ненумерованные списки.
    • В блоке lessoncontent целесообразно используйте совместно нумерованные списки и повествовательное содержание.
    • В блоке cleanup используйте нумерованные списки для описания шагов для очистки состояния кластера после выполнения задачи.
    • В блоке whatsnext сформируйте ненумерованный список тем (до 5), которые могут быть интересны читателю в качестве дополнительного чтения.

Пример завершенной темы, в которой используется шаблон руководства — Running a Stateless Application Using a Deployment.

Что дальше

9.4.5 - Организация контента

Этот сайт использует Hugo. В Hugo организация контента — основная концепция.

Списки страниц

Порядок страницы

Меню в сайдбаре, каталог страниц документации используют стандартный порядок перечисления Hugo, который сортирует элементы по весу (от 1), дате (начиная с самых новых) и затем по заголовку ссылки.

Таким образом, если вам нужно поднять страницу или раздел, определите её вес в фронтальной части:

title: Моя страница
weight: 10

Главное меню документации

Главное меню Документация состоит из разделов по пути docs/ с установленным флагом main_menu в фронтальной части файла раздела _index.md:

main_menu: true

Обратите внимание, что текст ссылки берётся из переменной linkTitle, поэтому, если вы хотите, чтобы он отличался от заголовка страницы, измените его в файле:

main_menu: true
title: Название страницы
linkTitle: Название, которое будет использоваться в ссылках

Документация в боковом меню

Меню сайдбара в документации собирается из текущего дерева разделов по пути docs/.

Оно отобразит все разделы и их страницы.

Если вы хотите, чтобы раздел или страница не отображались в меню, установите для флага toc_hide значение true в фронтальной части файла:

toc_hide: true

При переходе к непустому разделу будет отображаться указанный раздел или страница (например, _index.md). В противном случае выводиться первая страница в этом разделе.

Каталог документации

Каталог страниц на главной странице документации сгенерирован с учётом всех разделов и страниц документации.

Если вы хотите скрыть раздел или страницу, установите для флага toc_hide значение true в фронтальной части файла:

toc_hide: true

Главное меню

Ссылки сайта в верхнем правом меню, а также в футере, создаются посредством сканирования страниц. Этот процесс гарантирует, что страница действительно существует на сайте. Поэтому, если раздела case-studies на сайте (или в переводе) не существует, ссылка не появится.

Пакеты страниц

В дополнение к отдельным страницам с контентом (Markdown-файлам), Hugo поддерживает пакеты страниц (page bundles).

К примеру, пользовательские макрокоды Hugo — узел пакета (leaf bundle). Все, что находится в директории, включая index.md, будет частью пакета. Сюда также относятся относительные ссылки на страницы, изображения, которые могут быть обработаны и т.д.:

en/docs/home/contribute/includes
├── example1.md
├── example2.md
├── index.md
└── podtemplate.json

Другой распространённый пример — это пакет includes. Он устанавливает переменную headless: true, которая означает, что файл не будет доступен по собственному URL-адресу. Вместо этого он будет использоваться в других страницах как вставляемый файл.

en/includes
├── default-storage-class-prereqs.md
├── federated-task-tutorial-prereqs.md
├── index.md
├── partner-script.js
├── partner-style.css
├── task-tutorial-prereqs.md
├── user-guide-content-moved.md
└── user-guide-migration-notice.md

Необходимо отметить следующие особенности файлов в пакетах:

  • Для переведенных пакетов любые отсутствующие файлы будут унаследованы от файлов на оригинальном (английском) языке. Это позволяет избежать дублирования.
  • Все файлы в пакете — в Hugo называются ресурсы (Resources), в которых вы можете определить метаданные, зависимые от языка, например, параметры и заголовок, даже если они не поддерживают в фронтальной части (YAML-файлы и т.д.). Смотрите Метаданные ресурсов страницы для получения дополнительной информации.
  • Значение, которое вы получаете через .RelPermalink в Resource будет отличаться в зависимости от страницы. Смотрите Постоянные ссылки для получения дополнительной информации.

Стилизация

Исходные файлы стилей в формате SASS находятся в директории assets/sass и автоматически собираются Hugo.

Что дальше

9.4.6 - Пользовательские макрокоды Hugo

На этой странице объясняются пользовательские макрокоды Hugo, которые можно использовать в Markdown-файлах документации Kubernetes.

Узнать подробнее про макрокоды можно в документации Hugo.

Состояние функциональности

В Markdown странице (файл с расширением .md) вы можете добавить макрокод, чтобы отобразить версию и состояние документированной функциональной возможности.

Демонстрация состояния функциональности

Ниже показан фрагмент кода для вывода состояния функциональности, который сообщает о функциональности в стабильной версии Kubernetes 1.10.

{{< feature-state for_k8s_version="v1.10" state="stable" >}}

Результат:

СТАТУС ФИЧИ: Kubernetes v1.10 [stable]

Допустимые значения для state:

  • alpha
  • beta
  • deprecated
  • stable

Код состояния функциональности

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

{{< feature-state for_k8s_version="v1.10" state="stable" >}}

Результат:

СТАТУС ФИЧИ: Kubernetes v1.10 [stable]

Функциональность в альфа-версии

{{< feature-state state="alpha" >}}

Результат:

СТАТУС ФИЧИ: Kubernetes v1.31 [alpha]

Функциональность в бета-версии

{{< feature-state state="beta" >}}

Результат:

СТАТУС ФИЧИ: Kubernetes v1.31 [beta]

Функциональность в стабильной версии

{{< feature-state state="stable" >}}

Результат:

СТАТУС ФИЧИ: Kubernetes v1.31 [stable]

Устаревшая функциональность

{{< feature-state state="deprecated" >}}

Результат:

СТАТУС ФИЧИ: Kubernetes v1.31 [deprecated]

Глоссарий

Вы можете сослаться на термины из глоссария в виде всплывающей (при наведении мыши) подсказки, что удобно при чтении документации через интернет.

Исходные файлы терминов глоссария хранятся в отдельной директории по URL-адресу https://github.com/kubernetes/website/tree/master/content/en/docs/reference/glossary.

Демонстрация глоссария

Например, следующий фрагмент кода в Markdown будет отображен в виде всплывающей подсказки — cluster:

{{< glossary_tooltip text="cluster" term_id="cluster" >}}

Заголовки таблиц

Для улучшения доступности таблиц для программ для чтения с экрана, добавьте заголовок к таблице. Чтобы добавить заголовок таблицы, поместите таблицу в макрокод table и определите значение заголовка в параметре caption.

Пример:

{{< table caption="Конфигурационные параметры" >}}
Параметр | Описание | Значение по умолчанию
:---------|:------------|:-------
`timeout` | Тайм-аут для запросов | `30s`
`logLevel` | Уровень логирования | `INFO`
{{< /table >}}

Результат:

{{< table caption="Конфигурационные параметры" >}}

Параметр Описание Значение по умолчанию
timeout Тайм-аут для запросов 30s
logLevel Уровень логирования INFO
{{< /table >}}

Если вы изучите HTML-код таблицы, вы заметите следующий ниже элемент сразу после открывающего элемента <table>:

<caption style="display: none;"></caption>

Вкладки

Страница в формате Markdown (файл с расширением .md) на этом сайте может содержать набор вкладок для отображения нескольких разновидностей определённого решения.

Макрокод tabs принимает следующие параметры:

  • name: имя, отображаемое на вкладке.
  • codelang: если вы указываете встроенный контент для макрокода tab, вы можете сообщить Hugo, какой язык использовать для подсветки синтаксиса.
  • include: включаемый файл в вкладку. Если вкладка находится в узле пакета (leaf bundle) Hugo, то файл (может быть любым MIME-типом, который поддерживает Hugo) ищется в самом пакете. Если нет, то включаемое содержимое ищется относительно текущей страницы. Обратите внимание, что при использовании include вам следует использовать самозакрывающийся синтаксис. Например, {{</* tab name="Content File #1" include="example1" />}}. Язык может быть указан в codelang, в противном случае язык определяется из имени файла.
  • Если содержимое вкладки это Markdown, вам нужно использовать символ %. Например, {{% tab name="Вкладка 1" %}}This is **markdown**{{% /tab %}}
  • Вы можете совместно использовать перечисленные выше параметры. Ниже приведена демонстрация шорткода вкладок.

Ниже приведены примеры вкладок.

Демонстрация вкладок: подсветка синтаксиса в блоках кода

{{< tabs name="tab_with_code" >}}
{{{< tab name="Вкладка 1" codelang="bash" >}}
echo "Это вкладка 1."
{{< /tab >}}
{{< tab name="Вкладка 2" codelang="go" >}}
println "Это вкладка 2."
{{< /tab >}}}
{{< /tabs >}}

Результат:


echo "Это вкладка 1."


println "Это вкладка 2."

Демонстрация вкладок: встроенный Markdown и HTML

{{< tabs name="tab_with_md" >}}
{{% tab name="Markdown" %}}
Это **разметка Markdown.**
{{< note >}}
Также можно использовать макрокоды.
{{< /note >}}
{{% /tab %}}
{{< tab name="HTML" >}}
<div>
	<h3>Обычный HTML</h3>
	<p>Это <i>обычный</i> HTML.</p>
</div>
{{< /tab >}}
{{< /tabs >}}

Результат:

Это разметка Markdown.

Обычный HTML

Это обычный HTML.

Демонстрация вкладок: включение файлов

{{< tabs name="tab_with_file_include" >}}
{{< tab name="Content File #1" include="example1" />}}
{{< tab name="Content File #2" include="example2" />}}
{{< tab name="JSON File" include="podtemplate" />}}
{{< /tabs >}}

Результат:

Это пример содержимого в файле внутри пакета узла includes.

Это другой пример содержимого в файле внутри пакета узла includes.

  {
    "apiVersion": "v1",
    "kind": "PodTemplate",
    "metadata": {
      "name": "nginx"
    },
    "template": {
      "metadata": {
        "labels": {
          "name": "nginx"
        },
        "generateName": "nginx-"
      },
      "spec": {
         "containers": [{
           "name": "nginx",
           "image": "dockerfile/nginx",
           "ports": [{"containerPort": 80}]
         }]
      }
    }
  }

Что дальше

9.5 - Обзор справочной документации

Темы в этом разделе описывают, как генерировать справочные руководства Kubernetes.

Для сборки справочной документации посмотрите следующий ресурс:

9.5.1 - Участие в основном коде Kubernetes

На этой странице показано, как поучаствовать в основном содержимом проекта kubernetes/kubernetes. Вы можете исправить баги, найденные в документации по API Kubernetes или содержимом таких компонентов Kubernetes, как kubeadm, kube-apiserver и kube-controller-manager.

Если вместо этого вы хотите перегенерировать справочную документацию для API Kubernetes или компонентов с именем kube-* в основном коде, изучите следующие инструкции:

Подготовка к работе

Рассмотрение процесса в целом

Справочная документация для API Kubernetes и таких компонентов с kube-*, как kube-apiserver, kube-controller-manager, автоматически генерируются из исходного кода в основном репозитории Kubernetes.

Если вы заметили баги в сгенерированной документации, попробуйте его исправить через пулреквест в основной проект.

Клонирование репозитория Kubernetes

Если вы ещё не склонировали репозиторий kubernetes/kubernetes, сделайте это:

mkdir $GOPATH/src
cd $GOPATH/src
go get github.com/kubernetes/kubernetes

Определите базовую директорию вашей копии репозитория kubernetes/kubernetes. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/github.com/kubernetes/kubernetes. В остальных команд базовая директория будет именоваться как <k8s-base>.

Определите базовую директорию вашей копии репозитория kubernetes-sigs/reference-docs. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/github.com/kubernetes-sigs/reference-docs. В остальных команд базовая директория будет именоваться как <rdocs-base>.

Редактирование исходного кода Kubernetes

Справочная документация API Kubernetes генерируется автоматически из спецификации OpenAPI в исходном коде Kubernetes. Если вы хотите изменить справочную документацию API, сначала нужно изменить один или несколько комментариев в исходном коде Kubernetes.

Документация для компонентов kube-* также генерируется из основного исходного кода. Для изменения генерируемой документации вам нужно изменить соответствующий код компонента.

Внесение изменений в основной исходный код

Рассмотрим пример редактирования комментария в исходном коде Kubernetes.

В вашем локальном репозитории kubernetes/kubernetes переключитесь на ветку master и проверьте, что она актуальна:

cd <k8s-base>
git checkout master
git pull https://github.com/kubernetes/kubernetes master

Предположим, что в исходном файле в ветке master есть опечатка "atmost":

kubernetes/kubernetes/staging/src/k8s.io/api/apps/v1/types.go

В вашем локальном окружении откройте types.go и измените "atmost" на "at most".

Убедитесь, что вы изменили файл:

git status

Вывод этой команды покажет, что вы находитесь в ветке master и был изменён исходный файл types.go:

On branch master
...
    modified:   staging/src/k8s.io/api/apps/v1/types.go

Фиксация отредактированного файла

Выполните команду git add и git commit, чтобы зафиксировать внесенные вами изменения. На следующем шаге вы сделаете второй коммит. Следует отметить, что ваши изменения должны быть разделены на коммита.

Генерация спецификации OpenAPI и сопутствующих файлов

Перейдите в директорию <k8s-base> и выполните следующие скрипты:

hack/update-generated-swagger-docs.sh
hack/update-openapi-spec.sh
hack/update-generated-protobuf.sh

Выполните команду git status, чтобы посмотреть, какие файлы изменились.

On branch master
...
    modified:   api/openapi-spec/swagger.json
    modified:   api/openapi-spec/v3/apis__apps__v1_openapi.json
    modified:   pkg/generated/openapi/zz_generated.openapi.go
    modified:   staging/src/k8s.io/api/apps/v1/generated.proto
    modified:   staging/src/k8s.io/api/apps/v1/types_swagger_doc_generated.go

Изучите содержимое файла api/openapi-spec/swagger.json, чтобы убедиться в том, что опечатка была исправлена. Например, для этого вы можете выполнить команду git diff -a api/openapi-spec/swagger.json. Это важно, потому что изменённый файл swagger.json является результатом второй стадии процесса генерации документации.

Выполните команду git add и git commit для фиксации ваших изменения. Теперь вы можете увидеть два новых коммита: первый содержит отредактированный файл types.go, а второй — сгенерированную спецификацию OpenAPI и сопутствующие файлы. Оформляйте эти изменения в виде двух отдельных коммитов. Это означает, что не нужно объединять коммиты.

Отправьте свои изменения как пулреквест в ветку master репозитория kubernetes/kubernetes. Отслеживайте пулреквест и по мере необходимости отвечайте на комментарии рецензента. Не забывайте отслеживать активность в пулреквест до тех пор, пока он не будет принят.

PR 57758 — пример пулреквеста, который исправляет опечатку в исходном коде Kubernetes.

Применение вашего коммита в ветку выпуска

В предыдущем разделе вы отредактировали файл в ветке master, а затем запустили скрипты для генерации спецификации OpenAPI и смежных файлов. Затем вы отправили свои изменения в виде пулреквеста в ветку master репозитория kubernetes/kubernetes. Теперь представим, что вам нужно бэкпортировать изменения в ветку выпуска. К примеру, ветка master используется для разработки Kubernetes версии 1.10, а вы хотите применить ваши изменения в ветке release-1.9.

Напомним, что в вашем пулреквесте есть два коммита: первый для редактирования types.go, а второй — для файлов, сгенерированных скриптами. Следующий шаг — применить сделанный вами первый коммит в ветку release-1.9. Суть в том, чтобы выбрать коммит, который изменяет файл types.go, а не коммит с результатами выполнения скриптов. За инструкциями обратитесь к странице Propose a Cherry Pick.

Когда в вашем пулреквесте есть определённый коммит, который нужно применить в ветке release-1.9, вам нужно запустить перечисленные ниже скрипты в этой вете из вашего локального окружения.

hack/update-generated-swagger-docs.sh
hack/update-openapi-spec.sh
hack/update-generated-protobuf.sh
hack/update-api-reference-docs.sh

Теперь зафиксируйте изменения в вашем пулреквесте с применённым коммитом, теперь там будет сгенерированная спецификация OpenAPI и связанные с ней файлы. Отслеживайте этот пулреквест до тех пор, пока он не будет объединен в ветке release-1.9.

Сейчас у вас и в ветке master, и в ветке release-1.9 есть обновленный файл types.go вместе с множеством сгенерированных файлов, в которых отражаются изменения, внесенные вами в types.go. Обратите внимание, что сгенерированная спецификация OpenAPI и другие сгенерированные файлы в ветке release-1.9 не обязательно совпадают с сгенерированными файлами в ветке master. Сгенерированные файлы в ветке release-1.9 содержат элементы API только из Kubernetes 1.9. Сгенерированные файлы в ветке master могут содержать элементы API не только для версии 1.9, но и для 1.10, которая ещё находится в разработке.

Генерация справочной документации

В предыдущем разделе было показано, как отредактировать исходный файл, а затем сгенерировать несколько файлов, включая api/openapi-spec/swagger.json в репозитории kubernetes/kubernetes. Файл swagger.json — это файл определения OpenAPI, который используется для генерации справочной документации API.

Теперь вы можете приступить к изучению руководству Генерация справочной документации для API Kubernetes, чтобы создать справочную документацию API Kubernetes.

Что дальше

9.5.2 - Руководство по быстрому старту

На этой странице показано, как использовать скрипт update-imported-docs для генерации справочной документации Kubernetes. Скрипт автоматизирует настройку сборки и генерирует справочную документацию для выпуска.

Подготовка к работе

Требования:

  • Наличие компьютера под управлением ОС Linux или macOS.

  • Установленные следующие инструменты:

    • Python версии 3.7.x
    • Git
    • Golang версии 1.13+
    • Pip, который потребуется для установки PyYAML
    • PyYAML версии 5.1.2
    • make
    • gcc compiler/linker
    • Docker (требуется только для справочника команды kubectl)
  • В переменной окружении PATH должны прописаны пути до необходимых инструментов сборки, таких как Go и python.

  • Вам нужно знать, как создать пулреквест в репозитории на GitHub. Для этого нужно создание собственной копии репозитория. Для получения дополнительной информации смотрите раздел Работа из локальной копии.

Получение репозитория документации

Убедитесь, что ваша копия репозитория website обновлена в соответствии с оригинальным репозиторием kubernetes/website, а затем склонируйте вашу копию website.

mkdir github.com
cd github.com
git clone git@github.com:<your_github_username>/website.git

Определите базовую директорию вашей копии. Например, при выполнении предыдущего блока команд, то базовой директорией будет website. Далее в этом руководстве базовая директория в командах будет обозначаться <web-base>.

Краткий обзор update-imported-docs

Скрипт update-imported-docs находится в директории <web-base>/update-imported-docs/.

Этот скрипт генерирует следующие справочники:

  • Справочные страницы для компонентов и инструментов
  • Справочник команды kubectl
  • API-справочник Kubernetes

Скрипт update-imported-docs генерирует справочную документацию Kubernetes из исходного кода Kubernetes. Скрипт создает временную директорию /tmp на вашем компьютере и клонирует необходимые репозитории в эту директорию: kubernetes/kubernetes и kubernetes-sigs/reference-docs. Скрипт добавляет путь временной директории в переменную окружения GOPATH. Кроме этого определяются три дополнительные переменные среды:

  • K8S_RELEASE
  • K8S_ROOT
  • K8S_WEBROOT

Для успешного выполнения скрипта нужно передать два аргумента:

  • Конфигурационный файл в формате YAML (reference.yml)
  • Версия выпуска, например, 1.17

Конфигурационный файл содержит поле generate-command. Поле generate-command определяет ряд инструкций для сборки из kubernetes-sigs/reference-docs/Makefile. Переменная K8S_RELEASE определяет версию выпуска.

Скрипт update-imported-docs выполняет следующие шаги:

  1. Клонирует репозитории, указанные в конфигурационном файле. Для генерации справочной документации клонируемым репозиторием по умолчанию является kubernetes-sigs/reference-docs.
  2. Запускает команды в клонированных репозиториях для подготовки генератора документации, а затем генерирует файлы HTML и Markdown.
  3. Копирует сгенерированные файлы HTML и Markdown в локальную копию репозитория <web-base> в директории, указанные в конфигурационном файле.
  4. Обновляет ссылки на команды kubectl из kubectl.md, ссылаясь на разделы в справочнике по команде kubectl. . Когда сгенерированные файлы находятся в вашем локальной копии репозитория <web-base>, вы можете отправить их в виде пулреквеста в оригинальный репозиторий <web-base>.

Формат конфигурационного файла

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

repos:
- name: community
  remote: https://github.com/kubernetes/community.git
  branch: master
  files:
  - src: contributors/devel/README.md
    dst: docs/imported/community/devel.md
  - src: contributors/guide/README.md
    dst: docs/imported/community/guide.md

Каждый Markdown-файл документации, импортированный инструментом, должен соответствовать руководству по оформлению документации.

Настройка reference.yml

Откройте файл <web-base>/update-imported-docs/reference.yml для редактирования. Не изменяйте значение в поле generate-command, если не понимаете, как эта команда используется для сборки справочников. Вам нет необходимости править файл reference.yml. В некоторых случаях изменения в исходном коде основного репозитория могут потребовать внесения изменений в конфигурационный файл (например, зависимости версий golang и изменения сторонних библиотек). Если у вас возникли проблемы со сборкой, обратитесь за помощью к команде SIG-Docs на канале #sig-docs в Slack Kubernetes.

В файле reference.yml секция files содержат список полей src и dst. В поле src хранится путь к сгенерированному Markdown-файлу в клонированной директории сборки kubernetes-sigs/reference-docs, а поле dst определяет, куда скопировать этот файл в клонированном репозитории kubernetes/website. Например:

repos:
- name: reference-docs
  remote: https://github.com/kubernetes-sigs/reference-docs.git
  files:
  - src: gen-compdocs/build/kube-apiserver.md
    dst: content/en/docs/reference/command-line-tools-reference/kube-apiserver.md
  ...

Обратите внимание, что в случае наличия множества файлов, которые нужно скопировать из одной директории в другую, то для это можете воспользоваться подстановочными знаки в поле src. Вам нужно указать имя директории в поле dst. Например:

  files:
  - src: gen-compdocs/build/kubeadm*.md
    dst: content/en/docs/reference/setup-tools/kubeadm/generated/

Запуск инструмента update-imported-docs

Вы можете запустить инструмент update-imported-docs следующим образом:

cd <web-base>/update-imported-docs
./update-imported-docs <configuration-file.yml> <release-version>

Например:

./update-imported-docs reference.yml 1.17

Исправление ссылок

Конфигурационный файл release.yml содержит инструкции по исправлению относительных ссылок Для исправления относительных ссылок в импортированных файлах, установите для свойство gen-absolute-links в значение true. В качестве примера можете посмотреть файл release.yml.

Внесение изменений в kubernetes/website

Список сгенерированных и скопированных файлов в <web-base> можно узнать, как показано ниже:

cd <web-base>
git status

В выводе команды будут показаны новые и измененные файлы. Полученный вывод может отличаться в зависимости от изменений основного исходного кода.

Сгенерированные файлы инструментом

content/en/docs/reference/command-line-tools-reference/cloud-controller-manager.md
content/en/docs/reference/command-line-tools-reference/kube-apiserver.md
content/en/docs/reference/command-line-tools-reference/kube-controller-manager.md
content/en/docs/reference/command-line-tools-reference/kube-proxy.md
content/en/docs/reference/command-line-tools-reference/kube-scheduler.md
content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm.md
content/en/docs/reference/kubectl/kubectl.md

Сгенерированные справочные файлы для команды kubectl

static/docs/reference/generated/kubectl/kubectl-commands.html
static/docs/reference/generated/kubectl/navData.js
static/docs/reference/generated/kubectl/scroll.js
static/docs/reference/generated/kubectl/stylesheet.css
static/docs/reference/generated/kubectl/tabvisibility.js
static/docs/reference/generated/kubectl/node_modules/bootstrap/dist/css/bootstrap.min.css
static/docs/reference/generated/kubectl/node_modules/highlight.js/styles/default.css
static/docs/reference/generated/kubectl/node_modules/jquery.scrollto/jquery.scrollTo.min.js
static/docs/reference/generated/kubectl/node_modules/jquery/dist/jquery.min.js
static/docs/reference/generated/kubectl/css/font-awesome.min.css

Сгенерированные файлы и директории для справочника API Kubernetes

static/docs/reference/generated/kubernetes-api/v1.17/index.html
static/docs/reference/generated/kubernetes-api/v1.17/js/navData.js
static/docs/reference/generated/kubernetes-api/v1.17/js/scroll.js
static/docs/reference/generated/kubernetes-api/v1.17/js/query.scrollTo.min.js
static/docs/reference/generated/kubernetes-api/v1.17/css/font-awesome.min.css
static/docs/reference/generated/kubernetes-api/v1.17/css/bootstrap.min.css
static/docs/reference/generated/kubernetes-api/v1.17/css/stylesheet.css
static/docs/reference/generated/kubernetes-api/v1.17/fonts/FontAwesome.otf
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.eot
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.svg
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.ttf
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.woff
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.woff2

Выполните git add и git commit, чтобы зафиксировать файлы в репозитории.

Создание пулреквеста

Создайте пулреквест в репозиторий kubernetes/website. Отслеживайте свой пулреквест и при необходимости отвечайте на комментарии. Не забывайте отслеживать активность в собственном пулреквесте до тех пор, пока он не будет принят.

Спустя несколько минут после принятия вашего пулреквеста, обновленные темы справочника будут отображены в документации.

Что дальше

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

9.5.3 - Генерация справочной документации для API Kubernetes

На этой странице рассказывается про обновление справочной документации по API Kubernetes.

Справочная документация по API Kubernetes собирается из спецификации OpenAPI Kubernetes с использованием инструмента генерации kubernetes-sigs/reference-docs.

Если вы нашли баги в сгенерированной документации, то можете исправить их в основном коде.

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

Подготовка к работе

Требования:

  • Наличие компьютера под управлением ОС Linux или macOS.

  • Установленные следующие инструменты:

    • Python версии 3.7.x
    • Git
    • Golang версии 1.13+
    • Pip, который потребуется для установки PyYAML
    • PyYAML версии 5.1.2
    • make
    • gcc compiler/linker
    • Docker (требуется только для справочника команды kubectl)
  • В переменной окружении PATH должны прописаны пути до необходимых инструментов сборки, таких как Go и python.

  • Вам нужно знать, как создать пулреквест в репозитории на GitHub. Для этого нужно создание собственной копии репозитория. Для получения дополнительной информации смотрите раздел Работа из локальной копии.

Настройка локальных репозиториев

Создайте рабочую область и определите переменную окружения GOPATH.

mkdir -p $HOME/<workspace>

export GOPATH=$HOME/<workspace>

Загрузите локальные копии следующих репозиториев:

go get -u github.com/kubernetes-sigs/reference-docs

go get -u github.com/go-openapi/loads
go get -u github.com/go-openapi/spec

Если у вас ещё нет копии репозитория kubernetes/website, клонируйте её на свой компьютер:

git clone https://github.com/<your-username>/website $GOPATH/src/github.com/<your-username>/website

Склонируйте репозиторий kubernetes/kubernetes по пути k8s.io/kubernetes:

git clone https://github.com/kubernetes/kubernetes $GOPATH/src/k8s.io/kubernetes
  • Определите базовую директорию вашей копии репозитория kubernetes/kubernetes. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/k8s.io/kubernetes. В остальных командах базовая директория будет именоваться как <k8s-base>.

  • Определите базовую директорию вашей копии репозитория kubernetes/website. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/github.com/<your-username>/website. В остальных командах базовая директория будет именоваться как <web-base>.

  • Определите базовую директорию вашей копии репозитория kubernetes-sigs/reference-docs. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/github.com/kubernetes-sigs/reference-docs. В остальных командах базовая директория будет именоваться как <rdocs-base>.

Генерация справочной документации API

Далее в этом разделе рассматривается генерация справочной документации по API Kubernetes.

Настройка переменных для сборки

  • K8S_ROOT со значением <k8s-base>.
  • K8S_WEBROOT со значением <web-base>.
  • K8S_RELEASE со значением нужной версии документации. Например, если вы хотите собрать документацию для Kubernetes версии 1.17.0, определите переменную окружения K8S_RELEASE со значением 1.17.0.

Примеры:

export K8S_WEBROOT=${GOPATH}/src/github.com/<your-username>/website
export K8S_ROOT=${GOPATH}/src/k8s.io/kubernetes
export K8S_RELEASE=1.17.0

Создание версионированной директории и получение Open API spec

Скрипт сборки updateapispec создает версионированную директорию для сборки. После создания директории спецификация Open API генерируется из репозитория <k8s-base>. Таким образом версия конфигурационных файлов и спецификация Kubernetes Open API будут совпадать с версией выпуска. Имя версионированной директории имеет следующий вид: v<major>_<minor>.

В директории <rdocs-base> выполните следующий скрипт сборки:

cd <rdocs-base>
make updateapispec

Сборка справочной документации API

Скрипт сборки copyapi создает справочник API и копирует генерированные файлы в каталоги в <web-base>. Выполните следующую команду в <rdocs-base>:

cd <rdocs-base>
make copyapi

Убедитесь в том, что перечисленные ниже два файлы были сгенерированы:

[ -e "<rdocs-base>/gen-apidocs/build/index.html" ] && echo "index.html built" || echo "no index.html"
[ -e "<rdocs-base>/gen-apidocs/build/navData.js" ] && echo "navData.js built" || echo "no navData.js"

Перейдите в корень директории <web-base> и посмотрите, какие файлы были изменены:

cd <web-base>
git status

Вывод команды будет примерно следующим:

static/docs/reference/generated/kubernetes-api/v1.17/css/bootstrap.min.css
static/docs/reference/generated/kubernetes-api/v1.17/css/font-awesome.min.css
static/docs/reference/generated/kubernetes-api/v1.17/css/stylesheet.css
static/docs/reference/generated/kubernetes-api/v1.17/fonts/FontAwesome.otf
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.eot
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.svg
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.ttf
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.woff
static/docs/reference/generated/kubernetes-api/v1.17/fonts/fontawesome-webfont.woff2
static/docs/reference/generated/kubernetes-api/v1.17/index.html
static/docs/reference/generated/kubernetes-api/v1.17/js/jquery.scrollTo.min.js
static/docs/reference/generated/kubernetes-api/v1.17/js/navData.js
static/docs/reference/generated/kubernetes-api/v1.17/js/scroll.js

Обновление указателя API-справочника

При генерации справочной документации для нового выпуска в файле <web-base>/content/en/docs/reference/kubernetes-api/api-index.md нужно прописать номер предстоящей версии.

  • Откройте файл <web-base>/content/en/docs/reference/kubernetes-api/api-index.md и обновите номер версии справочника API. Например:

    ---
    title: v1.17
    ---
    
    [Kubernetes API v1.17](/docs/reference/generated/kubernetes-api/v1.17/)
    
  • Откройте файл <web-base>/content/en/docs/reference/_index.md и добавьте ссылку на последний справочник API. Удалите самую старую версию справочника API. В этом файле должно быть 5 ссылок на новейшие API-справочники.

Тестирование справочника API локально

Соберите обновлённую версию API-справочника на своём компьютере. Проверьте ваши изменения на локальной предварительной версии сайта.

cd <web-base>
make docker-serve

Фиксация изменений

В директории <web-base> выполните команду git add и git commit для фиксации изменений в репозитории.

Создайте пулреквест в репозиторий kubernetes/website. Отслеживайте свой пулреквест и при необходимости отвечайте на комментарии. Не забывайте отслеживать активность в собственном пулреквесте до тех пор, пока он не будет принят.

Отправьте свои изменения в виде пулреквеста в репозиторий kubernetes/kubernetes. Отслеживайте изменения в пулреквесте и по мере необходимости отвечайте на комментарии рецензента. Не забывайте проверять пулреквест до тех пор, пока он не будет принят.

Что дальше

9.5.4 - Генерация справочной документации для команд kubectl

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

Подготовка к работе

Требования:

  • Наличие компьютера под управлением ОС Linux или macOS.

  • Установленные следующие инструменты:

    • Python версии 3.7.x
    • Git
    • Golang версии 1.13+
    • Pip, который потребуется для установки PyYAML
    • PyYAML версии 5.1.2
    • make
    • gcc compiler/linker
    • Docker (требуется только для справочника команды kubectl)
  • В переменной окружении PATH должны прописаны пути до необходимых инструментов сборки, таких как Go и python.

  • Вам нужно знать, как создать пулреквест в репозитории на GitHub. Для этого нужно создание собственной копии репозитория. Для получения дополнительной информации смотрите раздел Работа из локальной копии.

Настройка локальных репозиториев

Создайте рабочую область и определите переменную окружения GOPATH.

mkdir -p $HOME/<workspace>

export GOPATH=$HOME/<workspace>

Загрузите локальные копии следующих репозиториев:

go get -u github.com/spf13/pflag
go get -u github.com/spf13/cobra
go get -u gopkg.in/yaml.v2
go get -u kubernetes-sigs/reference-docs

Если у вас ещё нет копии репозитория kubernetes/website, клонируйте её на свой компьютер:

git clone https://github.com/<your-username>/website $GOPATH/src/github.com/<your-username>/website

Склонируйте репозиторий kubernetes/kubernetes по пути k8s.io/kubernetes:

git clone https://github.com/kubernetes/kubernetes $GOPATH/src/k8s.io/kubernetes

Удалите пакет spf13 в $GOPATH/src/k8s.io/kubernetes/vendor/github.com.

rm -rf $GOPATH/src/k8s.io/kubernetes/vendor/github.com/spf13

В репозитории kubernetes/kubernetes использует исходный код kubectl и kustomize.

  • Определите базовую директорию вашей копии репозитория kubernetes/kubernetes. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/k8s.io/kubernetes. В остальных командах базовая директория будет именоваться как <k8s-base>.

  • Определите базовую директорию вашей копии репозитория kubernetes/website. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/github.com/<your-username>/website. В остальных команд базовая директория будет именоваться как <web-base>.

  • Определите базовую директорию вашей копии репозитория kubernetes-sigs/reference-docs. Например, если вы выполнили предыдущий шаг, чтобы получить репозиторий, вашей базовой директорией будет $GOPATH/src/github.com/kubernetes-sigs/reference-docs. В остальных команд базовая директория будет именоваться как <rdocs-base>.

В вашем локальном репозитории k8s.io/kubernetes переключитесь в нужную вам ветку и убедитесь, что она в актуальном состоянии. Например, если вам нужно сгенерировать документацию для Kubernetes 1.17, вы можете использовать эти команды:

cd <k8s-base>
git checkout v1.17.0
git pull https://github.com/kubernetes/kubernetes v1.17.0

Если вам не нужно изменять исходный код kubectl, следуйте инструкциям по определению переменных сборки.

Редактирование исходного кода kubectl

Справочная документация по команде kubectl генерируется автоматически из исходного кода kubectl. Если вы хотите изменить справочную документацию, сначала измените один или несколько комментариев в исходном коде kubectl. Сделайте изменения в локальный репозиторий kubernetes/kubernetes, а затем отправьте пулреквест в ветку master репозитория github.com/kubernetes/kubernetes.

PR 56673 — пример пулреквеста, который исправляет опечатку в исходном коде kubectl.

Отслеживайте пулреквест и по мере необходимости отвечайте на комментарии рецензента. Не забывайте отслеживать активность в пулреквест до тех пор, пока он не будет принят в ветку master репозитория kubernetes/kubernetes.

Применение вашего изменения в ветку выпуска

Теперь ваше изменение в ветке master, которая используется для разработки следующего выпуска Kubernetes. Если вы хотите добавить ваше изменение в документацию для уже выпущенной версии Kubernetes, вам нужно применить коммит с соответствующим изменением в нужную ветку выпуска.

Например, предположим, что ветка master используется для разработки Kubernetes 1.10, а вам нужно бэкпортировать ваше изменение в ветку release-1.15. За инструкциями обратитесь к странице Propose a Cherry Pick.

Отслеживайте ваш пулреквест с применённым изменением до тех пор, пока он не будет объединён в ветку выпуска.

Настройка переменных для сборки

Перейдите на <rdocs-base>. В командной строке установите следующие переменные окружения.

  • K8S_ROOT со значением <k8s-base>.
  • WEB_ROOT со значением <web-base>.
  • K8S_RELEASE со значением нужной версии документации. Например, если вы хотите собрать документацию для Kubernetes версии 1.17, определите переменную окружения K8S_RELEASE со значением 1.17.

Примеры:

export WEB_ROOT=$(GOPATH)/src/github.com/<your-username>/website
export K8S_ROOT=$(GOPATH)/src/k8s.io/kubernetes
export K8S_RELEASE=1.17

Создание версионированной директории

Скрипт сборки createversiondirs создаёт версионированную директорию и копирует туда конфигурационные файлы справочника kubectl. Имя версионированной директории имеет следующий вид: v<major>_<minor>.

В директории <rdocs-base> выполнение следующий скрипт сборки:

cd <rdocs-base>
make createversiondirs

Переход в тег выпуска в k8s.io/kubernetes

В вашем локальном репозитории <k8s-base> перейдите в ветку с версией Kubernetes, для которой вы хотите получить документацию. Например, если вы хотите сгенерировать документацию для Kubernetes 1.17, перейдите в тег v1.17.0. Убедитесь, что ваша локальная ветка содержит актуальные изменения.

cd <k8s-base>
git checkout v1.17.0
git pull https://github.com/kubernetes/kubernetes v1.17.0

Выполнение кода для генерации документации

В вашей локальной директории <rdocs-base> запустите скрипт сборки copycli. Команда выполняется от пользователя root:

cd <rdocs-base>
make copycli

Команда copycli удаляет временную директорию сборки, генерирует файлы команды kubectl и копирует полученную HTML-страницу справочника команде kubectl и ресурсы в <web-base>.

Проверка сгенерированных файлов

Убедитесь в том, что перечисленные ниже два файлы были сгенерированы:

[ -e "<rdocs-base>/gen-kubectldocs/generators/build/index.html" ] && echo "index.html built" || echo "no index.html"
[ -e "<rdocs-base>/gen-kubectldocs/generators/build/navData.js" ] && echo "navData.js built" || echo "no navData.js"

Проверка скопированных файлов

Убедитесь в том, все сгенерированные файлы были скопированы в вашу директорию <web-base>:

cd <web-base>
git status

В выводе должны перечислены изменённые файлы:

static/docs/reference/generated/kubectl/kubectl-commands.html
static/docs/reference/generated/kubectl/navData.js

Также в выводе должно быть:

static/docs/reference/generated/kubectl/scroll.js
static/docs/reference/generated/kubectl/stylesheet.css
static/docs/reference/generated/kubectl/tabvisibility.js
static/docs/reference/generated/kubectl/node_modules/bootstrap/dist/css/bootstrap.min.css
static/docs/reference/generated/kubectl/node_modules/highlight.js/styles/default.css
static/docs/reference/generated/kubectl/node_modules/jquery.scrollto/jquery.scrollTo.min.js
static/docs/reference/generated/kubectl/node_modules/jquery/dist/jquery.min.js
static/docs/reference/generated/kubectl/node_modules/font-awesome/css/font-awesome.min.css

Проверка документации локально

Соберите документацию Kubernetes в вашей директории <web-base>.

cd <web-base>
make docker-serve

Посмотрите локальную предварительную версию сайта.

Добавление и фиксация изменений в kubernetes/website

Выполните команду git add и git commit для фиксации файлов.

Создание пулреквеста

Создайте пулреквест в репозиторий kubernetes/website. Отслеживайте изменения в пулреквесте и по мере необходимости отвечайте на комментарии рецензента. Не забывайте проверять пулреквест до тех пор, пока он не будет принят.

Спустя несколько минут после принятия вашего пулреквеста, обновленные темы справочника будут отображены в документации.

Что дальше

9.5.5 - Генерация справочных страниц для компонентов и инструментов Kubernetes

На этой странице показывается, как собирать справочные страницы компонентов и инструментов Kubernetes.

Подготовка к работе

Начните с раздела с требованиями в руководстве по быстрому старту.

Для генерации справочных страниц компонентов и инструментов Kubernetes изучите страницу руководство по быстрому старту в справочной документации.

Что дальше

9.6 - Локализация документации Kubernetes

На этой странице рассказывается, как локализовать документацию на разные языки.

Начало работы

Из-за того, что участники не могут одобрять собственные пулреквесты, нужно как минимум два участника для инициализации локализацию.

Все команды по локализации должны быть самодостаточными. Это означает, что мы с радостью разместим вашу работу, но мы не можем сделать перевод за вас.

Определение двухбуквенного кода языка

Первым делом ознакомьтесь со стандартом ISO 639-1, чтобы найти двухбуквенный код страны для вашей локализации. Например, двухбуквенный код для корейского языка будет ko.

Создание копии репозитория

Для начала создайте собственную копию репозитория оригинального репозитория kubernetes/website.

Затем клонируйте свою копию репозитория и перейдите в неё с помощью команды cd:

git clone https://github.com/<username>/website
cd website

Создание пулреквеста

Далее откройте пулреквест (PR) с локализацией в репозиторий kubernetes/website.

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

В качестве примера добавления новой локализации, изучите PR, который добавляет документацию на французском.

Вступление в GitHub-организацию Kubernetes

Как только, как вы открыли PR с локализацией, вы можете стать членом организации Kubernetes на GitHub. Каждый член команды должен подать запрос на членство в организации в репозитории kubernetes/org.

Добавление команды локализации на GitHub

Теперь нужно добавить вашу команду локализации Kubernetes в файл sig-docs/teams.yaml. Для примера добавления команды локализации можете посмотреть PR, добавляющий испанскую команду локализации.

Члены @kubernetes/sig-docs-**-owners — могут одобрять PR, которые изменяют файлы внутри (и только там) директории с локализацией: /content/**/.

Для каждой локализации группа @kubernetes/sig-docs-**-reviews служит для автоматизации выбора проверяющих новых PR.

Члены @kubernetes/website-maintainers могут создавать новые ветки для координации работ по переводу.

Члены @kubernetes/website-milestone-maintainers могут использовать Prow-команду /milestone для контрольных точек для ишью или PR.

Настройка рабочего процесса

Затем добавьте собственную GitHub-метку для вашей локализации в репозиторий kubernetes/test-infra. Метка позволяет фильтровать ишью и пулреквесты по конкретному языку.

Смотрите пример добавления метки для итальянского языка.

Поиск сообщества

Сообщите участниками группы Kubernetes SIG Docs о вашем намерении перевода документации! Подключайтесь к Slack-каналу SIG Docs. Остальные команды по локализации с радостью помогут вам начать и ответят на любые вопросы.

Вы также можете создать Slack-канал для своей локализации в репозитории kubernetes/community. Для примера посмотрите PR с добавлением Slack-канала для индонезийского и португальского языков.

Необходимый минимум контента

Изменение конфигурации сайта

Сайт Kubernetes использует использует фреймворк Hugo. Конфигурация сайта у Hugo находится в файле hugo.toml. Для поддержки новой локализации вам нужно отредактировать файл hugo.toml.

Добавьте блок с конфигурацией для нового языка в hugo.toml после существующего блока [languages]. Например, конфигурация для немецкой локализации будет выглядить так:

[languages.de]
title = "Kubernetes"
description = "Produktionsreife Container-Verwaltung"
languageName = "Deutsch"
contentDir = "content/de"
weight = 3

При выбора значения для параметра weight в блока найдите языковой блок с наибольшим значением и прибавьте к нему 1.

Для получения дополнительной информации о многоязычной поддержке в Hugo посмотрите страницу "Multilingual Mode".

Добавление директории для локализации

Добавьте директорию для вашего языка в директорию content репозитория. Например, двухбуквенный код для немецкого будет de:

mkdir content/de

Перевод норм поведения сообщества

Откройте PR в репозитории cncf/foundation и добавьте перевод норм поведения на своём языке.

Добавление перевода для файла README

Чтобы помочь другим участников локализации добавьте новый файл README-**.md в корневую директорию k/website, где ** означает двухбуквенный код языка. Например, немецкий файл README будет именоваться как README-de.md.

Подготовьте рекомендации для участников в файле для конкретной локализации README-**.md. В этом файле должна быть точно такая же информация, что и в оригинальном README.md ту же информацию, включая также:

  • Контактное лицо проекта локализации
  • Любая другая информация, относящаяся к локализации

После создания перевода файла README добавьте ссылку на файл в основной английский файл README.md и добавьте контактную информацию на английском языке. Вы можете указать логин на GitHub, адрес электронной почты, Slack-канал или какой-нибудь способ связи. Вам также нужно добавить ссылку на перевод норм поведения в сообществе.

Настройка файлов OWNERS

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

Дополнительную информацию о файле OWNERS вы можете получить по ссылке go.k8s.io/owners.

Испанский файл OWNERS с кодом языка es выглядит следующим образом:

# See the OWNERS docs at https://go.k8s.io/owners

# This is the localization project for Spanish.
# Teams and members are visible at https://github.com/orgs/kubernetes/teams.

reviewers:
- sig-docs-es-reviews

approvers:
- sig-docs-es-owners

labels:
- language/es

После добавления файла OWNERS в определенном языке нужно обновить корневой файл OWNERS_ALIASES, добавив новые команды локализации Kubernetes — sig-docs-**-owners и sig-docs-**-reviews.

Для каждой команды добавьте список GitHub-пользователей из раздела Добавление команды локализации на GitHub, перечислите их в алфавитном порядке.

--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -48,6 +48,14 @@ aliases:
     - stewart-yu
     - xiangpengzhao
     - zhangxiaoyu-zidif
+  sig-docs-es-owners: # Admins for Spanish content
+    - alexbrand
+    - raelga
+  sig-docs-es-reviews: # PR reviews for Spanish content
+    - alexbrand
+    - electrocucaracha
+    - glo-pena
+    - raelga
   sig-docs-fr-owners: # Admins for French content
     - perriea
     - remyleone

Перевод контента

Локализация всей документации Kubernetes — колоссальная задача. Вполне нормально начать переводить что-то небольшое, а затем со временем делать перевод больших страниц.

Как минимум, все локализации должны включать:

Описание URL-адреса
Главная Все заголовки и подзаголовки URL-адресов
Установка Все заголовки и подзаголовки URL-адресов
Руководства Основы Kubernetes, Привет, Minikube
Надписи на сайте Все надписи сайта в собственном TOML-файле

Переведенные файлы должны находиться в собственной директории content/**/, но в во всём остальном должны быть такие, как и оригинал на английском. Например, чтобы подготовить Основы Kubernetes для перевода на немецкий язык, создайте поддиректорию в директории content/de/ и скопируйте туда оригинальный английский файл:

mkdir -p content/de/docs/tutorials
cp content/en/docs/tutorials/kubernetes-basics.md content/de/docs/tutorials/kubernetes-basics.md

С помощью соответствующих инструментов можно ускорить процесс перевода. Например, у некоторых редакторов есть плагины для быстрого перевода текста.

To ensure accuracy in grammar and meaning, members of your localization team should carefully review all machine-generated translations before publishing.

Исходные файлы

Локализация должна исходить из самой последней версии оригинальной документации — v1.31.

Для того, чтобы получить исходные файлы последней версии:

  1. Перейдите в репозиторий сайта Kubernetes по адресу https://github.com/kubernetes/website.
  2. Выберите ветку release-1.X самой последней версии.

Текущая последняя версия v1.31, поэтому веткой для этого релиза будет release-1.31.

Сообщения на сайте в i18n/

Локализации должны включать содержимое файла i18n/en.toml в новый языковой файл. В качестве примера рассмотрим немецкую локализацию: i18n/de.toml.

Добавьте новый файл локализации в i18n/. Например, для немецкой локализации (de):

cp i18n/en.toml i18n/de.toml

Затем переведите значение каждого сообщения:

[docs_label_i_am]
other = "ICH BIN..."

Локализация сообщений сайта позволяет изменить сообщения, используемые на всём сайте, к примеру, текст авторских прав в футере на каждой странице.

Глоссарий и руководство по оформления для языка

У некоторых языковых команд есть собственные руководства по оформлению и глоссарий. Например, посмотрите руководство корейской локализации.

Стратегия работы с ветками

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

Совместная работа в рабочих ветках может быть организована следующим образом:

  1. Член команды @kubernetes/website-maintainers создает ветку из оригинальной ветки на https://github.com/kubernetes/website.

    После того, как вы добавите свою команду локализации в репозиторий kubernetes/org, ваши утверждающие из группы будет присоединены к команде @kubernetes/website-maintainers.

    Мы рекомендуем следующую схему именования веток:

    dev-<оригинальная версия>-<код языка>.<контрольная точка команды>

    Например, утверждающий в немецкой группе локализации открывает рабочую ветку dev-1.12-de.1 непосредственно в репозитории kubernetes/website из ветки для Kubernetes v1.12.

  2. Остальные участники создают новые ветки с изменениями на основе рабочей ветки.

    Например, участник немецкой группы локализации открывает пулреквест с изменениями в kubernetes:dev-1.12-de.1 из username:local-branch-name.

  3. Утверждающий проверяет изменения и объединяют ветки в рабочую веткой.

  4. Периодически утверждающий объединяет рабочую ветку в оригинальную ветку, открывая и принимая новый пулреквест. Не забудьте объединить (squash) коммиты перед слиянием пулреквеста.

Повторяйте шаги 1-4 до тех пор, пока не будет завершена локализация. Например, по мере работы над немецким переводом, рабочие ветки будут меняться: dev-1.12-de.2, dev-1.12-de.3 и т.д.

Команды должны объединять переведённый контент в ту же ветку выпуска, из которой она была создана. Например, рабочая ветка, созданная из версии release-1.31, должна сливаться с веткой версии 1.17.

Утверждающему следует поддерживать рабочую веку в актуальном состоянии в соответствии с оригинальной веткой, разрешая конфликты при слиянии. Чем дольше существует рабочая ветки, тем больше потребуется сил для ее поддержки. Поэтому лучше как можно быстрее сливать рабочую ветку и открывать новую, а не поддерживать только одну-единственную в течение длительного времени.

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

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

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

Участие в работе над оригинальным контентом

SIG Docs приветствует участие и дополнения в английскую документацию.

Помощь для существующей локализации

Вы также можете добавлять или улучшать контент в уже существующей локализации. Обратитесь к соответствующему Slack-каналу для этого и начинайте помогать через PR.

Что дальше

Как только локализация будет соответствовать требованиям установленного рабочего процесса и содержать требуемый минимум контента, группа SIG Docs:

9.7 - Участие в SIG Docs

SIG Docs — это одна из специальных групп в проекте Kubernetes, которая занимается написанием, обновлением и поддержкой документации Kubernetes в целом. Перейдите на страницу про SIG Docs в GitHub-репозитории, чтобы узнать подробную информацию об этой группе.

SIG Docs активно принимает правки и дополнения в документацию, так и отзывы от всех участников. Любой может открыть пулреквест (PR), либо сообщить про ошибки в тексте или просто прокомментировать выполняемые пулреквесты.

Вы также можете стать членом, рецензентом или утверждающим. Эти роли расширяют ваши возможности, но и предлагают выполнение определенных обязанностей по рассмотрению и принятию изменений. Изучите содержимого файла community-membership в директории сообщества репозитория, чтобы узнать про членство в сообществе Kubernetes. В остальной части этой страницы кратко рассматривается функционирование ролей в группе SIG Docs, которая в совокупности отвечает за поддержание одного из самой публичной части Kubernetes — сайта и документации Kubernetes.

Роли и обязанности

  • Любой может поучаствовать в документацию Kubernetes. Для этого вам нужно только подписать CLA и иметь аккаунт на GitHub.
  • Члены организации Kubernetes — участники, которые активно занимаются пректом Kubernetes, как правило, открывая пулреквесты с принятыми изменениями. Посмотрите файл Членство в сообществе, чтобы узнать про необходимые условия для членства.
  • Рецензент SIG Docs — член организации Kubernetes, который занимается проверкой пулреквестов и поэтому был добавлен в соответствующую группу на GitHub и в файлы OWNERS в GitHub-репозитории.
  • Утверждающий SIG Docs — член организации с хорошей репутацией, который подтвердил неизменную приверженность проекту. Утверждающий может принимать пулреквесты и публиковаться от имени организации Kubernetes. Утверждающие также могут представлять группу SIG Docs в более крупном сообществе Kubernetes. Некоторые из задач утверждающего SIG Docs, например, координация новой версии, требуют значительных затрат по времени.

Любой

Кто угодно может сделать следующее:

  • Открыть ишью на GitHub в любую часть Kubernetes, включая документацию.
  • Дать рекомендацию или предложить улучшение в пулреквесте.
  • Предложить идею по улучшению в Slack](http://slack.k8s.io/) или в список рассылки SIG Docs.
  • Использовать команду /lgtm (сокращение от "looks good to me") бота Prow, чтобы одобрить изменения в пулреквесте.

После подписания CLA каждый также может:

  • Открыть пулреквест, чтобы улучшить существующий текст, либо что-то новое, или написать запись в блоге или описать пример использования.

Члены

Члены — это участники проекта Kubernetes, которые удовлетворяют критериям членства. SIG Docs ценит участие всех членов сообщества Kubernetes и часто просит дать обратную связь от членов других SIG-групп для соблюдения технической точности.

Любой член организации Kubernetes может сделать следующее:

  • Всё то же самое, что и любой другой участник
  • Использовать команду /lgtm в комментарии для автоматического добавления метки LGTM (looks good to me) для пулреквеста.
  • Использовать команду /hold в комментарии для блокировки слияния пулреквеста, если он имеет метку LGTM и другие утверждающие метки.
  • Использовать команду /assign в комментарии, чтобы назначить рецензента, который будет проверят пулреквест.

Членство

После того, как вы успешно отправили не менее 5 содержательных пулреквестов, вы можете стать членом организации Kubernetes. Следуйте нижеперечисленным шагам:

  1. Найдите двух рецензентов или утверждающих, которые поддержат ваше членство.

    Запросите спонсорство в канале #sig-docs Kubernetes Slack или в списке рассылки SIG Docs.

  2. Создайте ишью в репозитории kubernetes/org, чтобы запросить членство. Заполните шаблон, предварительно изучив правила членства в сообществе.

  3. Сообщите вашим спонсорам про вашу заявку на GitHub, упомянув их в ней на GitHub (добавив комментарий в форме @<GitHub-username>), либо отправив им ссылку напрямую, чтобы они могли добавить проголосовать ( +1).

  4. Когда ваше членство будет одобрено, член административной команды на GitHub, назначенный для обработки вашего пулреквеста, обновит ишью на GitHub, чтобы показать одобрение, а затем закроет проблему GitHub. Поздравляем, теперь вы член организации!

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

Рецензенты

Рецензенты — это члены GitHub-группы @kubernetes/sig-docs-pr-reviews. Рецензенты проверяют пулреквесты документации и оставлять обратную связь по предлагаемым изменениях. Рецензенты могут:

  • Делать всё то, что и любой участник и члены
  • Писать документацию для новой функциональности
  • Назначать метки и классифицировать ишью
  • Проверять пулреквесты и оставлять обязательные для выполнения рекомендации
  • Создавайте диаграммы, графику и встраиваемые скринкасты и видеоролики
  • Заниматься локализацией
  • Редактировать строки в коде, относящиеся к интерфейсу пользователя
  • Улучшать комментарии к коду

Выбор рецензентов для проверки пулреквестов

Процесс выбора рецензентов для проверки пулреквестов автоматизирован. Вы можете попросить проверку у определенного рецензента, написав комментарий в пулреквесте: /assign [@_github_handle]. Чтобы показать, что пулреквест является правильным с технической точки зрения и не требует дополнительных изменений, рецензент добавляет комментарий с командой /lgtm.

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

Также для совсем небольшого изменения, или такого, которое не требует технического рассмотрения, утверждающие SIG Docs одобрить его через комментарий с /lgtm.

Комментарий с /approve от рецензента игнорируется ботом и поэтому соответствующая метка не добавится к пулреквесту.

Как стать рецензентом

Если вы соответствуете требованием, то можете стать рецензентом SIG Docs. Рецензенты в других SIG-группах должны подать новую заявку для получения статуса рецензента в SIG Docs.

Для отправки заявки откройте пулреквест с добавлением самого себя в секцию reviewers корневого файла OWNERS в репозитории kubernetes/website. Запросите проверку вашего пулреквеста одному или нескольким текущим утверждающим в группе SIG Docs.

Если ваш пулреквест одобрен, вы становитесь рецензентом SIG Docs. Теперь бот K8s-ci-robot будет назначать и предлагать вас в качестве рецензента для проверки новых пулреквестов.

После того, как ваша кандидатура будет одобрена, попросите текущего утверждающего SIG Docs добавить вас в GitHub-группу @kubernetes/sig-docs-pr-reviews. Только члены GitHub-группы kubernetes-website-admins могут добавлять новых членов в какую-либо другую группу.

Утверждающие

Утверждающие — члены GitHub-группы @kubernetes/sig-docs-maintainers. Перейдите в раздел Команды и группы в SIG Docs для получения дополнительной информации.

Утверждающие могут делать следующее:

  • Все то же, что и обычные участники, члены и рецензенты
  • Публиковать изменения от других участников путём одобрения и слияния пулреквестов с помощью комментария с командой /approve. Если кто-то оставляет комментарий, не являясь при этом официальным рецензентом, бот проигнорирует такой одобряющий комментарий.
  • Примите участие в работе команды выпуска новых версий Kubernetes как представитель документации
  • Предлагать улучшения в руководстве по оформлению
  • Предлагать улучшения для тестов документации
  • Предлагать улучшения для сайта Kubernetes или других инструментов

Если у PR есть метка /lgtm, или если утверждающий оставляет комментарий с командной с /lgtm, PR автоматически сливается. Утверждающий SIG Docs должен оставлять комментарий с /lgtm только для тех изменений, которые не нуждаются в дополнительном техническом обзоре.

Как стать утверждающим

Если вы соответствуете требованием, вы можете стать утверждающим SIG Docs. Утверждающие в других SIG-группах должны подать новую заявку для получения статуса утверждающего в SIG Docs.

Для отправки заявки откройте пулреквест с добавлением самого себя в секцию approvers корневого файла OWNERS в репозитории kubernetes/website. Запросите проверку вашего пулреквеста одному или нескольким текущим утверждающим в группе SIG Docs.

Если ваш пулреквест одобрен, вы становитесь утверждающим SIG Docs. Теперь бот K8s-ci-robot будет назначать и предлагать вас в качестве рецензента для проверки новых пулреквестов.

После того, как ваша кандидатура будет одобрена, попросите текущего утверждающего SIG Docs добавить вас в GitHub-группу@kubernetes/sig-docs-maintainers. Только члены GitHub-группы kubernetes-website-admins могут добавлять новых членов в какую-либо другую группу.

Обязанности утверждающего

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

  • Утверждающие могут использовать команду /approve, которая сливает PR в репозиторий.

    Невнимательное слияние может нарушить работу сайта, поэтому имейте это в виду, когда объединяете какой-либо пулреквест.

  • Убедитесь, что предлагаемые изменения соответствуют правилам по содержанию.

    Если вы сомневаетесь или вы не уверены в чем-либо, не стесняйтесь обращаться для дополнительной проверки.

  • Проверьте, что тесты на Netlify пройдены успешно, перед тем как написать комментарий с /approve в PR.

    Netlify tests must pass before approving
  • Перед одобрением пулреквеста перейдите на предварительный просмотр сайта на Netlify для сделанных изменений в PR, и убедитесь, что всё содержимое выглядит хорошо.

  • Участвуйте в графике дежурства смотрителя PR, чтобы вас назначили дежурным проверяющим на неделю. SIG Docs ожидает, что все утверждающие примут участие в этом графике. За подробностям обратитесь к странице Be the PR Wrangler for a week.

Председатель SIG Docs

Каждая SIG-группа, включая SIG Docs, выбирает одного или нескольких членов из своей SIG-группы в качестве председателей. Это координаторы между SIG Docs и другими подразделениями в организации Kubernetes. От таких людей требуются обширные знания о структуре проекта Kubernetes в целом и как функционирует группа SIG Docs внутри неё. Смотрите раздел Руководство, чтобы узнать текущий список председателей.

Команды SIG Docs и автоматизация

Автоматизация в SIG Docs основывается на двух разных механизмах: группы GitHub и файлы OWNERS.

GitHub-группы

Группа SIG Docs представлена двумя командами на GitHub:

На каждую из них можно сослаться по имени (@name) в комментариях на GitHub, чтобы общаться со всеми участниками в этой группе.

Эти команды пересекаются, но назначение у них разное. Для назначения людей на ишью, пулреквестов и поддержки одобрений в PR бот использует информацию из файлов OWNERS.

Файлы OWNERS и вступительная часть

Проект Kubernetes использует инструмент автоматизации под названием prow, чтобы автоматизировать процесс, связанный с ишью и пулреквестами на GitHub. Репозиторий сайта Kubernetes использует два плагина prow:

  • blunderbuss
  • approve

Все эти плагины используют файлы OWNERS и OWNERS_ALIASES в корневой директории GitHub-репозитория kubernetes/website, чтобы контролировать работу prow по всему репозиторию.

Файл OWNERS содержит список людей, которые являются рецензентами и утверждающими в SIG Docs. Файлы OWNERS также может быть в поддиректориях и могут переопределять тех, кто может выступать в качестве рецензента или утверждающего в изменениях файлов этой директории и её поддиректорий. Для получения дополнительной информации о файлах OWNERS в целом, перейдите в OWNERS.

Кроме того, в каждом Markdown-файле могут быть указаны рецензенты и утверждающие в так называемой вступительной части (front-matter) в виде логинов участников или имён групп на GitHub.

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

Как происходит слияние

Когда пулреквест сливается в действующую ветку сайта (в данный момент это master), содержимое публикуется и становится общедоступным. Для обеспечения высокого качества публикуемого нами контента, мы доверяем слияние пулреквестов утверждающим SIG Docs. Ниже описан этот процесс.

  • Когда пулреквест имеет метки lgtm и approve, при этом у него нет метки hold, и то же время все тесты успешно проходят, то пулреквест автоматически сливается.
  • Члены организации Kubernetes и утверждающие SIG Docs могут оставлять комментарии со специальными командами, которые блокирует автоматическое объединение пулреквеста (добавление комментарий с текстом /hold или удаление ранее установленной метки /lgtm).
  • Любой участник Kubernetes может добавить метку lgtm, добавив комментарий, включающий в себя /lgtm.
  • Только утверждающие SIG Docs могут слить пулреквест путём добавления комментария с /approve. Некоторые утверждающие также играют дополнительные роли, например, дежурного по PR или председателя SIG Docs.

Что дальше

Для получения дополнительной информации про участие в документации Kubernetes, посмотрите следующие страницы: