Kubernetes: running a push-server with Gorush behind an AWS LoadBalancer
Tags: aws, kubernetes, tutorial
Published: 2020-02-06 17:57:35

---
title: Kubernetes: running a push-server with Gorush behind an AWS LoadBalancer
published: true
date: 2020-02-06 11:59:26 UTC
tags: AWS,Kubernetes,tutorial
canonical_url: https://rtfm.co.ua/en/kubernetes-running-a-push-server-with-gorush-behind-an-aws-loadbalancer/
---

[![](https://rtfm.co.ua/wp-content/uploads/2017/06/kuber-1.png)](https://rtfm.co.ua/wp-content/uploads/2017/06/kuber-1.png)Gorush is a Go-written application which we are planning to use to send push notifications to our mobile clients.

The project’s home – [https://github.com/appleboy/gorush](https://github.com/appleboy/gorush)

The service will be running in our Kubernetes cluster in a dedicated namespace and must be accessible within the cluster’s VPC only, so we will use an [Internal ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-create-internal-load-balancer.html) from AWS.

### Run Gorush service

#### Namespace

Clone a repository:

```
$ git clone https://github.com/appleboy/gorush
$ cd gorush/k8s/
```

Create a namespace and a [`confgiMap`](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) which will be used to configure access to a local Redis service:

```
$ kubectl apply -f gorush-namespace.yaml
namespace/gorush created

$ kubectl apply -f gorush-configmap.yaml
configmap/gorush-config created
```

We also can use this `configMap` later to add our own config-file for the Gorush service.

Check resources:

```
$ kubectl -n gorush get cm
NAME            DATA   AGE
gorush-config   2      20s
```

#### Redis

Spin up a Redis service:

```
$ kubectl apply -f gorush-redis-deployment.yaml
deployment.extensions/redis created

$ kubectl apply -f gorush-redis-service.yaml
service/redis created
```

#### Gorush

I’d like to add an additional pod with Debian to run tests after creating the Gorush to make sure it’s working, so let’s update the deployment file `gorush-deployment.yaml` with a new container named _Bastion_:

```
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: gorush
  namespace: gorush
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: gorush
        tier: frontend
    spec:
      containers:
      - image: appleboy/gorush
        name: gorush
        imagePullPolicy: Always
        ports:
        - containerPort: 8088
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8088
          initialDelaySeconds: 3
          periodSeconds: 3
        env:
        - name: GORUSH_STAT_ENGINE
          valueFrom:
            configMapKeyRef:
              name: gorush-config
              key: stat.engine
        - name: GORUSH_STAT_REDIS_ADDR
          valueFrom:
            configMapKeyRef:
              name: gorush-config
              key: stat.redis.host
      - image: debian
        name: bastion
        command: ["sleep"]
        args: ["6000"]
```

And now we can start the Gorush itself:

```
$ kubectl apply -f gorush-deployment.yaml
deployment.extensions/gorush created
```

Check pods:

```
$ kubectl -n gorush get po
NAME                      READY   STATUS    RESTARTS   AGE
gorush-59bd9dd4fc-dzm47   2/2     Running   0          8s
gorush-59bd9dd4fc-fkrhw   2/2     Running   0          8s
gorush-59bd9dd4fc-klsbz   2/2     Running   0          8s
redis-7d5844c58d-7j5jp    1/1     Running   0          3m1s
```

### AWS Internal Application Load Balancer

The next things to create are a Service with the [`NodePort`](https://rtfm.co.ua/en/kubernetes-part-1-architecture-and-main-components-overview/#NodePort) and an [`Ingress`](https://kubernetes.io/docs/concepts/services-networking/ingress/) service which will trigger an [`alb-ingress-controller`](https://github.com/kubernetes-sigs/aws-alb-ingress-controller) to create a new load balancer on an AWS account.

Update the `gorush-service.yaml` and uncomment the `NodePort` and comment out the `LoadBalancer` lines:

```
...
#type: LoadBalancer
type: NodePort
...
```

So now it looks like:

```
apiVersion: v1
kind: Service
metadata:
  name: gorush
  namespace: gorush
  labels:
    app: gorush
    tier: frontend
spec:
  selector:
    app: gorush
    tier: frontend
  # if your cluster supports it, uncomment the following to automatically create
  # an external load-balanced IP for the frontend service.
  #type: LoadBalancer
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8088
```

Create the service:

```
$ kubectl apply -f gorush-service.yaml
service/gorush created
```

And let’s configure the ALB. Update the `gorush-aws-alb-ingress.yaml`, add the `kubernetes.io/ingress.class: alb` to trigger the `alb-ingress-controller`, update _scheme_ to the _internal_ value, and set values for the subnets and a security-group.

Also, notice that `servicePort` was changed here from the original _8088_ to the _80_, as we are using an ALB and a dedicated `NodePort` Service:

```
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gorush
  namespace: gorush
  annotations:
    # Kubernetes Ingress Controller for AWS ALB
    # https://github.com/coreos/alb-ingress-controller
    #alb.ingress.kubernetes.io/scheme: internet-facing
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internal
    alb.ingress.kubernetes.io/subnets: subnet-010f9918532f52c6d, subnet-0f6dbde36b6669f48
    alb.ingress.kubernetes.io/security-groups: sg-0f1df776a767a2589
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: gorush
          servicePort: 80
```

Create an ALB:

```
$ kubectl apply -f gorush-aws-alb-ingress.yaml
ingress.extensions/gorush created
```

Check `alb-ingress-controller` logs:

```
$ kubectl logs -f -n kube-system $(kubectl get po -n kube-system | egrep -o 'alb-ingress[a-zA-Z0-9-]+')
...
E0206 11:08:52.664554       1 controller.go:217] kubebuilder/controller "msg"="Reconciler error" "error"="no object matching key "gorush/gorush" in local store"  "controller"="alb-ingress-controller" "request"={"Namespace":"gorush","Name":"gorush"}

I0206 11:08:53.731420       1 loadbalancer.go:191] gorush/gorush: creating LoadBalancer 3407a88c-gorush-gorush-f66a

I0206 11:08:54.372743       1 loadbalancer.go:208] gorush/gorush: LoadBalancer 3407a88c-gorush-gorush-f66a created, ARN: arn:aws:elasticloadbalancing:us-east-2:534***385:loadbalancer/app/3407a88c-gorush-gorush-f66a/d31b461c65a278f0

I0206 11:08:54.516572       1 targetgroup.go:119] gorush/gorush: creating target group 3407a88c-e50bdf2f1d39b9db54c
...

I0206 11:08:57.215907       1 rules.go:98] gorush/gorush: rule 1 modified with conditions [{    Field: "path-pattern",    Values: ["/*"]  }]
```

Check the `Ingress` service:

```
$ kubectl -n gorush get ingress
NAME     HOSTS   ADDRESS                                                                     PORTS   AGE
gorush   *       internal-3407a88c-gorush-gorush-f66a-***.us-east-2.elb.amazonaws.com   80      3m57s
```

### Testing the API

Let’s connect to our Bastion hos, install `dnsutils`, `dnsping` and the `curl` packages.

To get a Pod we can use the following command:

```
$ kubectl -n gorush get pod | grep gorush | cut -d" " -f 1 | tail -1
gorush-59bd9dd4fc-klsbz
```

And to connect to the _Bastion_:

```
$ kubectl -n gorush exec -ti $(kubectl -n gorush get pod | grep gorush | cut -d" " -f 1 | tail -1) -c bastion bash
root@gorush-59bd9dd4fc-klsbz:/#
```

Install necessary utils, and check if our push-service is working:

```
root@gorush-59bd9dd4fc-klsbz:/# apt update && apt -y install dnsutils curl dnsdiag

root@gorush-59bd9dd4fc-klsbz:/# curl dualstack.internal-3407a88c-gorush-gorush-f66a-***.us-east-2.elb.amazonaws.com
{"text":"Welcome to notification server."}
```

Looks good so far.

### Route53

Let’s check if our Internal ALB is resolved to a Private IP, as it’s type was set to the _Internal_:

```
root@gorush-59bd9dd4fc-klsbz:/# dig +short dualstack.internal-3407a88c-gorush-gorush-f66a-***.us-east-2.elb.amazonaws.com
10.0.15.167
10.0.23.138
```

Good.

We’d like to use an own URL to access the ALB created above, so let’s go to the AWS Route53, and add a new record pointed to the ALB as usual – via an `ALIAS`:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200206_134706.png)](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200206_134706.png)

And make a `GET` request from the _Bastion_ to make it running inside of the VPS using its own DNS to resolve the domain to the ALB’s Private IPs:

```
root@gorush-59bd9dd4fc-klsbz:/# dig push.example.com +short
10.0.23.138
10.0.15.167
```

The service:

```
root@gorush-59bd9dd4fc-klsbz:/# curl push.example.com
{"text":"Welcome to notification server."}
```

Done.


### Similar posts

- <small>08/10/2019</small> [Kubernetes: part 2 – a cluster set up on AWS with AWS cloud-provider and AWS LoadBalancer](https://rtfm.co.ua/en/kubernetes-part-2-a-cluster-set-up-on-aws-with-aws-cloud-provider-and-aws-loadbalancer/)  
- <small>01/30/2020</small> [Kubernetes: could not find the requested resource (get services http:heapster:) and running metrics-server](https://rtfm.co.ua/en/kubernetes-could-not-find-the-requested-resource-get-services-httpheapster-and-running-metrics-server/)   
- <small>08/30/2018</small> [AWS: Application Load Balancer – HTTP => HTTPS и host-header редиректы](https://rtfm.co.ua/aws-application-load-balancer-http-https-i-host-header-redirekty/) 
- <small>08/15/2019</small> [Kubernetes: part 3 – AWS EKS overview and manual EKS cluster set up](https://rtfm.co.ua/en/kubernetes-part-3-aws-eks-overview-and-manual-eks-cluster-set-up/)