<p>Sorry for my bad English but I don't know how to solve my problem.
So...
Introduction:
I have 2 microservices (I called them gRPCClient and gRPCServer, although it doesn’t matter what exactly). They need to communicate via TLS. Without Kubernets, everything is quite simple. I create my CA via cfssl in a docker container, then I get the root certificate from CA and I put it in trust for my grpc applications (I do this in Dockerfile), so that any certificate signed by my CA passes the test.</p>
<p>Now Kubernetes is included in the game. I'm playing locally with minikube. I create local cluster &quot;minikube start&quot; on mac (maybe this is important, I don’t know ...)</p>
<p>Problem:
How will this flow work with the Kubernetes? As I understand it, there is already a CA inside the Kubernetes (correct me if this is not so). I read many articles, but I really didn’t understand anything. I tried the examples from this article <a href="https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/" rel="nofollow noreferrer">https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/</a>
Step by step:</p>
<ol>
<li>Create a signature request</li>
</ol>
<pre><code>    cat &lt;&lt;EOF | cfssl genkey - | cfssljson -bare server
    {
      &quot;hosts&quot;: [
        &quot;my-svc.my-namespace.svc.cluster.local&quot;,
        &quot;my-pod.my-namespace.pod.cluster.local&quot;,
        &quot;192.0.2.24&quot;,
        &quot;10.0.34.2&quot;
      ],
      &quot;CN&quot;: &quot;my-pod.my-namespace.pod.cluster.local&quot;,
      &quot;key&quot;: {
        &quot;algo&quot;: &quot;ecdsa&quot;,
        &quot;size&quot;: 256
      }
    }
    EOF
</code></pre>
<p>The first thing I did not understand was the hosts. For example, my-svc.my-namespace.svc.cluster.local is the full name of my service? (I mean the service in Kubernetes as kind: Service). I have it in the namespace &quot;dev&quot; and its name is user-app-sesrvice. Should I specify user-app-sesrvice.dev.svc.cluster.local then? or it just user-app-sesrvice. Or is there some kind of command to get the full name of the service? 192.0.2.24 - as I understand it, is the IP of service, it is also unclear whether it is mandatory to specify it or is it possible only the name of the service? What if I have clusterIP: None installed, then I don't have IP for it. my-pod.my-namespace.pod.cluster.local - Should I specify this? If I have several pods, should I list them all? Then the problem is in the dynamics, because the pods are recreated, deleted and added, and I need to send a new request for signature each time. The same questions that I asked about service including some parts &quot;my-pod&quot; and &quot;namespace&quot;? Is it possible to see the full name of the pod with all this data. 10.0.34.2 - pods' IP. The same question about pods' IP.</p>
<p>I tried to specify the host and CN as name of my service name &quot;user-app-service&quot; (as if I was working without a Kubernetes). I created a signature and a key. Then all the steps, created a request object for signature in the Kubernetes</p>
<pre><code>    cat &lt;&lt;EOF | kubectl apply -f -
    apiVersion: certificates.k8s.io/v1beta1
    kind: CertificateSigningRequest
    metadata:
      name: my-svc.my-namespace
    spec:
      request: $(cat server.csr | base64 | tr -d '\n')
      usages:
      - digital signature
      - key encipherment
      - server auth
    EOF
</code></pre>
<p>Then I made it and I received a certificate
Further, based on security, I need to store the key and a certificate in secrets and then get it in the container (for the purposes of the test, I just put them in the container in the docker file, hard-coded), this is in the gRPC server. I run the deployment and created a client on golang, specifying config: = &amp;tls.Config{} in the code so that it would pull the trusted certificates from the system itself, I thought that the Kubernetes has a CA, but did not find how to get its certificate in the docs. I thought the Kubernetes adds them to all the containers himself. But I got the error Unavailable desc = connection error: desc = &quot;transport: authentication handshake failed: x509: certificate signed by unknown authority&quot;. How should all this work? Where can I get a CA certificate from a Kubernetes? And then, do I need to add it to each container with my hands in dockerfile? or is this not the right tactic and is there some kind of automation from the Kubernetes?</p>
<p>I found another way, this is to try to deploy cfssl <a href="https://hub.docker.com/r/cfssl/cfssl/" rel="nofollow noreferrer">https://hub.docker.com/r/cfssl/cfssl/</a> on the Kubernetes and already work with it, like there was no Kubernetes (I have not tried this method yet)</p>
<p>How to put all this into a working system, what options to use and why? Maybe there are some full articles. I wrote a lot, but I hope it’s clear. I really need the help.</p>

