Kubernetes cluster por $ 20 por mes

TL DR


Elevamos el clúster para el servicio de aplicaciones web sin estado con ingreso , encriptación , sin usar herramientas de automatización como kubespray, kubeadm y cualquier otra.
Tiempo de lectura: ~ 45-60 minutos, tiempo de reproducción: desde 3 horas.


Preámbulo


Me pidieron que escribiera un artículo por la necesidad de mi propio grupo de kubernetes para la experimentación. Las soluciones de instalación y configuración automatizadas de código abierto no funcionaron en mi caso, ya que utilicé distribuciones de Linux no convencionales. El trabajo intensivo con kubernetes en IPONWEB lo alienta a tener dicha plataforma, resolviendo sus tareas de una manera cómoda, incluso para proyectos en el hogar.


Componentes


Los siguientes componentes aparecerán en el artículo:


- Su Linux favorito - Usé Gentoo (nodo-1: systemd / node-2: openrc), Ubuntu 18.04.1.
- Servidor Kubernetes : kube-apiserver, kube-controller-manager, kube-Scheduler, kubelet, kube-proxy.
- Complementos Containerd + CNI (0.7.4) : para la contenedorización, tomaremos containerd + CNI en lugar de Docker (aunque inicialmente toda la configuración se cargó en Docker, por lo que nada evitará que se use si es necesario).
- CoreDNS : para organizar el descubrimiento del servicio de componentes que trabajan dentro del clúster kubernetes. Se recomienda una versión no inferior a 1.2.5, ya que con esta versión existe una buena compatibilidad para que los núcleos funcionen como un proceso que se ejecuta fuera del clúster.
- Franela : para organizar una pila de red, comunicar hogares y contenedores entre ellos.
- Tu db favorito .


Para todos


Limitaciones y Suposiciones


  • El artículo no examina el costo de las soluciones vps / vds en el mercado, así como la posibilidad de implementar máquinas en estos servicios. Se supone que ya tiene algo expandido, o puede hacerlo usted mismo. Además, la instalación / configuración de su base de datos favorita y el repositorio privado de Docker, si lo necesita, no están cubiertos.
  • Podemos usar los complementos containerd + cni y docker. Este artículo no considera el uso de Docker como herramienta de contenedorización. Si desea usar docker, usted mismo podrá configurar la franela en consecuencia , además deberá configurar kubelet, es decir, eliminar todas las opciones relacionadas con el contenedor. Como mostraron mis experimentos, docker y containerd en diferentes nodos como contenedores funcionarán correctamente.
  • No podemos usar host-gw backend para franela, lea la sección Configuración de franela para más detalles
  • No usaremos nada para monitorear, hacer copias de seguridad, guardar archivos de usuario (estado), almacenar archivos de configuración y código de aplicación (git / hg / svn / etc.)

Introduccion


En el curso del trabajo, utilicé una gran cantidad de fuentes, pero quiero mencionar por separado una guía bastante detallada de Kubernetes , que cubre aproximadamente el 90% de la configuración básica de su propio clúster. Si ya ha leído este manual, puede pasar directamente a la sección Configuración de franela .


Designaciones

Lista de Términos / Glosario


  • api-server: una máquina física o virtual en la que se encuentra un conjunto de aplicaciones para ejecutar y el correcto funcionamiento de kubernetes kube-apiserver. Para los propósitos de este artículo, es etcd, kube-apiserver, kube-controller-manager, kube-Scheduler.
  • master: una estación de trabajo dedicada o instalación de VPS, sinónimo de api-server.
  • nodo-X: una estación de trabajo dedicada o instalación de VPS, X indica el número de serie de la estación. En este artículo, todos los números son únicos y son clave para comprender:
    • nodo-1 - máquina número 1
    • nodo-2 - máquina número 2
  • vCPU: CPU virtual, núcleo del procesador. El número corresponde al número de núcleos: 1vCPU - un núcleo, 2vCPU - dos, y así sucesivamente.
  • usuario: usuario o espacio de usuario. Cuando se usan user$ instrucciones de la línea de comando user$ , el término se refiere a cualquier máquina cliente.
  • trabajador: el nodo de trabajo en el que se realizarán los cálculos directos, como sinónimo de node-X
  • recurso es la entidad en la que opera el clúster de Kubernetes. Los recursos de Kubernetes incluyen una gran cantidad de entidades relacionadas .

Soluciones de arquitectura de red


