etcd Kubernetes кластер дахь өгөгдөлтэй холбоотой бидний туршлага (K8s API-гүй)

Кластер доторх үйлчилгээнд хандахын тулд зарим мэдээллийн сан эсвэл үйлчилгээнд шууд холбогдох, локал програмыг кластер доторх програмуудтай холбох боломжтой болгохын тулд үйлчлүүлэгчид биднээс Kubernetes кластерт хандах хүсэлтийг улам бүр нэмэгдүүлж байна...

etcd Kubernetes кластер дахь өгөгдөлтэй холбоотой бидний туршлага (K8s API-гүй)

Жишээлбэл, өөрийн дотоод машинаас үйлчилгээ рүү холбогдох шаардлагатай байна memcached.staging.svc.cluster.local. Бид үйлчлүүлэгчийн холбогддог кластер доторх VPN ашиглан энэ боломжийг олгодог. Үүнийг хийхийн тулд бид pods, үйлчилгээний дэд сүлжээг зарлаж, DNS кластерийг үйлчлүүлэгч рүү илгээдэг. Тиймээс үйлчлүүлэгч үйлчилгээнд холбогдохыг оролдох үед memcached.staging.svc.cluster.local, хүсэлт нь кластерийн DNS руу очих ба хариуд нь кластер үйлчилгээний сүлжээ эсвэл под хаягаас энэ үйлчилгээний хаягийг хүлээн авдаг.

Бид K8-ийн кластеруудыг kubeadm ашиглан тохируулдаг бөгөөд үүнд үндсэн үйлчилгээний дэд сүлжээ байдаг 192.168.0.0/16, мөн хонхорцог сүлжээ нь байна 10.244.0.0/16. Ихэвчлэн бүх зүйл сайн ажилладаг, гэхдээ хэд хэдэн зүйл байдаг:

  • Дэд сүлжээ 192.168.*.* ихэвчлэн үйлчлүүлэгчийн оффисын сүлжээнд, тэр ч байтугай хөгжүүлэгчийн гэрийн сүлжээнд ихэвчлэн ашиглагддаг. Дараа нь бид зөрчилдөөнтэй тулгардаг: гэрийн чиглүүлэгчид энэ дэд сүлжээнд ажилладаг бөгөөд VPN нь эдгээр дэд сүлжээг кластераас үйлчлүүлэгч рүү түлхдэг.
  • Бид хэд хэдэн кластертай (үйлдвэрлэл, үе шат ба/эсвэл хэд хэдэн dev кластер). Дараа нь, анхдагч байдлаар, тэдгээр нь бүгд pods болон үйлчилгээний ижил дэд сүлжээтэй байх бөгөөд энэ нь хэд хэдэн кластер дахь үйлчилгээтэй нэгэн зэрэг ажиллахад ихээхэн бэрхшээл учруулдаг.

Бид аль хэдийн нэг төслийн хүрээнд үйлчилгээ болон pods-д зориулж өөр өөр дэд сүлжээг ашиглах практикийг аль эрт нэвтрүүлсэн - ерөнхийдөө бүх кластерууд өөр өөр сүлжээтэй байх болно. Гэсэн хэдий ч олон тооны кластерууд ажиллаж байгаа бөгөөд тэдгээр нь олон үйлчилгээ, төлөвтэй програмууд гэх мэтийг ажиллуулдаг тул би эхнээс нь эргүүлэхийг хүсэхгүй байна.

Дараа нь бид өөрөөсөө асуусан: одоо байгаа кластер дахь дэд сүлжээг хэрхэн өөрчлөх вэ?

Шийдвэр хайх

Хамгийн түгээмэл дадал бол дахин бүтээх явдал юм бүх ClusterIP төрлийн үйлчилгээ. Сонголт болгон, зөвлөгөө өгч чадна бөгөөд энэ нь:

Дараах процесс нь асуудалтай байна: бүх зүйл тохируулагдсаны дараа pods /etc/resolv.conf доторх DNS нэрийн сервер болгон хуучин IP гарч ирдэг.
Би шийдлийг олж чадаагүй байгаа тул kubeadm reset-ээр кластерыг бүхэлд нь дахин тохируулж, дахин эхлүүлэх шаардлагатай болсон.

Гэхдээ энэ нь хүн бүрт тохиромжгүй ... Манай хэргийн талаар илүү дэлгэрэнгүй танилцуулга энд байна:

  • Фланел ашигладаг;
  • Үүл болон техник хангамж дээр кластерууд байдаг;
  • Би кластер дахь бүх үйлчилгээг дахин байршуулахаас зайлсхийхийг хүсч байна;
  • Ерөнхийдөө бүх зүйлийг хамгийн бага асуудалтай хийх шаардлагатай байдаг;
  • Kubernetes хувилбар нь 1.16.6 (гэхдээ цаашдын алхмууд бусад хувилбаруудын хувьд ижил байх болно);
  • Гол ажил бол үйлчилгээний дэд сүлжээтэй kubeadm ашиглан кластерт байрлуулсан эсэхийг баталгаажуулах явдал юм 192.168.0.0/16, -ээр солино 172.24.0.0/16.

