<p>I am currently facing an issue in my Kubernetes cluster. While debugging that I had a question in mind which I didn't know the answer to.</p>
<p>I am using AWS EKS, version 1.15 but I don't think my question is related to any specific cloud or kubernetes version</p>
<p>I have a deployment. It has multiple containers. There is a service that exposes this deployment.</p>
<p>Suppose the deployment has 2 containers, C1 and C2. C1 takes 1 second to start but C2 takes 30 seconds to start(crazy!). So, when I start the pod at time t1, what happens is that once C1 starts immediately and the pod goes into running status but only 1/2 containers are ready. The pod C2 finally starts at time t2(t1+30seconds). At time t2, 2/2 containers are ready.</p>
<p>Also assume that C1 takes the incoming request from the service, it does something and then forwards request to C2, C2 does something and then returns it to C1. C1 finally returns to service and the response is served to client.</p>
<p>So, my question is, during the time between t2 and t1, when pod is in running state but only 1/2 container is ready, would the service forward requests to the pods?</p>
<p>Put another way, when does the service forward request to pods? If they are in running state and not matter how many containers are ready? OR if they are in running state and all containers are ready?</p>
<p>My thinking is that service won't forward as it won't make any sense if all the pods are not ready but I don't have any proof/document to justify it.</p>

<p>In order to make your scenario more understandable, lets call them <strong>web</strong> and <strong>api</strong>. those are the components of our service and while <strong>web</strong> will be ready in seconds, the <strong>api</strong> component will need more time.</p>
<p>First things first, we need to decide our deployment strategy. If we put <strong>web</strong> and <strong>api</strong> in the same deployment, then the <strong>service</strong> object on top of this deployment will enforce the definitions on both of them. So if you want to expose your <strong>web</strong> service on port 443, then the <strong>api</strong> will also be exposed on port 443. Yes, you can label those and set different definitions, but this is far from ideal.</p>
<p>We can say that the <strong>service</strong> objects in Kubernetes world acts like a <strong>load-balancer</strong>. So if you put two different components on the same deployment, and define a service object on top of them, then when you call your service from an outside network, you will end up reaching <strong>web</strong> or <strong>api</strong> endpoints, randomly.</p>
<p>You can check this image out for visualization: <a href="https://i.stack.imgur.com/mJ1Al.png" rel="nofollow noreferrer">Kubernetes Service Example</a></p>
<p>In an ideal world, you need to deploy this application in two different deployments, because they can be de-coupled and serves for different purposes. After deploying those, all you need to do is to deploy two different services to expose your deployments. From my understanding, the <strong>api</strong> is only operating in the internal network, so it can be <strong><a href="https://dev.to/kaoskater08/building-a-headless-service-in-kubernetes-3bk8#:%7E:text=A%20headless%20service%20is%20a,spec." rel="nofollow noreferrer">headless-service</a></strong>.</p>
<p>First things first, let's create a namespace (or project) for the application.</p>
<pre><code>kubectl create ns myapp
</code></pre>
<p>And define our deployment So for our <strong>web</strong> component, let's define the deployment file;</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 9376
</code></pre>
<p>and the service which exposes our web deployment to the outside network</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
</code></pre>
<p>You can see that the <strong>web-deployment</strong> deployment object has three replicas and the <strong>web-service</strong> service definition will load-balance the incoming requests accordingly.</p>
<p>Now, let's deploy the <strong>api</strong></p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-deployment
  labels:
    app: api
spec:
  replicas: 5
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: apirepo/api
        ports:
        - containerPort: 3000
</code></pre>
<p>and the headless service for the <strong>api-deployment</strong></p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: api-headless-service
spec:
  clusterIP: None 
  selector:
    app: api
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000 
</code></pre>
<p>and that's all. Now you can scale up or down your <strong>web</strong> and <strong>api</strong> deployments based on requests and the service definitions will load-balance those automatically and handle the service discovery.</p>