En el proceso de aumentar el clúster, no establecí la tarea de optimizar los recursos de hierro de tal manera que se ajustaran al presupuesto de $ 20 por mes. Solo era necesario ensamblar un clúster de trabajo con al menos dos nodos de trabajo (nodos). Por lo tanto, inicialmente el clúster se veía así:


  • máquina con 2 vCPU / 4G RAM: api-server + node-1 [20 $]
  • máquina con 2 vCPU / 4G RAM: nodo-2 [$ 20]

Después de que funcionó la primera versión del clúster, decidí reconstruirlo para distinguir entre los nodos responsables de ejecutar aplicaciones dentro del clúster (nodos de trabajo, también son trabajadores) y la API del servidor maestro.


Como resultado, obtuve la respuesta a la pregunta: "Cómo obtener un clúster más o menos económico, pero que funcione, si no quiero colocar las aplicaciones más gruesas allí".


Decisión de $ 20

Diseño
(Planificado para ser así)


Kubernetes Architecture Información general

Diseño
(Robado de Internet si alguien de repente todavía no sabe o no ha visto)


Componentes y su desempeño


El primer paso fue comprender cuántos recursos necesito para ejecutar paquetes de software que están directamente relacionados con el clúster. La búsqueda de "requisitos de hardware" no dio resultados específicos, por lo que tuve que abordar la tarea desde un punto de vista práctico. Como una medición de MEM y CPU, tomé estadísticas de systemd; podemos suponer que las mediciones se llevaron a cabo de una manera muy aficionada, pero no tuve la tarea de obtener valores precisos, ya que todavía no podía encontrar opciones más baratas que $ 5 por instancia.


¿Por qué exactamente $ 5?

Era posible encontrar VPS / VDS más barato al alojar servidores en Rusia o en la CEI, pero las tristes historias asociadas con ILV y sus acciones crean ciertos riesgos y dan lugar a un deseo natural de evitarlos.


Entonces


  • Servidor maestro / Configuración del servidor (Nodos maestros):
    • etcd (3.2.17): 80 - 100M, las métricas se tomaron en un momento seleccionado al azar. El consumo de memoria promedio de Etcd no superó los 300M;
    • kube-apiserver (1.12.x - 1.13.0): 237.6M ~ 300M;
    • kube-controller-manager (1.12.x - 1.13.0): aproximadamente 90M, no se elevó por encima de 100M;
    • Kube-Scheduler (1.12.x - 1.13.0): aproximadamente 20M, el consumo por encima de 30-50M no es fijo.
  • Configuración del servidor de trabajo (Nodos de trabajo):
    • kubelet (1.12.3 - 1.13.1): aproximadamente 35 Mb, el consumo por encima de 50M no es fijo;
    • kube-proxy (1.12.3 - 1.13.1): aproximadamente 7.5 - 10M;
    • franela (0.10.0): aproximadamente 15-20M;
    • núcleos (1.3.0): aproximadamente 25M;
    • containerd (1.2.1): el consumo de containerd es bajo, pero las estadísticas también muestran los procesos de contenedor iniciados por el demonio.

¿Se necesita containerd / docker en los nodos maestros?

No, no es necesario El nodo maestro no requiere acoplador o contenedor en sí, aunque hay una gran cantidad de manuales en Internet que, para algún propósito u otro, incluyen el uso del entorno para la contenedorización. En la configuración en cuestión, containerd se apagó intencionalmente de la lista de dependencias, sin embargo, no destaco ninguna ventaja obvia de este enfoque.


La configuración proporcionada anteriormente es mínima y suficiente para iniciar el clúster. No se requiere ninguna acción / componente adicional, a menos que desee agregar algo como desee.


Para construir un clúster de prueba o un clúster para proyectos domésticos, 1vCPU / 1G RAM será suficiente para que funcione el nodo maestro. Por supuesto, la carga en el nodo maestro variará según la cantidad de trabajadores involucrados, así como la disponibilidad y el volumen de solicitudes de terceros al servidor de API.


Exploté las configuraciones maestra y de trabajo de la siguiente manera:


  • 1x Maestro con componentes instalados: etcd, kube-apiserver, kube-controller-manager, kube-Scheduler
  • 2x trabajadores con componentes instalados: containerd, coredns, franela, kubelet, kube-proxy

Configuracion


