Google Cloud mixed HTTP/HTTPS Application load balancing - google-cloud-platform

I want to configure Google Could Load balancing so that:
All edge requests to port 443 terminate SSL at the load balancer and route to port 8080 in a managed instance group
All edge requests to port 80 route to port 8081 in a managed instance group which will then send a 307 response to the HTTPS service forcing SSL.
I have:
Global forwading rules
A global forwarding rule STATIC_IP:80 -> httpsreditect-target-proxy
A global forwarding rule STATIC_IP:443 -> webapp-target-proxy
Target proxies
httpsreditect-target-proxy -> httpredirect_urlmap
webapp-target-proxy -> webapp_urlmap
URL Maps
httpredirect_urlmap -> redirect_backend (8081 in the instance pool)
webapp_urlmap -> webapp_backend (8080 in the instance pool)
This does not work.
With this setup if I set the redirect_backend port to 8081 the webapp_backend port is also changed to 8081. Likewise if I set the webapp_backend port to 8080 then the redirect_backend port is set to 8080.
Is it possible to route traffic based on port to different backends? The option is their in the GUI, no validation errors, it feels like it should be possible but when a backend port is set all backends are then set to the same port?
I know putting HAProxy on the node is a solution and reverse proxy the microservices there but I'd rather have the Google Cloud Application Loadbalancer terminate SSL as using f1-micro instances.

The key to do this is an easily missed snippet at https://cloud.google.com/compute/docs/load-balancing/http/backend-service#restrictions_and_guidance.
Your configuration will be simpler if you do not add the same instance group to two different backends. If you do add the same instance group to two backends:
...
If your instance group serves two or more ports for several backends respectively, you have to specify different port names in the instance group.
The initial setup is non trivial so below is a reference.
Based on the example in my config:
A managed instance group
Main webapp running on port 80
HTTP redirect service running on port 8081
Firewall
Ensure you have firewall rules allowing a healthcheck access to your service from Google:
gcloud compute firewall-rules create allow-http-from-lb \
--description "Incoming http allowed from cloud loadbalancer." \
--allow tcp:80
--source-ranges "130.211.0.0/22"
gcloud compute firewall-rules create allow-http-redirect-from-lb \
--description "Incoming http redirect service allowed from cloud loadbalancer." \
--allow tcp:8081
--source-ranges "130.211.0.0/22"
Healthcheck
Ensure you have healthchecks setup for the two services checking on the correct internal ports.
gcloud compute http-health-checks create webapp-healthcheck \
--description "Main webapp healthcheck" \
--port 80 \
--request-path "/healthcheck"
gcloud compute http-health-checks create httpsredirect-service-healthcheck \
--description "HTTP redirect service healthcheck" \
--port 8081 \
--request-path "/healthcheck"
Configure named ports
The looks to be the key if your instance group has several microservices running on different ports that you want to expose under a common loadbalancer.
Replace INSTANCE_GROUP_NAME, REGION and the named-ports with correct values for your services.
gcloud compute instance-groups set-named-ports INSTANCE_GROUP_NAME \
--region=REGION \
--named-ports "webapp:80,httpsredirectservice:8081"
Create loadbalancer backends
Ensure the --port-name matches the correct named port from the previous step.
gcloud compute backend-services create webapp-lb-backend \
--http-health-check webapp-healthcheck \
--protocol http \
--description "Webapp load balancer backend" \
--port-name webapp
gcloud compute backend-services create httpsredirect-lb-backend \
--http-health-check webapp-healthcheck \
--protocol http \
--description "HTTP -> HTTPS redirect service load balancer backend" \
--port-name httpsredirectservice
Create URL Maps for the two services
Ensure --default-service uses the configured values from the previous step.
gcloud compute url-maps create webapp-urlmap \
--default-service webapp-lb-backend
gcloud compute url-maps create httpsredirect-urlmap \
--default-service httpsredirect-lb-backend
Create Target Proxies
Target proxies are referenced by one or more global forwarding rules and route the incoming HTTP or HTTPS requests to a URL map.
We create a https target proxy for the webapp to terminate SSL at the load balancer.
gcloud compute target-https-proxies create webapp-target-proxy \
--url-map webapp-urlmap \
--ssl-certificate [SSL_CERTIFICATES]
The redirect service:
gcloud compute target-http-proxies create httpsredirect-target-proxy \
--url-map httpsredirect-urlmap
Global forwarding rules
The final step is to create the global forwarding rules
gcloud compute forwarding-rules create webapp-forwarding-rule
--global \
--address LB_STATIC_IP \
--port-range 443 \
--target-https-proxy webapp-target-proxy
gcloud compute forwarding-rules create httpsredirect-forwarding-rule
--global \
--address LB_STATIC_IP \
--port-range 80 \
--target-http-proxy httpsredirect-target-proxy
Issues I hit
Ensure the firewall is configured correctly to allow healthchecks and healthchecks are setup.
If get intermitent 502 errors check the loadbalencers in the cloud console report healthy instances
Other notes
Because two url maps are needed you are charged for two load balancers looking at my billing info. Port 80 and port 443 both use their own load balancer
It doesn't look like it's possible to use a network loadbalancer bother terminating SSL and serving HTTP as can be done on AWS

