Uzoefu wetu na data katika kundi la etcd Kubernetes moja kwa moja (bila API ya K8s)

Kwa kuongezeka, wateja wanatuomba tutoe ufikiaji kwa nguzo ya Kubernetes ili kuweza kufikia huduma ndani ya nguzo: kuweza kuunganisha moja kwa moja kwenye hifadhidata au huduma fulani, kuunganisha programu ya ndani na programu zilizo ndani ya nguzo...

Uzoefu wetu na data katika kundi la etcd Kubernetes moja kwa moja (bila API ya K8s)

Kwa mfano, kuna haja ya kuunganisha kutoka kwa mashine ya ndani hadi kwenye huduma memcached.staging.svc.cluster.local. Tunatoa uwezo huu kwa kutumia VPN ndani ya nguzo ambayo mteja huunganisha. Ili kufanya hivyo, tunatangaza subnets za maganda, huduma na kusukuma nguzo ya DNS kwa mteja. Kwa hivyo, mteja anapojaribu kuunganishwa na huduma memcached.staging.svc.cluster.local, ombi huenda kwa kikundi cha DNS na kwa kujibu hupokea anwani ya huduma hii kutoka kwa mtandao wa huduma ya nguzo au anwani ya pod.

Tunasanidi vikundi vya K8 kwa kutumia kubeadm, ambapo subnet ya huduma chaguo-msingi iko 192.168.0.0/16, na mtandao wa maganda ni 10.244.0.0/16. Kawaida kila kitu hufanya kazi vizuri, lakini kuna vidokezo kadhaa:

  • Subnet 192.168.*.* mara nyingi hutumiwa katika mitandao ya ofisi ya mteja, na hata mara nyingi zaidi katika mitandao ya nyumbani ya wasanidi programu. Na kisha tunapata migogoro: vipanga njia vya nyumbani hufanya kazi kwenye subnet hii na VPN inasukuma subnets hizi kutoka kwa kikundi hadi kwa mteja.
  • Tuna makundi kadhaa (uzalishaji, hatua na/au makundi kadhaa ya wasanidi). Kisha, kwa default, wote watakuwa na subnets sawa kwa pods na huduma, ambayo inaleta matatizo makubwa kwa kazi ya wakati mmoja na huduma katika makundi kadhaa.

Kwa muda mrefu tumepitisha mazoezi ya kutumia subnets tofauti kwa huduma na maganda ndani ya mradi mmoja - kwa ujumla, ili makundi yote yawe na mitandao tofauti. Walakini, kuna idadi kubwa ya vikundi vinavyofanya kazi ambavyo nisingependa kusongesha kutoka mwanzo, kwani zinaendesha huduma nyingi, maombi ya hali, nk.

Na kisha tukajiuliza: jinsi ya kubadilisha subnet katika nguzo iliyopo?

Kutafuta maamuzi

Mazoezi ya kawaida ni kuunda upya wote huduma na aina ya ClusterIP. Kama chaguo, anaweza kushauri na hii:

Mchakato ufuatao una tatizo: baada ya kila kitu kusanidiwa, maganda yanakuja na IP ya zamani kama seva ya majina ya DNS katika /etc/resolv.conf.
Kwa kuwa bado sikupata suluhisho, ilibidi niweke upya nguzo nzima kwa kuweka upya kubeadm na kuianzisha tena.

Lakini hii haifai kwa kila mtu ... Hapa kuna utangulizi wa kina zaidi kwa kesi yetu:

  • Flannel hutumiwa;
  • Kuna makundi katika mawingu na kwenye vifaa;
  • Ningependa kuzuia kupeleka tena huduma zote kwenye nguzo;
  • Kuna haja ya ujumla kufanya kila kitu na idadi ndogo ya matatizo;
  • Toleo la Kubernetes ni 1.16.6 (hata hivyo, hatua zaidi zitakuwa sawa kwa matoleo mengine);
  • Kazi kuu ni kuhakikisha kuwa katika nguzo iliyotumika kwa kubeadm na subnet ya huduma 192.168.0.0/16, ibadilishe na 172.24.0.0/16.

Na ikawa kwamba kwa muda mrefu tumekuwa na nia ya kuona ni nini na jinsi gani katika Kubernetes imehifadhiwa katika etcd, nini kinaweza kufanywa nayo ... Kwa hivyo tulifikiria: "Kwa nini usisasishe tu data katika etcd, ukibadilisha anwani za IP za zamani (subnet) na mpya? "

