deploy Laravel in kubernetes

1/31/2019

I'm trying to deploy a laravel application in kubernetes at Google Cloud Platform.

I followed couple of tutorials and was successful trying them locally on a docker VM.

https://learnk8s.io/blog/kubernetes-deploy-laravel-the-easy-way

https://blog.cloud66.com/deploying-your-laravel-php-applications-with-cloud-66/

But when tried to deploy in kubernetes using an ingress to assign a domain name to the application. I keep getting the 502 bad gateway page.

I'm using a nginx ingress controller with image k8s.gcr.io/nginx-ingress-controller:0.8.3 and my ingress is as following

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - domainname.com
    secretName: sslcertificate
  rules:
  - host: domain.com
    http:
      paths:
      - backend:
          serviceName: service
          servicePort: 80
        path: /

this is my application service

apiVersion: v1
kind: Service
metadata:
  name: service
  labels:
    name: demo
    version: v1
spec:
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
  selector:
    name: demo
  type: NodePort

this is my ingress controller

apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  labels:
    k8s-app: default-http-backend
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    k8s-app: default-http-backend
---
apiVersion: v1
kind: ReplicationController
metadata:
  name: default-http-backend
spec:
  replicas: 1
  selector:
    k8s-app: default-http-backend
  template:
    metadata:
      labels:
        k8s-app: default-http-backend
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: default-http-backend
        # Any image is permissable as long as:
        # 1. It serves a 404 page at /
        # 2. It serves 200 on a /healthz endpoint
        image: gcr.io/google_containers/defaultbackend:1.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi
---
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-ingress-controller
  labels:
    k8s-app: nginx-ingress-lb
spec:
  replicas: 1
  selector:
    k8s-app: nginx-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: nginx-ingress-lb
        name: nginx-ingress-lb
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - image: gcr.io/google_containers/nginx-ingress-controller:0.8.3
        name: nginx-ingress-lb
        imagePullPolicy: Always
        readinessProbe:
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
        livenessProbe:
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          timeoutSeconds: 1
        # use downward API
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
            fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 443
          hostPort: 443
        # we expose 18080 to access nginx stats in url /nginx-status
        # this is optional
        - containerPort: 18080
          hostPort: 18080
        args:
        - /nginx-ingress-controller
        - --default-backend-service=$(POD_NAMESPACE)/default-http-backend

and here is my laravel application deployment

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: demo-rc
  labels:
    name: demo
    version: v1
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        name: demo
        version: v1
    spec:
      containers:
      - image: gcr.io/projectname/laravelapp:vx
        name: app-pod
        ports:
        - containerPort: 8080

I tried to add the domain entry to the hosts file but with no luck !! is there a specific configurations I have to add to the configmap.yaml file for the nginx ingress controller?

-- montatich
docker
google-cloud-platform
kubernetes
laravel
nginx

1 Answer

2/1/2019

In short, to be able to reach your application via external domain name (singapore.smartlabplatform.com), you need to create a A DNS record for GCP L4 Load Balancer's external IP address (this is in other words EXTERNAL-IP of your default nginx-ingress-controller's Service), here seen as pending:

==> v1/Service
NAME                            TYPE          CLUSTER-IP    EXTERNAL-IP  
nginx-ingress-controller        LoadBalancer  10.7.248.226  pending      
nginx-ingress-default-backend   ClusterIP     10.7.245.75   none

how to do this? it's explained on the GKE tutorials page here.

In the current state of your environment you can only reach your application in two ways:

  1. From outside, via Load Balancer EXTERNAL-IP:

    enter image description here

  2. From inside, your Kubernetes cluster using laravel-kubernetes-demo service dns name:

$ curl laravel-kubernetes-demo.default.svc.cluster.local

<title>Laravel Kubernetes Demo :: LearnK8s</title>

If you want all that magic, like the automatic creation of DNS records, happen along with appearance of host: domain.com in your ingress resource spec, you should use external-dns (makes Kubernetes resources discoverable via public DNS servers), and here is the tutorial on how to set it up specifically for GKE.

-- Nepomucen
Source: StackOverflow