Para configurar el asistente, se requieren los siguientes componentes:


  • etcd: para almacenar datos para api-server, así como para franela;


  • kube-apiserver - en realidad, api-server;


  • kube-controller-manager - para generar y procesar eventos;


  • kube-Scheduler: para la distribución de recursos registrados a través de api-server, por ejemplo, hearth .
    Para la configuración de caballos de batalla, se requieren los siguientes componentes:


  • kubelet: para ejecutar los hogares, para configurar los ajustes de red;


  • kube-proxy: para organizar el enrutamiento / equilibrio de los servicios de kubernetes;


  • núcleos: para el descubrimiento de servicios dentro de contenedores en ejecución;


  • franela: para organizar el acceso a la red de contenedores que operan en diferentes nodos, así como para la distribución dinámica de redes entre nodos de clúster (nodo kubernetes).



Coredns

Aquí se debe hacer una pequeña digresión: los núcleos también se pueden iniciar en el servidor maestro. No hay restricciones que obliguen a los coredns a ejecutarse en los nodos de trabajo, excepto el matiz de configuración coredns.service, que simplemente no se inicia en un servidor Ubuntu estándar / no modificado debido a un conflicto con el servicio resuelto systemd. No intenté resolver este problema, ya que los servidores 2 ns ubicados en los nodos de trabajo estaban muy contentos conmigo.


Para no perder tiempo ahora familiarizándose con todos los detalles del proceso de configuración de componentes, le sugiero que se familiarice con ellos en la guía de Kubernetes . Me centraré en las características distintivas de mi opción de configuración.


Archivos


Todos los archivos para el funcionamiento de los componentes del clúster para el asistente y los nodos de trabajo se colocan en / var / lib / kubernetes / por conveniencia. Si es necesario, puede colocarlos de otra manera.


Certificaciones


La base para la generación de certificados sigue siendo la misma Kubernetes de la manera difícil , prácticamente no hay diferencias significativas. Para regenerar certificados subordinados, se escribieron scripts de bash simples alrededor de aplicaciones cfssl ; esto fue muy útil en el proceso de depuración.


Puede generar certificados para sus necesidades utilizando los siguientes scripts, recetas de Kubernetes de la manera más difícil u otras herramientas adecuadas.


Generación de certificados utilizando scripts bash

Puede obtener scripts aquí: kubernetes bootstrap . Antes de comenzar, edite el archivo certs / env.sh , especificando su configuración. Un ejemplo:


 $ cd certs #:   certs$ ./generate-keys.sh # ... certificate generate output #:  kubeconfig     certs$ ./generate-configkube.sh 

Si usó env.sh y especificó correctamente todos los parámetros, entonces no es necesario tocar los certificados generados. Si cometió un error en algún momento, los certificados pueden regenerarse en partes. Los scripts de bash anteriores son triviales, ordenarlos no es difícil.


Una nota importante: a menudo no debe volver a crear los ca.pem y ca-key.pem , ya que son los certificados raíz para todos los certificados posteriores, en otras palabras, tendrá que recrear todos los certificados adjuntos y entregarlos a todas las máquinas y a todos los directorios necesarios.


El maestro


Los certificados necesarios para iniciar servicios en el nodo maestro deben colocarse en /var/lib/kubernetes/ :


  • ca.pem: este certificado se usa en todas partes, solo se puede generar una vez y luego usarse sin cambios, así que tenga cuidado. Cuando lo regenere, deberá copiarlo a todos los nodos, así como actualizar los archivos kubeconfig que lo usan (también en todas las máquinas).
  • ca-key.pem es lo mismo que copiar sobre nodos.
  • kube-controller-manager.pem: solo se necesita para kube-controller-manager.
  • kube-controller-manager-key.pem: solo se necesita para kube-controller-manager.
  • kubernetes.pem: se requiere para franela, núcleos al conectarse a etcd, kube-apiserver.


    Retiro teórico

    Esta característica se basa en la lógica de configuración de Kubernetes la vía difícil .
    En base a esto, este archivo será necesario en todas partes, tanto en el asistente como en los nodos de trabajo. No cambié el enfoque provisto por el manual original, ya que con su ayuda es posible organizar la operación del clúster de manera más rápida y clara y comprender el conjunto de dependencias.


    Mi opinión personal es que para etcd necesita certificados separados que no se superpongan con los certificados utilizados para kubernetes.




  • kubernetes-key.pem: permanece en servidores maestros.
  • service-account.pem: solo se necesita para los demonios kube-controller-manager.
  • service-account-key.pem - de manera similar.