Baada ya kutafuta zana zilizotengenezwa tayari za kufanya kazi na data katika etcd, hatukupata chochote ambacho kilitatua shida kabisa. (Kwa njia, ikiwa unajua kuhusu huduma zozote za kufanya kazi na data moja kwa moja katika etcd, tutashukuru viungo.) Walakini, hatua nzuri ya kuanzia ni msaidizi nk kutoka OpenShift (shukrani kwa waandishi wake!).

Huduma hii inaweza kuunganishwa na etcd kwa kutumia vyeti na kusoma data kutoka hapo kwa kutumia amri ls, get, dump.

Ongeza nkdhelper

Wazo linalofuata ni la kimantiki: "Ni nini kinakuzuia kuongeza huduma hii kwa kuongeza uwezo wa kuandika data kwa etcd?"

Ikawa toleo lililobadilishwa la etcdhelper na vitendaji viwili vipya changeServiceCIDR ΠΈ changePodCIDR. juu yake unaweza kuona kanuni hapa.

Vipengele vipya hufanya nini? Algorithm changeServiceCIDR:

  • tengeneza deserializer;
  • kusanya usemi wa kawaida kuchukua nafasi ya CIDR;
  • tunapitia huduma zote na aina ya ClusterIP kwenye nguzo:
    • amua thamani kutoka etcd kuwa kitu cha Go;
    • kwa kutumia usemi wa kawaida tunabadilisha baiti mbili za kwanza za anwani;
    • gawa huduma anwani ya IP kutoka kwa subnet mpya;
    • unda serializer, badilisha kitu cha Go kuwa protobuf, andika data mpya kwa etcd.

Kazi changePodCIDR kimsingi sawa changeServiceCIDR - tu badala ya kuhariri vipimo vya huduma, tunafanya kwa node na mabadiliko .spec.PodCIDR kwa subnet mpya.

Mazoezi

Badilisha huduma ya CIDR

Mpango wa kutekeleza kazi ni rahisi sana, lakini unahusisha muda wa chini wakati maganda yote kwenye nguzo yanaundwa upya. Baada ya kuelezea hatua kuu, tutashiriki pia mawazo juu ya jinsi, kwa nadharia, wakati huu wa kupungua unaweza kupunguzwa.

Hatua za maandalizi:

  • kusakinisha programu muhimu na kukusanya viraka etcdhelper;
  • chelezo etcd na /etc/kubernetes.

Mpango kazi fupi wa kubadilisha hudumaCIDR:

  • kubadilisha apiserver na mtawala-meneja hudhihirisha;
  • kutoa tena vyeti;
  • kubadilisha huduma za ClusterIP katika etcd;
  • anzisha upya maganda yote kwenye nguzo.

Ifuatayo ni mlolongo kamili wa vitendo kwa undani.

1. Sakinisha etcd-client kwa utupaji wa data:

apt install etcd-client

2. Jenga nkdhelper:

  • Sakinisha golang:
    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
  • Tunajiwekea akiba etcdhelper.go, tegemezi za kupakua, kukusanya:
    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. Tengeneza nakala nkd:

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. Badilisha subnet ya huduma katika maonyesho ya ndege ya Kubernetes. Katika faili /etc/kubernetes/manifests/kube-apiserver.yaml ΠΈ /etc/kubernetes/manifests/kube-controller-manager.yaml kubadilisha parameter --service-cluster-ip-range kwa subnet mpya: 172.24.0.0/16 badala ya 192.168.0.0/16.

5. Kwa kuwa tunabadilisha subnet ya huduma ambayo kubeadm hutoa vyeti vya apiserver (pamoja na), zinahitaji kutolewa tena:

  1. Hebu tuone ni vikoa na anwani za IP ambazo cheti cha sasa kimetolewa:
    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. Wacha tuandae usanidi mdogo wa 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. Wacha tufute crt ya zamani na ufunguo, kwani bila hii cheti kipya hakitatolewa:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Wacha tutoe tena vyeti vya seva ya API:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Wacha tuangalie ikiwa cheti kilitolewa kwa subnet mpya:
    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. Baada ya kutoa tena cheti cha seva ya API, anzisha tena kontena lake:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Wacha tuunda upya usanidi wa admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Wacha tuhariri data katika 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 

    Attention! Kwa wakati huu, azimio la kikoa huacha kufanya kazi kwenye nguzo, kwani katika maganda yaliyopo ndani /etc/resolv.conf anwani ya zamani ya CoreDNS (kube-dns) imesajiliwa, na kube-proksi hubadilisha sheria za iptables kutoka subnet ya zamani hadi mpya. Zaidi katika makala imeandikwa kuhusu chaguo iwezekanavyo ili kupunguza muda wa kupungua.

  9. Hebu turekebishe ConfigMap katika nafasi ya majina kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - kuchukua nafasi hapa clusterDNS kwa anwani mpya ya IP ya huduma ya kube-dns: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - tutaweza kurekebisha data.ClusterConfiguration.networking.serviceSubnet kwa subnet mpya.

  10. Kwa kuwa anwani ya kube-dns imebadilika, ni muhimu kusasisha usanidi wa kubelet kwenye nodi zote:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Kilichobaki ni kuanza tena maganda yote kwenye nguzo:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Punguza muda wa kupumzika

