Наше искуство са подацима у етцд Кубернетес кластеру директно (без К8с АПИ-ја)

Све чешће клијенти траже од нас да омогућимо приступ Кубернетес кластеру како би могли да приступе услугама у оквиру кластера: тако да могу директно да се повежу на неку базу података или сервис, да повежу локалну апликацију са апликацијама у оквиру кластера...

Наше искуство са подацима у етцд Кубернетес кластеру директно (без К8с АПИ-ја)

На пример, постоји потреба да се повежете са ваше локалне машине на услугу memcached.staging.svc.cluster.local. Ову могућност пружамо користећи ВПН унутар кластера на који се клијент повезује. Да бисмо то урадили, најављујемо подмреже подова, услуга и гурамо ДНС кластера клијенту. Дакле, када клијент покуша да се повеже са услугом memcached.staging.svc.cluster.local, захтев иде ка ДНС-у кластера и као одговор добија адресу ове услуге из мреже сервиса кластера или адресу под.

Конфигуришемо К8с кластере користећи кубеадм, где је подразумевана сервисна подмрежа 192.168.0.0/16, а мрежа махуна је 10.244.0.0/16. Обично све функционише добро, али постоји неколико тачака:

  • Подмрежа 192.168.*.* често се користи у мрежама клијентских канцеларија, а још чешће у кућним мрежама програмера. А онда добијамо конфликте: кућни рутери раде на овој подмрежи и ВПН гура ове подмреже из кластера до клијента.
  • Имамо неколико кластера (производни, сценски и/или неколико кластера за развој). Тада ће све оне подразумевано имати исте подмреже за подове и сервисе, што ствара велике потешкоће за истовремени рад са сервисима у више кластера.

Одавно смо усвојили праксу коришћења различитих подмрежа за услуге и подове у оквиру истог пројекта – уопштено, тако да сви кластери имају различите мреже. Међутим, постоји велики број кластера у раду које не бих желео да пребацујем од нуле, пошто покрећу многе сервисе, апликације са статусом итд.

А онда смо се запитали: како променити подмрежу у постојећем кластеру?

Тражење одлука

Најчешћа пракса је рекреација све услуге са типом ЦлустерИП. као опција, може саветовати и ово:

Следећи процес има проблем: након што је све конфигурисано, подови добијају стару ИП адресу као ДНС сервер имена у /етц/ресолв.цонф.
Пошто још увек нисам нашао решење, морао сам да ресетујем цео кластер помоћу кубеадм ресетовања и поново га покренем.

Али ово није погодно за све... Ево детаљнијих увода за наш случај:

  • Користи се фланел;
  • Постоје кластери и у облацима и на хардверу;
  • Желео бих да избегнем поновно распоређивање свих услуга у кластеру;
  • Постоји потреба да се генерално све ради са минималним бројем проблема;
  • Кубернетес верзија је 1.16.6 (међутим, даљи кораци ће бити слични за друге верзије);
  • Главни задатак је осигурати да у кластеру распоређеном помоћу кубеадм-а са услужном подмрежом 192.168.0.0/16, замените га са 172.24.0.0/16.

И десило се да смо дуго били заинтересовани да видимо шта се и како у Кубернетесу чува у етцд-у, шта се може урадити са тим... Па смо помислили: „Зашто једноставно не ажурирате податке у етцд-у, замењујући старе ИП адресе (подмрежу) новим? "

Трагајући за готовим алатима за рад са подацима у етцд-у, нисмо нашли ништа што би у потпуности решило проблем. (Успут, ако знате за било какве услужне програме за рад са подацима директно у етцд-у, били бисмо вам захвални на линковима.) Међутим, добра полазна тачка је етцдхелпер из ОпенСхифт (хвала његовим ауторима!).

Овај услужни програм може да се повеже на етцд користећи сертификате и да чита податке одатле помоћу команди ls, get, dump.

Додајте етцдхелпер

Следећа мисао је логична: „Шта вас спречава да додате овај услужни програм додавањем могућности писања података у етцд?“

Постао је модификована верзија етцдхелпера са две нове функције changeServiceCIDR и changePodCIDR. на њу можете видети код овде.

Шта раде нове функције? Алгоритам changeServiceCIDR:

  • креирајте десеријализатор;
  • компајлирати регуларни израз да замени ЦИДР;
  • пролазимо кроз све услуге са типом ЦлустерИП у кластеру:
    • декодирајте вредност из етцд у Го објекат;
    • помоћу регуларног израза замењујемо прва два бајта адресе;
    • доделите сервису ИП адресу из нове подмреже;
    • креирајте серијализатор, претворите Го објекат у протобуф, напишите нове податке у етцд.

Функција changePodCIDR суштински слични changeServiceCIDR - само уместо да уређујемо спецификацију услуге, ми то радимо за чвор и мењамо .spec.PodCIDR у нову подмрежу.

Пракса

Промените услугу ЦИДР

План за имплементацију задатка је веома једноставан, али укључује застоје у време поновног креирања свих махуна у кластеру. Након што опишемо главне кораке, поделићемо и размишљања о томе како, у теорији, ово време застоја може бити сведено на минимум.

