<p>In my setup, there is a set of containers that were initially built to run with <code>docker-compose</code>. After moving to Kubernetes I'm facing the following challenges:</p>
<ol>
<li><code>docker-compose</code> managed to provide some type of internal DNS that allowed a container to be addressed by its name. How do I create such a network in Kubernetes? What I found so far:</li>
</ol>
<ul>
<li>they could all be part of one pod and therefore communicate via localhost</li>
<li>they could all have a common label with matching key:value pairs and a service, but how does one handle Ports?</li>
</ul>
<ol start="2">
<li>I need to expose an internal Port to a certain NodePort as it has to be publicly available. How does such a service config look like? What I found so far:</li>
</ol>
<ul>
<li><p>something like this:</p>
<pre><code>      apiVersion: v1
      kind: Service
      metadata:
        labels:
          app: frontend
        name: frontend-nodeport
      spec:
        type: NodePort
        ports:
        - name: &quot;3000-30001&quot;
          port: 3000
          nodePort: 30001
        selector:
          app: frontend
      status:
        loadBalancer: {}`
</code></pre>
</li>
</ul>

<blockquote>
  <p>Docker-compose managed to provide some type of internal DNS that allowed a container to be addressed by its name. How do I create such a network in Kubernetes?</p>
</blockquote>

<p>As you researched, you can, indeed have two approaches:</p>

<ul>
<li><p><strong>IF</strong> you containers are to be <strong>scaled together</strong> then place them inside same pod and communicate through localhost over separate ports. This is less likely your case since this approach is more suitable when containerized app is more similar to processes on one physical box than a separate service/server.</p></li>
<li><p><strong>IF</strong> your containers are to be <strong>scaled separaltey</strong>, which is more probably your case, then use service. With services, in place of localhost (in previous point)  you will either use just service name as it is (if pods are in same namespace) or FQDN (servicename.namespace.svc.cluster.local) if services are accessed across namespaces. As opposed to previous point where you had to have different ports for your containers (since you address localhost), in this case you can have same port across multiple services, since service:port must be unique. Also with service you can remap ports from containers if you wish to do so as well.</p></li>
</ul>

<p>Since you asked this as an introductory question two words of caution:</p>

<ul>
<li>service resolution works from standpoint of pod/container. To test it you actually need to exec into actual container (or proxy from host) and this is common confusion point. Just to be on safe side test service:port accessibility within actual container, not from master.</li>
<li>Finally, just to mimic docker-compose setup for inter-container network, you don't need to expose NodePort or whatever. Service layer in kubernetes will take care of DNS handling. NodePort has different intention.</li>
</ul>

<blockquote>
  <p>I need to expose an internal Port to a certain NodePort. How does such a service config look like?</p>
</blockquote>

<p>You are on a good track, here is <a href="https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0" rel="nofollow noreferrer">nice overview</a> to get you started, and reference relevant to your question is given below:</p>

<pre><code>apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
selector:    
  app: my-app
spec:
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP
</code></pre>

<blockquote>
  <p>Edit: Could you please provide an example of how a service.yaml would look like if the containers are scaled seperately ?</p>
</blockquote>

<ul>
<li><p>First one is, say, api server, we'll call it <code>svc-my-api</code>, it will use pod(s) labeled <code>app: my-api</code> and communicate to pod's port 80 and will be accessible by other pods (in the same namespace) as host:<code>svc-my-api</code> and port:<code>8080</code></p>

<pre><code>apiVersion: v1
kind: Service
metadata:
  name: svc-my-api
  labels:
    app: my-api
spec:
  selector:
    app: my-api
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80
</code></pre></li>
<li><p>Second one is, say, mysql server, we'll call it <code>svc-my-database</code>. Supposing that containers from api pods (covered by previous service) want to access database, they will use host:<code>svc-my-database</code> and port:<code>3306</code>.</p>

<pre><code>apiVersion: v1
kind: Service
metadata:
  name: svc-my-database
  labels:
    app: my-database
spec:
  selector:
    app: my-database
  ports:
  - name: http
    protocol: TCP
    port: 3306
    targetPort: 3306
</code></pre></li>
</ul>