Unidades de trabajo


  • ca.pem: necesario para todos los servicios involucrados en los nodos de trabajo (kubelet, kube-proxy), así como para franela, núcleos. Entre otras cosas, su contenido se incluye en los archivos kubeconfig cuando se generan usando kubectl.
  • kubernetes-key.pem: solo se necesita para que la franela y los núcleos se conecten a etcd, que se encuentra en el nodo maestro api.
  • kubernetes.pem: similar al anterior, necesario solo para franela y coredns.
  • kubelet / node-1.pem - clave para la autorización nodo-1.
  • kubelet / node-1-key.pem - clave para la autorización nodo-1.

Importante! Si tiene más de un nodo, cada nodo incluirá los archivos node-X-key.pem , node-X.pem y node-X.kubeconfig dentro de kubelet.


Depuración de certificados

Depuración de certificados


A veces puede que necesite ver cómo está configurado el certificado para averiguar qué hosts IP / DNS se usaron para generarlo. El cfssl-certinfo -cert <cert> nos ayudará con esto. Por ejemplo, aprendemos esta información para node-1.pem :


 $ cfssl-certinfo -cert node-1.pem 

 { "subject": { "common_name": "system:node:node-1", "country": "RU", "organization": "system:nodes", "organizational_unit": "Infrastructure Unit", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "system:nodes", "Infrastructure Unit", "system:node:node-1" ] }, "issuer": { "common_name": "Kubernetes", "country": "RU", "organization": "Kubernetes", "organizational_unit": "Infrastructure", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "Kubernetes", "Infrastructure", "Kubernetes" ] }, "serial_number": "161113741562559533299282037709313751074033027073", "sans": [ "w40k.net", "node-1", "178.79.168.130", "192.168.164.230" ], "not_before": "2019-01-04T14:24:00Z", "not_after": "2029-01-01T14:24:00Z", "sigalg": "SHA256WithRSA", "authority_key_id": "6:C8:94:67:59:55:19:82:AD:ED:6D:50:F1:89:B:8D:46:78:FD:9A", "subject_key_id": "A1:5E:B3:3C:45:14:3D:C6:C:A:97:82:1:D5:2B:75:1A:A6:9D:B0", "pem": "<pem content>" } 

Todos los demás certificados para kubelet y kube-proxy están integrados directamente en el kubeconfig correspondiente.


kubeconfig


Todo el kubeconfig necesario se puede hacer usando Kubernetes de la manera difícil , sin embargo, aquí comienzan algunas diferencias. El manual utiliza configuraciones de cni bridge kubedns y cni bridge , también cubre coredns y franela . Estos dos servicios, a su vez, usan kubeconfig para kubeconfig en el clúster.


 $ cd certs #:  kubeconfig     certs$ ./generate-configkube.sh 

El maestro


Para el asistente, se necesitan los siguientes archivos kubeconfig (como se mencionó anteriormente, después de la generación se pueden tomar en certs/kubeconfig ):


 master /var/lib/kubernetes/$ tree -L 2 . +-- kube-controller-manager.kubeconfig L-- kube-scheduler  L-- kube-scheduler.kubeconfig 

Estos archivos serán necesarios para ejecutar cada uno de los componentes del servicio.


Unidades de trabajo


Para los nodos de trabajo, se requieren los siguientes archivos kubeconfig:


 node-1 /var/lib/kubernetes/$ tree -L 2 . +-- coredns ¦  L-- coredns.kubeconfig +-- flanneld ¦  L-- flanneld.kubeconfig +-- kubelet ¦  L-- node-1.kubeconfig L-- kube-proxy  L-- kube-proxy.kubeconfig 

Lanzamiento de servicio


Servicios

A pesar del hecho de que mis nodos de trabajo usan diferentes sistemas de inicialización, los ejemplos y el repositorio dan opciones usando systemd. Con su ayuda, es más fácil comprender qué proceso y con qué parámetros debe comenzar, además, no deberían causar grandes problemas al estudiar servicios con banderas de destino.


Para iniciar los servicios, debe copiar service-name.service a /lib/systemd/system/ o cualquier otro directorio donde se encuentren los servicios para systemd, y luego encender e iniciar el servicio. Ejemplo para kube-apiserver:


 $ systemctl enable kube-apiserver.service $ systemctl start kube-apiserver.service 

Por supuesto, todos los servicios deben ser ecológicos (es decir, en ejecución y en funcionamiento). Si encuentra un error, los journalct -xe o journal -f -t kube-apiserver lo ayudarán a comprender exactamente qué salió mal.