Тэгээд л бид Kubernetes-д etcd-д юу, хэрхэн хадгалагдаж байгааг, түүгээр юу хийж болохыг харахыг эртнээс сонирхож байсан... Тэгээд бид бодсон: "Хуучин IP хаягуудыг (дэд сүлжээ) шинэ хаягаар сольж, etcd дээрх өгөгдлийг шинэчилж яагаад болохгүй гэж??

etcd дахь өгөгдөлтэй ажиллах бэлэн хэрэгслийг хайж олоод асуудлыг бүрэн шийдсэн зүйл олдсонгүй. (Дашрамд хэлэхэд, хэрэв та etcd доторх өгөгдөлтэй шууд ажиллах хэрэгслүүдийн талаар мэддэг бол бид холбоосуудад талархах болно.) Гэсэн хэдий ч сайн эхлэлийн цэг юм etcdhelper OpenShift-ээс (зохиогчиддоо баярлалаа!).

Энэ хэрэгсэл нь гэрчилгээ ашиглан etcd-тэй холбогдож, тушаалуудыг ашиглан тэндээс өгөгдлийг унших боломжтой ls, get, dump.

etcdhelper нэмнэ үү

Дараагийн бодол нь логик юм: "Таныг etcd-д өгөгдөл бичих чадварыг нэмснээр энэ хэрэгслийг нэмэхэд юу саад болж байна вэ?"

Энэ нь хоёр шинэ функц бүхий etcdhelper-ийн өөрчлөгдсөн хувилбар болсон changeServiceCIDR и changePodCIDR. түүн дээр кодыг харж болно энд.

Шинэ функцууд юу хийдэг вэ? Алгоритм changeServiceCIDR:

  • цуваа арилгагч үүсгэх;
  • CIDR-ийг орлуулах ердийн илэрхийлэлийг эмхэтгэх;
  • Бид кластер дахь ClusterIP төрлийн бүх үйлчилгээгээр дамждаг:
    • etcd-ийн утгыг Go объект болгон тайлах;
    • ердийн илэрхийлэл ашиглан бид хаягийн эхний хоёр байтыг солино;
    • үйлчилгээнд шинэ дэд сүлжээнээс IP хаяг өгөх;
    • цуваа үүсгэгч үүсгэх, Go объектыг protobuf болгон хөрвүүлэх, etcd руу шинэ өгөгдөл бичих.

үйл ажиллагаа changePodCIDR үндсэндээ төстэй changeServiceCIDR - зөвхөн үйлчилгээний тодорхойлолтыг засварлахын оронд бид үүнийг зангилаа болон өөрчилдөг .spec.PodCIDR шинэ дэд сүлжээнд.

Практик

Үйлчилгээний CIDR-г өөрчлөх

Даалгаврыг хэрэгжүүлэх төлөвлөгөө нь маш энгийн боловч кластер дахь бүх хонхорцог дахин бүтээгдэж байх үед сул зогсолтыг агуулдаг. Үндсэн алхмуудыг тайлбарласны дараа бид онолын хувьд энэ зогсолтыг хэрхэн багасгах талаар санал бодлоо хуваалцах болно.

Бэлтгэл үе шатууд:

  • шаардлагатай програм хангамжийг суулгаж, засварласан etcdhelper-ийг угсрах;
  • нөөц гэх мэт ба /etc/kubernetes.

Үйлчилгээ CIDR-ийг өөрчлөх үйл ажиллагааны товч төлөвлөгөө:

  • apiserver болон контроллер-менежерийн манифестуудыг өөрчлөх;
  • гэрчилгээг дахин гаргах;
  • etcd дахь ClusterIP үйлчилгээг өөрчлөх;
  • кластер дахь бүх pods-ыг дахин эхлүүлэх.

Дараахь үйлдлүүдийн бүрэн дарааллыг нарийвчлан харуулав.

1. Өгөгдлийн дамп хийх etcd-client-ийг суулгана уу:

apt install etcd-client

