Kubernetes
K8s Top Commands
Список nodes
kubectl get nodes
# kubectl get nodes -o wide
Создать namespace
kubectl create ns my-ns
Сохранить манифест
kubectl get ns my-ns -o yaml > ns.yaml
Применить манифест
kubectl apply -f ns.yaml
Подробное info
kubectl describe ns my-ns
Добавить label
kubectl label ns my-ns kubernetes=rulezz
Добавить аннотацию
kubectl annotate ns my-ns annotations=likelabels
Установка K8s
Авто развертывание k8s кластера
Terraform создание VMs
Ресурсы облака Yandex.Cloud на Ubuntu 24.04 server (2-CPU/4gb-RAM/30gb-Disk)
main.tf
terraform {
required_providers {
yandex = {
source = "yandex-cloud/yandex"
}
local = {
source = "hashicorp/local"
}
}
}
provider "yandex" {
service_account_key_file = "${file("~/.ssh/yc.service.key")}"
folder_id = "b1gtv3uhmd1feqdajugp"
zone = "ru-central1-a"
}
# Актуальный образ Ubuntu 24.04 LTS
data "yandex_compute_image" "last_ubuntu" {
family = "ubuntu-24-04-lts"
}
# Существующая подсеть, в которую разместятся все ВМ
data "yandex_vpc_subnet" "default_a" {
name = "default-ru-central1-a"
}
locals {
task_name = "kube"
worker_names = ["node01", "node02", "node03"]
ssh_pub_key = file("~/.ssh/yc.pub")
ssh_priv_key = "~/.ssh/yc"
}
# Control-plane нода (inventory-имя — kube-master)
resource "yandex_compute_instance" "cplane01" {
name = "${local.task_name}-cplane01"
platform_id = "standard-v3"
resources {
cores = 2
memory = 4
}
boot_disk {
initialize_params {
image_id = data.yandex_compute_image.last_ubuntu.id
size = 30
}
}
labels = {
task_name = local.task_name
user_email = "xeonmp22_at_gmail.com"
role = "control-plane"
}
network_interface {
subnet_id = data.yandex_vpc_subnet.default_a.subnet_id
nat = true
}
metadata = {
ssh-keys = "ubuntu:${local.ssh_pub_key}"
}
}
# 3 worker-ноды (node01..node03), создаются циклом по local.worker_names
resource "yandex_compute_instance" "workers" {
for_each = toset(local.worker_names)
name = "${local.task_name}-${each.key}"
platform_id = "standard-v3"
resources {
cores = 2
memory = 4
}
boot_disk {
initialize_params {
image_id = data.yandex_compute_image.last_ubuntu.id
size = 30
}
}
labels = {
task_name = local.task_name
user_email = "xeonmp22_at_gmail.com"
role = "worker"
}
network_interface {
subnet_id = data.yandex_vpc_subnet.default_a.subnet_id
nat = true
}
metadata = {
ssh-keys = "ubuntu:${local.ssh_pub_key}"
}
}
# Генерирует inventory.ini с реальными IP всех 4 ВМ (шаблон — inventory.tpl)
resource "local_file" "ansible_inventory" {
filename = "${path.module}/inventory.ini"
content = templatefile("${path.module}/inventory.tpl", {
master_ip = yandex_compute_instance.cplane01.network_interface.0.nat_ip_address
master_internal_ip = yandex_compute_instance.cplane01.network_interface.0.ip_address
workers = yandex_compute_instance.workers
ssh_priv_key = local.ssh_priv_key
})
}
# Ждёт готовности SSH на control-plane перед запуском Ansible
resource "null_resource" "wait_ssh_master" {
depends_on = [yandex_compute_instance.cplane01]
connection {
type = "ssh"
user = "ubuntu"
host = yandex_compute_instance.cplane01.network_interface.0.nat_ip_address
private_key = file(local.ssh_priv_key)
timeout = "7m"
}
provisioner "remote-exec" {
inline = ["echo check connection"]
}
}
# Ждёт готовности SSH на каждой worker-ноде перед запуском Ansible
resource "null_resource" "wait_ssh_workers" {
for_each = yandex_compute_instance.workers
depends_on = [yandex_compute_instance.workers]
connection {
type = "ssh"
user = "ubuntu"
host = each.value.network_interface.0.nat_ip_address
private_key = file(local.ssh_priv_key)
timeout = "7m"
}
provisioner "remote-exec" {
inline = ["echo check connection"]
}
}
# Устанавливает Ansible-коллекции
resource "null_resource" "ansible_collections" {
provisioner "local-exec" {
command = "ansible-galaxy collection install community.general ansible.posix"
}
}
# Единый запуск playbook.yml сразу на все 4 ноды (master + workers)
resource "null_resource" "provision_cluster" {
depends_on = [
null_resource.ansible_collections,
local_file.ansible_inventory,
null_resource.wait_ssh_master,
null_resource.wait_ssh_workers,
]
provisioner "local-exec" {
command = "ansible-playbook -i ${local_file.ansible_inventory.filename} playbook.yml"
}
}
output "cplane01_internal_ip" {
value = yandex_compute_instance.cplane01.network_interface.0.ip_address
}
output "cplane01_external_ip" {
value = yandex_compute_instance.cplane01.network_interface.0.nat_ip_address
}
output "workers_ips" {
value = {
for k, v in yandex_compute_instance.workers : k => {
internal = v.network_interface.0.ip_address
external = v.network_interface.0.nat_ip_address
}
}
}
inventory.tpl
[kube-master]
kube-master ansible_host=${master_ip} internal_ip=${master_internal_ip}
[kube-node]
%{ for name, inst in workers ~}
${name} ansible_host=${inst.network_interface.0.nat_ip_address}
%{ endfor ~}
[k8s_cluster:children]
kube-master
kube-node
[k8s_cluster:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=${ssh_priv_key}
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
Ansible Пост-Настройка VMs
playbook.yml
---
- name: Common OS / kubeadm / kubelet / kubectl prerequisites (все ноды)
hosts: k8s_cluster
become: true
vars:
k8s_minor_version: "1.37"
tasks:
- name: Common prerequisites
ansible.builtin.import_tasks: common-prereqs.yml
handlers:
- name: Restart containerd
ansible.builtin.systemd:
name: containerd
state: restarted
- name: Initialize control-plane and get join command
hosts: kube-master
become: true
vars:
pod_network_cidr: "10.244.0.0/16"
tasks:
- name: Check whether the cluster is already initialized
ansible.builtin.stat:
path: /etc/kubernetes/admin.conf
register: admin_conf
- name: kubeadm init
ansible.builtin.command: >
kubeadm init
--apiserver-advertise-address={{ internal_ip }}
--pod-network-cidr={{ pod_network_cidr }}
when: not admin_conf.stat.exists
- name: Create .kube directory for ubuntu user
ansible.builtin.file:
path: /home/ubuntu/.kube
state: directory
owner: ubuntu
group: ubuntu
mode: "0700"
- name: Copy admin.conf into ubuntu kubeconfig
ansible.builtin.copy:
src: /etc/kubernetes/admin.conf
dest: /home/ubuntu/.kube/config
remote_src: true
owner: ubuntu
group: ubuntu
mode: "0600"
- name: Apply Flannel CNI manifest
become_user: ubuntu
environment:
KUBECONFIG: /home/ubuntu/.kube/config
ansible.builtin.command: >
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
- name: Wait for control-plane node to become Ready
become_user: ubuntu
environment:
KUBECONFIG: /home/ubuntu/.kube/config
ansible.builtin.shell: >
kubectl get nodes --no-headers | awk '{print $2}' | grep -q '^Ready$'
register: node_ready
retries: 20
delay: 10
until: node_ready.rc == 0
changed_when: false
- name: Getting join command
ansible.builtin.shell: kubeadm token create --print-join-command
register: k8s_token
- name: Setting kubernetes worker nodes
hosts: kube-node
become: true
gather_facts: false
tasks:
- name: Check whether this node already joined the cluster
ansible.builtin.stat:
path: /etc/kubernetes/kubelet.conf
register: kubelet_conf
- name: Joining cluster
ansible.builtin.shell: "{{ hostvars['kube-master']['k8s_token'].stdout }}"
when: not kubelet_conf.stat.exists
common-prereqs.yml
- name: Disable swap
ansible.builtin.command: swapoff -a
changed_when: false
- name: Remove swap entry from /etc/fstab
ansible.builtin.replace:
path: /etc/fstab
regexp: '^([^#].*\sswap\s.*)$'
replace: '# \1'
- name: Load kernel modules (overlay, br_netfilter)
community.general.modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
- name: Persist kernel modules across reboots
ansible.builtin.copy:
dest: /etc/modules-load.d/k8s.conf
content: |
overlay
br_netfilter
- name: Set sysctl params required by Kubernetes networking
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_file: /etc/sysctl.d/k8s.conf
reload: true
loop:
- { name: "net.bridge.bridge-nf-call-iptables", value: "1" }
- { name: "net.bridge.bridge-nf-call-ip6tables", value: "1" }
- { name: "net.ipv4.ip_forward", value: "1" }
- name: Install containerd
ansible.builtin.apt:
name: containerd
update_cache: true
state: present
- name: Ensure /etc/containerd exists
ansible.builtin.file:
path: /etc/containerd
state: directory
- name: Generate default containerd config (if not present)
ansible.builtin.shell: containerd config default > /etc/containerd/config.toml
args:
creates: /etc/containerd/config.toml
- name: Enable SystemdCgroup in containerd config
ansible.builtin.replace:
path: /etc/containerd/config.toml
regexp: "SystemdCgroup = false"
replace: "SystemdCgroup = true"
notify: Restart containerd
- name: Ensure containerd is started and enabled
ansible.builtin.systemd:
name: containerd
state: started
enabled: true
- name: Install packages required to add the Kubernetes apt repo
ansible.builtin.apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gpg
state: present
- name: Create /etc/apt/keyrings directory
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
mode: "0755"
- name: Download Kubernetes apt signing key
ansible.builtin.get_url:
url: "https://pkgs.k8s.io/core:/stable:/v{{ k8s_minor_version }}/deb/Release.key"
dest: /tmp/k8s-release.key
mode: "0644"
- name: Dearmor key into apt keyring
ansible.builtin.shell: gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg /tmp/k8s-release.key
args:
creates: /etc/apt/keyrings/kubernetes-apt-keyring.gpg
- name: Add Kubernetes apt repository
ansible.builtin.copy:
dest: /etc/apt/sources.list.d/kubernetes.list
content: "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v{{ k8s_minor_version }}/deb/ /\n"
- name: Install kubelet, kubeadm, kubectl
ansible.builtin.apt:
name:
- kubelet
- kubeadm
- kubectl
update_cache: true
state: present
- name: Hold kubelet/kubeadm/kubectl at installed version
ansible.builtin.dpkg_selections:
name: "{{ item }}"
selection: hold
loop:
- kubelet
- kubeadm
- kubectl
Ручная установка k8s кластера
| Hypervisor | VM/Node | Role | IP |
| srv-01 | vm-01 | control-plane | 192.168.1.10 |
| srv-01 | vm-02 | worker | 192.168.1.11 |
| srv-02 | vm-03 | worker | 192.168.1.12 |
| srv-02 | vm-04 | worker | 192.168.1.13 |
Требуется полная сетевая связность между хостами-гипервизорами.
VM-01/02/03/04
Подготовка ОС
Уникальные hostname / MAC / product_uuid
sudo hostnamectl set-hostname vm-01 # своё имя на каждой ноде
ip link # проверка MAC
sudo cat /sys/class/dmi/id/product_uuid # проверка uuid
Прописать /etc/hosts со всеми 4 IP+именами (или настроить DNS).
Отключение swap
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
Включение Модулей ядра и sysctl
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
Диапазоны открытых портов:Control-plane: 6443, 2379-2380, 10250, 10259, 10257
Workers: 10250, 30000-32767
Установка containerd
sudo apt-get update
sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
Установка kubeadm, kubelet, kubectl
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
Замените v1.34 на актуальную минорную версию (Kubernetes Releases)
VM-01
Инициализация control-plane
sudo kubeadm init \
--apiserver-advertise-address=192.168.1.10 \
--pod-network-cidr=10.244.0.0/16
Сохраните tokenиз команды kubeadm join ...
Повторная генерация: kubeadm token create --print-join-command
Настройка kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Сетевой плагин CNI
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubectl get nodes — control-plane должна перейти в Ready
VM-02/03/04
Подключение workers
sudo kubeadm join 192.168.1.10:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
TEST k8s кластера
На VM-01 controller-manager
kubectl get nodes -o wide
kubectl get pods -A
Успешный результат
All NODEs — Ready
System PODs (coredns, kube-proxy, CNI) — Running
Для управления с другой машины скопируйте ~/.kube/config с vm-01
Схемы k8s