No se apresure a iniciar todos los servidores a la vez, para empezar será suficiente para habilitar etcd y kube-apiserver. Si todo salió bien, e inmediatamente obtuvo los cuatro servicios en el asistente, el lanzamiento del asistente se puede considerar exitoso.


El maestro


Puede usar la configuración systemd o generar scripts de inicio para la configuración que está utilizando. Como ya se mencionó, para el maestro que necesita:


- systemd / etcd
- systemd / kube-apiserver
- systemd / kube-controller-manager
- systemd / kube-Scheduler


Unidades de trabajo


- systemd / containerd
- systemd / kubelet
- systemd / kube-proxy
- systemd / coredns
- systemd / franela


Cliente


Para que el cliente funcione, solo copie certs/kubeconfig/admin.kubeconfig (después de generarlo o escribirlo usted mismo) en ${HOME}/.kube/config


Descargue kubectl y verifique el funcionamiento de kube-apiserver. Permítanme recordarles una vez más que en esta etapa, para que kube-apiserver funcione, solo debería funcionar etcd. Los componentes restantes serán necesarios para la operación completa del clúster un poco más tarde.


Compruebe que kube-apiserver y kubectl funcionan:


 $ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."} 

Configuración de franela


Como configuración de franela, me decidí por el backend vxlan . Lea más sobre backends aquí .


host-gw y por qué no funcionará

Debo decir de inmediato que ejecutar un clúster de kubernetes en un VPS probablemente lo limitará a usar el servidor host-gw . Al no ser un ingeniero de redes experimentado, pasé unos dos días depurando para comprender cuál era el problema con su uso en proveedores populares de VDS / VPS.


Linode.com y digitalocean han sido probados. La esencia del problema es que los proveedores no proporcionan L2 honesto para una red privada. Esto, a su vez, hace que sea imposible mover el tráfico de red entre nodos en esta configuración:


Tráfico


Para que el tráfico de red funcione entre los nodos, será suficiente el enrutamiento normal. No olvide que net.ipv4.ip_forward debe establecerse en 1, y la cadena FORWARD en la tabla de filtros no debe contener reglas de prohibición para los nodos.


 node1$ ip route add 10.200.12.0/24 via 192.168.1.2 node2$ ip route add 10.200.8.0/24 via 192.168.1.1 

 [10.200.80.23 container-1]->[192.168.1.1 node-1]->[192.168.1.2 node-2]->[10.200.12.5 container-2] 

Esto es exactamente lo que no funciona en el VPS / VDS indicado (y, muy probablemente, generalmente en todos).


Por lo tanto, si la configuración de una solución con alto rendimiento de red entre los nodos es importante para usted, aún debe gastar más de $ 20 para organizar el clúster.


Puede usar set-flannel-config.sh de etc / set-flannel-config.sh para establecer la configuración de franela deseada. Es importante recordar : si decide cambiar el backend, deberá eliminar la configuración en etcd y reiniciar todos los demonios de franela en todos los nodos, así que elíjalo con prudencia. El valor predeterminado es vxlan.


 master$ export ETCDCTL_CA_FILE='/var/lib/kubernetes/ca.pem' master$ export ETCDCTL_CERT_FILE='/var/lib/kubernetes/kubernetes.pem' master$ export ETCDCTL_KEY_FILE='/var/lib/kubernetes/kubernetes-key.pem' master$ export ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' master$ etcdctl ls /coreos.com/network/subnets/ /coreos.com/network/subnets/10.200.8.0-24 /coreos.com/network/subnets/10.200.12.0-24 master$ etcdctl get /coreos.com/network/subnets/10.200.8.0-24 {"PublicIP":"178.79.168.130","BackendType":"vxlan","BackendData":{"VtepMAC":"22:ca:ac:15:71:59"}} 

Después de haber registrado la configuración deseada en etcd, debe configurar el servicio para ejecutarlo en cada uno de los nodos de trabajo.


servicio de franela


Un ejemplo para el servicio se puede tomar aquí: systemd / flannel


