Մեր փորձը տվյալների հետ etcd Kubernetes կլաստերում ուղղակիորեն (առանց K8s API)

Հաճախորդները գնալով մեզ խնդրում են մուտք գործել Kubernetes կլաստեր, որպեսզի կարողանան օգտվել կլաստերի ներսում ծառայություններից, որպեսզի նրանք կարողանան ուղղակիորեն միանալ տվյալների բազայի կամ ծառայության, տեղական հավելվածը միացնել կլաստերի հավելվածների հետ...

Մեր փորձը տվյալների հետ etcd Kubernetes կլաստերում ուղղակիորեն (առանց K8s API)

Օրինակ, ձեր տեղական մեքենայից ծառայությանը միանալու անհրաժեշտություն կա memcached.staging.svc.cluster.local. Մենք տրամադրում ենք այս հնարավորությունը՝ օգտագործելով VPN այն կլաստերի մեջ, որին միանում է հաճախորդը: Դա անելու համար մենք հայտարարում ենք փոդերի, ծառայությունների ենթացանցեր և հաճախորդին հրում կլաստերային DNS: Այսպիսով, երբ հաճախորդը փորձում է միանալ ծառայությանը memcached.staging.svc.cluster.local, հարցումը գնում է կլաստերի DNS և ի պատասխան ստանում է այս ծառայության հասցեն կլաստերի սպասարկման ցանցից կամ pod հասցեից։

Մենք կարգավորում ենք K8s կլաստերները՝ օգտագործելով kubeadm, որտեղ գտնվում է ծառայության լռելյայն ենթացանցը 192.168.0.0/16, իսկ պատիճների ցանցն է 10.244.0.0/16. Սովորաբար ամեն ինչ լավ է աշխատում, բայց կան մի քանի կետ.

  • Ենթացանց 192.168.*.* հաճախ օգտագործվում է հաճախորդների գրասենյակային ցանցերում և նույնիսկ ավելի հաճախ ծրագրավորողների տնային ցանցերում: Եվ հետո մենք ստանում ենք կոնֆլիկտներ. տնային երթուղիչները աշխատում են այս ենթացանցում, և VPN-ն այս ենթացանցերը մղում է կլաստերից դեպի հաճախորդ:
  • Մենք ունենք մի քանի կլաստերներ (արտադրական, բեմական և/կամ մի քանի մշակող կլաստերներ): Այնուհետև, լռելյայնորեն, բոլորը կունենան նույն ենթացանցերը pods-ի և ծառայությունների համար, ինչը մեծ դժվարություններ է ստեղծում մի քանի կլաստերներում ծառայությունների հետ միաժամանակյա աշխատանքի համար։

Մենք վաղուց որդեգրել ենք տարբեր ենթացանցերի օգտագործման պրակտիկա՝ ծառայությունների և փոդերի համար մեկ նախագծի շրջանակներում, ընդհանրապես, որպեսզի բոլոր կլաստերներն ունենան տարբեր ցանցեր: Այնուամենայնիվ, կան մեծ թվով կլաստերներ, որոնք ես չէի ցանկանա զրոյից շրջել, քանի որ դրանք գործարկում են բազմաթիվ ծառայություններ, պետական ​​ծրագրեր և այլն:

Եվ հետո մենք ինքներս մեզ հարցրինք. ինչպե՞ս փոխել ենթացանցը գոյություն ունեցող կլաստերում:

Որոշումների որոնում

Ամենատարածված պրակտիկան վերստեղծելն է բոլորը ծառայություններ ClusterIP տիպով: Որպես տարբերակ՝ կարող է խորհուրդ տալ եւ այս:

Հետևյալ պրոցեսը խնդիր ունի. ամեն ինչ կարգավորվելուց հետո pods-ը հայտնվում է հին IP-ով որպես DNS անվանասերվեր /etc/resolv.conf-ում:
Քանի որ ես դեռ չեմ գտել լուծումը, ես ստիպված էի վերականգնել ամբողջ կլաստերը kubeadm reset-ով և նորից գործարկել այն:

Բայց սա բոլորի համար հարմար չէ... Ահա մեր գործի ավելի մանրամասն ներածությունները.

  • Օգտագործվում է ֆլանել;
  • Կլաստերներ կան և՛ ամպերի, և՛ ապարատների վրա.
  • Ես կցանկանայի խուսափել կլաստերի բոլոր ծառայությունների վերաբաշխումից.
  • Պետք է ընդհանրապես ամեն ինչ անել նվազագույն թվով խնդիրներով.
  • Kubernetes տարբերակը 1.16.6 է (սակայն, հետագա քայլերը նման կլինեն այլ տարբերակների համար);
  • Հիմնական խնդիրն է ապահովել, որ կլաստերի մեջ տեղակայվի kubeadm-ը սպասարկման ենթացանցով 192.168.0.0/16, փոխարինեք այն 172.24.0.0/16.

Եվ եղավ այնպես, որ մենք վաղուց հետաքրքրված էինք տեսնել, թե ինչ և ինչպես է Kubernetes-ում պահվում etcd-ում, ինչ կարելի է անել դրա հետ… Ուստի մենք մտածեցինք.Ինչու պարզապես չթարմացնել տվյալները etcd-ով, փոխարինելով հին IP հասցեները (ենթացանցը) նորերով? "

Տվյալների հետ աշխատելու համար պատրաստի գործիքներ փնտրելով etcd-ում, մենք չգտանք որևէ բան, որն ամբողջությամբ լուծեր խնդիրը: (Ի դեպ, եթե դուք գիտեք որևէ կոմունալ ծառայությունների մասին ուղղակիորեն etcd-ում տվյալների հետ աշխատելու համար, մենք կգնահատենք հղումները:) Այնուամենայնիվ, լավ մեկնարկային կետն է etcdhelper OpenShift-ից (շնորհակալություն դրա հեղինակներին!).