Припремни кораци:

  • инсталирање потребног софтвера и склапање закрпљеног етцдхелпера;
  • резервна копија итд. и /etc/kubernetes.

Кратак акциони план за промену услугеЦИДР:

  • промена манифеста аписервера и контролора-менаџера;
  • поновно издавање сертификата;
  • промена ЦлустерИП услуга у етцд;
  • поново покрените све подове у кластеру.

У наставку је детаљан комплетан редослед радњи.

1. Инсталирајте етцд-цлиент за думп података:

apt install etcd-client

2. Направи етцдхелпер:

  • Инсталирајте голанг:
    GOPATH=/root/golang
    mkdir -p $GOPATH/local
    curl -sSL https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz | tar -xzvC $GOPATH/local
    echo "export GOPATH="$GOPATH"" >> ~/.bashrc
    echo 'export GOROOT="$GOPATH/local/go"' >> ~/.bashrc
    echo 'export PATH="$PATH:$GOPATH/local/go/bin"' >> ~/.bashrc
  • Штедимо за себе etcdhelper.go, преузимање зависности, прикупљање:
    wget https://raw.githubusercontent.com/flant/examples/master/2020/04-etcdhelper/etcdhelper.go
    go get go.etcd.io/etcd/clientv3 k8s.io/kubectl/pkg/scheme k8s.io/apimachinery/pkg/runtime
    go build -o etcdhelper etcdhelper.go

3. Направите резервну копију итд.:

backup_dir=/root/backup
mkdir ${backup_dir}
cp -rL /etc/kubernetes ${backup_dir}
ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt --key=/etc/kubernetes/pki/etcd/server.key --cert=/etc/kubernetes/pki/etcd/server.crt --endpoints https://192.168.199.100:2379 snapshot save ${backup_dir}/etcd.snapshot

4. Промените подмрежу услуге у манифестима Кубернетес контролне равни. У фајловима /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml промените параметар --service-cluster-ip-range у нову подмрежу: 172.24.0.0/16 уместо 192.168.0.0/16.

5. Пошто мењамо сервисну подмрежу којој кубеадм издаје сертификате за аписервер (укључујући и њих), потребно их је поново издати:

  1. Хајде да видимо за које домене и ИП адресе је издат тренутни сертификат:
    openssl x509 -noout -ext subjectAltName </etc/kubernetes/pki/apiserver.crt
    X509v3 Subject Alternative Name:
        DNS:dev-1-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:apiserver, IP Address:192.168.0.1, IP Address:10.0.0.163, IP Address:192.168.199.100
  2. Хајде да припремимо минималну конфигурацију за кубеадм:
    cat kubeadm-config.yaml
    apiVersion: kubeadm.k8s.io/v1beta1
    kind: ClusterConfiguration
    networking:
      podSubnet: "10.244.0.0/16"
      serviceSubnet: "172.24.0.0/16"
    apiServer:
      certSANs:
      - "192.168.199.100" # IP-адрес мастер узла
  3. Избришемо стари црт и кључ, јер без тога нови сертификат неће бити издат:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Хајде да поново издамо сертификате за АПИ сервер:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Хајде да проверимо да ли је сертификат издат за нову подмрежу:
    openssl x509 -noout -ext subjectAltName </etc/kubernetes/pki/apiserver.crt
    X509v3 Subject Alternative Name:
        DNS:kube-2-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, IP Address:172.24.0.1, IP Address:10.0.0.163, IP Address:192.168.199.100
  6. Након поновног издавања сертификата АПИ сервера, поново покрените његов контејнер:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Хајде да поново генеришемо конфигурацију за admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Уредимо податке у етцд:
    ./etcdhelper -cacert /etc/kubernetes/pki/etcd/ca.crt -cert /etc/kubernetes/pki/etcd/server.crt -key /etc/kubernetes/pki/etcd/server.key -endpoint https://127.0.0.1:2379 change-service-cidr 172.24.0.0/16 

    Упозорење! У овом тренутку, резолуција домена престаје да ради у кластеру, јер у постојећим подовима /etc/resolv.conf стара ЦореДНС адреса (кубе-днс) је регистрована, а кубе-проки мења иптаблес правила са старе подмреже на нову. Даље у чланку је написано о могућим опцијама за минимизирање застоја.

  9. Хајде да поправимо ЦонфигМап у именском простору kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - замени овде clusterDNS на нову ИП адресу кубе-днс услуге: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - ми ћемо то поправити data.ClusterConfiguration.networking.serviceSubnet у нову подмрежу.

  10. Пошто је кубе-днс адреса промењена, потребно је ажурирати кубелет конфигурацију на свим чворовима:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Све што остаје је да поново покренете све подове у кластеру:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Минимизирајте застоје