servicio de franela
 [Unit] Description=Flanneld overlay address etcd agent After=network.target [Service] Type=notify #: current host ip. don't change if ip have not changed Environment=PUBLIC_IP=178.79.168.130 Environment=FLANNEL_ETCD=https://192.168.153.60:2379 ExecStart=/usr/bin/flanneld \ -etcd-endpoints=${FLANNEL_ETCD} -etcd-prefix=${FLANNEL_ETCD_KEY} \ -etcd-cafile=/var/lib/kubernetes/ca.pem \ -etcd-certfile=/var/lib/kubernetes/kubernetes.pem \ -etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \ -etcd-prefix=/coreos.com/network \ -healthz-ip=127.0.0.1 \ -subnet-file=/run/flannel/subnet.env \ -public-ip=${PUBLIC_IP} \ -kubeconfig-file=/var/lib/kubernetes/config/kubeconfig/flanneld.kubeconfig \ $FLANNEL_OPTIONS ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure RestartSec=5 [Install] RequiredBy=docker.service 

Personalización


Como se describió anteriormente, necesitamos los archivos ca.pem, kubernetes.pem y kubernetes-key.pem para autorización en etcd. Todos los demás parámetros no tienen ningún significado sagrado. Lo único que es realmente importante es configurar la dirección IP global a través de la cual los paquetes de red irán entre redes:


Redes de franela
( Superposición de redes de host múltiple con franela )


 #:   node-1$ systemctl enable flanneld.service #:  node-1$ systemctl start flanneld 

