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
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 haya creado 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
En el resultado, se muestran detalles con 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
Crear 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
A continuación, se presentan 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 servicio 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
. Si deseas ver esta configuración de puerto, observa el Dockerfile y el código fuente de la aplicación.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.
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 tu servicio 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 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 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 puertos de nodos, inhabilita la asignación de puertos de nodos del balanceador de cargas mediante la configuración del campo allocateLoadBalancerNodePorts
en false
en las especificaciones del servicio LoadBalancer
. Esta configuración evita que Kubernetes asigne puertos de nodos a los servicios 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
Borra tu Service
Para borrar tu 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 tu Deployment
Para borrar tu Deployment, sigue estos pasos:
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
.