How to structure a Kubernetes Project for a Web Application?

11/22/2018

I like to create an app with kubernetes.

  • I have api server, frontend server, a few scrapers and so on.
  • I'd like to put the api and the frontend in the same pod, and all the scrapers in other pod.
  • I'd like to be able to deploy a single project, only the api for example or a specific scraper.
  • Each app has a docker file and circle ci configuration for deploy

How should I structure my project?
Should each app be in it's own repository or should I use monorepo?
Where should I keep the k8s.yaml (since it relates to all projects)?
Where should I apply the k8s configurations? Should it happen on each deploy? How can I config domain names for each service easily?

-- Naor
gcloud
kubernetes

2 Answers

11/22/2018

There is some points:

I'd like to put the api and the frontend in the same pod, and all the scrapers in other pod.

It's ok. as long as they are on different containers in same pod. multi container pods are accessible from each other with localhost address. and pods can see each other with DNS. (and yes half healthy means unhealthy)

How should I structure my project?

I use different repo for different container. but its ok for every pod = 1 repo. Its easier to maintain this way, and you have separate CI/CD builds which ables you to update each app separately. Storing each Deployment manifest YAML file in the root of repo is a good idea. Because one Deployment means 1 app (one set of pods).

Where should I apply the k8s configurations? Should it happen on each deploy? How can I config domain names for each service easily?

In Deployment manifest file you can store configs in ENVs or use a config map. You dont need to use kubectl apply for each deployment. In your CI you can do this for each deploy:

- docker build -t {registry}:{version} .
- docker push {registry}:{version}
- kubectl set image deployment/{API_NAME} {containername}={registry}:{version} -n {NAMESPACE}

You need a reverse proxy in front of your APIs as a gateway, best option is Ingress which is easy to deploy and config. and it knows your pods. Ingress config can be like:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: api
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: api.yourdomain.com
    http:
      paths:
      - path: /application1
        backend:
          serviceName: app1-production
          servicePort: 80 
      - path: /application2
        backend:
          serviceName: app2-production
          servicePort: 80 

or just use one subdomain per api, as you prefer.

-- Nima Hashemi
Source: StackOverflow

11/22/2018

It really depends on your use case but I would advise certain practices for making life easier:

I'd like to put the api and the frontend in the same pod, and all the scrapers in other pod.

Don't put more than one container in a same pod (unless it's a sidecar like conduit, istio, etc...) because it will be really tough to perform health checks on your pods (if one container is down and the other one is up, the pod is... half-healthy?)

I'd like to be able to deploy a single project, only the api for example or a specific scraper.

Where should I keep the k8s.yaml (since it relates to all projects)?

Separate the yaml files to their own projects directories so that you can deploy them independently and for better readability.

Using a monorepo has it's advantages, the code is in one place, etc... But if you will have CI, as the repo gets bigger, your builds might become slower so you would either need to optimize (use build caching or such) or have a separate CI for each business domain or logical group you might have.

How should I structure my project?

Separate infrastructure from application so that if one day you want to switch from GCE to AWS or Azure and also for better readability.

Where should I apply the k8s configurations? Should it happen on each deploy? How can I config domain names for each service easily?

Kubernetes has got a really extensive list of examples on all the ways you can inject configuration to your apps, this really depends on your use case. You don't need to configure domain names for each service, only the ones that are exposed to the outside world. You can use an Ingress object or a proxy.

The things you need to consider:

Logging - this is a very important topic because having scalable pods can be tricky business. I would really take my time to deploy some tight distributed logging.

Environments - Develop/Production or Develop/Staging/Production or ... ? Whatever you choose, make sure they have minimal differences and that each step can be easily deployable.

-- Urosh T.
Source: StackOverflow