Después de que franela se inicie correctamente, debe encontrar la interfaz de red flannel.N en su sistema:


 node-1$ ifconfig flannel.100: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.200.8.0 netmask 255.255.255.255 broadcast 0.0.0.0 inet6 fe80::20ca:acff:fe15:7159 prefixlen 64 scopeid 0x20<link> ether 22:ca:ac:15:71:59 txqueuelen 0 (Ethernet) RX packets 18853 bytes 1077085 (1.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 11856 bytes 264331154 (252.0 MiB) TX errors 0 dropped 47 overruns 0 carrier 0 collisions 0 

Verificar que sus interfaces funcionen correctamente en todos los nodos es bastante simple. En mi caso, el nodo 1 y el nodo 2 tienen redes 10.200.8.0/24 y 10.200.12.0/24, respectivamente, por lo que con una solicitud icmp regular verificamos su disponibilidad:


 #:  node-2  node-1 node-1 $ ping -c 1 10.200.12.0 PING 10.200.12.0 (10.200.12.0) 56(84) bytes of data. 64 bytes from 10.200.12.0: icmp_seq=1 ttl=64 time=4.58 ms #:  node-1  node-2 node-2 $ ping -c 1 10.200.8.0 PING 10.200.8.0 (10.200.8.0) 56(84) bytes of data. 64 bytes from 10.200.8.0: icmp_seq=1 ttl=64 time=1.44 ms 

En caso de algún problema, se recomienda verificar si hay reglas de corte en iptables sobre UDP entre hosts.


Configuración de contenedor


Coloque etc / containerd / config.toml en /etc/containerd/config.toml o donde sea conveniente para usted, lo principal es recordar cambiar la ruta al archivo de configuración en el servicio (containerd.service, descrito a continuación).


Configuración con algunas modificaciones del estándar. Es importante no configurar enable_tls_streaming = true si no comprende por qué lo está haciendo. De lo contrario, kubectl exec dejará de funcionar y dará un error de que el certificado fue firmado por una parte desconocida.


containerd.service


containerd.service
 [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target [Service] ; uncomment this if your overlay module are built as module ; ExecStartPre=/sbin/modprobe overlay ExecStart=/usr/bin/containerd \ -c /etc/containerd/config.toml Restart=always RestartSec=5 Delegate=yes KillMode=process OOMScoreAdjust=-999 LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity [Install] WantedBy=multi-user.target 

Personalización


, , cri-tools .
etc/crictl.yaml /etc/crictl.yaml . :


 node-1$ CONTAINERD_NAMESPACE=k8s.io crictl ps CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT POD ID 

, - kubernetes , crictl , , .


CNI Plugins


CNI , , , .


Personalización


cni plugins /opt/cni/bin/


/etc/cni/net.d :


/etc/cni/net.d/10-flannel.conflist
 { "cniVersion": "0.3.0", "name": "cbr0", "plugins": [ { "type": "flannel", "name": "kubenet", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true }, "externalSetMarkChain": "KUBE-MARK-MASQ" } ] } 

/etc/cni/net.d/99-loopback.conf
 { "cniVersion": "0.3.0", "type": "loopback" } 

, . , , Red Hat Docker Podman , Intro to Podman


Kubelet


kubelet ( cni) — . kubelet hostname. , "" kubectl logs , kubectl exec , kubectl port-forward .


kubelet-config.yaml

, etc/kubelet-config.yaml , , . :


 systemReserved: cpu: 200m memory: 600Mi 

, GO kubernetes, , . . 0.2 vCPU 600 MB .


, , kubelet, kube-proxy, coredns, flannel . , — 2 vCPU / 4G ram, , kubernetes + postgresql .


- (micro nodes) .


kubelet.service


service : systemd/kubelet


kubelet.service
 [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes Requires=containerd.service [Service] #Environment=NODE_IP=192.168.164.230 Environment=NODE_IP=178.79.168.130 #: node name given by env Environment=NODE_NAME=w40k.net ExecStart=kubelet \ --allow-privileged \ --root-dir=/var/lib/kubernetes/kubelet \ --config=/var/lib/kubernetes/kubelet/kubelet-config.yaml \ --kubeconfig=/var/lib/kubernetes/kubelet/node-1.kubeconfig \ --cni-bin-dir=/opt/cni/bin \ --cni-conf-dir=/etc/cni/net.d/ \ --network-plugin=cni \ --container-runtime=remote \ --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \ --image-pull-progress-deadline=10m \ --node-ip=${NODE_IP} \ --hostname-override=${NODE_NAME} \ --v=1 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 

Personalización


, RBAC , kubelet.


etc/kubelet-default-rbac.yaml , kubelet :


 user$ kubectl apply -f etc/kubelet-default-rbac.yaml 

, , .


 #:   node-1$ systemctl enable kubelet.service #:  node-1$ systemctl start kubelet 

, api :


 $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME w40k.net Ready <none> 5m v1.13.1 178.79.168.130 <none> Gentoo/Linux 4.18.16-x86_64-linode118 containerd://1.2.1 

Kube Proxy


: systemd/kubelet . , , kube-proxy-config.yaml : etc/kube-proxy


kube-proxy.service


kube-proxy.service
 [Unit] Description=Kubernetes Proxy Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] ExecStart=kube-proxy \ --config=/var/lib/kubernetes/kube-proxy/kube-proxy-config.yaml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 

Personalización


 #:   node-1$ systemctl enable kube-proxy.service #:  node-1$ systemctl start kube-proxy 

kube-proxy "" iptables, , - kubernetes (- ). .


CoreDNS


Corefile : etc/coredns/Corefile , :


/etc/coredns/Corefile
 .:53 { errors log stdout health :8081 kubernetes cluster.local 10.200.0.0/16 { endpoint https://178.79.148.185:6443 tls /var/lib/kubernetes/kubernetes.pem /var/lib/kubernetes/kubernetes-key.pem /var/lib/kubernetes/ca.pem pods verified upstream /etc/resolv.conf kubeconfig /var/lib/kubernetes/config/kubeconfig/coredns.kubeconfig default } proxy . /etc/resolv.conf cache 30 } 

coredns.kubeconfig pem- ( ) worker . , coredns systemd-resolved. , Ubuntu , , , , . .


coredns.service


coredns.service
 [Unit] Description=CoreDNS Documentation=https://coredns.io/ After=network.target [Service] ExecStart=/usr/bin/coredns -conf /etc/coredns/Corefile Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 

Personalización


 #:   node-1$ systemctl enable coredns.service #:  node-1$ systemctl start coredns 

, , :


 node-1$ dig kubernetes.default.svc.cluster.local @127.0.0.1 #:    ;kubernetes.default.svc.cluster.local. IN A ;; ANSWER SECTION: kubernetes.default.svc.cluster.local. 5 IN A 10.32.0.1 

, coredns ip kubernetes .
, kubernetes.default kube-controller-manager, :


 $ kubectl get svc -n default NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 26h 

nginx-ingress & cert-manager


, . nginx-ingress cert-manager.


nginx kubernetes ingress (master), :


  user$ git clone https://github.com/nginxinc/kubernetes-ingress.git user$ cd kubernetes-ingress/deployments user$ kubectl apply -f common/ns-and-sa.yaml user$ kubectl apply -f common/nginx-config.yaml user$ kubectl apply -f common/default-server-secret.yaml user$ kubectl apply -f daemon-set/nginx-ingress.yaml user$ kubectl apply -f rbac/rbac.yaml 

cert manager (v0.5.2)


  user$ git clone https://github.com/jetstack/cert-manager.git user$ cd cert-manager && git co v0.5.2 user$ cd contrib/manifests/cert-manager user$ kubectl apply -f with-rbac.yaml 

, , , :


 NAMESPACE NAME READY STATUS RESTARTS AGE cert-manager cert-manager-554c76fbb7-t9762 1/1 Running 0 3h38m nginx-ingress nginx-ingress-sdztf 1/1 Running 0 10h nginx-ingress nginx-ingress-vrf85 1/1 Running 0 10h 

cert-manager nginx-ingress running state, , . , Running . .



, . , kubernetes resource : app/k8s


 user$ kube apply -f ns-and-sa.yaml user$ kube apply -f configmap.yaml #:  secret-example.yaml       #: secret.yaml user$ kube apply -f secret.yaml user$ kube apply -f tls-production.yaml user$ kube apply -f deployment.yaml user$ kube apply -f service.yaml user$ kube apply -f ingress-production.yaml 

, - . , ( kubernetes-example.w40k.net), , , cert-manager nginx-ingress . , ingress tls/ssl.


:



, - . - , , .


Referencias


, , :


Kubernetes the hard way
Multi-Host Networking Overlay with Flannel
Intro to Podman
Stateless Applications
What is ingress


:


Kubernetes Networking: Behind the scenes ( )
A Guide to the Kubernetes Networking Model
Understanding kubernetes networking: services ( )


Q&A


<tbd>, .



, , . , , - , , .


Api Server


kube-apiserver.service , api-server' curl http . - .
admin.kubeconfig ${HOME}/.kube/config, kubectl api-server (kube-apiserver).


( ) HTTP 200 OK + , api-server :


 curl -H "Authorization: Bearer e5qXNAtwwCHUUwyLilZmAoFPozrQwUpw" -k -L https://<api-server-address>:6443/api/v1/ 

Kube Controller Manager


, controller manager api , . , service account' :


 $ kubectl get sa NAME SECRETS AGE default 1 19h 

, , kube-controller-manager .


Kube Scheduler


. , , debug/job.yaml kubectl describe <type/resource> .
, kube controller manager .


 #:   job user$ kubectl apply -f debug/job.yaml job.batch/app created #:  ,   job user$ kubectl get pods -l job-name=app NAME READY STATUS RESTARTS AGE app-9kr9z 0/1 Completed 0 54s #: ,        #:   user$ kubectl describe pods app-9kr9z # ...   ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 12s default-scheduler Successfully assigned example/app-9kr9z to w40k.net 

, default-scheduler pod w40k.net. - , — .


. , , , — "". systemd .


kube scheduler


Kubelet


Kubelet kubernetes . kubelet . kubernetes event ( kubectl get events -o wide ) .


( )


Kube Proxy


kube-proxy :


  • ( Flannel , );
  • iptables, filter nat .

, 10.32.0.0/24 "". , . iptables, , , - +. icmp , ping' . , .


, kube-proxy, :


 #:    user$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 10.32.0.195 <none> 80/TCP 5m #:     user$ kubectl get pods -o wide #:     ' NAME READY STATUS RESTARTS AGE IP NODE backend-896584448-4r94s 1/1 Running 0 11h 10.200.8.105 w40k.net backend-896584448-np992 1/1 Running 0 11h 10.200.12.68 docker.grart.net #:  10   /status/ endpoint ,       #:       node-1$ for i in `seq 10`; do curl -L http://10.32.0.195/status/; done okokokokokokokokokok node-1$ conntrack -L -d 10.32.0.195 tcp 6 62 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62158 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62158 [ASSURED] mark=0 use=1 tcp 6 60 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62144 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62144 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62122 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62122 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62142 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62142 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62130 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62130 [ASSURED] mark=0 use=1 tcp 6 61 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62150 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62150 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62116 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62116 [ASSURED] mark=0 use=1 tcp 6 57 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62118 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62118 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62132 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62132 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62114 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62114 [ASSURED] mark=0 use=1 

src/dst (9 10 ). , src :


  • 10.200.8.105
  • 10.200.12.68

, . , - ( , ) . .


 #: node-1   10.200.8.105, node-2 10.200.12.68, #:      8000  #:  node-1 node-1$ curl -L http://10.200.8.105:8000/status/ ok node-1$ curl -L http://10.200.12.68:8000/status/ ok #:  node-2 node-2$ curl -L http://10.200.8.105:8000/status/ ok node-2$ curl -L http://10.200.12.68:8000/status/ ok 

, , conntrack , , kube-proxy. , nat :


node-1$ iptables -t nat -vnL


.


. , , . , . - , , .


Source: https://habr.com/ru/post/es435228/


All Articles