53 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 (Capítulo 50, 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 (Nota).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: Parte 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 Capítulo 54, Configuración de red avanzada.Los clústeres IPv6 de pila única requieren un clúster de gestión de pila dual.
La arquitectura debe ser
x86_64oaarch64, dependiendo de la arquitectura del equipo sin sistema operativo que se va 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 de conexión del plano de control que utiliza la dirección VIP ya reservada (reemplazando el ${EDGE_VIP_ADDRESS_IPV4}) que se va a configurar y el indicador cloudProviderEnabled establecido en false porque se utilizan los tres nodos sin sistema operativo.
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: Metal3Cluster
metadata:
name: multinode-cluster
namespace: default
spec:
controlPlaneEndpoint:
host: ${EDGE_VIP_ADDRESS_IPV4}
port: 6443
cloudProviderEnabled: falseEl 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: Sección 60.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áticamentePROVIDERIDynode-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 bloque
storageque contiene los manifiestos necesarios para instalar los charts de HelmMetalLByendpoint-copier-operator.El archivo de recurso personalizado
metalLBque incluye elIPaddressPooly elL2Advertisementutilizados para exponer externamente el servidor de API para este clúster de descarga a través de la direcciónVIPconfigurada (reemplazando${EDGE_VIP_ADDRESS_IPV4}con esa direcciónVIPseleccionada).El archivo
endpoint-svc.yamlque se va a utilizar para configurar el serviciokubernetes-vippara que sea expuesto porMetalLBa través de la direcciónVIPconfigurada.El archivo
rke2-traefik-config.yamlque proporciona la configuración de ampliación para elRKE2gráfico de Helmrke2-traefikintegrado.El archivo
metallb-traefik-cr.yamlque contiene los manifiestos de instancia de recursos personalizadosMetalLB(IPAddressPoolyL2Advertisement) necesarios para exponer externamente el servicio Ingress a través de las IPs virtuales${INGRESS_IPV4}y${INGRESS_IPV6}.
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.36.3+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"
# Note we use _ as a delimiter for sed here because the providerid includes / characters
ExecStart=/bin/sh -c "sed -i \"s_PROVIDERID_$(jq -r .providerid /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
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: 307.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: 307.0.3+up0.16.1
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
spec:
type: LoadBalancer
externalTrafficPolicy: Local
allocateLoadBalancerNodePorts: false
mode: 0644
user:
name: root
group:
name: root
mode: 0644
user:
name: root
group:
name: root
- path: /var/lib/rancher/rke2/server/manifests/metallb-traefik-cr.yaml
overwrite: true
contents:
inline: |
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ingress-ippool
namespace: metallb-system
spec:
addresses:
- ${INGRESS_IPV4}/32
- ${INGRESS_IPV6}/128
serviceAllocation:
priority: 100
serviceSelectors:
- matchExpressions:
- {key: app.kubernetes.io/name, operator: In, values: [rke2-traefik]} # assign to rke2-traefik LB svc
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ingress-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- ingress-ippool
mode: 0644
user:
name: root
group:
name: root
kubelet:
extraArgs:
- provider-id=metal3://PROVIDERID
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 (Capítulo 50, 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/v1beta2
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
diskFormat: 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/v1beta2
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://PROVIDERID
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"
# Note we use _ as a delimiter for sed here because the providerid includes / characters
ExecStart=/bin/sh -c "sed -i \"s_PROVIDERID_$(jq -r .providerid /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/v1beta2
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
diskFormat: 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/v1beta2
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