Related

How to run Jupyter, locally, connecting to Google Cloud VM using only internal IP address?

I configured a Compute Engine instance with only an internal IP (10.X.X.10). I am able to ssh into it via gcloud with IAP with tunneling, access and copy files storage via Private Google Access and VPC was set up with no conflicting IP ranges:
gcloud compute ssh --zone "us-central1-c" "vm_name" --tunnel-through-iap --project "projectXXX"
Now I want to open Jupyter notebook without creating an external IP in the VM.
Identity-Aware Proxy (IAP) is working well, Private Google Access also. After that I enabled a NAT Gateway, that generated an external IP (35.X.X.155).
I configured Jupyter by running jupyter notebook --generate-config, set up a password "sha"
Now I run Jupyter by typing this on gcloud SSH:
python /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser &
Replacing:http://instance-XXX/?token=abcd
By:http://35.X.X.155/?token=abcd
But the external IP is not accessible, not even in the browser, neither in http nor in https. Note that I'm not considering using a Network Load Balancing, because it's not necessary.
Ping 35.X.X.155 works perfectly
I also tried jupyter notebook --gateway-url=http://NAT-gateway:8888
without success
Look at this as an alternative to a bastion (VM with external IP)
Any ideas on how to solve this issue ?
UPDATE: Looks like I have to find a way to SSH into the NAT Gateway.
What you are trying to do can be accomplished using IAP for TCP forwarding, and there is no need to use NAT at all in this scenario. Here are the steps to follow:
Ensure you have ports 22 and 8080 allowed in the project's firewall:
gcloud compute firewall-rules list
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
allow-8080-ingress-from-iap default INGRESS 1000 tcp:8080 False
allow-ssh-ingress-from-iap default INGRESS 1000 tcp:22 False
On your endpoint's gcloud CLI, log in to GCP and set the project to where the instance is running:
gcloud config set project $GCP_PROJECT_NAME
Check if you already have SSH keys generated in your system:
ls -1 ~/.ssh/*
#=>
/. . ./id_rsa
/. . ./id_rsa.pub
If you don't have any, you can generate them with the command: ssh-keygen -t rsa -f ~/.ssh/id_rsa -C id_rsa
Add the SSH keys to your project's metadata:
gcloud compute project-info add-metadata \
--metadata ssh-keys="$(gcloud compute project-info describe \
--format="value(commonInstanceMetadata.items.filter(key:ssh-keys).firstof(value))")
$(whoami):$(cat ~/.ssh/id_rsa.pub)"
#=>
Updated [https://www.googleapis.com/compute/v1/projects/$GCP_PROJECT_NAME].
Assign the iap.tunnelResourceAccessor role to the user:
gcloud projects add-iam-policy-binding $GCP_PROJECT_NAME \
--member=user:$USER_ID \
--role=roles/iap.tunnelResourceAccessor
Start an IAP tunnel pointing to your instance:port and bind it to your desired localhost port (in this case, 9000):
gcloud compute start-iap-tunnel $INSTANCE_NAME 8080 \
--local-host-port=localhost:9000
Testing if tunnel connection works.
Listening on port [9000].
At this point, you should be able to access your Jupyter Notebook in http://127.0.0.1:9000?token=abcd.
Note: The start-iap-tunnel command is not a one-time running command and should be issued and kept running every time you want to access your Jupyter Notebook implementation.

Where can i find my cluster domain in EKS?

I am trying to deploy the jpetstore app to EKS and have come across this variable that needs to be filled in. (https://github.com/IBM-Cloud/jpetstore-kubernetes/blob/master/jpetstore/jpetstore.yaml)
In the documentation it states that i can it using the commands:
Edit jpetstore/jpetstore.yaml and jpetstore/jpetstore-mmssearch.yaml and replace all instances of:
<CLUSTER DOMAIN> with your Ingress Subdomain (ibmcloud ks cluster get --cluster CLUSTER_NAME)
(https://github.com/IBM-Cloud/jpetstore-kubernetes)
but this is for ibm cloud and i need it for EKS.
Where can i get this <CLUSTER DOMAIN> value from?
You can define your own name in the ingress spec, example host: jpetstore.example.com. You need to install AWS LB Controller; which will handle your ingress request and create an ALB based on your ingress spec. You then access like: curl -H 'HOST: jpetstore.example.com' http://<your new alb endpoint>

Layer 2 connection between VMs in GCP?

I have two machines in the same VPC (under same subnet range) in GCP. I want to ping MAC address from one instance to another (ie. layer 2 connection). Is this supported in GCP?
If not, is GRE tunnel supported between the two VMs in the above configuration or any other tunneling?
My mail goal is to establish a layer 2 connection.
Andromeda (Google's Network) is a Software Defined Networking (SDN). Andromeda's goal is to expose the raw performance of the underlying network while simultaneously exposing network function virtualization.
Hence, Andromeda itself is not a Cloud Platform networking product; rather, it is the basis for delivering Cloud Platform networking services with high performance, availability, isolation, and security. For example, Cloud Platform firewalls, routing, and forwarding rules all leverage the underlying internal Andromeda APIs and infrastructure.
Also, By default, the instances are configured with a 255.255.255.255 mask (to prevent instance ARP table exhaustion), and when a new connection is initiated, the packet will be sent to the subnet’s gateway MAC address, regardless if the destination IP is outside or within the subnet range. Thus, the instance might need to make an ARP request to resolve the gateway’s MAC address first.
Unfortunately Google doesn't allow GRE traffic[1].
So, my recommendation is to run some test like iperf or MTR between them in order to validate layer 2.
You can not have L2 connectivity this out of the box. However, you can setup a VXLAN or other kind of tunnels between VMs if you really need L2 connectivity for some odd reason. I've written a blog about how to do this: https://samos-it.com/posts/gce-vm-vxlan-l2-connectivity.html (Copy pasting the main pieces below)
Create the VMs
In this section you will create 2 Ubuntu 20.04 VMs
Let's start by creating vm-1
gcloud compute instances create vm-1 \
--image-family=ubuntu-2004-lts --image-project=ubuntu-os-cloud \
--zone=us-central1-a \
--boot-disk-size 20G \
--boot-disk-type pd-ssd \
--can-ip-forward \
--network default \
--machine-type n1-standard-2
Repeat the same command creating vm-2 this time:
gcloud compute instances create vm-2 \
--image-family=ubuntu-2004-lts --image-project=ubuntu-os-cloud \
--zone=us-central1-a \
--boot-disk-size 20G \
--boot-disk-type pd-ssd \
--can-ip-forward \
--network default \
--machine-type n1-standard-2
Verify that SSH to both VMs is available and up. You might need o be patient.
gcloud compute ssh root#vm-1 --zone us-central1-a --command "echo 'SSH to vm-1 succeeded'"
gcloud compute ssh root#vm-2 --zone us-central1-a --command "echo 'SSH to vm-2 succeeded'"
Setup VXLAN mesh between the VMs
In this section, you will be creating the VXLAN mesh between vm-1 and vm-2 that you just created.
Create bash variables that will be used for setting up the VXLAN mesh
VM1_VPC_IP=$(gcloud compute instances describe vm-1 \
--format='get(networkInterfaces[0].networkIP)')
VM2_VPC_IP=$(gcloud compute instances describe vm-2 \
--format='get(networkInterfaces[0].networkIP)')
echo $VM1_VPC_IP
echo $VM2_VPC_IP
Create the VXLAN device and mesh on vm-1
gcloud compute ssh root#vm-1 --zone us-central1-a << EOF
set -x
ip link add vxlan0 type vxlan id 42 dev ens4 dstport 0
bridge fdb append to 00:00:00:00:00:00 dst $VM2_VPC_IP dev vxlan0
ip addr add 10.200.0.2/24 dev vxlan0
ip link set up dev vxlan0
EOF
Create the VXLAN device and mesh on vm-2
gcloud compute ssh root#vm-2 --zone us-central1-a << EOF
set -x
ip link add vxlan0 type vxlan id 42 dev ens4 dstport 0
bridge fdb append to 00:00:00:00:00:00 dst $VM1_VPC_IP dev vxlan0
ip addr add 10.200.0.3/24 dev vxlan0
ip link set up dev vxlan0
EOF
Start a tcpdump on vm-1
gcloud compute ssh root#vm-1 --zone us-central1-a
tcpdump -i vxlan0 -n
In another session ping vm-2 from vm-1 and take a look at tcpdump output. Notice the arp.
gcloud compute ssh root#vm-1 --zone us-central1-a
ping 10.200.0.3

Google Cloud Platform - receiving a 502 error for a backend not passing health checks

I have been following this guide to deploy Pega 7.4 on Google Cloud compute engine. Everything went smoothly however on the Load Balancer health check the service continues to be unhealthy.
When visiting the external IP a 502 is returned and in trying to troubleshoot GCP told us to "Make sure that your backend is healthy and supports HTTP/2 protocol". Well in the guide this command:
gcloud compute backend-services create pega-app \
--health-checks=pega-health \
--port-name=pega-web \
--session-affinity=GENERATED_COOKIE \
--protocol=HTTP --global
The protocol is HTTP but is this the same as HTTP/2?
What else could be wrong besides checking that the firewall setup allows the health checker and load balancer to pass through (below)?
gcloud compute firewall-rules create pega-internal \
--description="Pega node to node communication requirements" \
--action=ALLOW \
--rules=tcp:9300-9399,tcp:5701-5800 \
--source-tags=pega-app \
--target-tags=pega-app
gcloud compute firewall-rules create pega-web-external \
--description="Pega external web ports" \
--action=ALLOW \
--rules=tcp:8080,tcp:8443 \
--source-ranges=130.211.0.0/22,35.191.0.0/16 \
--target-tags=pega-app
Edit:
So the Instance group has a named port on 8080
gcloud compute instance-groups managed set-named-ports pega-app \
--named-ports=pega-web:8080 \
--region=${REGION}
And the health check config:
gcloud compute health-checks create http pega-health \
--request-path=/prweb/PRRestService/monitor/pingservice/ping \
--port=8080
I have checked VM Instance logs on the pega-app and getting 404 when trying to hit the ping service.
My problem was that I used a configured using a Static IP address without applying a domain name system record like this: gcloud compute addresses create pega-app --global I skipped this step so it generates ephemeral IP addresses each time the instances have to boot up.

GCP destination group instances not being checked

I'm trying to create a TCP/UDP load balancer on GCP to allow HA on my service, but I've noticed that when I create a destination group, all instances in that group are marked as unhealthy and are not being checked by google (I've seen the machine logs to check it). The firewall is open because is for testing purpose, so I'm sure that is not the problem.
I've created an HTTP/S load balancer using a backend with similar check configuration and the same machine is marked as healthy, so is not a problem of that machine (even now the logs shows how google is really checking that instance).
Both checks are HTTP to port 80, so I'm not able to see where's the problem and the difference between both kind of load balancers checkers.
Also I've checked to disable health check but the instance still marked as unhealthy and the traffic is not being sent to any of the instances, so the load balancer is not usefull it all.
Is necessary any other configuration to make it check the instance?
Thanks and greetings!!
Creating a TCP load balancer
When you're using any of the Google Cloud load balancers, you need not expose your VM's external ports to the internet, only your load balancer needs to be able to reach it.
The steps to create a TCP load balancer are described here. I find it convenient to use gcloud and run the commands, but you can also use the Cloud Console UI to achieve the same result.
I tried the below steps and it works for me (you can easily modify this to make it work with UDP as well - remember you still need HTTP health checks even when using UDP load balancing):
# Create 2 new instances
gcloud compute instances create vm1 --zone us-central1-f
gcloud compute instances create vm2 --zone us-central1-f
# Make sure you have some service running on port 80 on these VMs after creation.
# Create an address resource to act as the frontend VIP.
gcloud compute addresses create net-lb-ip-1 --region us-central1
# Create a HTTP health check (by default uses port 80).
$ gcloud compute http-health-checks create hc-1
# Create a target pool associated with the health check you just created.
gcloud compute target-pools create tp-1 --region us-central1 --http-health-check hc-1
# Add the instances to the target pool
gcloud compute target-pools add-instances tp-1 --instances vm1,vm2 --instances-zone us-central1-f
# Create a forwarding rule associated with the frontend VIP address we created earlier
# which will forward the traffic to the target pool.
$ gcloud compute forwarding-rules create fr-1 --region us-central1 --ports 80 --address net-lb-ip-1 --target-pool tp-1
# Describe the forwarding rule
gcloud compute forwarding-rules describe fr-1 --region us-central1
IPAddress: 1.2.3.4
IPProtocol: TCP
creationTimestamp: '2017-07-19T10:11:12.345-07:00'
description: ''
id: '1234567890'
kind: compute#forwardingRule
loadBalancingScheme: EXTERNAL
name: fr-1
portRange: 80-80
region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/us-central1
selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/us-central1/forwardingRules/fr-1
target: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/us-central1/targetPools/tp-1
# Check the health status of the target pool and verify that the
# target pool considers the backend instances to be healthy
$ gcloud compute target-pools get-health tp-1
---
healthStatus:
- healthState: HEALTHY
instance: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/us-central1-f/instances/vm1
ipAddress: 1.2.3.4
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/us-central1-f/instances/vm2
ipAddress: 1.2.3.4
kind: compute#targetPoolInstanceHealth
HTTP Health Checks are required for non-proxy TCP/UDP load balancers
If you're using a UDP load balancer (which is considered Network Load Balancing in Google CLoud), you will need to spin up a basic HTTP server which can respond to HTTP health checks in addition to your service which is listening on a UDP port for incoming traffic.
The same also applies to non-proxy based TCP load balancers (which is also considered Network Load balancing in Google Cloud).
This is documented here.
Health checking
Health checks ensure that Compute Engine forwards new connections only
to instances that are up and ready to receive them. Compute Engine
sends health check requests to each instance at the specified
frequency; once an instance exceeds its allowed number of health check
failures, it is no longer considered an eligible instance for
receiving new traffic. Existing connections will not be actively
terminated which allows instances to shut down gracefully and to close
TCP connections.
The health check continues to query unhealthy instances, and returns
an instance to the pool once the specified number of successful checks
is met.
Network load balancing relies on legacy HTTP Health checks for
determining instance health. Even if your service does not use HTTP,
you'll need to at least run a basic web server on each instance that
the health check system can query.