Այս օգտակար ծրագիրը կարող է միանալ etcd-ին՝ օգտագործելով վկայագրեր և կարդալ տվյալներ այնտեղից՝ օգտագործելով հրամանները ls, get, dump.

Ավելացնել etcdhelper

Հաջորդ միտքը տրամաբանական է. «Ի՞նչն է խանգարում ձեզ ավելացնել այս օգտակար ծրագիրը՝ ավելացնելով տվյալներ գրելու հնարավորությունը etcd-ում»:

Այն դարձավ etcdhelper-ի փոփոխված տարբերակը երկու նոր գործառույթներով changeServiceCIDR и changePodCIDR. նրա վրա դուք կարող եք տեսնել կոդը այստեղ.

Ի՞նչ են անում նոր գործառույթները: Ալգորիթմ changeServiceCIDR:

  • ստեղծել ապասերիալիզատոր;
  • կազմել կանոնավոր արտահայտություն՝ CIDR-ին փոխարինելու համար.
  • մենք անցնում ենք բոլոր ծառայությունները ClusterIP տիպով կլաստերի մեջ.
    • վերծանել արժեքը etcd-ից Go օբյեկտի մեջ;
    • օգտագործելով կանոնավոր արտահայտություն, մենք փոխարինում ենք հասցեի առաջին երկու բայթերը.
    • ծառայությանը նշանակեք IP հասցե նոր ենթացանցից.
    • ստեղծել սերիալիզատոր, Go օբյեկտը վերածել պրոտոբուֆի, նոր տվյալներ գրել etcd-ում:

Ֆունկցիա changePodCIDR ըստ էության նման changeServiceCIDR - միայն ծառայության ճշգրտումը խմբագրելու փոխարեն մենք դա անում ենք հանգույցի համար և փոխում .spec.PodCIDR դեպի նոր ենթացանց:

Պրակտիկա

Փոխել ծառայությունը CIDR

Առաջադրանքն իրականացնելու պլանը շատ պարզ է, բայց այն ներառում է ընդհատում, մինչ կլաստերի բոլոր պատյանները վերստեղծվում են: Հիմնական քայլերը նկարագրելուց հետո մենք նաև կկիսվենք մտքերով, թե տեսականորեն ինչպես կարելի է նվազագույնի հասցնել այս պարապուրդը:

Նախապատրաստական ​​քայլեր.

  • անհրաժեշտ ծրագրաշարի տեղադրում և կարկատված etcdhelper-ի հավաքում;
  • կրկնօրինակում և այլն /etc/kubernetes.

Ծառայությունը փոխելու համառոտ գործողությունների ծրագիրCIDR.

  • apiserver-ի և վերահսկիչ-մենեջերի մանիֆեստների փոփոխություն;
  • վկայականների վերաթողարկում;
  • ClusterIP ծառայությունների փոփոխություն etcd-ում;
  • կլաստերի բոլոր պատյանների վերագործարկումը:

Ստորև ներկայացված է գործողությունների ամբողջական հաջորդականությունը՝ մանրամասն։

1. Տեղադրեք etcd-client տվյալների աղբավայրի համար.

apt install etcd-client

2. Կառուցել etcdhelper:

  • Տեղադրեք 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
  • Մենք խնայում ենք մեզ համար 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. Մնում է միայն վերագործարկել կլաստերի բոլոր պատյանները.
    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

Միևնույն ժամանակ, մենք որոշեցինք նայել, թե ինչպես կարելի է փոփոխել podNetwork-ը՝ օգտագործելով ստացված etcdhelper-ը: Գործողությունների հաջորդականությունը հետևյալն է.

  • կոնֆիգուրացիաների ամրագրում kube-system;
  • kube-controller-manager մանիֆեստի ամրագրում;
  • փոխել 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. Փոխարինեք podCIDR-ը՝ փոփոխություններ կատարելով անմիջապես 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. Եկեք ստուգենք, որ 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-ը չի կարողանա սկսել, և կլաստերի պատյանները չեն պլանավորվի:

Փաստորեն, podCIDR-ը փոխելը կարող է նույնիսկ ավելի պարզ լինել (օրինակ. այնքան) Բայց մենք ուզում էինք սովորել, թե ինչպես աշխատել etcd-ի հետ ուղղակիորեն, քանի որ կան դեպքեր, երբ խմբագրում ենք Kubernetes օբյեկտները etcd-ում. միայնակ հնարավոր տարբերակ. (Օրինակ, դուք չեք կարող պարզապես փոխել «Ծառայության» դաշտը առանց պարապուրդի spec.clusterIP.)

Լրիվ

Հոդվածում քննարկվում է etcd-ում տվյալների հետ ուղղակիորեն աշխատելու հնարավորությունը, այսինքն. շրջանցելով Kubernetes API-ն: Երբեմն այս մոտեցումը թույլ է տալիս «խորամանկ բաներ» անել։ Մենք փորձարկեցինք տեքստում տրված գործողությունները իրական K8 կլաստերների վրա: Այնուամենայնիվ, դրանց պատրաստակամության կարգավիճակը լայնածավալ օգտագործման համար է PoC (հայեցակարգի ապացույց). Հետևաբար, եթե ցանկանում եք օգտագործել etcdhelper կոմունալ ծրագրի փոփոխված տարբերակը ձեր կլաստերների վրա, դա արեք ձեր ռիսկով:

PS

Կարդացեք նաև մեր բլոգում.

Source: www.habr.com

Добавить комментарий