Размишљања о томе како да минимизирате застоје:

  1. Након промене манифеста контролне равни, креирајте нову кубе-днс услугу, на пример, са именом kube-dns-tmp и нову адресу 172.24.0.10.
  2. Направи if у етцдхелпер-у, који неће модификовати кубе-днс услугу.
  3. Замените адресу у свим кубелетима ClusterDNS на нову, док ће стара служба наставити да ради истовремено са новом.
  4. Сачекајте да се махуне са апликацијама преврну или саме из природних разлога или у договорено време.
  5. Избриши услугу kube-dns-tmp и промените serviceSubnetCIDR за кубе-днс услугу.

Овај план ће вам омогућити да минимизирате застоје на ~ минут - током трајања уклањања услуге kube-dns-tmp и промену подмреже за услугу kube-dns.

Модифицатион подНетворк

У исто време, одлучили смо да погледамо како да изменимо подНетворк користећи резултујући етцдхелпер. Редослед радњи је следећи:

  • поправљање конфигурација у kube-system;
  • поправљање манифеста кубе-контролера-менаџера;
  • промените подЦИДР директно у етцд;
  • поново покрените све чворове кластера.

Сада више о овим акцијама:

1. Измените ЦонфигМап у именском простору kube-system:

kubectl -n kube-system edit cm kubeadm-config

- исправљање data.ClusterConfiguration.networking.podSubnet у нову подмрежу 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

- исправљање data.config.conf.clusterCIDR: 10.55.0.0/16.

2. Измените манифест контролора-менаџера:

vim /etc/kubernetes/manifests/kube-controller-manager.yaml

- исправљање --cluster-cidr=10.55.0.0/16.

3. Погледајте тренутне вредности .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses за све чворове кластера:

kubectl get no -o json | jq '[.items[] | {"name": .metadata.name, "podCIDR": .spec.podCIDR, "podCIDRs": .spec.podCIDRs, "InternalIP": (.status.addresses[] | select(.type == "InternalIP") | .address)}]'

[
  {
    "name": "kube-2-master",
    "podCIDR": "10.244.0.0/24",
    "podCIDRs": [
      "10.244.0.0/24"
    ],
    "InternalIP": "192.168.199.2"
  },
  {
    "name": "kube-2-master",
    "podCIDR": "10.244.0.0/24",
    "podCIDRs": [
      "10.244.0.0/24"
    ],
    "InternalIP": "10.0.1.239"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.244.1.0/24",
    "podCIDRs": [
      "10.244.1.0/24"
    ],
    "InternalIP": "192.168.199.222"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.244.1.0/24",
    "podCIDRs": [
      "10.244.1.0/24"
    ],
    "InternalIP": "10.0.4.73"
  }
]

4. Замените подЦИДР уношењем промена директно у етцд:

./etcdhelper -cacert /etc/kubernetes/pki/etcd/ca.crt -cert /etc/kubernetes/pki/etcd/server.crt -key /etc/kubernetes/pki/etcd/server.key -endpoint https://127.0.0.1:2379 change-pod-cidr 10.55.0.0/16

5. Хајде да проверимо да ли се подЦИДР заиста променио:

kubectl get no -o json | jq '[.items[] | {"name": .metadata.name, "podCIDR": .spec.podCIDR, "podCIDRs": .spec.podCIDRs, "InternalIP": (.status.addresses[] | select(.type == "InternalIP") | .address)}]'

[
  {
    "name": "kube-2-master",
    "podCIDR": "10.55.0.0/24",
    "podCIDRs": [
      "10.55.0.0/24"
    ],
    "InternalIP": "192.168.199.2"
  },
  {
    "name": "kube-2-master",
    "podCIDR": "10.55.0.0/24",
    "podCIDRs": [
      "10.55.0.0/24"
    ],
    "InternalIP": "10.0.1.239"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.55.1.0/24",
    "podCIDRs": [
      "10.55.1.0/24"
    ],
    "InternalIP": "192.168.199.222"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.55.1.0/24",
    "podCIDRs": [
      "10.55.1.0/24"
    ],
    "InternalIP": "10.0.4.73"
  }
]

6. Хајде да поново покренемо све чворове кластера један по један.

7. Ако оставите бар један чвор стари подЦИДР, тада кубе-цонтроллер-манагер неће моћи да се покрене, а подови у кластеру неће бити заказани.

У ствари, промена подЦИДР-а може да се уради још једноставније (нпр. тако). Али желели смо да научимо како да радимо директно са етцд-ом, јер постоје случајеви када уређујете Кубернетес објекте у етцд-у - сингл могућа варијанта. (На пример, не можете само да промените поље услуге без прекида рада spec.clusterIP.)

Укупан

У чланку се говори о могућности директног рада са подацима у етцд-у, тј. заобилазећи Кубернетес АПИ. Понекад вам овај приступ омогућава да радите „шкакљиве ствари“. Тестирали смо операције дате у тексту на стварним К8с кластерима. Међутим, њихов статус спремности за широку употребу је ПоЦ (доказ концепта). Стога, ако желите да користите модификовану верзију услужног програма етцдхелпер на својим кластерима, урадите то на сопствени ризик.

ПС

Прочитајте и на нашем блогу:

Извор: ввв.хабр.цом

Додај коментар