<p>I am going to break down my answer into a couple of parts:</p>
<h2>Kubernetes Services and DNS Discovery</h2>
<p>In general, it is recommended to put a Service in front of a Deployment that manages pods in Kubernetes.
The Service creates a stable DNS and IP endpoint for pods that may be deleted and be assigned a different
IP address when recreated. DNS service discovery is automatically enabled with a ClusterIP type service and
is in the format: <code>&lt;service name&gt;.&lt;kubernetes namespace&gt;.svc.&lt;cluster domain&gt;</code> where cluster domain is usually
<code>cluster.local</code>. This means that we can use the autocreated DNS and assigned ClusterIP in our altnames for our
certificate.</p>
<h2>Kubernetes Internal CA</h2>
<p>Kubernetes does have an internal CA along with API methods to post CSRs and have those CSRs signed
by the CA however I would not use the internal CA for securing microservices. The internal CA is
primarily used by the kubelet and other internal cluster processes to authenticate to the Kubernetes
API server. There is no functionality for autorenewal and I think the cert will always be signed for 30 days.</p>
<h2>Kubernetes-native Certificate Management</h2>
<p>You can install and use <a href="https://cert-manager.io/docs/" rel="noreferrer">cert-manager</a> to have the cluster automatically create and manage certificates
for you using custom resources. They have excellent examples on their website so I would encourage you
to check that out if it is of interest. You should be able to use the <a href="https://cert-manager.io/docs/configuration/ca/" rel="noreferrer">CA Issuer Type</a> and create
<a href="https://cert-manager.io/docs/usage/certificate/" rel="noreferrer">Certificate Resources</a> that will create a certificate as a Kubernetes Secret. For the altnames, refer
to the below certificate generation steps in the manual section of my response.</p>
<h2>Manually Create and Deploy Certificates</h2>
<p>You should be able to achieve they same result using your &quot;without Kubernetes&quot; approach using cfssl:</p>
<ol>
<li><p>generate CA using cfssl</p>
</li>
<li><p>add CA as trusted in image (using your Dockerfile approach)</p>
</li>
<li><p>create Kubernetes Service (for example purposes I will use <code>kubectl create</code>)</p>
<pre><code>$ kubectl create service clusterip grpcserver --tcp=8000
</code></pre>
</li>
<li><p>describe the created Kubernetes Service, note IP will most likely be different in your case</p>
<pre><code>$ kubectl describe service/grpcserver
Name:              grpcserver
Namespace:         default
Labels:            app=grpcserver
Annotations:       &lt;none&gt;
Selector:          app=grpcserver
Type:              ClusterIP
IP:                10.108.125.158
Port:              8000  8000/TCP
TargetPort:        8000/TCP
Endpoints:         &lt;none&gt;
Session Affinity:  None
Events:            &lt;none&gt;
</code></pre>
</li>
<li><p>generate certificate for gRPCServer with a CN of grpcserver.default.svc.cluster.local the following altnames:</p>
<ul>
<li>grpcserver</li>
<li>grpcserver.default.svc</li>
<li>grpcserver.default.svc.cluster.local</li>
<li>10.108.125.158</li>
</ul>
</li>
<li><p>generate the client certificate with cfssl</p>
</li>
<li><p>put both certificates into Secret objects</p>
<pre><code>kubectl create secret tls server --cert=server.pem --key=server.key
kubectl create secret tls client --cert=client.pem --key=client.key
</code></pre>
</li>
<li><p><a href="https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets" rel="noreferrer">mount</a> the secret into the podspec</p>
</li>
</ol>
