En este documento, se describe cómo implementar una aplicación en Google Distributed Cloud.
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
En los siguientes pasos, se crea 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 la implementación.kubectl apply -f my-deployment.yaml --kubeconfig CLUSTER_KUBECONFIG
Reemplaza CLUSTER_KUBECONFIG por la ruta de acceso del archivo kubeconfig del clúster de usuario.
Obtén información básica sobre tu Deployment para confirmar que se creó correctamente:
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
En el resultado, se muestran detalles con un buen formato sobre el 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 este parámetro de configuración de puerto si observas el Dockerfile y el código fuente de la app.Usa
kubectl apply
para crear el servicio 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 de usuario.
Observa tu servicio:
kubectl get service my-service --output yaml --kubeconfig CLUSTER_KUBECONFIG
El resultado es similar a este:
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 tu servicio tiene una
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 los grupos de direcciones del balanceador de cargas (spec.loadBalancer.addressPools
) en el archivo de configuración del clúster.Por ejemplo, toma los valores que se muestran en el resultado anterior para tu servicio:
- 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 a tu 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 de 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 servicios de tipo LoadBalancer
.
Estas asignaciones pueden agotar rápidamente 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 de nodo del balanceador de cargas configurando el campo allocateLoadBalancerNodePorts
en false
en la especificación del servicio LoadBalancer
. Este parámetro de configuración evita que Kubernetes asigne puertos de nodo a los servicios. Para obtener más información, consulta Cómo inhabilitar la asignación de NodePort del balanceador de cargas en la documentación de Kubernetes.
Este es un manifiesto para crear un servicio 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
Borra el Service
Para borrar tu servicio, haz lo siguiente:
Usa
kubectl delete
para borrar tu servicio 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, sigue estos pasos:
Usa
kubectl delete
para borrar tu Deployment de tu 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
.