ProHoster > Blog > Administración > A nosa experiencia con datos no clúster de etcd Kubernetes directamente (sen API K8s)
A nosa experiencia con datos no clúster de etcd Kubernetes directamente (sen API K8s)
Cada vez máis, os clientes pídennos que proporcionemos acceso ao clúster de Kubernetes para poder acceder aos servizos dentro do clúster: poder conectarnos directamente a algunha base de datos ou servizo, conectar unha aplicación local con aplicacións dentro do clúster...
Por exemplo, é necesario conectarse desde a súa máquina local a un servizo memcached.staging.svc.cluster.local. Ofrecemos esta capacidade mediante unha VPN dentro do clúster ao que se conecta o cliente. Para iso, anunciamos subredes de pods, servizos e push cluster DNS ao cliente. Así, cando un cliente tenta conectarse ao servizo memcached.staging.svc.cluster.local, a solicitude diríxese ao DNS do clúster e, en resposta, recibe o enderezo deste servizo da rede de servizos do clúster ou do enderezo do pod.
Configuramos os clústeres K8s usando kubeadm, onde está a subrede de servizo predeterminada 192.168.0.0/16, e a rede de pods é 10.244.0.0/16. Normalmente todo funciona ben, pero hai un par de puntos:
Subrede 192.168.*.* utilízase a miúdo en redes de oficina cliente e aínda máis frecuentemente nas redes domésticas de desenvolvedores. E entón temos conflitos: os enrutadores domésticos traballan nesta subrede e a VPN empurra estas subredes do clúster ao cliente.
Temos varios clústeres (produción, escenario e/ou varios dev). Entón, por defecto, todos eles terán as mesmas subredes para pods e servizos, o que crea grandes dificultades para o traballo simultáneo con servizos en varios clústeres.
Hai tempo que adoptamos a práctica de usar diferentes subredes para servizos e pods dentro do mesmo proxecto, en xeral, para que todos os clústeres teñan redes diferentes. Non obstante, hai un gran número de clústeres en funcionamento que non me gustaría trasladar desde cero, xa que executan moitos servizos, aplicacións con estado, etc.
E entón preguntámonos: como cambiar a subrede nun clúster existente?
Busca de decisións
A práctica máis común é recrear todo servizos co tipo ClusterIP. Como opción, pode aconsellar e este:
O seguinte proceso ten un problema: despois de todo configurado, os pods aparecen coa IP antiga como servidor de nomes DNS en /etc/resolv.conf.
Como aínda non atopei a solución, tiven que restablecer todo o clúster con kubeadm reset e inicialo de novo.
Pero isto non é apto para todos... Aquí tes introducións máis detalladas para o noso caso:
Úsase franela;
Hai clusters tanto nas nubes como no hardware;
Gustaríame evitar volver implantar todos os servizos do clúster;
Hai que facer en xeral todo cun mínimo de problemas;
A versión de Kubernetes é 1.16.6 (non obstante, os pasos posteriores serán similares para outras versións);
A tarefa principal é garantir que nun clúster despregado usando kubeadm cunha subrede de servizo 192.168.0.0/16, substitúeo por 172.24.0.0/16.
E ocorreu que levabamos moito tempo interesados en ver que e como se almacena en Kubernetes en etcd, que se pode facer con el... Así que pensamos: “Por que non actualizar os datos en etcd, substituíndo os vellos enderezos IP (subrede) por outros novos? "
Despois de buscar ferramentas preparadas para traballar con datos en etcd, non atopamos nada que resolvese completamente o problema. (Por certo, se coñeces algunha utilidade para traballar con datos directamente en etcd, agradeceríamos as ligazóns). Non obstante, un bo punto de partida é etcdhelper desde OpenShift(grazas aos seus autores!).
Esta utilidade pode conectarse a etcd usando certificados e ler datos desde alí usando comandos ls, get, dump.
Engadir etcdhelper
O seguinte pensamento é lóxico: "Que é o que che impide engadir esta utilidade engadindo a capacidade de escribir datos en etcd?"
Converteuse nunha versión modificada de etcdhelper con dúas novas funcións changeServiceCIDR и changePodCIDR. sobre ela podes ver o código aquí.
Que fan as novas funcións? Algoritmo changeServiceCIDR:
crear un deserializador;
compilar unha expresión regular para substituír CIDR;
pasamos por todos os servizos co tipo ClusterIP no clúster:
decodificar o valor de etcd nun obxecto Go;
usando unha expresión regular substituímos os dous primeiros bytes do enderezo;
asignarlle ao servizo un enderezo IP da nova subrede;
creamos un serializador, convertemos o obxecto Go en protobuf, escribimos novos datos en etcd.
Función changePodCIDR esencialmente similares changeServiceCIDR - só en vez de editar a especificación do servizo, facémolo para o nodo e cambiamos .spec.PodCIDR a unha nova subrede.
Práctica
Cambio de servizo CIDR
O plan para implementar a tarefa é moi sinxelo, pero implica un tempo de inactividade no momento da recreación de todos os pods do clúster. Despois de describir os pasos principais, tamén compartiremos ideas sobre como, en teoría, este tempo de inactividade se pode minimizar.
Pasos preparatorios:
instalar o software necesario e montar o etcdhelper parcheado;
copia de seguridade etcd e /etc/kubernetes.
Breve plan de acción para cambiar o servizo CIDR:
cambiar os manifestos apiserver e controller-manager;
reemisión de certificados;
cambiar os servizos ClusterIP en etcd;
reinicio de todos os pods do clúster.
A seguinte é unha secuencia completa de accións en detalle.
Aforramos para nós etcdhelper.go, descargar dependencias, recoller:
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
4. Cambie a subrede do servizo nos manifestos do plano de control de Kubernetes. En arquivos /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml cambiar o parámetro --service-cluster-ip-range a unha nova subrede: 172.24.0.0/16 en vez de 192.168.0.0/16.
5. Dado que estamos cambiando a subrede de servizo á que kubeadm emite certificados para apiserver (incluído), hai que volver emitilos:
Vexamos para que dominios e enderezos IP se emitiu o certificado actual:
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
Imos preparar unha configuración mínima para kubeadm:
Atención! Neste momento, a resolución do dominio deixa de funcionar no clúster, xa que nos pods existentes /etc/resolv.conf o antigo enderezo CoreDNS (kube-dns) está rexistrado e kube-proxy cambia as regras de iptables da subrede antiga á nova. Máis adiante no artigo está escrito sobre posibles opcións para minimizar o tempo de inactividade.
Imos corrixir ConfigMap no espazo de nomes kube-system:
kubectl -n kube-system edit cm kubelet-config-1.16
- substituír aquí clusterDNS ao novo enderezo IP do servizo kube-dns: kubectl -n kube-system get svc kube-dns.
kubectl -n kube-system edit cm kubeadm-config
- arreglarémolo data.ClusterConfiguration.networking.serviceSubnet a unha nova subrede.
Dado que o enderezo de kube-dns cambiou, é necesario actualizar a configuración de kubelet en todos os nós:
Todo o que queda é reiniciar todos os pods do clúster:
kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'
Minimizar o tempo de inactividade
Pensamentos sobre como minimizar o tempo de inactividade:
Despois de cambiar os manifestos do plano de control, cree un novo servizo kube-dns, por exemplo, co nome kube-dns-tmp e novo enderezo 172.24.0.10.
Facer if en etcdhelper, que non modificará o servizo kube-dns.
Substitúe o enderezo en todos os kubelets ClusterDNS a un novo, mentres que o servizo antigo seguirá funcionando simultaneamente co novo.
Agarde ata que as vainas con aplicacións pasen por si mesmas por razóns naturais ou nunha hora acordada.
Eliminar servizo kube-dns-tmp e cambiar serviceSubnetCIDR para o servizo kube-dns.
Este plan permitirache minimizar o tempo de inactividade a ~un minuto durante a duración da eliminación do servizo kube-dns-tmp e cambiar a subrede para o servizo kube-dns.
Modificación podNetwork
Ao mesmo tempo, decidimos ver como modificar podNetwork usando o etcdhelper resultante. A secuencia de accións é a seguinte:
corrixindo as configuracións kube-system;
corrixindo o manifesto kube-controller-manager;
cambiar podCIDR directamente en etcd;
reinicie todos os nodos do clúster.
Agora máis sobre estas accións:
1. Modifique o ConfigMap no espazo de nomes kube-system:
kubectl -n kube-system edit cm kubeadm-config
- corrixindo data.ClusterConfiguration.networking.podSubnet a unha nova subrede 10.55.0.0/16.
6. Reiniciemos todos os nodos do clúster un por un.
7. Se deixas polo menos un nodo antigo podCIDR, entón kube-controller-manager non poderá iniciarse e non se programarán os pods do clúster.
De feito, cambiar podCIDR pódese facer aínda máis sinxelo (por exemplo, así). Pero queriamos aprender a traballar con etcd directamente, porque hai casos cando se editan obxectos de Kubernetes en etcd: o único variante posible. (Por exemplo, non pode simplemente cambiar o campo Servizo sen tempo de inactividade spec.clusterIP.)
Total
O artigo discute a posibilidade de traballar con datos en etcd directamente, é dicir. evitando a API de Kubernetes. Ás veces, este enfoque permíteche facer "cousas complicadas". Probamos as operacións indicadas no texto en clusters reais de K8s. Non obstante, o seu estado de preparación para o seu uso xeneralizado é PoC (proba de concepto). Polo tanto, se queres utilizar unha versión modificada da utilidade etcdhelper nos teus clústeres, faino baixo o teu propio risco.