2. etcdhelper бүтээх:

  • Голанг суулгах:
    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. Kubernetes удирдлагын хавтгайн манифест дахь үйлчилгээний дэд сүлжээг өөрчил. Файл дотор /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. Бид kubeadm-аас apiserver-д (үүнд) гэрчилгээ олгодог үйлчилгээний дэд сүлжээг өөрчилж байгаа тул тэдгээрийг дахин олгох шаардлагатай:

  1. Одоогийн гэрчилгээг ямар домэйн, IP хаягаар олгосон болохыг харцгаая.
    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. kubeadm-д зориулсан хамгийн бага тохиргоог бэлдье:
    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. Хуучин crt болон түлхүүрийг устгацгаая, учир нь үүнгүйгээр шинэ гэрчилгээ олгохгүй.
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. API серверийн гэрчилгээг дахин гаргацгаая:
    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. API серверийн гэрчилгээг дахин гаргасны дараа түүний контейнерийг дахин эхлүүлнэ үү:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Тохиргоог дахин сэргээцгээе admin.conf:
    kubeadm alpha certs renew admin.conf
  8. etcd доторх өгөгдлийг засъя:
    ./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 

    Анхаар Одоогийн байдлаар домайны нарийвчлал нь кластерт ажиллахаа больсон, учир нь одоо байгаа pods-д байдаг /etc/resolv.conf хуучин CoreDNS хаяг (kube-dns) бүртгэгдсэн бөгөөд kube-proxy нь iptables дүрмийг хуучин дэд сүлжээнээс шинэ болгон өөрчилдөг. Цаашид нийтлэлд сул зогсолтыг багасгах боломжит хувилбаруудын талаар бичсэн болно.

  9. Нэрийн талбарт ConfigMap-г засъя kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - энд солих clusterDNS kube-dns үйлчилгээний шинэ IP хаяг руу: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - Бид үүнийг засах болно data.ClusterConfiguration.networking.serviceSubnet шинэ дэд сүлжээнд.

  10. Kube-dns хаяг өөрчлөгдсөн тул бүх зангилаа дээрх kubelet тохиргоог шинэчлэх шаардлагатай байна.
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Үлдсэн зүйл бол кластер дахь бүх pods-ыг дахин эхлүүлэх явдал юм.
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Сул зогсолтыг багасгах

Сул зогсолтыг хэрхэн багасгах тухай бодол:

  1. Хяналтын хавтгайн манифестуудыг өөрчилсний дараа шинэ kube-dns үйлчилгээг үүсгэнэ үү, жишээ нь нэрээр. kube-dns-tmp болон шинэ хаяг 172.24.0.10.
  2. Хийх if etcdhelper-д байгаа бөгөөд энэ нь kube-dns үйлчилгээг өөрчлөхгүй.
  3. Бүх kubelets дахь хаягийг солино уу ClusterDNS шинэ үйлчилгээ рүү шилжих бол хуучин үйлчилгээ нь шинэ үйлчилгээтэй зэрэгцэн ажиллах болно.
  4. Аппликейшн бүхий хонхорцог байгалийн шалтгаанаар эсвэл тохиролцсон цагтаа өөрөө эргэлдэх хүртэл хүлээнэ үү.
  5. Үйлчилгээг устгах kube-dns-tmp болон өөрчлөх serviceSubnetCIDR kube-dns үйлчилгээний хувьд.

Энэхүү төлөвлөгөө нь үйлчилгээг устгах хугацаанд ажиллах хугацааг ~ нэг минут хүртэл багасгах боломжийг танд олгоно kube-dns-tmp мөн үйлчилгээний дэд сүлжээг өөрчлөх kube-dns.

Өөрчлөлт podNetwork

Үүний зэрэгцээ бид үүссэн etcdhelper ашиглан podNetwork-ийг хэрхэн өөрчлөх талаар авч үзэхээр шийдсэн. Үйлдлүүдийн дараалал дараах байдалтай байна.

  • тохиргоог засах kube-system;
  • kube-хянагч-менежерийн манифестийг засах;
  • podCIDR-г шууд etcd-д өөрчлөх;
  • бүх кластерийн зангилааг дахин ачаална уу.

Одоо эдгээр үйлдлийн талаар дэлгэрэнгүй:

1. Нэрийн талбарт ConfigMaps-г өөрчил 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. etcd-д шууд өөрчлөлт хийж podCIDR-г солино уу:

./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. PodCIDR үнэхээр өөрчлөгдсөн эсэхийг шалгацгаая:

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. Хэрэв та дор хаяж нэг зангилаа үлдээвэл хуучин podCIDR, дараа нь kube-controller-manager эхлүүлэх боломжгүй бөгөөд кластер дахь pods хуваарьт байхгүй болно.

Үнэн хэрэгтээ podCIDR-ийг өөрчлөх нь илүү хялбар байж болно (жишээлбэл, тэгээд). Гэхдээ etcd дээр Kubernetes объектуудыг засварлах тохиолдол байдаг тул бид шууд etcd-тэй хэрхэн ажиллах талаар сурахыг хүссэн. цорын ганц боломжит хувилбар. (Жишээ нь, та үйлчилгээний талбарыг зогсолтгүйгээр өөрчлөх боломжгүй spec.clusterIP.)

Үр дүн

Энэ нийтлэлд etcd дахь өгөгдөлтэй шууд ажиллах боломжийг авч үзэх болно, i.e. Kubernetes API-г тойрч гарах. Заримдаа энэ арга нь танд "хүнд хэцүү зүйлсийг" хийх боломжийг олгодог. Бид текстэд өгөгдсөн үйлдлүүдийг бодит K8 кластерууд дээр туршиж үзсэн. Гэсэн хэдий ч тэдний өргөн хэрэглээнд бэлэн байдлын статус PoC (үзэл баримтлалын баталгаа). Тиймээс, хэрэв та etcdhelper хэрэгслийн өөрчилсөн хувилбарыг кластер дээрээ ашиглахыг хүсвэл эрсдэлээ өөрөө даана уу.

PS

Мөн манай блог дээрээс уншина уу:

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх