52 Aprovisionamiento de clúster descendente con aprovisionamiento de red dirigido (multinodo) #
Esta sección describe el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida y MetalLB como estrategia de equilibrador de carga.
Esta es la forma más sencilla de automatizar el aprovisionamiento de un clúster descendente. El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida y MetalLB.
Requisitos
La imagen generada mediante
EIB, tal como se describe en la sección anterior (Chapter 49, Preparar la imagen del clúster descendente para escenarios conectados), con la configuración mínima para configurar el clúster descendente debe estar ubicada en el clúster de gestión exactamente en la vía que configuró en esta sección (Note).El servidor de gestión creado y disponible para ser utilizado en las siguientes secciones. Para obtener más información, consultad la sección del Clúster de gestión: Part V, “Configuración del clúster de gestión”.
Flujo de trabajo
El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida:
Inscribid los tres hosts de equipo sin sistema operativo para que estén disponibles para el proceso de aprovisionamiento.
Aprovisionad los tres hosts de equipo sin sistema operativo para instalar y configurar el sistema operativo y el clúster de Kubernetes utilizando
MetalLB.
Inscribid los hosts de equipo sin sistema operativo
El primer paso es inscribir los tres hosts de equipo sin sistema operativo en el clúster de gestión para que estén disponibles para ser aprovisionados.
Para ello, debéis crear los siguientes archivos (bmh-example-node1.yaml, bmh-example-node2.yaml y bmh-example-node3.yaml) en el clúster de gestión, para especificar las credenciales de BMC que se utilizarán y el objeto BaremetalHost que se inscribirá en el clúster de gestión.
Solo debéis reemplazar los valores entre
$\{…\}por los valores reales.Os guiaremos a través del proceso para un solo host. Los mismos pasos se aplican a los otros dos nodos.
apiVersion: v1
kind: Secret
metadata:
name: node1-example-credentials
type: Opaque
data:
username: ${BMC_NODE1_USERNAME}
password: ${BMC_NODE1_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
name: node1-example
labels:
cluster-role: control-plane
spec:
architecture: x86_64
online: true
bootMACAddress: ${BMC_NODE1_MAC}
bmc:
address: ${BMC_NODE1_ADDRESS}
disableCertificateVerification: true
credentialsName: node1-example-credentialsDónde:
${BMC_NODE1_USERNAME}— El nombre de usuario para la BMC del primer host bare-metal.${BMC_NODE1_PASSWORD}— La contraseña para la BMC del primer host bare-metal.${BMC_NODE1_MAC}— La dirección MAC del primer host bare-metal que se debe utilizar.${BMC_NODE1_ADDRESS}— La URL para el BMC del primer host bare-metal (por ejemplo,redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). La parte del host de la URL puede ser una dirección IP (v4 o v6) o un nombre de dominio, donde la infraestructura existente lo permita. Para obtener más información sobre las diferentes opciones disponibles según su proveedor de hardware, consulte el siguiente enlace.
Si no se ha especificado ninguna configuración de red para el host, ya sea en el momento de la creación de la imagen o a través de la definición
BareMetalHost, se utilizará un mecanismo de autoconfiguración (DHCP, DHCPv6, SLAAC). Para obtener más detalles o configuraciones complejas, consulte el Chapter 53, Configuración de red avanzada.Los clústeres IPv6 de pila única están en estado de vista previa técnica y aún no son compatibles oficialmente.
La arquitectura debe ser
x86_64oaarch64, dependiendo de la arquitectura de los hosts de equipo sin sistema operativo que se van a inscribir.Todos los servidores modernos vienen con un BMC capaz de manejar pila dual; sin embargo, la compatibilidad con IPv6 (y posiblemente la opción de usar nombres de host para la capacidad VirtualMedia) debe verificarse antes de su uso en producción en un entorno de pila dual.
Una vez creado el archivo, se debe ejecutar el siguiente comando en el clúster de gestión para comenzar a inscribir los equipos sin sistema operativo en el clúster de gestión:
$ kubectl apply -f bmh-example-node1.yaml
$ kubectl apply -f bmh-example-node2.yaml
$ kubectl apply -f bmh-example-node3.yamlLos nuevos objetos de equipo sin sistema operativo se inscriben, cambiando su estado de registro a inspección y disponible. Los cambios se pueden comprobar utilizando el siguiente comando:
$ kubectl get bmh -o wideEl objeto BaremetalHost está en el estado registering hasta que se validan las credenciales BMC. Una vez validadas las credenciales, el objeto BaremetalHost cambia su estado a inspecting, y este paso podría llevar algún tiempo dependiendo del hardware (hasta 20 minutos). Durante la fase de inspección, se recupera la información del hardware y se actualiza el objeto de Kubernetes. Compruebe la información utilizando el siguiente comando: kubectl get bmh -o yaml.
Paso de aprovisionamiento
Una vez que los tres equipos sin sistema operativo están inscritos y disponibles, el siguiente paso es aprovisionar los equipos sin sistema operativo para instalar y configurar el sistema operativo y el clúster de Kubernetes, creando un equilibrador de carga para gestionarlos.
Para ello, se debe crear el siguiente archivo (capi-provisioning-example.yaml) en el clúster de gestión con la siguiente información (el `capi-provisioning-example.yaml se puede generar uniendo los siguientes bloques).
Solo se deben reemplazar los valores entre
$\{…\}con los valores reales.La dirección
VIPes una dirección IP reservada que no está asignada a ningún nodo y se utiliza para configurar el equilibrador de carga. En un clúster de pila dual, se pueden especificar tanto una IPv4 como una IPv6, pero en los siguientes ejemplos se dará prioridad a la dirección IPv4.
A continuación se muestra la definición del clúster, donde la red del clúster se puede configurar utilizando los bloques pods y services. Además, contiene las referencias a los objetos del plano de control y de la infraestructura (utilizando el proveedor Metal3) que se van a utilizar.
apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
name: multinode-cluster
namespace: default
labels:
cluster-api.cattle.io/rancher-auto-import: "true"
spec:
clusterNetwork:
pods:
cidrBlocks:
- 192.168.0.0/18
- fd00:1234:4321::/48
services:
cidrBlocks:
- 10.96.0.0/12
- fd00:5678:8765:4321::/112
controlPlaneRef:
apiGroup: controlplane.cluster.x-k8s.io
kind: RKE2ControlPlane
name: multinode-cluster
infrastructureRef:
apiGroup: infrastructure.cluster.x-k8s.io
kind: Metal3Cluster
name: multinode-clusterSon posibles tanto despliegues de pila única como de pila dual; elimine los CIDR IPv6 y las direcciones VIP IPv6 (en las secciones siguientes) para un clúster solo IPv4.
Añadir la etiqueta
cluster-api.cattle.io/rancher-auto-import: "true"a los objetoscluster.x-k8s.ioimportará el clúster a Rancher (creando un objetoclusters.management.cattle.iocorrespondiente). Consulte la documentación de Cluster API para obtener más información.
El objeto Metal3Cluster especifica el punto final del plano de control que utiliza la dirección VIP ya reservada (reemplazando el ${EDGE_VIP_ADDRESS_IPV4}) para ser configurado y el noCloudProvider porque se utilizan los tres nodos de equipo sin sistema operativo.
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
name: multinode-cluster
namespace: default
spec:
controlPlaneEndpoint:
host: ${EDGE_VIP_ADDRESS_IPV4}
port: 6443
noCloudProvider: trueEl objeto RKE2ControlPlane especifica la configuración del plano de control que se va a utilizar, y el objeto Metal3MachineTemplate especifica la imagen del plano de control que se va a utilizar.
Una anotación de exclusión del equilibrador de carga que informa a los equilibradores de carga externos como MetalLB de que un nodo va a ser vaciado durante las operaciones de ciclo de vida, como la actualización de versión de los clústeres en sentido descendente. Para obtener información, consulte: Section 59.1, “Exclusión del equilibrador de carga”
El número de réplicas que se van a utilizar (en este caso, tres).
El modo de anuncio que debe utilizar el equilibrador de carga (
addressutiliza la implementación L2), así como la dirección que se va a utilizar (reemplazando el${EDGE_VIP_ADDRESS}con la direcciónVIP).El
serverConfigcon el complementoCNIque se va a utilizar (en este caso,Cilium), y la(s) dirección(es) y nombre(s)VIPadicionales que se incluirán entlsSan.El bloque agentConfig contiene el
Ignitionformato que se debe utilizar y eladditionalUserDataque se debe utilizar para configurar elRKE2nodo con información como:El servicio systemd denominado
rke2-preinstall.servicepara reemplazar automáticamente elBAREMETALHOST_UUIDy elnode-namedurante el proceso de aprovisionamiento utilizando la información de Ironic además de añadir la etiquetametal3.io/uuida los objetos Node con el UUIDBareMetalHost.El servicio systemd denominado
rke2-traefik-deployment.servicepara establecer la opción de configuración server de RKE2ingress-controlleren el archivo/etc/rancher/rke2/config.yamlatraefik.El bloque
storageque contiene los gráficos de Helm que se deben utilizar para instalar elMetalLBy elendpoint-copier-operator.El archivo de recurso personalizado
metalLBcon elIPaddressPooly elL2Advertisementque se deben utilizar (reemplazando${EDGE_VIP_ADDRESS_IPV4}con la direcciónVIP).El archivo
endpoint-svc.yamlque se debe utilizar para configurar el serviciokubernetes-vipque utilizará elMetalLBpara gestionar la direcciónVIP.
El último bloque de información contiene la versión de Kubernetes que se debe utilizar. El
${RKE2_VERSION}es la versión deRKE2que se debe utilizar reemplazando este valor (por ejemplo,v1.35.4+rke2r1).
apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
name: multinode-cluster
namespace: default
annotations: {
rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion: "true"
}
spec:
infrastructureRef:
apiGroup: infrastructure.cluster.x-k8s.io
kind: Metal3MachineTemplate
name: multinode-cluster-controlplane
replicas: 3
version: ${RKE2_VERSION}
rolloutStrategy:
type: "RollingUpdate"
rollingUpdate:
maxSurge: 0
registrationMethod: "control-plane-endpoint"
registrationAddress: ${EDGE_VIP_ADDRESS}
serverConfig:
cni: cilium
tlsSan:
- ${EDGE_VIP_ADDRESS_IPV4}
- ${EDGE_VIP_ADDRESS_IPV6}
- https://${EDGE_VIP_ADDRESS_IPV4}.sslip.io
- https://${EDGE_VIP_ADDRESS_IPV6}.sslip.io
agentConfig:
format: ignition
additionalUserData:
config: |
variant: fcos
version: 1.4.0
systemd:
units:
- name: rke2-preinstall.service
enabled: true
contents: |
[Unit]
Description=rke2-preinstall
Wants=network-online.target
Before=rke2-install.service
ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
[Service]
Type=oneshot
User=root
ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \" - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
ExecStartPost=/bin/sh -c "umount /mnt"
[Install]
WantedBy=multi-user.target
# rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
- name: rke2-traefik-deployment.service
enabled: true
contents: |
[Unit]
Description=rke2-traefik-deployment
Wants=rke2-preinstall.service
Before=rke2-install.service
ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
[Service]
Type=oneshot
User=root
ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
[Install]
WantedBy=multi-user.target
storage:
directories:
- path: /var/lib/rancher/rke2/server/manifests
overwrite: true
files:
# https://docs.rke2.io/networking/multus_sriov#using-multus-with-cilium
- path: /var/lib/rancher/rke2/server/manifests/rke2-cilium-config.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-cilium
namespace: kube-system
spec:
valuesContent: |-
cni:
exclusive: false
mode: 0644
user:
name: root
group:
name: root
- path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: endpoint-copier-operator
namespace: kube-system
spec:
chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
targetNamespace: endpoint-copier-operator
version: 306.0.1+up0.3.0
createNamespace: true
- path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: metallb
namespace: kube-system
spec:
chart: oci://registry.suse.com/edge/charts/metallb
targetNamespace: metallb-system
version: 306.0.2+up0.15.3
createNamespace: true
- path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
overwrite: true
contents:
inline: |
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- ${EDGE_VIP_ADDRESS_IPV4}/32
- ${EDGE_VIP_ADDRESS_IPV6}/128
serviceAllocation:
priority: 100
namespaces:
- default
serviceSelectors:
- matchExpressions:
- {key: "serviceType", operator: In, values: [kubernetes-vip]}
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- kubernetes-vip-ip-pool
- path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
overwrite: true
contents:
inline: |
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
labels:
serviceType: kubernetes-vip
spec:
ipFamilyPolicy: PreferDualStack
ports:
- name: rke2-api
port: 9345
protocol: TCP
targetPort: 9345
- name: k8s-api
port: 6443
protocol: TCP
targetPort: 6443
type: LoadBalancer
- path: /var/lib/rancher/rke2/server/manifests/rke2-traefik-config.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-traefik
namespace: kube-system
spec:
valuesContent: |-
ingressClass:
isDefaultClass: true
ports:
web:
hostPort: null # disallow hostPort
exposedPort: 80
websecure:
hostPort: null # disallow hostPort
exposedPort: 443
service:
enabled: true
type: LoadBalancer
spec:
externalTrafficPolicy: Local
allocateLoadBalancerNodePorts: false # k8s GA from 1.24; supported by MetalLB
mode: 0644
user:
name: root
group:
name: root
kubelet:
extraArgs:
- provider-id=metal3://BAREMETALHOST_UUID
nodeName: "Node-multinode-cluster"El objeto Metal3MachineTemplate especifica la siguiente información:
El
dataTemplateque se va a utilizar como referencia para la plantilla.El
hostSelectorque se debe utilizar coincidiendo con la etiqueta creada durante el proceso de inscripción.El
imageque se debe utilizar como referencia a la imagen generada medianteEIBen la sección (Chapter 49, Preparar la imagen del clúster descendente para escenarios conectados) anterior, ychecksumychecksumTypeque se deben utilizar para validar la imagen.
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: multinode-cluster-controlplane
namespace: default
spec:
template:
spec:
dataTemplate:
name: multinode-cluster-controlplane-template
hostSelector:
matchLabels:
cluster-role: control-plane
image:
checksum: http://imagecache.local:8080/eibimage-output-telco.raw.sha256
checksumType: sha256
format: raw
url: http://imagecache.local:8080/eibimage-output-telco.rawEl objeto Metal3DataTemplate especifica el metaData para el clúster en sentido descendente.
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
name: multinode-cluster-controlplane-template
namespace: default
spec:
clusterName: multinode-cluster
metaData:
objectNames:
- key: name
object: machine
- key: local-hostname
object: machine
- key: local_hostname
object: machineLos siguientes archivos yaml son un ejemplo de configuración para los nodos trabajadores.
A MachineDeployment:
apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDeployment
metadata:
labels:
cluster.x-k8s.io/cluster-name: multinode-cluster
nodepool: nodepool-0
name: multinode-cluster-workers
namespace: default
spec:
clusterName: multinode-cluster
replicas: 3
selector:
matchLabels:
cluster.x-k8s.io/cluster-name: multinode-cluster
nodepool: nodepool-0
template:
metadata:
labels:
cluster.x-k8s.io/cluster-name: multinode-cluster
nodepool: nodepool-0
spec:
bootstrap:
configRef:
apiGroup: bootstrap.cluster.x-k8s.io
kind: RKE2ConfigTemplate
name: multinode-cluster-workers
clusterName: multinode-cluster
infrastructureRef:
apiGroup: infrastructure.cluster.x-k8s.io
kind: Metal3MachineTemplate
name: multinode-cluster-workers
deletion:
nodeDrainTimeoutSeconds: 0
version: ${RKE2_VERSION}El objeto RKE2ConfigTemplate especifica la plantilla de configuración que se debe utilizar para los nodos trabajadores de clústeres multinodo.
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: RKE2ConfigTemplate
metadata:
name: multinode-cluster-workers
namespace: default
spec:
template:
spec:
agentConfig:
format: ignition
kubelet:
extraArgs:
- provider-id=metal3://BAREMETALHOST_UUID
nodeName: "Node-multinode-cluster-worker"
additionalUserData:
config: |
variant: fcos
version: 1.4.0
systemd:
units:
- name: rke2-preinstall.service
enabled: true
contents: |
[Unit]
Description=rke2-preinstall
Wants=network-online.target
Before=rke2-install.service
ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
[Service]
Type=oneshot
User=root
ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \" - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
ExecStartPost=/bin/sh -c "umount /mnt"
[Install]
WantedBy=multi-user.targetEl objeto Metal3MachineTemplate contiene referencias a dataTemplate, hostSelector y image para los nodos trabajadores:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: multinode-cluster-workers
namespace: default
spec:
template:
spec:
dataTemplate:
name: multinode-cluster-workers-template
hostSelector:
matchLabels:
cluster-role: worker
image:
checksum: http://imagecache.local:8080/eibimage-slmicro-rt-telco.raw.sha256
checksumType: sha256
format: raw
url: http://imagecache.local:8080/eibimage-slmicro-rt-telco.rawEl objeto Metal3DataTemplate especifica la metaData para el clúster descendente para los nodos trabajadores:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
name: multinode-cluster-workers-template
namespace: default
spec:
clusterName: multinode-cluster
metaData:
objectNames:
- key: name
object: machine
- key: local-hostname
object: machine
- key: local_hostname
object: machineUna vez creado el archivo uniendo los bloques anteriores, ejecute el siguiente comando en el clúster de gestión para comenzar a aprovisionar los tres nuevos hosts como equipos sin sistema operativo:
$ kubectl apply -f capi-provisioning-example.yaml