En este documento se describe cómo desplegar una aplicación en Google Distributed Cloud.
Antes de empezar
Para desplegar una carga de trabajo, debes tener un clúster de usuario, híbrido o independiente que pueda ejecutar cargas de trabajo.
Crear un despliegue
Con los siguientes pasos se crea un Deployment en tu clúster:
Copia el siguiente manifiesto en 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
Sustituye CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig de tu clúster.
Obtén información básica sobre tu implementación para confirmar que se ha creado correctamente:
kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra que la implementación tiene tres pods que están disponibles:
NAME READY UP-TO-DATE AVAILABLE AGE my-deployment 3/3 3 3 27s
Lista los pods de tu Deployment:
kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
La salida 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 tu implementación:
kubectl get deployment my-deployment --output yaml --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra detalles sobre la especificación y el estado del despliegue:
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 implementación:
kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
El resultado muestra detalles sobre la implementación con un formato adecuado, 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 servicio de tipo LoadBalancer
.
Una forma de exponer tu Deployment a clientes que no estén en tu clúster es crear un Service de Kubernetes de tipo
LoadBalancer
.
Para crear un servicio de tipo LoadBalancer
, sigue estos pasos:
Copia el siguiente manifiesto en 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 tener en cuenta sobre el servicio en este ejercicio:
Todos los pods que tengan la etiqueta
app: metrics
y la etiquetadepartment: sales
son miembros del servicio. Los pódcasts demy-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 miembro del pod debe tener un contenedor que esté escuchando en el puerto TCP
8080
.
De forma predeterminada, el contenedor
hello-app
escucha en el puerto TCP8080
. Puedes ver este ajuste de puerto en 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
Sustituye CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig de tu clúster.
Ver tu servicio:
kubectl get service my-service --output yaml --kubeconfig CLUSTER_KUBECONFIG
El resultado debería ser 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
) procede del intervalo de direcciones que especificaste al definir los grupos de direcciones del balanceador de carga (spec.loadBalancer.addressPools
) en el archivo de configuración del clúster.Por ejemplo, toma los valores que se muestran en el resultado anterior de 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 dirige a tu balanceador de carga y, desde ahí, se reenvía a un pod miembro en el puerto TCP8080
.- Dirección IP externa:
Llamar a tu servicio:
curl INGRESS_IP_ADDRESS
Sustituye INGRESS_IP_ADDRESS por la dirección IP de entrada de la sección
status
del servicio que has obtenido 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
. Por lo tanto, un servicio de tipo LoadBalancer
tiene una dirección IP de clúster y uno o varios valores de nodePort
.
De forma predeterminada, Kubernetes asigna puertos de nodo a los servicios de tipo LoadBalancer
.
Estas asignaciones pueden agotar rápidamente los puertos de nodo disponibles de los 2768 asignados a tu clúster. Para guardar los puertos de nodo, inhabilita la asignación de puertos de nodo del balanceador de carga definiendo el campo allocateLoadBalancerNodePorts
como false
en la especificación del servicio LoadBalancer
. Este ajuste impide que Kubernetes asigne puertos de nodo a los servicios LoadBalancer. Para obtener más información, consulta el artículo sobre cómo inhabilitar la asignación de NodePort del balanceador de carga en la documentación de Kubernetes.
Aquí tienes 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
Eliminar tu Servicio
Para eliminar tu Servicio, sigue estos pasos:
Usa
kubectl delete
para eliminar tu servicio del clúster:kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
Comprueba que tu servicio se haya eliminado:
kubectl get services --kubeconfig CLUSTER_KUBECONFIG
La salida ya no muestra
my-service
.
Eliminar tu implementación
Para eliminar tu implementación, sigue estos pasos:
Usa
kubectl delete
para eliminar tu Deployment del clúster:kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
Verifica que se ha eliminado tu implementación:
kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
La salida ya no muestra
my-deployment
.
Siguientes pasos
Crear objetos Ingress y Service