Get your external IP with gpip

When we at Redeploy develop automation solutions or build/deploy pipelines we often need to get hold of our external IP so we can add it to access rules in a firewall or ACL, so that the job/agent has access to the intended cloud service.

There are many services that provides this functionality, but hosting it yourself provides control of availability and credibility. Therefore we decided to develop our own with the goal of it being small in size and easy to host and deploy.

Enter gpip. A microservice that returns the public/external IP of the caller. It’s delivered in a container image with the size of 5.84MB.

The source code is located on GitHub and the image at DockerHub.

Usage

The API provides two ways to get your IP.

  • JSON
  • Plain text

JSON:

Accept: application/json
GET /

Response
{"ip":"ip-address"}

Plain text:

Accept: text/plain
GET /

Response:
ip-address

Deploying the service

gpip can be hosted in a matter of ways:

  • Kubernetes (AKS)
  • WebApp for Containers
  • Virtual Machine

Any platform that can pass on source IP, either through the use of headers Forwarded, X-Forwarded-For and X-Real-IP or some other form of manipulating the remote address of the request will do.

In this post we give examples on how to deploy the service to Kubernetes, WebApp for Containers and how to build the binary to deploy it any way you want. Azure Container Instances would have been a good fit. It does not however support forwarding of origin IP at the time of this writing.

Do make sure to have an ingress with an TLS certificate as an entry point to the service. The service relies on an ingress/reverse proxy to handle TLS.

Kubernetes

To deploy the service into an AKS cluster (or any Kubernetes kluster) use the following definitions as guidelines.
A helm chart is in the works, but for now these will have to do:

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpip
  labels:
    app: gpip
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gpip
  template:
    metadata:
      labels:
        app: gpip
    spec:
      containers:
      - name: gpip
        image: redeployab/gpip:1.0.1
        resources:
          requests:
            cpu: 100m
            memory: 64Mi
          limits:
            cpu: 100m
            memory: 64Mi
        ports:
        - containerPort: 5050
        readinessProbe:
          tcpSocket:
            port: 5050
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 5050
          initialDelaySeconds: 15
          periodSeconds: 20

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: gpip
spec:
  selector:
    app: gpip
  type: ClusterIP
  ports:
  - name: http
    protocol: TCP
    port: 5050

And finally an example ingress.

ingress.yaml (example using nginx-ingress)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gpip
  namespace: gpip
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: gpip
          servicePort: 5050
        path: /(.*)

The ingress configuration is an example, therefore be sure to setup yours with an TLS certificate.

WebApp for Containers

Deploying an App Service plan and a WebApp:

Provision App Service

rgName=resource-group-name
planName=app-service-plan-name
appName=webapp-name
location=azure-region

az appservice plan create \
  --resource-group $rgName \
  --name $planName \
  --location $location \
  --sku S1 \
  --number-of-workers 1 \
  --is-linux

az webapp create \
  --resource-group $rgName \
  --plan $planName \
  --name $appName \
  ---deployment-container-image-name redeployab/gpip:1.0.1

When the provisioning is complete the service is ready for requests at: $appName.azurewebsites.net.

Build an executable binary

gpip does not have to be run in a container. Build the binary and host the service in a way you find the most fitting.

# Clone the repository.
git clone https://github.com/RedeployAB/gpip.git

cd gpip
chmod u+x build.sh

./build.sh --version 1.0.1 --platform linux|darwin

That concludes this post and we hope you have enjoyed the read!

If you want to discuss more, connect with me on LinkedIn.