Mawazo ya jinsi ya kupunguza wakati wa kupumzika:

  1. Baada ya kubadilisha maonyesho ya ndege ya udhibiti, unda huduma mpya ya kube-dns, kwa mfano, na jina kube-dns-tmp na anwani mpya 172.24.0.10.
  2. Fanya if katika etcdhelper, ambayo haitarekebisha huduma ya kube-dns.
  3. Badilisha anwani katika kubelets zote ClusterDNS kwa mpya, wakati huduma ya zamani itaendelea kufanya kazi wakati huo huo na mpya.
  4. Subiri hadi maganda yaliyo na programu yageuke yenyewe kwa sababu za asili au kwa wakati uliokubaliwa.
  5. Futa huduma kube-dns-tmp na mabadiliko serviceSubnetCIDR kwa huduma ya kube-dns.

Mpango huu utakuruhusu kupunguza muda hadi ~a minute - kwa muda wa uondoaji wa huduma kube-dns-tmp na kubadilisha subnet kwa ajili ya huduma kube-dns.

Marekebisho ya podNetwork

Wakati huo huo, tuliamua kuangalia jinsi ya kurekebisha podNetwork kwa kutumia etcdhelper kusababisha. Mlolongo wa vitendo ni kama ifuatavyo:

  • kurekebisha mipangilio ndani kube-system;
  • kurekebisha kube-controller-manager;
  • badilisha podCIDR moja kwa moja katika etcd;
  • anzisha upya nodi zote za nguzo.

Sasa zaidi kuhusu vitendo hivi:

1. Rekebisha ConfigMaps katika nafasi ya majina kube-system:

kubectl -n kube-system edit cm kubeadm-config

- kurekebisha data.ClusterConfiguration.networking.podSubnet kwa subnet mpya 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

- kurekebisha data.config.conf.clusterCIDR: 10.55.0.0/16.

2. Rekebisha faili ya maelezo ya kidhibiti-kidhibiti:

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

- kurekebisha --cluster-cidr=10.55.0.0/16.

3. Angalia maadili ya sasa .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses kwa nodi zote za nguzo:

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. Badilisha podCIDR kwa kufanya mabadiliko moja kwa moja kwa 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-pod-cidr 10.55.0.0/16

5. Hebu tuangalie ikiwa podCIDR imebadilika kweli:

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. Hebu tuanze upya nodi zote za nguzo moja kwa moja.

7. Ukiacha angalau nodi moja podCIDR ya zamani, basi kube-controller-manager hataweza kuanza, na maganda kwenye nguzo hayataratibiwa.

Kwa kweli, kubadilisha podCIDR kunaweza kufanywa rahisi zaidi (kwa mfano, hivyo) Lakini tulitaka kujifunza jinsi ya kufanya kazi na etcd moja kwa moja, kwa sababu kuna matukio wakati wa kuhariri vitu vya Kubernetes katika etcd - pekee lahaja iwezekanavyo. (Kwa mfano, huwezi kubadilisha tu uwanja wa Huduma bila wakati wa kupumzika spec.clusterIP.)

Jumla ya

Kifungu kinazungumzia uwezekano wa kufanya kazi na data katika etcd moja kwa moja, i.e. kupita Kubernetes API. Wakati mwingine njia hii inakuwezesha kufanya "mambo ya hila". Tulijaribu shughuli zilizotolewa katika maandishi kwenye nguzo halisi za K8s. Hata hivyo, hali yao ya utayari kwa matumizi yaliyoenea ni PoC (ushahidi wa dhana). Kwa hivyo, ikiwa unataka kutumia toleo lililobadilishwa la matumizi ya etcdhelper kwenye nguzo zako, fanya hivyo kwa hatari yako mwenyewe.

PS

Soma pia kwenye blogi yetu:

Chanzo: mapenzi.com

Kuongeza maoni