Why use NAT?

If an application is deployed using Kubernetes, most of the time there will be more than one pod serving the requests. If auto-scaling is enabled, Kubernetes creates and kills nodes and pods according to the load. This means the IP address of the outbound requests can change anytime. If your application needs to connect to a database that is living behind a firewall/VPC, you need to whitelist the IP address of the application. But in our example, the IP changes over time.

What is NAT?

Network Address Translation gateway is usually when the instances in a private cloud wants to connect to internet but do not want internet to initiate incoming connections.

In short, all the outbound connections from an instance can be configured to go through NAT and the IP address that the destination server sees will be the IP address of the NAT gateway which is static.

Configuring NAT for GKE Clusters

Note: Please ensure that you create a standard cluster. This is because an autopilot cluster does not provide granular access to Kubernetes-related namespaces, despite being suggested by GCP.

Creating Cloud NAT:

  1. Open Google Cloud and navigate to Cloud NAT: https://console.cloud.google.com/net-services/nat.
  2. Click on "Create Cloud NAT Gateway."
  3. Create a new Cloud Router by selecting the VPC network associated with the cluster.
  4. Under Cloud NAT Mapping, select "Managed Proxy Load Balancers." This option enables you to choose a "Cloud NAT IP Address." Select "Manual" from the dropdown menu, allowing you to create a static IP address.

Cloud NAT differ in behaviour with a private and public cluster. When creating a public GKE cluster by default, each node is provisioned with a public IP address, and outbound traffic is routed through these node IPs.

In the case of a private cluster, nodes do not have public IPs. Therefore, when configuring Cloud NAT, internet-bound traffic gains precedence, enabling you to acquire a fixed IP address for your outgoing traffic. To provide outbound internet access for your Pods and Services, configure Cloud NAT to Specify subnet ranges for NAT.

Masquerading in GKE

For a Public GKE cluster, it's important to note that internal calls within the cluster are not masqueraded and instead utilize the pod’s IP addresses. On the other hand, external traffic is masqueraded to the Node’s IP addresses. This behaviour is the default setting.

Steps to Configure Static IP Address for Public GKE Cluster

For testing purposes, any pod can be used to check the IP address assigned to it.

You can follow the steps below to create Cloud NAT. However, since the cluster is public, configuring Masquerade is also necessary.

  1. Create two files below, config & ip-masq-agent.yaml & apply on Kubernetes. This is an additional step required for the public Cluster.

config:

nonMasqueradeCIDRs:
  - 0.0.0.0/0
masqLinkLocal: true
resyncInterval: 60s

ip-masq-agent.yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ip-masq-agent
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: ip-masq-agent
  template:
    metadata:
      labels:
        k8s-app: ip-masq-agent
    spec:
      hostNetwork: true
      containers:
      - name: ip-masq-agent
        image: gcr.io/google-containers/ip-masq-agent-amd64:v2.4.1
        args:
            - --masq-chain=IP-MASQ
            # To non-masquerade reserved IP ranges by default, uncomment the line below.
            # - --nomasq-all-reserved-ranges
        securityContext:
          privileged: true
        volumeMounts:
          - name: config
            mountPath: /etc/config
      volumes:
        - name: config
          configMap:
            # Note this ConfigMap must be created in the same namespace as the
            # daemon pods - this spec uses kube-system
            name: ip-masq-agent
            optional: true
            items:
              # The daemon looks for its config in a YAML file at /etc/config/ip-masq-agent
              - key: config
                path: ip-masq-agent
      tolerations:
      - effect: NoSchedule
        operator: Exists
      - effect: NoExecute
        operator: Exists
      - key: "CriticalAddonsOnly"
        operator: "Exists"

These files need to be applied to the kube-system namespace:
kubectl create configmap ip-masq-agent --from-file config --namespace kube-system
kubectl apply -f ip-masq-agent.yaml

Configuring static IP addresses for a public GKE cluster involves additional steps, particularly when considering networking configurations like Cloud NAT and Masquerade. By following the outlined steps and applying necessary configurations, you can ensure the proper functioning and security of your public GKE cluster.