En este documento, se describe cómo implementar una aplicación en GKE en Bare Metal.
Antes de comenzar
Para implementar una carga de trabajo, debes tener un clúster de usuario, híbrido o independiente que pueda ejecutar cargas de trabajo.
Crear una implementación
Sigue estos pasos para crear un Deployment en tu clúster:
Luego, copia el siguiente manifiesto a un archivo llamado
my-deployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: selector: matchLabels: app: metrics department: sales replicas: 3 template: metadata: labels: app: metrics department: sales spec: containers: - name: hello image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
Usa
kubectl apply
para crear el Deployment:kubectl apply -f my-deployment.yaml --kubeconfig CLUSTER_KUBECONFIG
Reemplaza CLUSTER_KUBECONFIG por la ruta de acceso del archivo kubeconfig del clúster.
Obtén información básica sobre tu Deployment para confirmar que se creó de forma correcta:
kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra que el Deployment tiene tres Pods y que todos están disponibles:
NAME READY UP-TO-DATE AVAILABLE AGE my-deployment 3/3 3 3 27s
Obtén una lista de los Pods del Deployment:
kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra que tu Deployment tiene tres Pods en ejecución:
NAME READY STATUS RESTARTS AGE my-deployment-869f65669b-5259x 1/1 Running 0 34s my-deployment-869f65669b-9xfrs 1/1 Running 0 34s my-deployment-869f65669b-wn4ft 1/1 Running 0 34s
Obtén información detallada sobre el Deployment:
kubectl get deployment my-deployment --output yaml --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra detalles sobre la especificación y el estado del Deployment:
apiVersion: apps/v1 kind: Deployment metadata: ... generation: 1 name: my-deployment namespace: default ... spec: ... replicas: 3 revisionHistoryLimit: 10 selector: matchLabels: app: metrics department: sales ... spec: containers: - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0 imagePullPolicy: IfNotPresent name: hello resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 status: availableReplicas: 3 conditions: - lastTransitionTime: "2023-06-29T16:17:17Z" lastUpdateTime: "2023-06-29T16:17:17Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2023-06-29T16:17:12Z" lastUpdateTime: "2023-06-29T16:17:17Z" message: ReplicaSet "my-deployment-869f65669b" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing observedGeneration: 1 readyReplicas: 3 replicas: 3 updatedReplicas: 3
Describe tu Deployment:
kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra detalles con un buen formato sobre la Deployment, incluido el ReplicaSet asociado:
Name: my-deployment Namespace: default CreationTimestamp: Thu, 29 Jun 2023 16:17:12 +0000 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=metrics,department=sales Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=metrics department=sales Containers: hello: Image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: my-deployment-869f65669b (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 6m50s deployment-controller Scaled up replica set my-deployment-869f65669b to 3
Crea un Service de tipo LoadBalancer
Una forma de exponer el Deployment a clientes fuera de tu clúster es crear un Service de Kubernetes de tipo LoadBalancer
.
Para crear un Service de tipo LoadBalancer
, haz lo siguiente:
Luego, copia el siguiente manifiesto a un archivo llamado
my-service.yaml
:apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: metrics department: sales type: LoadBalancer ports: - port: 80 targetPort: 8080
Estos son los aspectos importantes que debes comprender sobre el servicio en este ejercicio:
Cualquier pod que tenga las etiquetas
app: metrics
ydepartment: sales
es miembro del servicio. Los Pods enmy-deployment
tienen estas etiquetas.Cuando un cliente envía una solicitud al Service en el puerto TCP
80
, la solicitud se reenvía a un Pod miembro en el puerto TCP8080
.Cada Pod miembro debe tener un contenedor que escuche en el puerto TCP
8080
.
De forma predeterminada, el contenedor
hello-app
escucha en el puerto TCP8080
. Puedes ver la configuración del puerto en el Dockerfile y el código fuente de la app.Usa
kubectl apply
para crear el Service en tu clúster:kubectl apply -f my-service.yaml --kubeconfig CLUSTER_KUBECONFIG
Reemplaza CLUSTER_KUBECONFIG por la ruta de acceso del archivo kubeconfig del clúster.
Observa tu servicio:
kubectl get service my-service --output yaml --kubeconfig CLUSTER_KUBECONFIG
El resultado es similar al siguiente:
apiVersion: v1 kind: Service metadata: ... name: my-service namespace: default ... spec: allocateLoadBalancerNodePorts: true clusterIP: 10.96.2.165 clusterIPs: - 10.96.2.165 externalTrafficPolicy: Cluster internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - nodePort: 31565 port: 80 protocol: TCP targetPort: 8080 selector: app: metrics department: sales sessionAffinity: None type: LoadBalancer status: loadBalancer: ingress: - ip: 192.168.1.13
En el resultado anterior, puedes ver que el Service tiene un
clusterIP
y una dirección IP externa. También tiene unnodePort
, unport
y untargetPort
.El
clusterIP
no es relevante para este ejercicio. La dirección IP externa (status.loadBalancer.ingress.ip
) proviene del rango de direcciones que especificaste cuando definiste grupos de direcciones del balanceador de cargas (spec.loadBalancer.addressPools
) en el archivo de configuración del clúster.Como ejemplo, toma los valores que se muestran en el resultado anterior para tu Service:
- Dirección IP externa:
192.168.1.13
port
:80
nodePort
:31565
targetPort
:8080
Un cliente envía una solicitud a
192.168.1.13
en el puerto TCP80
. La solicitud se enruta al balanceador de cargas y desde allí se reenvía a un Pod miembro en el puerto TCP8080
.- Dirección IP externa:
Llama a tu Service:
curl INGRESS_IP_ADDRESS
Reemplaza INGRESS_IP_ADDRESS por la dirección IP de entrada en la sección
status
del servicio que recuperaste en el paso anterior (status.loadBalancer.ingress
).El resultado muestra un mensaje
Hello, world!
:Hello, world! Version: 2.0.0 Hostname: my-deployment-869f65669b-wn4ft
Límites de puertos LoadBalancer
El tipo LoadBalancer
es una extensión del tipo NodePort
. Entonces, un servicio de tipo LoadBalancer
tiene una dirección IP de clúster y uno o más valores nodePort
.
De forma predeterminada, Kubernetes asigna puertos de nodo a Services de tipo LoadBalancer
.
Estas asignaciones pueden agotar con rapidez los puertos de nodo disponibles de los 2,768 asignados a tu clúster. Para guardar los puertos de nodo, inhabilita la asignación de puertos del nodo del balanceador de cargas mediante la configuración del campo allocateLoadBalancerNodePorts
en false
en la especificación del Service LoadBalancer
. Esta configuración evita que Kubernetes asigne puertos de nodo a los servicios de LoadBalancer. Para obtener más información, consulta Inhabilita la asignación de NodePort del balanceador de cargas en la documentación de Kubernetes.
A continuación, se muestra un manifiesto para crear un Service que no use ningún puerto de nodo:
apiVersion: v1
kind: Service
metadata:
name: service-does-not-use-nodeports
spec:
selector:
app: my-app
type: LoadBalancer
ports:
- port: 8000
# Set allocateLoadBalancerNodePorts to false
allocateLoadBalancerNodePorts: false
Borrar el servicio
Para borrar el Service, haz lo siguiente:
Usa
kubectl delete
para borrar el Service del clúster:kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
Verifica que se haya borrado tu Service:
kubectl get services --kubeconfig CLUSTER_KUBECONFIG
El resultado ya no muestra
my-service
.
Borra el Deployment
Para borrar tu Deployment, haz lo siguiente:
Usa
kubectl delete
para borrar el Deployment del clúster:kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
Verifica que se haya borrado el Deployment:
kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
El resultado ya no muestra
my-deployment
.