K8s на bare metal

Чуть-чуть про грабли при развёртывании k8s-кластера

Автор: Олег Бобок / @Нетология групп

Одна нода, менеджмент, systemd

Systemd умеет:

Запускать приложения в нужном порядке, когда они вам нужны;

мониторить их, перезапускать, если они упали;

контроллировать и лимитировать расход ресурсов ими;

монтировать разделы;

конфигурировать сетевые устройства;

запускать задачи по заданному расписанию;

Systemd - монстр!

Systemd - монстр монолит!

А что же с Kubernetes?

Всё, кроме нескольких подов, относящихся к control plane, можно заменить!

Что относится к control plane?

  • kube-apiserver
  • kube-scheduler
  • kube-controller-manager
  • cloud-controller-manager (мы же про bare metal)
  • kube-proxy

Что можно заменить?

...
...

Всё остальное!

Аддоны kubernetes

  • DNS
  • Container Resource Monitoring
  • Cluster Level Logging
  • И вдобавок:

  • Ingress controllers
  • Куча всего

Что необходимо скачать, чтобы развернуть k8s-кластер?

  • kubelet – поддерживает жизнь кластера
  • kubeadm – удобен для развёртывания и обновления кластера

Чего ради всё это?

  • Балансировка и афинность сессий
  • Метрики через prometheus/grafana
  • Закрыть RPC

Как сделано в итоге?

  • Балансировка и афинность сессий - ipvs на kube-proxy
  • Метрики через prometheus/grafana - coreos-charts (helm)
  • Закрыть RPC - calico

Обычное развёртывание


$ kubeadm init
$ kubeadm join server:port --token secret-token \
--discovery-token-ca-cert-hash sha256:ca-cert-hash
						

Чуточку кастомное развертывание


$ kubeadm init --config config.yml
$ kubeadm join server:port --token secret-token \
--discovery-token-ca-cert-hash sha256:ca-cert-hash
						

На чём держать?

Container linux (aka CoreOS)

  • Простой провижнинг
  • Минималистичный

Сеть


networkd:
  units:
    - name: 00-eth1.network
      contents: |
        [Match]
        Name=eth1

        [Network]
        Address=10.0.0.2/8
        				

Разбивка дисков


storage:
  disks:
  - device: '/dev/vdb'
      wipe_table: true
      partitions:
        - label: 'STORAGE'
          number: 1
          start: 0
          size: 0
          type_guid: linux_filesystem_data
          				

Форматирование дисков


  filesystems:
    - name: 'STORAGE'
      mount:
        device: '/dev/disk/by-partlabel/STORAGE'
        format: 'xfs'
        wipe_filesystem: true
        label: 'STORAGE'
        				

Файлы


  files:
    - filesystem: 'root'
      path: '/etc/modules-load.d/nf_conntrack_ipv4.conf'
      mode: 0644
      contents:
        inline: 'nf_conntrack_ipv4'
    - filesystem: root
      path: /etc/default/kubelet
      mode: 0644
      owner: root
      group: root
      contents:
        inline: "KUBELET_EXTRA_ARGS=--authentication-token-webhook"
        				

Systemd


systemd:
  units:
    - name: storage.mount
      enabled: true
      contents: |
        [Mount]
        What=/dev/disk/by-label/STORAGE
        Where=/storage
        Type=xfs

        [Install]
        WantedBy=local-fs.target

						

А что насчет самого конфига k8s?

Вот он!


apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
api:
  advertiseAddress: 10.0.0.2
apiServerCertSANs:
- 10.0.0.2
- 10.12.0.10
- example.com
kubeProxy:
  config:
    mode: ipvs
    ipvs:
      SyncPeriod: '15s'
						

И ещё чуть-чуть


networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.12.0.0/16
  podSubnet: 192.168.0.0/16
kubeletConfiguration:
  feature-gates: "CoreDNS=true"
						

Собственно, грабли

    Где искать?

  • kubelet
  • docker
  • CNI
  • Как проявляются?

  • DNS
  • Нет метрик
  • Не стартует DNS
  • Кластер недоступен

Удивительно, но kube-proxy в этом списке нет

  • С kube-proxy всё ясно
  • Prometheus. Мистика. А мистика обычно с kubelet, и непонятно, что же именно не работает
  • С calico – crd всех спасут!

Calico

  • Calico - не только лишь CNI
  • Более того, много что ещё оно умеет


Встречайте

cluster-level firewall!!!

Calico

    API

  • hostEndpoint
  • globalNetworkPolicy

apiVersion: v1
kind: hostEndpoint
metadata:
  name: eth0
  node: myhost
  labels:
    type: production
spec:
  interfaceName: eth0
  expectedIPs: 
  - 192.168.0.1
  profiles: 
  - profile1
						

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: allow-tcp-6379
spec:
  selector: role == 'database'
  types:
  - Ingress
  ingress:
  - action: Allow
    protocol: TCP
    source:
      notNets:
        - 10.0.0.0/8	
    destination:
      ports:
      - 6379
						

CRD

Custom Resource Definition

projectcalico.org/v3 -> crd.projectcalico.org/v1

Prometheus

Боль, как обычно, в kubelet


KUBELET_EXTRA_ARGS=--authentication-token-webhook
						

Грабли kubelet

  • До 1.11.0 – конфигурация размазана по файлам и переменным окружения
  • Файлы под управлением kubeadm
  • Переменные окружения под управлением systemd (и, вероятно, пакетного менеджера)

Грабли docker

На самом деле, CoreDNS

На самом деле, CoreDNS container linux (но с docker)

  • До 1745.7.0 использовался /etc/coreos/docker-1.12
  • docker 1.12 не поддерживает securityContext.allowPrivilegeEscalation: false
  • С 1745.7.0 готов torcx

Грабли CNI

  • Изменения iptables – остаются после смерти контейнера
  • Ребутать здоровую ноду – не страшно
  • Не забывать разрешающие политики!!!
  • Не забывать их устанавливать первыми!!!

Как сделано в итоге?

  • Балансировка и афинность сессий - ipvs на kube-proxy
  • Метрики через prometheus/grafana - coreos-charts (helm)
  • Закрыть RPC - calico

Спасибо за внимание!

Остались вопросы?

https://t.me/bobizma
https://www.facebook.com/oleg.bobok